diff --git a/pkg/yqlib/candidate_node_goccy_yaml.go b/pkg/yqlib/candidate_node_goccy_yaml.go index 89471f18..3e861b83 100644 --- a/pkg/yqlib/candidate_node_goccy_yaml.go +++ b/pkg/yqlib/candidate_node_goccy_yaml.go @@ -69,6 +69,9 @@ func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap, an o.Kind = ScalarNode o.Tag = "!!null" o.Value = node.GetToken().Value + if node.GetToken().Type == goccyToken.ImplicitNullType { + o.Value = "" + } case ast.StringType: o.Kind = ScalarNode o.Tag = "!!str" @@ -112,7 +115,7 @@ func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap, an for _, mappingValueNode := range mappingNode.Values { err := o.goccyProcessMappingValueNode(mappingValueNode, cm, anchorMap) if err != nil { - return ast.ErrInvalidAnchorName + return err } } if mappingNode.FootComment != nil { @@ -126,7 +129,7 @@ func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap, an mappingValueNode := node.(*ast.MappingValueNode) err := o.goccyProcessMappingValueNode(mappingValueNode, cm, anchorMap) if err != nil { - return ast.ErrInvalidAnchorName + return err } case ast.SequenceType: log.Debugf("UnmarshalYAML - a sequence node") diff --git a/pkg/yqlib/goccy_yaml_test.go b/pkg/yqlib/goccy_yaml_test.go index 8389e913..9c1158cb 100644 --- a/pkg/yqlib/goccy_yaml_test.go +++ b/pkg/yqlib/goccy_yaml_test.go @@ -7,96 +7,96 @@ import ( ) var goccyYamlFormatScenarios = []formatScenario{ - // { - // description: "basic - 3", - // skipDoc: true, - // input: "3", - // expected: "3\n", - // }, - // { - // description: "basic - 3.1", - // skipDoc: true, - // input: "3.1", - // expected: "3.1\n", - // }, - // { - // description: "basic - mike", - // skipDoc: true, - // input: "mike: 3", - // expected: "mike: 3\n", - // }, - // { - // description: "basic - map multiple entries", - // skipDoc: true, - // input: "mike: 3\nfred: 12\n", - // expected: "mike: 3\nfred: 12\n", - // }, - // { - // description: "basic - 3.1", - // skipDoc: true, - // input: "{\n mike: 3\n}", - // expected: "{mike: 3}\n", - // }, - // { - // description: "basic - tag with number", - // skipDoc: true, - // input: "mike: !!cat 3", - // expected: "mike: !!cat 3\n", - // }, - // { - // description: "basic - array of numbers", - // skipDoc: true, - // input: "- 3", - // expected: "- 3\n", - // }, - // { - // description: "basic - single line array", - // skipDoc: true, - // input: "[3]", - // expected: "[3]\n", - // }, - // { - // description: "basic - plain string", - // skipDoc: true, - // input: `a: meow`, - // expected: "a: meow\n", - // }, - // { - // description: "basic - double quoted string", - // skipDoc: true, - // input: `a: "meow"`, - // expected: "a: \"meow\"\n", - // }, - // { - // description: "basic - single quoted string", - // skipDoc: true, - // input: `a: 'meow'`, - // expected: "a: 'meow'\n", - // }, - // { - // description: "basic - string block", - // skipDoc: true, - // input: "a: |\n meow\n", - // expected: "a: |\n meow\n", - // }, - // { - // description: "basic - long string", - // skipDoc: true, - // input: "a: the cute cat wrote a long sentence that wasn't wrapped at all.\n", - // expected: "a: the cute cat wrote a long sentence that wasn't wrapped at all.\n", - // }, - // { - // description: "basic - string block", - // skipDoc: true, - // input: "a: |-\n meow\n", - // expected: "a: |-\n meow\n", - // }, - // { - // description: "basic - line comment", - // skipDoc: true, - // input: "a: meow # line comment\n", - // expected: "a: meow # line comment\n", - // }, + { + description: "basic - 3", + skipDoc: true, + input: "3", + expected: "3\n", + }, + { + description: "basic - 3.1", + skipDoc: true, + input: "3.1", + expected: "3.1\n", + }, + { + description: "basic - mike", + skipDoc: true, + input: "mike: 3", + expected: "mike: 3\n", + }, + { + description: "basic - map multiple entries", + skipDoc: true, + input: "mike: 3\nfred: 12\n", + expected: "mike: 3\nfred: 12\n", + }, + { + description: "basic - 3.1", + skipDoc: true, + input: "{\n mike: 3\n}", + expected: "{mike: 3}\n", + }, + { + description: "basic - tag with number", + skipDoc: true, + input: "mike: !!cat 3", + expected: "mike: !!cat 3\n", + }, + { + description: "basic - array of numbers", + skipDoc: true, + input: "- 3", + expected: "- 3\n", + }, + { + description: "basic - single line array", + skipDoc: true, + input: "[3]", + expected: "[3]\n", + }, + { + description: "basic - plain string", + skipDoc: true, + input: `a: meow`, + expected: "a: meow\n", + }, + { + description: "basic - double quoted string", + skipDoc: true, + input: `a: "meow"`, + expected: "a: \"meow\"\n", + }, + { + description: "basic - single quoted string", + skipDoc: true, + input: `a: 'meow'`, + expected: "a: 'meow'\n", + }, + { + description: "basic - string block", + skipDoc: true, + input: "a: |\n meow\n", + expected: "a: |\n meow\n", + }, + { + description: "basic - long string", + skipDoc: true, + input: "a: the cute cat wrote a long sentence that wasn't wrapped at all.\n", + expected: "a: the cute cat wrote a long sentence that wasn't wrapped at all.\n", + }, + { + description: "basic - string block", + skipDoc: true, + input: "a: |-\n meow\n", + expected: "a: |-\n meow\n", + }, + { + description: "basic - line comment", + skipDoc: true, + input: "a: meow # line comment\n", + expected: "a: meow # line comment\n", + }, // { // description: "basic - head comment", // skipDoc: true, @@ -109,54 +109,54 @@ var goccyYamlFormatScenarios = []formatScenario{ // input: "# head comment\na: #line comment\n meow\n", // expected: "# head comment\na: meow #line comment\n", // go-yaml does this // }, - // { - // description: "basic - foot comment", - // skipDoc: true, - // input: "a: meow\n# foot comment\n", - // expected: "a: meow\n# foot comment\n", - // }, - // { - // description: "basic - foot comment", - // skipDoc: true, - // input: "a: meow\nb: woof\n# foot comment\n", - // expected: "a: meow\nb: woof\n# foot comment\n", - // }, - // { - // description: "basic - boolean", - // skipDoc: true, - // input: "true\n", - // expected: "true\n", - // }, - // { - // description: "basic - null", - // skipDoc: true, - // input: "a: null\n", - // expected: "a: null\n", - // }, - // { - // description: "basic - ~", - // skipDoc: true, - // input: "a: ~\n", - // expected: "a: ~\n", - // }, - // { - // description: "basic - ~", - // skipDoc: true, - // input: "null\n", - // expected: "null\n", - // }, - // { - // skipDoc: true, - // description: "trailing comment", - // input: "test:", - // expected: "test:", - // }, - // { - // skipDoc: true, - // description: "trailing comment", - // input: "test: null\n# this comment will be removed", - // expected: "test: null\n# this comment will be removed\n", - // }, + { + description: "basic - foot comment", + skipDoc: true, + input: "a: meow\n# foot comment\n", + expected: "a: meow\n# foot comment\n", + }, + { + description: "basic - foot comment", + skipDoc: true, + input: "a: meow\nb: woof\n# foot comment\n", + expected: "a: meow\nb: woof\n# foot comment\n", + }, + { + description: "basic - boolean", + skipDoc: true, + input: "true\n", + expected: "true\n", + }, + { + description: "basic - null", + skipDoc: true, + input: "a: null\n", + expected: "a: null\n", + }, + { + description: "basic - ~", + skipDoc: true, + input: "a: ~\n", + expected: "a: ~\n", + }, + { + description: "basic - ~", + skipDoc: true, + input: "null\n", + expected: "null\n", + }, + { + skipDoc: true, + description: "blank value round trip", + input: "test:", + expected: "test:\n", + }, + { + skipDoc: true, + description: "trailing comment", + input: "test: null\n# this comment will be removed", + expected: "test: null\n# this comment will be removed\n", + }, // { // description: "doc separator", // skipDoc: true, @@ -169,106 +169,106 @@ var goccyYamlFormatScenarios = []formatScenario{ // input: "--- cat", // expected: "---\ncat\n", // }, - // { - // description: "scalar with doc separator", - // skipDoc: true, - // input: "---cat", - // expected: "---cat\n", - // }, - // { - // description: "basic - null", - // skipDoc: true, - // input: "null", - // expected: "null\n", - // }, - // { - // description: "basic - ~", - // skipDoc: true, - // input: "~", - // expected: "~\n", - // }, - // { - // description: "octal", - // skipDoc: true, - // input: "0o30", - // expression: "tag", - // expected: "!!int\n", - // }, - // { - // description: "basic - [null]", - // skipDoc: true, - // input: "[null]", - // expected: "[null]\n", - // }, - // { - // description: "multi document", - // skipDoc: true, - // input: "a: mike\n---\nb: remember", - // expected: "a: mike\n---\nb: remember\n", - // }, - // { - // description: "single doc anchor map", - // skipDoc: true, - // input: "a: &remember mike\nb: *remember", - // expected: "a: mike\nb: *remember\n", - // }, - // { - // description: "explode doc anchor map", - // skipDoc: true, - // input: "a: &remember mike\nb: *remember", - // expression: "explode(.)", - // expected: "a: mike\nb: mike\n", - // }, - // { - // description: "multi document anchor map", - // skipDoc: true, - // input: "a: &remember mike\n---\nb: *remember", - // expression: "explode(.)", - // expected: "a: mike\n---\nb: mike\n", - // }, - // { - // description: "merge anchor", - // skipDoc: true, - // input: "a: &remember\n c: mike\nb:\n <<: *remember", - // expected: "a: &remember\n c: mike\nb:\n <<: *remember\n", - // }, + { + description: "scalar with doc separator", + skipDoc: true, + input: "---cat", + expected: "---cat\n", + }, + { + description: "basic - null", + skipDoc: true, + input: "null", + expected: "null\n", + }, + { + description: "basic - ~", + skipDoc: true, + input: "~", + expected: "~\n", + }, + { + description: "octal", + skipDoc: true, + input: "0o30", + expression: "tag", + expected: "!!int\n", + }, + { + description: "basic - [null]", + skipDoc: true, + input: "[null]", + expected: "[null]\n", + }, + { + description: "multi document", + skipDoc: true, + input: "a: mike\n---\nb: remember", + expected: "a: mike\n---\nb: remember\n", + }, + { + description: "single doc anchor map", + skipDoc: true, + input: "a: &remember mike\nb: *remember", + expected: "a: &remember mike\nb: *remember\n", + }, + { + description: "explode doc anchor map", + skipDoc: true, + input: "a: &remember mike\nb: *remember", + expression: "explode(.)", + expected: "a: mike\nb: mike\n", + }, + { + description: "multi document anchor map", + skipDoc: true, + input: "a: &remember mike\n---\nb: *remember", + expression: "explode(.)", + expected: "a: mike\n---\nb: mike\n", + }, + { + description: "merge anchor", + skipDoc: true, + input: "a: &remember\n c: mike\nb:\n <<: *remember", + // fine to have !!merge as that's what the current impl does + expected: "a: &remember\n c: mike\nb:\n !!merge <<: *remember\n", + }, { description: "custom tag", skipDoc: true, input: "a: !cat mike", expected: "a: !cat mike\n", }, - // { - // description: "basic - [~]", - // skipDoc: true, - // input: "[~]", - // expected: "[~]\n", - // }, - // { - // description: "basic - null map value", - // skipDoc: true, - // input: "a: null", - // expected: "a: null\n", - // }, - // { - // description: "basic - number", - // skipDoc: true, - // input: "3", - // expected: "3\n", - // }, - // { - // description: "basic - float", - // skipDoc: true, - // input: "3.1", - // expected: "3.1\n", - // }, - // { - // description: "basic - float", - // skipDoc: true, - // input: "[1, 2]", - // expected: "[1, 2]\n", - // }, - + { + description: "basic - [~]", + skipDoc: true, + input: "[~]", + expected: "[~]\n", + }, + { + description: "basic - null map value", + skipDoc: true, + input: "a: null", + expected: "a: null\n", + }, + { + description: "basic - number", + skipDoc: true, + input: "3", + expected: "3\n", + }, + { + description: "basic - float", + skipDoc: true, + input: "3.1", + expected: "3.1\n", + }, + { + description: "basic - float", + skipDoc: true, + input: "[1, 2]", + expected: "[1, 2]\n", + }, } func testGoccyYamlScenario(t *testing.T, s formatScenario) { diff --git a/pkg/yqlib/operator_anchors_aliases_test.go b/pkg/yqlib/operator_anchors_aliases_test.go index 8b423b37..a24f3fdd 100644 --- a/pkg/yqlib/operator_anchors_aliases_test.go +++ b/pkg/yqlib/operator_anchors_aliases_test.go @@ -223,9 +223,20 @@ var anchorOperatorScenarios = []expressionScenario{ "D0, P[], (!!map)::a: mike\n", }, }, + { + description: "Explode with alias keys", + subdescription: "No space between alias", + skipDoc: true, + document: `{f : {a: &a cat, *a: b}}`, + expression: `explode(.f)`, + expected: []string{ + "D0, P[], (!!map)::{f: {a: cat, cat: b}}\n", + }, + skipForGoccy: true, // can't handle no space between alias + }, { description: "Explode with alias keys", - document: `{f : {a: &a cat, *a: b}}`, + document: `{f : {a: &a cat, *a : b}}`, expression: `explode(.f)`, expected: []string{ "D0, P[], (!!map)::{f: {a: cat, cat: b}}\n", diff --git a/pkg/yqlib/operator_style_test.go b/pkg/yqlib/operator_style_test.go index e20e93f2..11214092 100644 --- a/pkg/yqlib/operator_style_test.go +++ b/pkg/yqlib/operator_style_test.go @@ -47,10 +47,10 @@ var styleOperatorScenarios = []expressionScenario{ }, { skipDoc: true, - document: "bing: &foo frog\na:\n c: cat\n <<: [*foo]", + document: "bing: &foo {x: z}\na:\n c: cat\n <<: [*foo]", expression: `(... | select(tag=="!!str")) style="single"`, expected: []string{ - "D0, P[], (!!map)::'bing': &foo 'frog'\n'a':\n 'c': 'cat'\n !!merge <<: [*foo]\n", + "D0, P[], (!!map)::'bing': &foo {'x': 'z'}\n'a':\n 'c': 'cat'\n !!merge <<: [*foo]\n", }, }, { diff --git a/pkg/yqlib/operator_traverse_path_test.go b/pkg/yqlib/operator_traverse_path_test.go index 4a2c7917..a069e9f6 100644 --- a/pkg/yqlib/operator_traverse_path_test.go +++ b/pkg/yqlib/operator_traverse_path_test.go @@ -43,6 +43,7 @@ var traversePathOperatorScenarios = []expressionScenario{ expected: []string{ "D0, P[x], (!!null)::null\n", }, + skipForGoccy: true, // throws an error instead, that's fine }, { skipDoc: true, @@ -553,6 +554,7 @@ var traversePathOperatorScenarios = []expressionScenario{ document: badAliasSample, expression: ".steps[]", expectedError: "can only use merge anchors with maps (!!map), but got !!seq", + skipForGoccy: true, // throws an error on parsing, that's fine }, } diff --git a/pkg/yqlib/operator_unique_test.go b/pkg/yqlib/operator_unique_test.go index 7b2c1629..0b81f64e 100644 --- a/pkg/yqlib/operator_unique_test.go +++ b/pkg/yqlib/operator_unique_test.go @@ -99,6 +99,7 @@ var uniqueOperatorScenarios = []expressionScenario{ expected: []string{ "D0, P[], (!!seq)::# abc\n[{name: harry, pet: cat}, {pet: fish}]\n# xyz\n", }, + skipForGoccy: true, // https://github.com/goccy/go-yaml/issues/757 }, } diff --git a/pkg/yqlib/operators_test.go b/pkg/yqlib/operators_test.go index fe6cadcc..eef6da26 100644 --- a/pkg/yqlib/operators_test.go +++ b/pkg/yqlib/operators_test.go @@ -29,12 +29,27 @@ type expressionScenario struct { expectedError string dontFormatInputForDoc bool // dont format input doc for documentation generation requiresFormat string + skipForGoccy bool } +var goccyTesting = false + +var testingDecoder = NewYamlDecoder(ConfiguredYamlPreferences) + func TestMain(m *testing.M) { logging.SetLevel(logging.ERROR, "") + if os.Getenv("DEBUG") == "true" { + logging.SetLevel(logging.DEBUG, "") + } ConfiguredYamlPreferences.ColorsEnabled = false ConfiguredJSONPreferences.ColorsEnabled = false + + goccyTesting = os.Getenv("GOCCY") == "true" + + if goccyTesting { + testingDecoder = NewGoccyYAMLDecoder() + } + Now = func() time.Time { return time.Date(2021, time.May, 19, 1, 2, 3, 4, time.UTC) } @@ -53,10 +68,13 @@ func NewSimpleYamlPrinter(writer io.Writer, unwrapScalar bool, indent int, print func readDocument(content string, fakefilename string, fakeFileIndex int) (*list.List, error) { reader := bufio.NewReader(strings.NewReader(content)) - return readDocuments(reader, fakefilename, fakeFileIndex, NewYamlDecoder(ConfiguredYamlPreferences)) + return readDocuments(reader, fakefilename, fakeFileIndex, testingDecoder) } func testScenario(t *testing.T, s *expressionScenario) { + if s.skipForGoccy { + return + } var err error node, err := getExpressionParser().ParseExpression(s.expression) if err != nil { @@ -192,7 +210,7 @@ func formatYaml(yaml string, filename string) string { panic(err) } streamEvaluator := NewStreamEvaluator() - _, err = streamEvaluator.Evaluate(filename, strings.NewReader(yaml), node, printer, NewYamlDecoder(ConfiguredYamlPreferences)) + _, err = streamEvaluator.Evaluate(filename, strings.NewReader(yaml), node, printer, testingDecoder) if err != nil { panic(err) }