# Test that the various encodings support encoding comments from CUE.
# We cover multiple output modes (def, eval, export) as well as multiple encodings,
# and also comments coming from definitions, unifications, and disjunctions.
# Note that some encodings have no support for comments, like JSON.
# This is meant mainly as an end-to-end smoke test; specific edge cases
# should be tested in each encoding package.

# TODO(mvdan): test importing comments into CUE as well.
# TODO(mvdan): comments at the end of a file are not exported.
# TODO(mvdan): comments at the start of a struct are not exported.
# TODO(mvdan): comments attached to a list or its elements are not exported.
# TODO(mvdan): comments between fields or list elements are not exported.

exec cue def --out cue .
cmp stdout def-cue.stdout

# TODO(mvdan): why does eval not include comments when def and export do?
exec cue eval --out cue .
cmp stdout eval-cue.stdout

exec cue export --out cue .
cmp stdout export-cue.stdout

exec cue export --out json .
cmp stdout export-json.stdout

# TODO(mvdan): YAML should support exporting comments.
exec cue export --out yaml .
cmp stdout export-yaml.stdout

# TODO(mvdan): TOML should support exporting comments.
exec cue export --out toml .
cmp stdout export-toml.stdout

-- basic.cue --
// comment at the start of a file.

// Package p is an example package.
package p

// top-level comment before a simple field.
foo: "bar"
// top-level comment after a simple field.

// top-level comment before a struct
struct: {
	// comment at the start of a struct.

	// comment in a struct field
	field1: "message1"

	// comment between struct fields.

	field2: "message2"

	// comment at the end of a struct.
}

// top-level comment before a list.
list: [
	// comment at the start of a list.

	1,
	// comment in a list element.
	2,

	// comment between list elements.

	3,

	// comment at the end of a list.
]

// comment at the end of a file.
-- schema.cue --
package p

// Schema declares a schema.
#Schema: {
	// name is the schema name.
	name?: string
}
-- data.cue --
package p

// Data fits the schema.
Data: #Schema & {
	// name is a specific name.
	name: "Foo"
}

// implicitUnified is any non-empty string.
implicitUnified: string & != ""

// implicitUnified is some string value.
implicitUnified: "some value"

// explicitUnified1 sets a default value.
explicitUnified1: string | *"some default"

// explicitUnified2 sets a value.
explicitUnified2: "some value"

// explicitUnified unifies two values.
explicitUnified: explicitUnified1 & explicitUnified2

// disjunction1 has a default.
_disjunction1: string | *"some default"

// disjunction2 has no default.
_disjunction2: int

// disjunction is like a sum type.
disjunction: _disjunction1 | _disjunction2

-- def-cue.stdout --
// comment at the start of a file.

// Package p is an example package.
package p

// top-level comment before a simple field.
foo: "bar"

// top-level comment before a struct
struct: {
	// comment in a struct field
	field1: "message1"
	field2: "message2"

	// comment at the end of a struct.
}

// Data fits the schema.
Data: #Schema & {
	// name is a specific name.
	name: "Foo"
}

// Schema declares a schema.
#Schema: {
	// name is the schema name.
	name?: string
}

// top-level comment before a list.
list: [1, 2, 3]

// implicitUnified is any non-empty string.

// implicitUnified is some string value.
implicitUnified: "some value"

// explicitUnified1 sets a default value.
explicitUnified1: string | *"some default"

// explicitUnified2 sets a value.
explicitUnified2: "some value"

// explicitUnified unifies two values.
explicitUnified: explicitUnified1 & explicitUnified2

// disjunction1 has a default.
_disjunction1: string | *"some default"

// disjunction2 has no default.
_disjunction2: int

// disjunction is like a sum type.
disjunction: _disjunction1 | _disjunction2
-- eval-cue.stdout --
#Schema: {}
Data: {
    name: "Foo"
}
foo:              "bar"
implicitUnified:  "some value"
explicitUnified1: "some default"
explicitUnified2: "some value"
explicitUnified:  "some value"
disjunction:      "some default"
struct: {
    field1: "message1"
    field2: "message2"
}
list: [1, 2, 3]
-- export-cue.stdout --
// Data fits the schema.
Data: {
	// name is a specific name.

	// name is the schema name.
	name: "Foo"
}

// top-level comment before a simple field.
foo: "bar"

// implicitUnified is any non-empty string.

// implicitUnified is some string value.
implicitUnified: "some value"

// explicitUnified1 sets a default value.
explicitUnified1: "some default"

// explicitUnified2 sets a value.
explicitUnified2: "some value"

// explicitUnified unifies two values.
explicitUnified: "some value"

// disjunction is like a sum type.
disjunction: "some default"

// top-level comment before a struct
struct: {
	// comment in a struct field
	field1: "message1"
	field2: "message2"

	// comment at the end of a struct.
}

// top-level comment before a list.
list: [1, 2, 3]
-- export-json.stdout --
{
    "Data": {
        "name": "Foo"
    },
    "foo": "bar",
    "implicitUnified": "some value",
    "explicitUnified1": "some default",
    "explicitUnified2": "some value",
    "explicitUnified": "some value",
    "disjunction": "some default",
    "struct": {
        "field1": "message1",
        "field2": "message2"
    },
    "list": [
        1,
        2,
        3
    ]
}
-- export-yaml.stdout --
Data:
  name: Foo
foo: bar
implicitUnified: some value
explicitUnified1: some default
explicitUnified2: some value
explicitUnified: some value
disjunction: some default
struct:
  field1: message1
  field2: message2
list:
  - 1
  - 2
  - 3
-- export-toml.stdout --
disjunction = 'some default'
explicitUnified = 'some value'
explicitUnified1 = 'some default'
explicitUnified2 = 'some value'
foo = 'bar'
implicitUnified = 'some value'
list = [1, 2, 3]

[Data]
name = 'Foo'

[struct]
field1 = 'message1'
field2 = 'message2'
