diff --git a/pkg/yqlib/treeops/operator_collect_object.go b/pkg/yqlib/treeops/operator_collect_object.go index e46971c..eea0db8 100644 --- a/pkg/yqlib/treeops/operator_collect_object.go +++ b/pkg/yqlib/treeops/operator_collect_object.go @@ -28,6 +28,11 @@ func collect(d *dataTreeNavigator, aggregate *list.List, remainingMatches *list. candidate := remainingMatches.Remove(remainingMatches.Front()).(*CandidateNode) splatted, err := Splat(d, nodeToMap(candidate)) + + for splatEl := splatted.Front(); splatEl != nil; splatEl = splatEl.Next() { + splatEl.Value.(*CandidateNode).Path = nil + } + if err != nil { return nil, err } @@ -44,10 +49,8 @@ func collect(d *dataTreeNavigator, aggregate *list.List, remainingMatches *list. splatCandidate := splatEl.Value.(*CandidateNode) newCandidate := aggCandidate.Copy() newCandidate.Path = nil - splatCandidateClone := splatCandidate.Copy() - splatCandidateClone.Path = nil - newCandidate, err := multiply(d, newCandidate, splatCandidateClone) + newCandidate, err := multiply(d, newCandidate, splatCandidate) if err != nil { return nil, err } diff --git a/pkg/yqlib/treeops/operator_collect_object_test.go b/pkg/yqlib/treeops/operator_collect_object_test.go index bd90ac1..a573a05 100644 --- a/pkg/yqlib/treeops/operator_collect_object_test.go +++ b/pkg/yqlib/treeops/operator_collect_object_test.go @@ -9,15 +9,15 @@ var collectObjectOperatorScenarios = []expressionScenario{ document: `{name: Mike, age: 32}`, expression: `{.name: .age}`, expected: []string{ - "D0, P[0], (!!map)::Mike: 32\n", + "D0, P[], (!!map)::Mike: 32\n", }, }, { document: `{name: Mike, pets: [cat, dog]}`, expression: `{.name: .pets[]}`, expected: []string{ - "D0, P[0], (!!map)::Mike: cat\n", - "D0, P[1], (!!map)::Mike: dog\n", + "D0, P[], (!!map)::Mike: cat\n", + "D0, P[], (!!map)::Mike: dog\n", }, }, { @@ -36,6 +36,29 @@ var collectObjectOperatorScenarios = []expressionScenario{ expected: []string{ `D0, P[], (!!map)::a: Mike b: {cows: [apl, bba]} +`, + }, + }, + { + document: ``, + expression: `{"wrap": "frog"}`, + expected: []string{ + "D0, P[], (!!map)::wrap: frog\n", + }, + }, + { + document: `{name: Mike}`, + expression: `{"wrap": .}`, + expected: []string{ + "D0, P[], (!!map)::wrap: {name: Mike}\n", + }, + }, + { + document: `{name: Mike}`, + expression: `{"wrap": {"further": .}}`, + expected: []string{ + `D0, P[], (!!map)::wrap: + further: {name: Mike} `, }, }, diff --git a/pkg/yqlib/treeops/operator_create_map.go b/pkg/yqlib/treeops/operator_create_map.go index eaea672..5abfdbd 100644 --- a/pkg/yqlib/treeops/operator_create_map.go +++ b/pkg/yqlib/treeops/operator_create_map.go @@ -19,11 +19,11 @@ func CreateMapOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode mapPairs, err := crossFunction(d, matchingNodes, pathNode, func(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) { node := yaml.Node{Kind: yaml.MappingNode, Tag: "!!map"} - log.Debugf("LHS:", lhs.Node.Value) - log.Debugf("RHS:", rhs.Node.Value) + log.Debugf("LHS:", NodeToString(lhs)) + log.Debugf("RHS:", NodeToString(rhs)) node.Content = []*yaml.Node{ - lhs.Node, - rhs.Node, + UnwrapDoc(lhs.Node), + UnwrapDoc(rhs.Node), } return &CandidateNode{Node: &node, Document: document, Path: path}, nil diff --git a/pkg/yqlib/treeops/operator_create_map_test.go b/pkg/yqlib/treeops/operator_create_map_test.go index 65839b5..dee6e36 100644 --- a/pkg/yqlib/treeops/operator_create_map_test.go +++ b/pkg/yqlib/treeops/operator_create_map_test.go @@ -35,6 +35,13 @@ var createMapOperatorScenarios = []expressionScenario{ "D0, P[], (!!seq)::- b: {cows: [apl, bba]}\n", }, }, + { + document: `{name: Mike}`, + expression: `"wrap": .`, + expected: []string{ + "D0, P[], (!!seq)::- wrap: {name: Mike}\n", + }, + }, } func TestCreateMapOperatorScenarios(t *testing.T) { diff --git a/pkg/yqlib/treeops/operator_multilpy.go b/pkg/yqlib/treeops/operator_multilpy.go index 6224e7c..1dd4217 100644 --- a/pkg/yqlib/treeops/operator_multilpy.go +++ b/pkg/yqlib/treeops/operator_multilpy.go @@ -53,25 +53,41 @@ func multiply(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode) (*Ca if lhs.Node.Kind == yaml.MappingNode && rhs.Node.Kind == yaml.MappingNode || (lhs.Node.Kind == yaml.SequenceNode && rhs.Node.Kind == yaml.SequenceNode) { - var results = list.New() - recursiveDecent(d, results, nodeToMap(rhs)) - var pathIndexToStartFrom int = 0 - if results.Front() != nil { - pathIndexToStartFrom = len(results.Front().Value.(*CandidateNode).Path) + var newBlank = &CandidateNode{ + Path: lhs.Path, + Document: lhs.Document, + Filename: lhs.Filename, + Node: &yaml.Node{}, } + var newThing, err = mergeObjects(d, newBlank, lhs) + if err != nil { + return nil, err + } + return mergeObjects(d, newThing, rhs) - for el := results.Front(); el != nil; el = el.Next() { - err := applyAssignment(d, pathIndexToStartFrom, lhs, el.Value.(*CandidateNode)) - if err != nil { - return nil, err - } - } - return lhs, nil } return nil, fmt.Errorf("Cannot multiply %v with %v", NodeToString(lhs), NodeToString(rhs)) } +func mergeObjects(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) { + var results = list.New() + recursiveDecent(d, results, nodeToMap(rhs)) + + var pathIndexToStartFrom int = 0 + if results.Front() != nil { + pathIndexToStartFrom = len(results.Front().Value.(*CandidateNode).Path) + } + + for el := results.Front(); el != nil; el = el.Next() { + err := applyAssignment(d, pathIndexToStartFrom, lhs, el.Value.(*CandidateNode)) + if err != nil { + return nil, err + } + } + return lhs, nil +} + func createTraversalTree(path []interface{}) *PathTreeNode { if len(path) == 0 { return &PathTreeNode{Operation: &Operation{OperationType: SelfReference}} diff --git a/pkg/yqlib/treeops/operator_multiply_test.go b/pkg/yqlib/treeops/operator_multiply_test.go index b2cc2b4..dfad3b8 100644 --- a/pkg/yqlib/treeops/operator_multiply_test.go +++ b/pkg/yqlib/treeops/operator_multiply_test.go @@ -74,6 +74,13 @@ b: "D0, P[], (!!map)::{a: [3, 4, 5], b: [3, 4, 5]}\n", }, }, + { + document: `{a: cat}`, + expression: `. * {"a": {"c": .a}}`, + expected: []string{ + "D0, P[], (!!map)::{a: {c: cat}}\n", + }, + }, } func TestMultiplyOperatorScenarios(t *testing.T) {