Fixed creation of candidateNode in operators to include file metadata

This commit is contained in:
Mike Farah 2021-01-12 19:36:28 +11:00
parent 49ac2bac13
commit 7518dac99c
19 changed files with 72 additions and 107 deletions

View File

@ -21,7 +21,23 @@ func (n *CandidateNode) GetKey() string {
return fmt.Sprintf("%v - %v", n.Document, n.Path) return fmt.Sprintf("%v - %v", n.Document, n.Path)
} }
func (n *CandidateNode) CreateChildPath(path interface{}) []interface{} { func (n *CandidateNode) CreateChild(path interface{}, node *yaml.Node) *CandidateNode {
return &CandidateNode{
Node: node,
Path: n.createChildPath(path),
Document: n.Document,
Filename: n.Filename,
FileIndex: n.FileIndex,
}
}
func (n *CandidateNode) createChildPath(path interface{}) []interface{} {
if path == nil {
newPath := make([]interface{}, len(n.Path))
copy(newPath, n.Path)
return newPath
}
//don't use append as they may actually modify the path of the orignal node! //don't use append as they may actually modify the path of the orignal node!
newPath := make([]interface{}, len(n.Path)+1) newPath := make([]interface{}, len(n.Path)+1)
copy(newPath, n.Path) copy(newPath, n.Path)

View File

@ -47,12 +47,7 @@ func add(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode) (*Candida
lhs.Node = UnwrapDoc(lhs.Node) lhs.Node = UnwrapDoc(lhs.Node)
rhs.Node = UnwrapDoc(rhs.Node) rhs.Node = UnwrapDoc(rhs.Node)
target := &CandidateNode{ target := lhs.CreateChild(nil, &yaml.Node{})
Path: lhs.Path,
Document: lhs.Document,
Filename: lhs.Filename,
Node: &yaml.Node{},
}
lhsNode := lhs.Node lhsNode := lhs.Node
switch lhsNode.Kind { switch lhsNode.Kind {

View File

@ -54,8 +54,8 @@ func getAliasOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode *
for el := matchingNodes.Front(); el != nil; el = el.Next() { for el := matchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode) candidate := el.Value.(*CandidateNode)
node := &yaml.Node{Kind: yaml.ScalarNode, Value: candidate.Node.Value, Tag: "!!str"} node := &yaml.Node{Kind: yaml.ScalarNode, Value: candidate.Node.Value, Tag: "!!str"}
lengthCand := &CandidateNode{Node: node, Document: candidate.Document, Path: candidate.Path} result := candidate.CreateChild(nil, node)
results.PushBack(lengthCand) results.PushBack(result)
} }
return results, nil return results, nil
} }
@ -110,8 +110,8 @@ func getAnchorOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode
candidate := el.Value.(*CandidateNode) candidate := el.Value.(*CandidateNode)
anchor := candidate.Node.Anchor anchor := candidate.Node.Anchor
node := &yaml.Node{Kind: yaml.ScalarNode, Value: anchor, Tag: "!!str"} node := &yaml.Node{Kind: yaml.ScalarNode, Value: anchor, Tag: "!!str"}
lengthCand := &CandidateNode{Node: node, Document: candidate.Document, Path: candidate.Path} result := candidate.CreateChild(nil, node)
results.PushBack(lengthCand) results.PushBack(result)
} }
return results, nil return results, nil
} }

View File

@ -18,21 +18,22 @@ func collectOperator(d *dataTreeNavigator, matchMap *list.List, pathNode *PathTr
var results = list.New() var results = list.New()
node := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"} node := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
var collectC *CandidateNode
var document uint = 0 if matchMap.Front() != nil {
var path []interface{} collectC = matchMap.Front().Value.(*CandidateNode).CreateChild(nil, node)
if len(collectC.Path) > 0 {
collectC.Path = collectC.Path[:len(collectC.Path)-1]
}
} else {
collectC = &CandidateNode{Node: node}
}
for el := matchMap.Front(); el != nil; el = el.Next() { for el := matchMap.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode) candidate := el.Value.(*CandidateNode)
log.Debugf("Collecting %v", NodeToString(candidate)) log.Debugf("Collecting %v", NodeToString(candidate))
if path == nil && candidate.Path != nil && len(candidate.Path) > 1 {
path = candidate.Path[:len(candidate.Path)-1]
document = candidate.Document
}
node.Content = append(node.Content, UnwrapDoc(candidate.Node)) node.Content = append(node.Content, UnwrapDoc(candidate.Node))
} }
collectC := &CandidateNode{Node: node, Document: document, Path: path}
results.PushBack(collectC) results.PushBack(collectC)
return results, nil return results, nil

View File

@ -35,7 +35,7 @@ func collectObjectOperator(d *dataTreeNavigator, matchMap *list.List, pathNode *
for el := matchMap.Front(); el != nil; el = el.Next() { for el := matchMap.Front(); el != nil; el = el.Next() {
candidateNode := el.Value.(*CandidateNode) candidateNode := el.Value.(*CandidateNode)
for i := 0; i < len(first.Node.Content); i++ { for i := 0; i < len(first.Node.Content); i++ {
rotated[i].PushBack(createChildCandidate(candidateNode, i)) rotated[i].PushBack(candidateNode.CreateChild(i, candidateNode.Node.Content[i]))
} }
} }
@ -52,15 +52,6 @@ func collectObjectOperator(d *dataTreeNavigator, matchMap *list.List, pathNode *
} }
func createChildCandidate(candidate *CandidateNode, index int) *CandidateNode {
return &CandidateNode{
Document: candidate.Document,
Path: candidate.CreateChildPath(index),
Filename: candidate.Filename,
Node: candidate.Node.Content[index],
}
}
func collect(d *dataTreeNavigator, aggregate *list.List, remainingMatches *list.List) (*list.List, error) { func collect(d *dataTreeNavigator, aggregate *list.List, remainingMatches *list.List) (*list.List, error) {
if remainingMatches.Len() == 0 { if remainingMatches.Len() == 0 {
return aggregate, nil return aggregate, nil

View File

@ -84,8 +84,8 @@ func getCommentsOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNod
comment = strings.Replace(comment, "# ", "", 1) comment = strings.Replace(comment, "# ", "", 1)
node := &yaml.Node{Kind: yaml.ScalarNode, Value: comment, Tag: "!!str"} node := &yaml.Node{Kind: yaml.ScalarNode, Value: comment, Tag: "!!str"}
lengthCand := &CandidateNode{Node: node, Document: candidate.Document, Path: candidate.Path} result := candidate.CreateChild(nil, node)
results.PushBack(lengthCand) results.PushBack(result)
} }
return results, nil return results, nil
} }

View File

@ -72,11 +72,7 @@ func deleteFromMap(candidate *CandidateNode, childPath interface{}) {
key := contents[index] key := contents[index]
value := contents[index+1] value := contents[index+1]
childCandidate := &CandidateNode{ childCandidate := candidate.CreateChild(key.Value, value)
Node: value,
Document: candidate.Document,
Path: candidate.CreateChildPath(key.Value),
}
shouldDelete := key.Value == childPath shouldDelete := key.Value == childPath

View File

@ -13,7 +13,7 @@ func getDocumentIndexOperator(d *dataTreeNavigator, matchingNodes *list.List, pa
for el := matchingNodes.Front(); el != nil; el = el.Next() { for el := matchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode) candidate := el.Value.(*CandidateNode)
node := &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", candidate.Document), Tag: "!!int"} node := &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", candidate.Document), Tag: "!!int"}
scalar := &CandidateNode{Node: node, Document: candidate.Document, Path: candidate.Path} scalar := candidate.CreateChild(nil, node)
results.PushBack(scalar) results.PushBack(scalar)
} }
return results, nil return results, nil

View File

@ -44,12 +44,7 @@ func envOperator(d *dataTreeNavigator, matchMap *list.List, pathNode *PathTreeNo
log.Debug("ENV value", node.Value) log.Debug("ENV value", node.Value)
log.Debug("ENV Kind", node.Kind) log.Debug("ENV Kind", node.Kind)
target := &CandidateNode{ target := &CandidateNode{Node: node}
Path: make([]interface{}, 0),
Document: 0,
Filename: "",
Node: node,
}
return nodeToMap(target), nil return nodeToMap(target), nil
} }

View File

@ -15,8 +15,8 @@ func getFilenameOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNod
for el := matchingNodes.Front(); el != nil; el = el.Next() { for el := matchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode) candidate := el.Value.(*CandidateNode)
node := &yaml.Node{Kind: yaml.ScalarNode, Value: candidate.Filename, Tag: "!!str"} node := &yaml.Node{Kind: yaml.ScalarNode, Value: candidate.Filename, Tag: "!!str"}
lengthCand := &CandidateNode{Node: node, Document: candidate.Document, Path: candidate.Path} result := candidate.CreateChild(nil, node)
results.PushBack(lengthCand) results.PushBack(result)
} }
return results, nil return results, nil
@ -30,8 +30,8 @@ func getFileIndexOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNo
for el := matchingNodes.Front(); el != nil; el = el.Next() { for el := matchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode) candidate := el.Value.(*CandidateNode)
node := &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", candidate.FileIndex), Tag: "!!int"} node := &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", candidate.FileIndex), Tag: "!!int"}
lengthCand := &CandidateNode{Node: node, Document: candidate.Document, Path: candidate.Path} result := candidate.CreateChild(nil, node)
results.PushBack(lengthCand) results.PushBack(result)
} }
return results, nil return results, nil

View File

@ -29,6 +29,14 @@ var fileOperatorScenarios = []expressionScenario{
"D0, P[], (!!int)::0\n", "D0, P[], (!!int)::0\n",
}, },
}, },
{
skipDoc: true,
document: "a: cat\nb: dog",
expression: `.. lineComment |= filename`,
expected: []string{
"D0, P[], (!!map)::a: cat # sample.yml\nb: dog # sample.yml\n",
},
},
} }
func TestFileOperatorsScenarios(t *testing.T) { func TestFileOperatorsScenarios(t *testing.T) {

View File

@ -27,8 +27,8 @@ func lengthOperator(d *dataTreeNavigator, matchMap *list.List, pathNode *PathTre
} }
node := &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", length), Tag: "!!int"} node := &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", length), Tag: "!!int"}
lengthCand := &CandidateNode{Node: node, Document: candidate.Document, Path: candidate.Path} result := candidate.CreateChild(nil, node)
results.PushBack(lengthCand) results.PushBack(result)
} }
return results, nil return results, nil

View File

@ -64,12 +64,7 @@ func multiply(preferences *multiplyPreferences) func(d *dataTreeNavigator, lhs *
if lhs.Node.Kind == yaml.MappingNode && rhs.Node.Kind == yaml.MappingNode || if lhs.Node.Kind == yaml.MappingNode && rhs.Node.Kind == yaml.MappingNode ||
(lhs.Node.Kind == yaml.SequenceNode && rhs.Node.Kind == yaml.SequenceNode) { (lhs.Node.Kind == yaml.SequenceNode && rhs.Node.Kind == yaml.SequenceNode) {
var newBlank = &CandidateNode{ var newBlank = lhs.CreateChild(nil, &yaml.Node{})
Path: lhs.Path,
Document: lhs.Document,
Filename: lhs.Filename,
Node: &yaml.Node{},
}
var newThing, err = mergeObjects(d, newBlank, lhs, false) var newThing, err = mergeObjects(d, newBlank, lhs, false)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -31,8 +31,8 @@ func getPathOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode *P
content[pathIndex] = createPathNodeFor(path) content[pathIndex] = createPathNodeFor(path)
} }
node.Content = content node.Content = content
lengthCand := &CandidateNode{Node: node, Document: candidate.Document, Path: candidate.Path} result := candidate.CreateChild(nil, node)
results.PushBack(lengthCand) results.PushBack(result)
} }
return results, nil return results, nil

View File

@ -68,7 +68,7 @@ var recursiveDescentOperatorScenarios = []expressionScenario{
document: `{a: {name: frog, b: {name: blog, age: 12}}}`, document: `{a: {name: frog, b: {name: blog, age: 12}}}`,
expression: `[.. | select(has("name"))]`, expression: `[.. | select(has("name"))]`,
expected: []string{ expected: []string{
"D0, P[a], (!!seq)::- {name: frog, b: {name: blog, age: 12}}\n- {name: blog, age: 12}\n", "D0, P[], (!!seq)::- {name: frog, b: {name: blog, age: 12}}\n- {name: blog, age: 12}\n",
}, },
}, },
{ {
@ -165,7 +165,7 @@ var recursiveDescentOperatorScenarios = []expressionScenario{
document: `{a: &cat {c: frog}, b: *cat}`, document: `{a: &cat {c: frog}, b: *cat}`,
expression: `[..]`, expression: `[..]`,
expected: []string{ expected: []string{
"D0, P[a], (!!seq)::- {a: &cat {c: frog}, b: *cat}\n- &cat {c: frog}\n- frog\n- *cat\n", "D0, P[], (!!seq)::- {a: &cat {c: frog}, b: *cat}\n- &cat {c: frog}\n- frog\n- *cat\n",
}, },
}, },
{ {
@ -187,7 +187,7 @@ var recursiveDescentOperatorScenarios = []expressionScenario{
document: mergeDocSample, document: mergeDocSample,
expression: `.foobar | [..]`, expression: `.foobar | [..]`,
expected: []string{ expected: []string{
"D0, P[foobar], (!!seq)::- c: foobar_c\n !!merge <<: *foo\n thing: foobar_thing\n- foobar_c\n- *foo\n- foobar_thing\n", "D0, P[], (!!seq)::- c: foobar_c\n !!merge <<: *foo\n thing: foobar_thing\n- foobar_c\n- *foo\n- foobar_thing\n",
}, },
}, },
{ {
@ -195,7 +195,7 @@ var recursiveDescentOperatorScenarios = []expressionScenario{
document: mergeDocSample, document: mergeDocSample,
expression: `.foobar | [...]`, expression: `.foobar | [...]`,
expected: []string{ expected: []string{
"D0, P[foobar], (!!seq)::- c: foobar_c\n !!merge <<: *foo\n thing: foobar_thing\n- c\n- foobar_c\n- !!merge <<\n- *foo\n- thing\n- foobar_thing\n", "D0, P[], (!!seq)::- c: foobar_c\n !!merge <<: *foo\n thing: foobar_thing\n- c\n- foobar_c\n- !!merge <<\n- *foo\n- thing\n- foobar_thing\n",
}, },
}, },
{ {

View File

@ -100,8 +100,8 @@ func getStyleOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode *
style = "<unknown>" style = "<unknown>"
} }
node := &yaml.Node{Kind: yaml.ScalarNode, Value: style, Tag: "!!str"} node := &yaml.Node{Kind: yaml.ScalarNode, Value: style, Tag: "!!str"}
lengthCand := &CandidateNode{Node: node, Document: candidate.Document, Path: candidate.Path} result := candidate.CreateChild(nil, node)
results.PushBack(lengthCand) results.PushBack(result)
} }
return results, nil return results, nil

View File

@ -55,8 +55,8 @@ func getTagOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode *Pa
for el := matchingNodes.Front(); el != nil; el = el.Next() { for el := matchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode) candidate := el.Value.(*CandidateNode)
node := &yaml.Node{Kind: yaml.ScalarNode, Value: UnwrapDoc(candidate.Node).Tag, Tag: "!!str"} node := &yaml.Node{Kind: yaml.ScalarNode, Value: UnwrapDoc(candidate.Node).Tag, Tag: "!!str"}
lengthCand := &CandidateNode{Node: node, Document: candidate.Document, Path: candidate.Path} result := candidate.CreateChild(nil, node)
results.PushBack(lengthCand) results.PushBack(result)
} }
return results, nil return results, nil

View File

@ -67,11 +67,8 @@ func traverse(d *dataTreeNavigator, matchingNode *CandidateNode, operation *Oper
return traverse(d, matchingNode, operation) return traverse(d, matchingNode, operation)
case yaml.DocumentNode: case yaml.DocumentNode:
log.Debug("digging into doc node") log.Debug("digging into doc node")
return traverse(d, &CandidateNode{
Node: matchingNode.Node.Content[0], return traverse(d, matchingNode.CreateChild(nil, matchingNode.Node.Content[0]), operation)
Filename: matchingNode.Filename,
FileIndex: matchingNode.FileIndex,
Document: matchingNode.Document}, operation)
default: default:
return list.New(), nil return list.New(), nil
} }
@ -121,11 +118,7 @@ func traverseArrayIndices(matchingNode *CandidateNode, indicesToTraverse []*yaml
} else if node.Kind == yaml.MappingNode { } else if node.Kind == yaml.MappingNode {
return traverseMapWithIndices(matchingNode, indicesToTraverse, prefs) return traverseMapWithIndices(matchingNode, indicesToTraverse, prefs)
} else if node.Kind == yaml.DocumentNode { } else if node.Kind == yaml.DocumentNode {
return traverseArrayIndices(&CandidateNode{ return traverseArrayIndices(matchingNode.CreateChild(nil, matchingNode.Node.Content[0]), indicesToTraverse, prefs)
Node: matchingNode.Node.Content[0],
Filename: matchingNode.Filename,
FileIndex: matchingNode.FileIndex,
Document: matchingNode.Document}, indicesToTraverse, prefs)
} }
log.Debugf("OperatorArrayTraverse skipping %v as its a %v", matchingNode, node.Tag) log.Debugf("OperatorArrayTraverse skipping %v as its a %v", matchingNode, node.Tag)
return list.New(), nil return list.New(), nil
@ -159,11 +152,7 @@ func traverseArrayWithIndices(candidate *CandidateNode, indices []*yaml.Node) (*
var index int64 var index int64
for index = 0; index < int64(len(node.Content)); index = index + 1 { for index = 0; index < int64(len(node.Content)); index = index + 1 {
newMatches.PushBack(&CandidateNode{ newMatches.PushBack(candidate.CreateChild(index, node.Content[index]))
Document: candidate.Document,
Path: candidate.CreateChildPath(index),
Node: node.Content[index],
})
} }
return newMatches, nil return newMatches, nil
@ -190,11 +179,7 @@ func traverseArrayWithIndices(candidate *CandidateNode, indices []*yaml.Node) (*
return nil, fmt.Errorf("Index [%v] out of range, array size is %v", index, contentLength) return nil, fmt.Errorf("Index [%v] out of range, array size is %v", index, contentLength)
} }
newMatches.PushBack(&CandidateNode{ newMatches.PushBack(candidate.CreateChild(index, node.Content[indexToUse]))
Node: node.Content[indexToUse],
Document: candidate.Document,
Path: candidate.CreateChildPath(index),
})
} }
return newMatches, nil return newMatches, nil
} }
@ -216,13 +201,8 @@ func traverseMap(matchingNode *CandidateNode, key string, prefs *traversePrefere
valueNode := &yaml.Node{Tag: "!!null", Kind: yaml.ScalarNode, Value: "null"} valueNode := &yaml.Node{Tag: "!!null", Kind: yaml.ScalarNode, Value: "null"}
node := matchingNode.Node node := matchingNode.Node
node.Content = append(node.Content, &yaml.Node{Kind: yaml.ScalarNode, Value: key}, valueNode) node.Content = append(node.Content, &yaml.Node{Kind: yaml.ScalarNode, Value: key}, valueNode)
candidateNode := &CandidateNode{ candidateNode := matchingNode.CreateChild(key, valueNode)
Node: valueNode,
Path: append(matchingNode.Path, key),
Document: matchingNode.Document,
}
newMatches.Set(candidateNode.GetKey(), candidateNode) newMatches.Set(candidateNode.GetKey(), candidateNode)
} }
results := list.New() results := list.New()
@ -258,18 +238,10 @@ func doTraverseMap(newMatches *orderedmap.OrderedMap, candidate *CandidateNode,
} else if splat || keyMatches(key, wantedKey) { } else if splat || keyMatches(key, wantedKey) {
log.Debug("MATCHED") log.Debug("MATCHED")
if prefs.IncludeMapKeys { if prefs.IncludeMapKeys {
candidateNode := &CandidateNode{ candidateNode := candidate.CreateChild(key.Value, key)
Node: key,
Path: candidate.CreateChildPath(key.Value),
Document: candidate.Document,
}
newMatches.Set(fmt.Sprintf("keyOf-%v", candidateNode.GetKey()), candidateNode) newMatches.Set(fmt.Sprintf("keyOf-%v", candidateNode.GetKey()), candidateNode)
} }
candidateNode := &CandidateNode{ candidateNode := candidate.CreateChild(key.Value, value)
Node: value,
Path: candidate.CreateChildPath(key.Value),
Document: candidate.Document,
}
newMatches.Set(candidateNode.GetKey(), candidateNode) newMatches.Set(candidateNode.GetKey(), candidateNode)
} }
} }
@ -280,11 +252,7 @@ func doTraverseMap(newMatches *orderedmap.OrderedMap, candidate *CandidateNode,
func traverseMergeAnchor(newMatches *orderedmap.OrderedMap, originalCandidate *CandidateNode, value *yaml.Node, wantedKey string, prefs *traversePreferences, splat bool) error { func traverseMergeAnchor(newMatches *orderedmap.OrderedMap, originalCandidate *CandidateNode, value *yaml.Node, wantedKey string, prefs *traversePreferences, splat bool) error {
switch value.Kind { switch value.Kind {
case yaml.AliasNode: case yaml.AliasNode:
candidateNode := &CandidateNode{ candidateNode := originalCandidate.CreateChild(nil, value.Alias)
Node: value.Alias,
Path: originalCandidate.Path,
Document: originalCandidate.Document,
}
return doTraverseMap(newMatches, candidateNode, wantedKey, prefs, splat) return doTraverseMap(newMatches, candidateNode, wantedKey, prefs, splat)
case yaml.SequenceNode: case yaml.SequenceNode:
for _, childValue := range value.Content { for _, childValue := range value.Content {

View File

@ -26,7 +26,7 @@ func createBooleanCandidate(owner *CandidateNode, value bool) *CandidateNode {
valString = "false" valString = "false"
} }
node := &yaml.Node{Kind: yaml.ScalarNode, Value: valString, Tag: "!!bool"} node := &yaml.Node{Kind: yaml.ScalarNode, Value: valString, Tag: "!!bool"}
return &CandidateNode{Node: node, Document: owner.Document, Path: owner.Path} return owner.CreateChild(nil, node)
} }
func nodeToMap(candidate *CandidateNode) *list.List { func nodeToMap(candidate *CandidateNode) *list.List {