Skip to content

Commit 8d3be1a

Browse files
committed
Length (and some other operators) should not include head/foot comments #1231
1 parent 7040337 commit 8d3be1a

15 files changed

+122
-25
lines changed

examples/data1.yaml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,12 @@
1-
a: mike
2-
b: [t, f]
1+
# --------------------------------------------------
2+
# It's a test with comment
3+
# --------------------------------------------------
4+
test:
5+
- name: a
6+
- name: b
7+
- name: c
8+
groups:
9+
- name: a
10+
- name: b
11+
- name: c
12+
- name: c

examples/data2.yaml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1-
c:
2-
d: hamster
1+
# --------------------------------------------------
2+
# It's a test with comment
3+
# --------------------------------------------------
4+
groups:
5+
- name: d

pkg/yqlib/candidate_node.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,18 +86,24 @@ func (n *CandidateNode) CreateChildInArray(index int, node *yaml.Node) *Candidat
8686

8787
func (n *CandidateNode) CreateReplacement(node *yaml.Node) *CandidateNode {
8888
return &CandidateNode{
89-
Node: node,
90-
Path: n.createChildPath(nil),
91-
LeadingContent: n.LeadingContent,
92-
Parent: n.Parent,
93-
Key: n.Key,
94-
IsMapKey: n.IsMapKey,
95-
Document: n.Document,
96-
Filename: n.Filename,
97-
FileIndex: n.FileIndex,
89+
Node: node,
90+
Path: n.createChildPath(nil),
91+
Parent: n.Parent,
92+
Key: n.Key,
93+
IsMapKey: n.IsMapKey,
94+
Document: n.Document,
95+
Filename: n.Filename,
96+
FileIndex: n.FileIndex,
9897
}
9998
}
10099

100+
func (n *CandidateNode) CreateReplacementWithDocWrappers(node *yaml.Node) *CandidateNode {
101+
replacement := n.CreateReplacement(node)
102+
replacement.LeadingContent = n.LeadingContent
103+
replacement.TrailingContent = n.TrailingContent
104+
return replacement
105+
}
106+
101107
func (n *CandidateNode) createChildPath(path interface{}) []interface{} {
102108
if path == nil {
103109
newPath := make([]interface{}, len(n.Path))

pkg/yqlib/operator_collect_test.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,23 @@ var collectOperatorScenarios = []expressionScenario{
2929
},
3030
},
3131
{
32-
skipDoc: true,
33-
document: "{a: apple}\n---\n{b: frog}",
34-
32+
skipDoc: true,
33+
document: "{a: apple}\n---\n{b: frog}",
3534
expression: `[.]`,
3635
expected: []string{
3736
"D0, P[], (!!seq)::- {a: apple}\n- {b: frog}\n",
3837
},
3938
},
39+
{
40+
description: "with comments",
41+
skipDoc: true,
42+
document: "# abc\n[{a: apple}]\n\n# xyz\n",
43+
44+
expression: `[.[]]`,
45+
expected: []string{
46+
"D0, P[], (!!seq)::- {a: apple}\n",
47+
},
48+
},
4049
{
4150
skipDoc: true,
4251
document: ``,

pkg/yqlib/operator_entries.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func entrySeqFor(key *yaml.Node, value *yaml.Node) *yaml.Node {
2020

2121
func toEntriesFromMap(candidateNode *CandidateNode) *CandidateNode {
2222
var sequence = &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
23-
var entriesNode = candidateNode.CreateReplacement(sequence)
23+
var entriesNode = candidateNode.CreateReplacementWithDocWrappers(sequence)
2424

2525
var contents = unwrapDoc(candidateNode.Node).Content
2626
for index := 0; index < len(contents); index = index + 2 {
@@ -34,7 +34,7 @@ func toEntriesFromMap(candidateNode *CandidateNode) *CandidateNode {
3434

3535
func toEntriesfromSeq(candidateNode *CandidateNode) *CandidateNode {
3636
var sequence = &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
37-
var entriesNode = candidateNode.CreateReplacement(sequence)
37+
var entriesNode = candidateNode.CreateReplacementWithDocWrappers(sequence)
3838

3939
var contents = unwrapDoc(candidateNode.Node).Content
4040
for index := 0; index < len(contents); index = index + 1 {
@@ -94,7 +94,7 @@ func parseEntry(entry *yaml.Node, position int) (*yaml.Node, *yaml.Node, error)
9494

9595
func fromEntries(candidateNode *CandidateNode) (*CandidateNode, error) {
9696
var node = &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map"}
97-
var mapCandidateNode = candidateNode.CreateReplacement(node)
97+
var mapCandidateNode = candidateNode.CreateReplacementWithDocWrappers(node)
9898

9999
var contents = unwrapDoc(candidateNode.Node).Content
100100

@@ -141,9 +141,11 @@ func withEntriesOperator(d *dataTreeNavigator, context Context, expressionNode *
141141
var results = list.New()
142142

143143
for el := toEntries.MatchingNodes.Front(); el != nil; el = el.Next() {
144+
candidate := el.Value.(*CandidateNode)
145+
144146
//run expression against entries
145147
// splat toEntries and pipe it into Rhs
146-
splatted, err := splat(context.SingleChildContext(el.Value.(*CandidateNode)), traversePreferences{})
148+
splatted, err := splat(context.SingleChildContext(candidate), traversePreferences{})
147149
if err != nil {
148150
return Context{}, err
149151
}
@@ -160,6 +162,10 @@ func withEntriesOperator(d *dataTreeNavigator, context Context, expressionNode *
160162
if err != nil {
161163
return Context{}, err
162164
}
165+
collected.LeadingContent = candidate.LeadingContent
166+
collected.TrailingContent = candidate.TrailingContent
167+
168+
log.Debugf("**** collected %v", collected.LeadingContent)
163169

164170
fromEntries, err := fromEntriesOperator(d, context.SingleChildContext(collected), expressionNode)
165171
if err != nil {

pkg/yqlib/operator_entries_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,15 @@ var entriesOperatorScenarios = []expressionScenario{
6262
"D0, P[], (!!map)::KEY_c: 1\nKEY_d: 2\n",
6363
},
6464
},
65+
{
66+
skipDoc: true,
67+
document: `[{a: 1, b: 2}, {c: 1, d: 2}]`,
68+
expression: `.[] | with_entries(.key |= "KEY_" + .)`,
69+
expected: []string{
70+
"D0, P[], (!!map)::KEY_a: 1\nKEY_b: 2\n",
71+
"D0, P[], (!!map)::KEY_c: 1\nKEY_d: 2\n",
72+
},
73+
},
6574
{
6675
description: "Use with_entries to filter the map",
6776
document: `{a: { b: bird }, c: { d: dog }}`,
@@ -70,6 +79,15 @@ var entriesOperatorScenarios = []expressionScenario{
7079
"D0, P[], (!!map)::a: {b: bird}\n",
7180
},
7281
},
82+
{
83+
description: "Use with_entries to filter the map; head comment",
84+
skipDoc: true,
85+
document: "# abc\n{a: { b: bird }, c: { d: dog }}\n# xyz",
86+
expression: `with_entries(select(.value | has("b")))`,
87+
expected: []string{
88+
"D0, P[], (!!map)::# abc\na: {b: bird}\n# xyz\n",
89+
},
90+
},
7391
}
7492

7593
func TestEntriesOperatorScenarios(t *testing.T) {

pkg/yqlib/operator_env_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,16 @@ var envOperatorScenarios = []expressionScenario{
150150
expression: `"the ${notThere} ${alsoNotThere}" | envsubst(nu,ff)`,
151151
expectedError: "variable ${notThere} not set",
152152
},
153+
{
154+
description: "with header/footer",
155+
skipDoc: true,
156+
environmentVariables: map[string]string{"myenv": "cat meow"},
157+
document: "# abc\n{v: \"${myenv}\"}\n# xyz\n",
158+
expression: `(.. | select(tag == "!!str")) |= envsubst`,
159+
expected: []string{
160+
"D0, P[], (!!map)::# abc\n{v: \"cat meow\"}\n# xyz\n",
161+
},
162+
},
153163
}
154164

155165
func TestEnvOperatorScenarios(t *testing.T) {

pkg/yqlib/operator_length_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ var lengthOperatorScenarios = []expressionScenario{
3232
},
3333
{
3434
skipDoc: true,
35-
document: `{a: key no exist}`,
35+
document: "# abc\n{a: key no exist}",
3636
expression: `.b | length`,
3737
expected: []string{
3838
"D0, P[b], (!!int)::0\n",

pkg/yqlib/operator_pick.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func pickOperator(d *dataTreeNavigator, context Context, expressionNode *Express
7979
return Context{}, fmt.Errorf("cannot pick indicies from type %v (%v)", node.Tag, candidate.GetNicePath())
8080
}
8181

82-
results.PushBack(candidate.CreateReplacement(replacement))
82+
results.PushBack(candidate.CreateReplacementWithDocWrappers(replacement))
8383
}
8484

8585
return context.ChildContext(results), nil

pkg/yqlib/operator_pick_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,15 @@ var pickOperatorScenarios = []expressionScenario{
1414
"D0, P[], (doc)::myMap: {hamster: squeek, cat: meow}\n",
1515
},
1616
},
17+
{
18+
description: "Pick keys from map with comments",
19+
skipDoc: true,
20+
document: "# abc\nmyMap: {cat: meow, dog: bark, thing: hamster, hamster: squeek}\n# xyz\n",
21+
expression: `.myMap |= pick(["hamster", "cat", "goat"])`,
22+
expected: []string{
23+
"D0, P[], (doc)::# abc\nmyMap: {hamster: squeek, cat: meow}\n# xyz\n",
24+
},
25+
},
1726
{
1827
description: "Pick indices from array",
1928
subdescription: "Note that the order of the indexes matches the pick order and non existent indexes are skipped.",
@@ -23,6 +32,15 @@ var pickOperatorScenarios = []expressionScenario{
2332
"D0, P[], (!!seq)::[lion, cat]\n",
2433
},
2534
},
35+
{
36+
description: "Pick indices from array with comments",
37+
skipDoc: true,
38+
document: "# abc\n[cat, leopard, lion]\n# xyz",
39+
expression: `pick([2, 0, 734, -5])`,
40+
expected: []string{
41+
"D0, P[], (!!seq)::# abc\n[lion, cat]\n# xyz\n",
42+
},
43+
},
2644
}
2745

2846
func TestPickOperatorScenarios(t *testing.T) {

0 commit comments

Comments
 (0)