From cd50b357870f51810e400e5b64d7eeeb76f555db Mon Sep 17 00:00:00 2001 From: Mike Farah Date: Mon, 17 Apr 2023 17:23:48 +1000 Subject: [PATCH] getting closer --- pkg/yqlib/candidate_node.go | 36 +++++++++--- pkg/yqlib/candidate_node_yaml.go | 2 +- pkg/yqlib/candidiate_node_json.go | 1 + .../operators/anchor-and-alias-operators.md | 4 +- pkg/yqlib/doc/operators/comment-operators.md | 58 +++++++++++++++++++ pkg/yqlib/operator_column_test.go | 4 +- pkg/yqlib/operator_create_map.go | 8 ++- pkg/yqlib/operator_create_map_test.go | 16 +++++ 8 files changed, 115 insertions(+), 14 deletions(-) diff --git a/pkg/yqlib/candidate_node.go b/pkg/yqlib/candidate_node.go index 82ceb5d2..6c05c63b 100644 --- a/pkg/yqlib/candidate_node.go +++ b/pkg/yqlib/candidate_node.go @@ -138,10 +138,11 @@ func (n *CandidateNode) getParsedKey() interface{} { } func (n *CandidateNode) GetPath() []interface{} { - if n.Parent != nil && n.getParsedKey() != nil { - return append(n.Parent.GetPath(), n.getParsedKey()) - } key := n.getParsedKey() + if n.Parent != nil && key != nil { + return append(n.Parent.GetPath(), key) + } + if key != nil { return []interface{}{key} } @@ -153,6 +154,8 @@ func (n *CandidateNode) GetNicePath() string { path := n.GetPath() for i, element := range path { elementStr := fmt.Sprintf("%v", element) + log.Debugf("element: %v", element) + log.Debugf("elementStr: %v", elementStr) switch element.(type) { case int: sb.WriteString("[" + elementStr + "]") @@ -176,10 +179,15 @@ func (n *CandidateNode) AsList() *list.List { } func (n *CandidateNode) AddKeyValueChild(rawKey *CandidateNode, rawValue *CandidateNode) { - value := rawValue.unwrapDocument() - value.Key = rawKey.unwrapDocument() - value.Key.IsMapKey = true - n.Content = append(n.Content, value.Key, value) + key := rawKey.unwrapDocument().Copy() + key.Parent = n + key.IsMapKey = true + + value := rawValue.unwrapDocument().Copy() + value.Parent = n + value.Key = key + + n.Content = append(n.Content, key, value) } func (n *CandidateNode) GetValueRep() (interface{}, error) { @@ -233,10 +241,16 @@ func (n *CandidateNode) CopyAsReplacement(replacement *CandidateNode) *Candidate newCopy := replacement.Copy() newCopy.Parent = n.Parent newCopy.Key = n.Key + newCopy.IsMapKey = n.IsMapKey + log.Debugf("n path: %v", n.GetNicePath()) + log.Debugf("HERE**************") + log.Debugf("newCopy path: %v", newCopy.GetNicePath()) + newCopy.Document = n.Document newCopy.Filename = n.Filename newCopy.FileIndex = n.FileIndex + return newCopy } @@ -275,7 +289,7 @@ func (n *CandidateNode) doCopy(cloneContent bool) *CandidateNode { copyKey = n.Key.Copy() } - return &CandidateNode{ + clone := &CandidateNode{ Kind: n.Kind, Style: n.Style, @@ -308,6 +322,12 @@ func (n *CandidateNode) doCopy(cloneContent bool) *CandidateNode { EvaluateTogether: n.EvaluateTogether, IsMapKey: n.IsMapKey, } + + for _, newChild := range content { + newChild.Parent = clone + } + + return clone } // updates this candidate from the given candidate node diff --git a/pkg/yqlib/candidate_node_yaml.go b/pkg/yqlib/candidate_node_yaml.go index 9fea92fd..12752033 100644 --- a/pkg/yqlib/candidate_node_yaml.go +++ b/pkg/yqlib/candidate_node_yaml.go @@ -172,7 +172,7 @@ func (o *CandidateNode) UnmarshalYAML(node *yaml.Node, anchorMap map[string]*Can o.Content = make([]*CandidateNode, len(node.Content)) for i := 0; i < len(node.Content); i += 1 { keyNode := o.CreateChild() - keyNode.IsMapKey = true // can't remember if we need this for sequences + keyNode.IsMapKey = true keyNode.Tag = "!!int" keyNode.Kind = ScalarNode keyNode.Value = fmt.Sprintf("%v", i) diff --git a/pkg/yqlib/candidiate_node_json.go b/pkg/yqlib/candidiate_node_json.go index 76d0080c..99119511 100644 --- a/pkg/yqlib/candidiate_node_json.go +++ b/pkg/yqlib/candidiate_node_json.go @@ -95,6 +95,7 @@ func (o *CandidateNode) UnmarshalJSON(data []byte) error { childKey.Kind = ScalarNode childKey.Tag = "!!int" childKey.Value = fmt.Sprintf("%v", i) + childKey.IsMapKey = true child.Parent = o child.Document = o.Document diff --git a/pkg/yqlib/doc/operators/anchor-and-alias-operators.md b/pkg/yqlib/doc/operators/anchor-and-alias-operators.md index 5c231186..0bcbc260 100644 --- a/pkg/yqlib/doc/operators/anchor-and-alias-operators.md +++ b/pkg/yqlib/doc/operators/anchor-and-alias-operators.md @@ -27,7 +27,9 @@ will output ```yaml item_value: &item_value value: true -thingOne: false +thingOne: + name: item_1 + value: false thingTwo: name: item_2 !!merge <<: *item_value diff --git a/pkg/yqlib/doc/operators/comment-operators.md b/pkg/yqlib/doc/operators/comment-operators.md index 185e19d7..a232fe19 100644 --- a/pkg/yqlib/doc/operators/comment-operators.md +++ b/pkg/yqlib/doc/operators/comment-operators.md @@ -74,6 +74,39 @@ then yq '[... | {"p": path | join("."), "isKey": is_key, "hc": headComment, "lc": lineComment, "fc": footComment}]' sample.yml ``` will output +```yaml +- p: "" + isKey: false + hc: "" + lc: "" + fc: "" +- p: hello + isKey: null + true: null + hc: null + "": null + lc: null + hello-world-comment: null + fc: null +- p: hello + isKey: false + hc: "" + lc: "" + fc: "" +- p: hello.message + isKey: null + true: null + hc: null + "": null + lc: null + fc: null +- p: hello.message + isKey: false + hc: "" + lc: "" + fc: "" +``` + ## Retrieve comment - map key example From the previous example, we know that the comment is on the 'hello' _key_ as a lineComment @@ -106,6 +139,31 @@ then yq '[... | {"p": path | join("."), "isKey": is_key, "hc": headComment, "lc": lineComment, "fc": footComment}]' sample.yml ``` will output +```yaml +- p: "" + isKey: false + hc: "" + lc: "" + fc: "" +- p: name + isKey: null + true: null + hc: null + "": null + lc: null + fc: null +- p: name + isKey: false + hc: "" + lc: "" + fc: "" +- p: name.0 + isKey: false + hc: under-name-comment + lc: "" + fc: "" +``` + ## Retrieve comment - array example From the previous example, we know that the comment is on the first child as a headComment diff --git a/pkg/yqlib/operator_column_test.go b/pkg/yqlib/operator_column_test.go index 36845883..c232ee84 100644 --- a/pkg/yqlib/operator_column_test.go +++ b/pkg/yqlib/operator_column_test.go @@ -19,7 +19,7 @@ var columnOperatorScenarios = []expressionScenario{ document: "a: cat\nb: bob", expression: `.b | key | column`, expected: []string{ - "D0, P[b], (!!int)::1\n", + "D0, P[1], (!!int)::1\n", }, }, { @@ -27,7 +27,7 @@ var columnOperatorScenarios = []expressionScenario{ document: "a: cat", expression: `.a | key | column`, expected: []string{ - "D0, P[a], (!!int)::1\n", + "D0, P[1], (!!int)::1\n", }, }, { diff --git a/pkg/yqlib/operator_create_map.go b/pkg/yqlib/operator_create_map.go index ac9b17a3..d3f74578 100644 --- a/pkg/yqlib/operator_create_map.go +++ b/pkg/yqlib/operator_create_map.go @@ -48,15 +48,19 @@ func sequenceFor(d *dataTreeNavigator, context Context, matchingNode *CandidateN matches.PushBack(matchingNode) } + log.Debugf("**********sequenceFor %v", NodeToString(matchingNode)) + mapPairs, err := crossFunction(d, context.ChildContext(matches), expressionNode, func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) { - node := CandidateNode{Kind: MappingNode, Tag: "!!map"} + node := &CandidateNode{Kind: MappingNode, Tag: "!!map"} + + log.Debugf("**********adding key %v and value %v", NodeToString(lhs), NodeToString(rhs)) node.AddKeyValueChild(lhs, rhs) node.Document = document - return &node, nil + return node, nil }, false) if err != nil { diff --git a/pkg/yqlib/operator_create_map_test.go b/pkg/yqlib/operator_create_map_test.go index e01bf778..42eb4fa9 100644 --- a/pkg/yqlib/operator_create_map_test.go +++ b/pkg/yqlib/operator_create_map_test.go @@ -28,6 +28,22 @@ var createMapOperatorScenarios = []expressionScenario{ "D0, P[frog], (!!str)::jumps\n", }, }, + { + document: `{name: Mike, pets: [cat, dog]}`, + expression: `(.name: .pets.[]) | .[0][0] | ..`, + expected: []string{ + "D0, P[], (!!map)::Mike: cat\n", + "D0, P[Mike], (!!str)::cat\n", + }, + }, + { + description: "check path of nested child", + document: "pets:\n cows: value", + expression: `("b":.pets) | .[0][0] | .b.cows`, + expected: []string{ + "D0, P[b cows], (!!str)::value\n", + }, + }, { document: `{name: Mike, age: 32}`, expression: `.name: .age`,