mirror of
https://github.com/mikefarah/yq.git
synced 2026-09-05 09:04:58 +08:00
goccy yaml decoder supports anchor/aliases
This commit is contained in:
@@ -9,14 +9,14 @@ import (
|
||||
goccyToken "github.com/goccy/go-yaml/token"
|
||||
)
|
||||
|
||||
func (o *CandidateNode) goccyDecodeIntoChild(childNode ast.Node, cm yaml.CommentMap) (*CandidateNode, error) {
|
||||
func (o *CandidateNode) goccyDecodeIntoChild(childNode ast.Node, cm yaml.CommentMap, anchorMap map[string]*CandidateNode) (*CandidateNode, error) {
|
||||
newChild := o.CreateChild()
|
||||
|
||||
err := newChild.UnmarshalGoccyYAML(childNode, cm)
|
||||
err := newChild.UnmarshalGoccyYAML(childNode, cm, anchorMap)
|
||||
return newChild, err
|
||||
}
|
||||
|
||||
func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap) error {
|
||||
func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap, anchorMap map[string]*CandidateNode) error {
|
||||
log.Debugf("UnmarshalYAML %v", node)
|
||||
log.Debugf("UnmarshalYAML %v", node.Type().String())
|
||||
log.Debugf("UnmarshalYAML Node Value: %v", node.String())
|
||||
@@ -62,6 +62,7 @@ func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap) er
|
||||
o.Kind = ScalarNode
|
||||
o.Tag = "!!bool"
|
||||
case ast.NullType:
|
||||
log.Debugf("its a null type with value %v", node.GetToken().Value)
|
||||
o.Kind = ScalarNode
|
||||
o.Tag = "!!null"
|
||||
o.Value = node.GetToken().Value
|
||||
@@ -92,7 +93,7 @@ func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap) er
|
||||
// to solve the multiline > problem
|
||||
o.Value = astLiteral.Value.Value
|
||||
case ast.TagType:
|
||||
if err := o.UnmarshalGoccyYAML(node.(*ast.TagNode).Value, cm); err != nil {
|
||||
if err := o.UnmarshalGoccyYAML(node.(*ast.TagNode).Value, cm, anchorMap); err != nil {
|
||||
return err
|
||||
}
|
||||
o.Tag = node.(*ast.TagNode).Start.Value
|
||||
@@ -106,7 +107,7 @@ func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap) er
|
||||
o.Style = FlowStyle
|
||||
}
|
||||
for _, mappingValueNode := range mappingNode.Values {
|
||||
err := o.goccyProcessMappingValueNode(mappingValueNode, cm)
|
||||
err := o.goccyProcessMappingValueNode(mappingValueNode, cm, anchorMap)
|
||||
if err != nil {
|
||||
return ast.ErrInvalidAnchorName
|
||||
}
|
||||
@@ -120,7 +121,7 @@ func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap) er
|
||||
o.Kind = MappingNode
|
||||
o.Tag = "!!map"
|
||||
mappingValueNode := node.(*ast.MappingValueNode)
|
||||
err := o.goccyProcessMappingValueNode(mappingValueNode, cm)
|
||||
err := o.goccyProcessMappingValueNode(mappingValueNode, cm, anchorMap)
|
||||
if err != nil {
|
||||
return ast.ErrInvalidAnchorName
|
||||
}
|
||||
@@ -141,7 +142,7 @@ func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap) er
|
||||
keyNode.Kind = ScalarNode
|
||||
keyNode.Value = fmt.Sprintf("%v", i)
|
||||
|
||||
valueNode, err := o.goccyDecodeIntoChild(astSeq[i], cm)
|
||||
valueNode, err := o.goccyDecodeIntoChild(astSeq[i], cm, anchorMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -149,6 +150,22 @@ func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap) er
|
||||
valueNode.Key = keyNode
|
||||
o.Content[i] = valueNode
|
||||
}
|
||||
case ast.AnchorType:
|
||||
log.Debugf("UnmarshalYAML - an anchor node")
|
||||
anchorNode := node.(*ast.AnchorNode)
|
||||
err := o.UnmarshalGoccyYAML(anchorNode.Value, cm, anchorMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.Anchor = anchorNode.Name.String()
|
||||
anchorMap[o.Anchor] = o
|
||||
|
||||
case ast.AliasType:
|
||||
log.Debugf("UnmarshalYAML - an alias node")
|
||||
aliasNode := node.(*ast.AliasNode)
|
||||
o.Kind = AliasNode
|
||||
o.Value = aliasNode.Value.String()
|
||||
o.Alias = anchorMap[o.Value]
|
||||
|
||||
default:
|
||||
log.Debugf("UnmarshalYAML - node idea of the type!!")
|
||||
@@ -157,16 +174,16 @@ func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap) er
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *CandidateNode) goccyProcessMappingValueNode(mappingEntry *ast.MappingValueNode, cm yaml.CommentMap) error {
|
||||
func (o *CandidateNode) goccyProcessMappingValueNode(mappingEntry *ast.MappingValueNode, cm yaml.CommentMap, anchorMap map[string]*CandidateNode) error {
|
||||
log.Debug("UnmarshalYAML MAP KEY entry %v", mappingEntry.Key)
|
||||
keyNode, err := o.goccyDecodeIntoChild(mappingEntry.Key, cm)
|
||||
keyNode, err := o.goccyDecodeIntoChild(mappingEntry.Key, cm, anchorMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyNode.IsMapKey = true
|
||||
|
||||
log.Debug("UnmarshalYAML MAP VALUE entry %v", mappingEntry.Value)
|
||||
valueNode, err := o.goccyDecodeIntoChild(mappingEntry.Value, cm)
|
||||
valueNode, err := o.goccyDecodeIntoChild(mappingEntry.Value, cm, anchorMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ import (
|
||||
type goccyYamlDecoder struct {
|
||||
decoder yaml.Decoder
|
||||
cm yaml.CommentMap
|
||||
// anchor map persists over multiple documents for convenience.
|
||||
anchorMap map[string]*CandidateNode
|
||||
}
|
||||
|
||||
func NewGoccyYAMLDecoder() Decoder {
|
||||
@@ -25,6 +27,7 @@ func NewGoccyYAMLDecoder() Decoder {
|
||||
func (dec *goccyYamlDecoder) Init(reader io.Reader) error {
|
||||
dec.cm = yaml.CommentMap{}
|
||||
dec.decoder = *yaml.NewDecoder(reader, yaml.CommentToMap(dec.cm), yaml.UseOrderedMap())
|
||||
dec.anchorMap = make(map[string]*CandidateNode)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -38,7 +41,7 @@ func (dec *goccyYamlDecoder) Decode() (*CandidateNode, error) {
|
||||
}
|
||||
|
||||
candidateNode := &CandidateNode{}
|
||||
if err := candidateNode.UnmarshalGoccyYAML(ast, dec.cm); err != nil {
|
||||
if err := candidateNode.UnmarshalGoccyYAML(ast, dec.cm, dec.anchorMap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
+233
-128
@@ -7,132 +7,138 @@ 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 - line comment",
|
||||
skipDoc: true,
|
||||
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 - 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,
|
||||
// input: "# head comment\na: meow\n",
|
||||
// expected: "# head comment\na: meow\n", // go-yaml does this
|
||||
// },
|
||||
// {
|
||||
// description: "basic - head and line comment",
|
||||
// skipDoc: true,
|
||||
// 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,
|
||||
@@ -148,8 +154,107 @@ var goccyYamlFormatScenarios = []formatScenario{
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// description: "trailing comment",
|
||||
// input: "test:\n# this comment will be removed",
|
||||
// expected: "test:\n# this comment will be removed",
|
||||
// input: "test: null\n# this comment will be removed",
|
||||
// expected: "test: null\n# this comment will be removed\n",
|
||||
// },
|
||||
// {
|
||||
// description: "doc separator",
|
||||
// skipDoc: true,
|
||||
// input: "# hi\n---\na: cat\n---",
|
||||
// expected: "---\na: cat\n",
|
||||
// },
|
||||
// {
|
||||
// description: "scalar with doc separator",
|
||||
// skipDoc: true,
|
||||
// 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: "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",
|
||||
// },
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user