Fixed traverse issue

This commit is contained in:
Mike Farah 2023-05-30 08:46:51 +10:00
parent d933c00904
commit 82f717226c
4 changed files with 130 additions and 80 deletions

View File

@ -211,7 +211,7 @@ func (n *CandidateNode) SetParent(parent *CandidateNode) {
n.Parent = parent n.Parent = parent
} }
func (n *CandidateNode) AddKeyValueChild(rawKey *CandidateNode, rawValue *CandidateNode) { func (n *CandidateNode) AddKeyValueChild(rawKey *CandidateNode, rawValue *CandidateNode) (*CandidateNode, *CandidateNode) {
key := rawKey.unwrapDocument().Copy() key := rawKey.unwrapDocument().Copy()
key.SetParent(n) key.SetParent(n)
key.IsMapKey = true key.IsMapKey = true
@ -221,6 +221,7 @@ func (n *CandidateNode) AddKeyValueChild(rawKey *CandidateNode, rawValue *Candid
value.Key = key value.Key = key
n.Content = append(n.Content, key, value) n.Content = append(n.Content, key, value)
return key, value
} }
func (n *CandidateNode) AddChild(rawChild *CandidateNode) { func (n *CandidateNode) AddChild(rawChild *CandidateNode) {

View File

@ -9,6 +9,56 @@ Add behaves differently according to the type of the LHS:
Use `+=` as a relative append assign for things like increment. Note that `.a += .x` is equivalent to running `.a = .a + .x`. Use `+=` as a relative append assign for things like increment. Note that `.a += .x` is equivalent to running `.a = .a + .x`.
## Concatenate arrays
Given a sample.yml file of:
```yaml
{a: [1, 2], b: [3, 4]}
```
then
```bash
yq '.a + .b' sample.yml
```
will output
```yaml
[1, 2, 3, 4]
```
## Concatenate to existing array
Note that the styling of `a` is kept.
Given a sample.yml file of:
```yaml
a: [1,2]
b:
- 3
- 4
```
then
```bash
yq '.a += .b' sample.yml
```
will output
```yaml
a: [1, 2, 3, 4]
b:
- 3
- 4
```
## Concatenate null to array
Given a sample.yml file of:
```yaml
{a: [1, 2]}
```
then
```bash
yq '.a + null' sample.yml
```
will output
```yaml
[1, 2, null]
```
## Append to existing array ## Append to existing array
Note that the styling is copied from existing array elements Note that the styling is copied from existing array elements

View File

@ -5,83 +5,83 @@ import (
) )
var addOperatorScenarios = []expressionScenario{ var addOperatorScenarios = []expressionScenario{
// { {
// skipDoc: true, skipDoc: true,
// document: `[{a: foo, b: bar}, {a: 1, b: 2}]`, document: `[{a: foo, b: bar}, {a: 1, b: 2}]`,
// expression: ".[] | .a + .b", expression: ".[] | .a + .b",
// expected: []string{ expected: []string{
// "D0, P[0 a], (!!str)::foobar\n", "D0, P[0 a], (!!str)::foobar\n",
// "D0, P[1 a], (!!int)::3\n", "D0, P[1 a], (!!int)::3\n",
// }, },
// }, },
// { {
// skipDoc: true, skipDoc: true,
// document: `a: key`, document: `a: key`,
// expression: `. += {"key": "b"}`, expression: `. += {"key": "b"}`,
// expected: []string{ expected: []string{
// "D0, P[], (!!map)::a: key\nkey: b\n", "D0, P[], (!!map)::a: key\nkey: b\n",
// }, },
// }, },
// { {
// skipDoc: true, skipDoc: true,
// document: `[[c], [b]]`, document: `[[c], [b]]`,
// expression: `.[] | . += "a"`, expression: `.[] | . += "a"`,
// expected: []string{ expected: []string{
// "D0, P[0], (!!seq)::[c, a]\n", "D0, P[0], (!!seq)::[c, a]\n",
// "D0, P[1], (!!seq)::[b, a]\n", "D0, P[1], (!!seq)::[b, a]\n",
// }, },
// }, },
// { {
// skipDoc: true, skipDoc: true,
// document: `{}`, document: `{}`,
// expression: "(.a + .b) as $x | .", expression: "(.a + .b) as $x | .",
// expected: []string{ expected: []string{
// "D0, P[], (doc)::{}\n", "D0, P[], (doc)::{}\n",
// }, },
// }, },
// { {
// skipDoc: true, skipDoc: true,
// document: `a: 0`, document: `a: 0`,
// expression: ".a += .b.c", expression: ".a += .b.c",
// expected: []string{ expected: []string{
// "D0, P[], (doc)::a: 0\n", "D0, P[], (doc)::a: 0\n",
// }, },
// }, },
// { {
// description: "Concatenate arrays", description: "Concatenate arrays",
// document: `{a: [1,2], b: [3,4]}`, document: `{a: [1,2], b: [3,4]}`,
// expression: `.a + .b`, expression: `.a + .b`,
// expected: []string{ expected: []string{
// "D0, P[a], (!!seq)::[1, 2, 3, 4]\n", "D0, P[a], (!!seq)::[1, 2, 3, 4]\n",
// }, },
// }, },
// { {
// description: "Concatenate to existing array", description: "Concatenate to existing array",
// subdescription: "Note that the styling of `a` is kept.", subdescription: "Note that the styling of `a` is kept.",
// document: "a: [1,2]\nb:\n - 3\n - 4", document: "a: [1,2]\nb:\n - 3\n - 4",
// dontFormatInputForDoc: true, dontFormatInputForDoc: true,
// expression: `.a += .b`, expression: `.a += .b`,
// expected: []string{ expected: []string{
// "D0, P[], (doc)::a: [1, 2, 3, 4]\nb:\n - 3\n - 4\n", "D0, P[], (doc)::a: [1, 2, 3, 4]\nb:\n - 3\n - 4\n",
// }, },
// }, },
// { {
// skipDoc: true, skipDoc: true,
// expression: `[1] + ([2], [3])`, expression: `[1] + ([2], [3])`,
// expected: []string{ expected: []string{
// "D0, P[], (!!seq)::- 1\n- 2\n", "D0, P[], (!!seq)::- 1\n- 2\n",
// "D0, P[], (!!seq)::- 1\n- 3\n", "D0, P[], (!!seq)::- 1\n- 3\n",
// }, },
// }, },
// { {
// description: "Concatenate null to array", description: "Concatenate null to array",
// document: `{a: [1,2]}`, document: `{a: [1,2]}`,
// expression: `.a + null`, expression: `.a + null`,
// expected: []string{ expected: []string{
// "D0, P[a], (!!seq)::[1, 2]\n", "D0, P[a], (!!seq)::[1, 2]\n",
// }, },
// }, },
{ {
skipDoc: true, skipDoc: true,
description: "Concatenate to empty array", description: "Concatenate to empty array",

View File

@ -234,19 +234,18 @@ func traverseMap(context Context, matchingNode *CandidateNode, keyNode *Candidat
} }
if !splat && !prefs.DontAutoCreate && !context.DontAutoCreate && newMatches.Len() == 0 { if !splat && !prefs.DontAutoCreate && !context.DontAutoCreate && newMatches.Len() == 0 {
log.Debugf("no matches, creating one") log.Debugf("no matches, creating one for %v", NodeToString(keyNode))
//no matches, create one automagically //no matches, create one automagically
valueNode := matchingNode.CreateChild() valueNode := matchingNode.CreateChild()
valueNode.Kind = ScalarNode valueNode.Kind = ScalarNode
valueNode.Tag = "!!null" valueNode.Tag = "!!null"
valueNode.Value = "null" valueNode.Value = "null"
valueNode.Key = keyNode
if len(matchingNode.Content) == 0 { if len(matchingNode.Content) == 0 {
matchingNode.Style = 0 matchingNode.Style = 0
} }
matchingNode.AddKeyValueChild(keyNode, valueNode) keyNode, valueNode = matchingNode.AddKeyValueChild(keyNode, valueNode)
if prefs.IncludeMapKeys { if prefs.IncludeMapKeys {
newMatches.Set(keyNode.GetKey(), keyNode) newMatches.Set(keyNode.GetKey(), keyNode)