diff --git a/dencoding/yaml_decoder.go b/dencoding/yaml_decoder.go index d868cf3c..ce1975f7 100644 --- a/dencoding/yaml_decoder.go +++ b/dencoding/yaml_decoder.go @@ -64,6 +64,8 @@ func (decoder *YAMLDecoder) getNodeValue(node *yaml.Node) (any, error) { return decoder.getSequenceNodeValue(node) case yaml.ScalarNode: return decoder.getScalarNodeValue(node) + case yaml.AliasNode: + return decoder.getNodeValue(node.Alias) default: return nil, fmt.Errorf("unhandled node kind: %v", node.Kind) } @@ -72,20 +74,26 @@ func (decoder *YAMLDecoder) getNodeValue(node *yaml.Node) (any, error) { func (decoder *YAMLDecoder) getMappingNodeValue(node *yaml.Node) (any, error) { res := NewMap() - for i := 0; i < len(node.Content); i += 2 { - keyNode := node.Content[i] - valueNode := node.Content[i+1] + content := make([]*yaml.Node, 0) + content = append(content, node.Content...) + + var keyNode *yaml.Node + var valueNode *yaml.Node + for { + if len(content) == 0 { + break + } + + keyNode, valueNode, content = content[0], content[1], content[2:] - var keyValue any if keyNode.ShortTag() == yamlTagMerge { - keyValue = valueNode.Value - valueNode = valueNode.Alias - } else { - var err error - keyValue, err = decoder.getNodeValue(keyNode) - if err != nil { - return nil, err - } + content = append(valueNode.Alias.Content, content...) + continue + } + + keyValue, err := decoder.getNodeValue(keyNode) + if err != nil { + return nil, err } value, err := decoder.getNodeValue(valueNode) diff --git a/dencoding/yaml_decoder_test.go b/dencoding/yaml_decoder_test.go index 34679bb0..172bc53c 100644 --- a/dencoding/yaml_decoder_test.go +++ b/dencoding/yaml_decoder_test.go @@ -98,12 +98,16 @@ key2: value6 }) t.Run("YamlAliases", func(t *testing.T) { - b := []byte(`foo: &foo + b := []byte(`foo: &foofoo bar: 1 - baz: "baz" + baz: &baz "baz" spam: ham: "eggs" - <<: *foo + bar: 0 + <<: *foofoo + baz: "bazbaz" + +baz: *baz `) dec := dencoding.NewYAMLDecoder(bytes.NewReader(b)) @@ -121,16 +125,15 @@ spam: got = append(got, v) } - fooMap := dencoding.NewMap(). - Set("bar", int64(1)). - Set("baz", "baz") - spamMap := dencoding.NewMap(). - Set("ham", "eggs"). - Set("foo", fooMap) - exp := dencoding.NewMap(). - Set("foo", fooMap). - Set("spam", spamMap) + Set("foo", dencoding.NewMap(). + Set("bar", int64(1)). + Set("baz", "baz")). + Set("spam", dencoding.NewMap(). + Set("ham", "eggs"). + Set("bar", int64(1)). + Set("baz", "bazbaz")). + Set("baz", "baz") if len(got) != 1 { t.Errorf("expected result len of %d, got %d", 1, len(got)) diff --git a/internal/command/select_test.go b/internal/command/select_test.go index 31a39550..8841df71 100644 --- a/internal/command/select_test.go +++ b/internal/command/select_test.go @@ -254,21 +254,25 @@ octal: 8`)), t.Run("Issue285 - YAML alias on read", runTest( []string{"-r", "yaml", "-w", "yaml"}, - []byte(`foo: &foo + []byte(`foo: &foofoo bar: 1 - baz: baz + baz: &baz "baz" spam: - ham: eggs - <<: *foo + ham: "eggs" + bar: 0 + <<: *foofoo + baz: "bazbaz" + +baz: *baz `), []byte(`foo: bar: 1 baz: baz spam: ham: eggs - foo: - bar: 1 - baz: baz + bar: 1 + baz: bazbaz +baz: baz `), nil, nil,