From a389bb64b8e6e2f37c029929c80b3cba3c352e74 Mon Sep 17 00:00:00 2001 From: Mike Farah Date: Fri, 31 Mar 2023 16:24:23 +1100 Subject: [PATCH] Fixed bug when splatting empty array #1613 --- pkg/yqlib/operator_collect.go | 5 +++++ pkg/yqlib/operator_traverse_path.go | 7 ++++++- pkg/yqlib/operator_traverse_path_test.go | 7 +++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/pkg/yqlib/operator_collect.go b/pkg/yqlib/operator_collect.go index a7f25465..2a114592 100644 --- a/pkg/yqlib/operator_collect.go +++ b/pkg/yqlib/operator_collect.go @@ -27,6 +27,7 @@ func collectOperator(d *dataTreeNavigator, context Context, expressionNode *Expr log.Debugf("-- collectOperation") if context.MatchingNodes.Len() == 0 { + log.Debugf("nothing to collect") node := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq", Value: "[]"} candidate := &CandidateNode{Node: node} return context.SingleChildContext(candidate), nil @@ -41,6 +42,7 @@ func collectOperator(d *dataTreeNavigator, context Context, expressionNode *Expr } if evaluateAllTogether { + log.Debugf("collect together") collectedNode, err := collectTogether(d, context, expressionNode.RHS) if err != nil { return Context{}, err @@ -56,6 +58,8 @@ func collectOperator(d *dataTreeNavigator, context Context, expressionNode *Expr collectedNode := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"} collectCandidate := candidate.CreateReplacement(collectedNode) + log.Debugf("collect rhs: %v", expressionNode.RHS.Operation.toString()) + collectExpResults, err := d.GetMatchingNodes(context.SingleChildContext(candidate), expressionNode.RHS) if err != nil { return Context{}, err @@ -66,6 +70,7 @@ func collectOperator(d *dataTreeNavigator, context Context, expressionNode *Expr log.Debugf("found this: %v", NodeToString(resultC)) collectedNode.Content = append(collectedNode.Content, unwrapDoc(resultC.Node)) } + log.Debugf("done collect rhs: %v", expressionNode.RHS.Operation.toString()) results.PushBack(collectCandidate) } diff --git a/pkg/yqlib/operator_traverse_path.go b/pkg/yqlib/operator_traverse_path.go index 54e6baa7..4308545a 100644 --- a/pkg/yqlib/operator_traverse_path.go +++ b/pkg/yqlib/operator_traverse_path.go @@ -80,6 +80,8 @@ func traverseArrayOperator(d *dataTreeNavigator, context Context, expressionNode // BUT we still return the original context back (see jq) // https://stedolan.github.io/jq/manual/#Variable/SymbolicBindingOperator:...as$identifier|... + log.Debugf("--traverseArrayOperator") + if expressionNode.RHS != nil && expressionNode.RHS.RHS != nil && expressionNode.RHS.RHS.Operation.OperationType == createMapOpType { return sliceArrayOperator(d, context, expressionNode.RHS.RHS) } @@ -103,6 +105,8 @@ func traverseArrayOperator(d *dataTreeNavigator, context Context, expressionNode } var indicesToTraverse = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Content + log.Debugf("indicesToTraverse %v", len(indicesToTraverse)) + //now we traverse the result of the lhs against the indices we found result, err := traverseNodesWithArrayIndices(lhs, indicesToTraverse, prefs) if err != nil { @@ -231,7 +235,8 @@ func traverseMap(context Context, matchingNode *CandidateNode, keyNode *yaml.Nod return nil, err } - if !prefs.DontAutoCreate && !context.DontAutoCreate && newMatches.Len() == 0 { + if !splat && !prefs.DontAutoCreate && !context.DontAutoCreate && newMatches.Len() == 0 { + log.Debugf("no matches, creating one") //no matches, create one automagically valueNode := &yaml.Node{Tag: "!!null", Kind: yaml.ScalarNode, Value: "null"} diff --git a/pkg/yqlib/operator_traverse_path_test.go b/pkg/yqlib/operator_traverse_path_test.go index e82acc2b..5d62447c 100644 --- a/pkg/yqlib/operator_traverse_path_test.go +++ b/pkg/yqlib/operator_traverse_path_test.go @@ -35,6 +35,13 @@ steps: ` var traversePathOperatorScenarios = []expressionScenario{ + { + skipDoc: true, + description: "splat empty map", + document: "{}", + expression: ".[]", + expected: []string{}, + }, { skipDoc: true, document: `[[1]]`,