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
}
func (n *CandidateNode) AddKeyValueChild(rawKey *CandidateNode, rawValue *CandidateNode) {
func (n *CandidateNode) AddKeyValueChild(rawKey *CandidateNode, rawValue *CandidateNode) (*CandidateNode, *CandidateNode) {
key := rawKey.unwrapDocument().Copy()
key.SetParent(n)
key.IsMapKey = true
@ -221,6 +221,7 @@ func (n *CandidateNode) AddKeyValueChild(rawKey *CandidateNode, rawValue *Candid
value.Key = key
n.Content = append(n.Content, key, value)
return key, value
}
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`.
## 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
Note that the styling is copied from existing array elements

View File

@ -5,83 +5,83 @@ import (
)
var addOperatorScenarios = []expressionScenario{
// {
// skipDoc: true,
// document: `[{a: foo, b: bar}, {a: 1, b: 2}]`,
// expression: ".[] | .a + .b",
// expected: []string{
// "D0, P[0 a], (!!str)::foobar\n",
// "D0, P[1 a], (!!int)::3\n",
// },
// },
// {
// skipDoc: true,
// document: `a: key`,
// expression: `. += {"key": "b"}`,
// expected: []string{
// "D0, P[], (!!map)::a: key\nkey: b\n",
// },
// },
// {
// skipDoc: true,
// document: `[[c], [b]]`,
// expression: `.[] | . += "a"`,
// expected: []string{
// "D0, P[0], (!!seq)::[c, a]\n",
// "D0, P[1], (!!seq)::[b, a]\n",
// },
// },
// {
// skipDoc: true,
// document: `{}`,
// expression: "(.a + .b) as $x | .",
// expected: []string{
// "D0, P[], (doc)::{}\n",
// },
// },
// {
// skipDoc: true,
// document: `a: 0`,
// expression: ".a += .b.c",
// expected: []string{
// "D0, P[], (doc)::a: 0\n",
// },
// },
{
skipDoc: true,
document: `[{a: foo, b: bar}, {a: 1, b: 2}]`,
expression: ".[] | .a + .b",
expected: []string{
"D0, P[0 a], (!!str)::foobar\n",
"D0, P[1 a], (!!int)::3\n",
},
},
{
skipDoc: true,
document: `a: key`,
expression: `. += {"key": "b"}`,
expected: []string{
"D0, P[], (!!map)::a: key\nkey: b\n",
},
},
{
skipDoc: true,
document: `[[c], [b]]`,
expression: `.[] | . += "a"`,
expected: []string{
"D0, P[0], (!!seq)::[c, a]\n",
"D0, P[1], (!!seq)::[b, a]\n",
},
},
{
skipDoc: true,
document: `{}`,
expression: "(.a + .b) as $x | .",
expected: []string{
"D0, P[], (doc)::{}\n",
},
},
{
skipDoc: true,
document: `a: 0`,
expression: ".a += .b.c",
expected: []string{
"D0, P[], (doc)::a: 0\n",
},
},
// {
// description: "Concatenate arrays",
// document: `{a: [1,2], b: [3,4]}`,
// expression: `.a + .b`,
// expected: []string{
// "D0, P[a], (!!seq)::[1, 2, 3, 4]\n",
// },
// },
// {
// description: "Concatenate to existing array",
// subdescription: "Note that the styling of `a` is kept.",
// document: "a: [1,2]\nb:\n - 3\n - 4",
// dontFormatInputForDoc: true,
// expression: `.a += .b`,
// expected: []string{
// "D0, P[], (doc)::a: [1, 2, 3, 4]\nb:\n - 3\n - 4\n",
// },
// },
// {
// skipDoc: true,
// expression: `[1] + ([2], [3])`,
// expected: []string{
// "D0, P[], (!!seq)::- 1\n- 2\n",
// "D0, P[], (!!seq)::- 1\n- 3\n",
// },
// },
// {
// description: "Concatenate null to array",
// document: `{a: [1,2]}`,
// expression: `.a + null`,
// expected: []string{
// "D0, P[a], (!!seq)::[1, 2]\n",
// },
// },
{
description: "Concatenate arrays",
document: `{a: [1,2], b: [3,4]}`,
expression: `.a + .b`,
expected: []string{
"D0, P[a], (!!seq)::[1, 2, 3, 4]\n",
},
},
{
description: "Concatenate to existing array",
subdescription: "Note that the styling of `a` is kept.",
document: "a: [1,2]\nb:\n - 3\n - 4",
dontFormatInputForDoc: true,
expression: `.a += .b`,
expected: []string{
"D0, P[], (doc)::a: [1, 2, 3, 4]\nb:\n - 3\n - 4\n",
},
},
{
skipDoc: true,
expression: `[1] + ([2], [3])`,
expected: []string{
"D0, P[], (!!seq)::- 1\n- 2\n",
"D0, P[], (!!seq)::- 1\n- 3\n",
},
},
{
description: "Concatenate null to array",
document: `{a: [1,2]}`,
expression: `.a + null`,
expected: []string{
"D0, P[a], (!!seq)::[1, 2]\n",
},
},
{
skipDoc: true,
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 {
log.Debugf("no matches, creating one")
log.Debugf("no matches, creating one for %v", NodeToString(keyNode))
//no matches, create one automagically
valueNode := matchingNode.CreateChild()
valueNode.Kind = ScalarNode
valueNode.Tag = "!!null"
valueNode.Value = "null"
valueNode.Key = keyNode
if len(matchingNode.Content) == 0 {
matchingNode.Style = 0
}
matchingNode.AddKeyValueChild(keyNode, valueNode)
keyNode, valueNode = matchingNode.AddKeyValueChild(keyNode, valueNode)
if prefs.IncludeMapKeys {
newMatches.Set(keyNode.GetKey(), keyNode)