This commit is contained in:
Mike Farah 2020-10-12 10:09:13 +11:00
parent b025000f20
commit 7c4cf72468
4 changed files with 150 additions and 24 deletions

View File

@ -18,7 +18,7 @@ func readDoc(t *testing.T, content string) []*CandidateNode {
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
return []*CandidateNode{&CandidateNode{Node: &dataBucket, Document: 0}} return []*CandidateNode{&CandidateNode{Node: dataBucket.Content[0], Document: 0}}
} }
func resultsToString(results []*CandidateNode) string { func resultsToString(results []*CandidateNode) string {
@ -54,7 +54,7 @@ func TestDataTreeNavigatorSimple(t *testing.T) {
test.AssertResult(t, expected, resultsToString(results)) test.AssertResult(t, expected, resultsToString(results))
} }
func TestDataTreeNavigatorSubtractSimple(t *testing.T) { func TestDataTreeNavigatorDeleteSimple(t *testing.T) {
nodes := readDoc(t, `a: nodes := readDoc(t, `a:
b: apple b: apple
@ -79,7 +79,7 @@ func TestDataTreeNavigatorSubtractSimple(t *testing.T) {
test.AssertResult(t, expected, resultsToString(results)) test.AssertResult(t, expected, resultsToString(results))
} }
func TestDataTreeNavigatorSubtractTwice(t *testing.T) { func TestDataTreeNavigatorDeleteTwice(t *testing.T) {
nodes := readDoc(t, `a: nodes := readDoc(t, `a:
b: apple b: apple
@ -106,7 +106,7 @@ func TestDataTreeNavigatorSubtractTwice(t *testing.T) {
test.AssertResult(t, expected, resultsToString(results)) test.AssertResult(t, expected, resultsToString(results))
} }
func TestDataTreeNavigatorSubtractWithUnion(t *testing.T) { func TestDataTreeNavigatorDeleteWithUnion(t *testing.T) {
nodes := readDoc(t, `a: nodes := readDoc(t, `a:
b: apple b: apple
@ -133,7 +133,7 @@ func TestDataTreeNavigatorSubtractWithUnion(t *testing.T) {
test.AssertResult(t, expected, resultsToString(results)) test.AssertResult(t, expected, resultsToString(results))
} }
func TestDataTreeNavigatorSubtractByIndex(t *testing.T) { func TestDataTreeNavigatorDeleteByIndex(t *testing.T) {
nodes := readDoc(t, `a: nodes := readDoc(t, `a:
- b: apple - b: apple
@ -160,6 +160,86 @@ func TestDataTreeNavigatorSubtractByIndex(t *testing.T) {
test.AssertResult(t, expected, resultsToString(results)) test.AssertResult(t, expected, resultsToString(results))
} }
func TestDataTreeNavigatorDeleteByFind(t *testing.T) {
nodes := readDoc(t, `a:
- b: apple
- b: sdfsd
- b: apple`)
path, errPath := treeCreator.ParsePath("(a .- (* == apple))")
if errPath != nil {
t.Error(errPath)
}
results, errNav := treeNavigator.GetMatchingNodes(nodes, path)
if errNav != nil {
t.Error(errNav)
}
expected := `
-- Node --
Document 0, path: [a]
Tag: !!seq, Kind: SequenceNode, Anchor:
- b: sdfsd
`
test.AssertResult(t, expected, resultsToString(results))
}
func TestDataTreeNavigatorDeleteArrayByFind(t *testing.T) {
nodes := readDoc(t, `a:
- apple
- sdfsd
- apple`)
path, errPath := treeCreator.ParsePath("(a .- (. == apple))")
if errPath != nil {
t.Error(errPath)
}
results, errNav := treeNavigator.GetMatchingNodes(nodes, path)
if errNav != nil {
t.Error(errNav)
}
expected := `
-- Node --
Document 0, path: [a]
Tag: !!seq, Kind: SequenceNode, Anchor:
- sdfsd
`
test.AssertResult(t, expected, resultsToString(results))
}
func TestDataTreeNavigatorDeleteViaSelf(t *testing.T) {
nodes := readDoc(t, `- apple
- sdfsd
- apple`)
path, errPath := treeCreator.ParsePath("(. .- .)")
if errPath != nil {
t.Error(errPath)
}
results, errNav := treeNavigator.GetMatchingNodes(nodes, path)
if errNav != nil {
t.Error(errNav)
}
expected := `
-- Node --
Document 0, path: []
Tag: !!seq, Kind: SequenceNode, Anchor:
- sdfsd
`
test.AssertResult(t, expected, resultsToString(results))
}
func TestDataTreeNavigatorDeleteAndWrite(t *testing.T) { func TestDataTreeNavigatorDeleteAndWrite(t *testing.T) {
nodes := readDoc(t, `a: nodes := readDoc(t, `a:
@ -192,7 +272,7 @@ func TestDataTreeNavigatorDeleteAndWrite(t *testing.T) {
test.AssertResult(t, expected, resultsToString(results)) test.AssertResult(t, expected, resultsToString(results))
} }
func TestDataTreeNavigatorSubtractArray(t *testing.T) { func TestDataTreeNavigatorDeleteArray(t *testing.T) {
nodes := readDoc(t, `a: nodes := readDoc(t, `a:
- b: apple - b: apple
@ -268,6 +348,56 @@ func TestDataTreeNavigatorSimpleAssign(t *testing.T) {
test.AssertResult(t, expected, resultsToString(results)) test.AssertResult(t, expected, resultsToString(results))
} }
func TestDataTreeNavigatorSimpleAssignSelf(t *testing.T) {
nodes := readDoc(t, `a:
b: apple`)
path, errPath := treeCreator.ParsePath("a(. == apple)(. := frog)")
if errPath != nil {
t.Error(errPath)
}
results, errNav := treeNavigator.GetMatchingNodes(nodes, path)
if errNav != nil {
t.Error(errNav)
}
expected := `
-- Node --
Document 0, path: [a b]
Tag: !!str, Kind: ScalarNode, Anchor:
frog
`
test.AssertResult(t, expected, resultsToString(results))
}
func TestDataTreeNavigatorSimpleAssignByFind(t *testing.T) {
nodes := readDoc(t, `a:
b: apple`)
path, errPath := treeCreator.ParsePath("(b == apple) := frog)")
if errPath != nil {
t.Error(errPath)
}
results, errNav := treeNavigator.GetMatchingNodes(nodes, path)
if errNav != nil {
t.Error(errNav)
}
expected := `
-- Node --
Document 0, path: [a b]
Tag: !!str, Kind: ScalarNode, Anchor:
frog
`
test.AssertResult(t, expected, resultsToString(results))
}
func TestDataTreeNavigatorArraySplat(t *testing.T) { func TestDataTreeNavigatorArraySplat(t *testing.T) {
nodes := readDoc(t, `- b: apple nodes := readDoc(t, `- b: apple

View File

@ -26,8 +26,10 @@ func DeleteChildOperator(d *dataTreeNavigator, matchingNodes *orderedmap.Ordered
if candidate.Node.Kind == yaml.SequenceNode { if candidate.Node.Kind == yaml.SequenceNode {
deleteFromArray(candidate, nodesToDelete) deleteFromArray(candidate, nodesToDelete)
} else { } else if candidate.Node.Kind == yaml.MappingNode {
deleteFromMap(candidate, nodesToDelete) deleteFromMap(candidate, nodesToDelete)
} else {
log.Debug("Cannot delete from node that's not a map or array %v", NodeToString(candidate))
} }
} }
return lhs, nil return lhs, nil

View File

@ -84,17 +84,10 @@ func EqualsOperator(d *dataTreeNavigator, matchMap *orderedmap.OrderedMap, pathN
valuePattern := pathNode.Rhs.PathElement.StringValue valuePattern := pathNode.Rhs.PathElement.StringValue
log.Debug("checking %v", candidate) log.Debug("checking %v", candidate)
// if pathNode.Lhs.PathElement.PathElementType == SelfReference {
// if Match(candidate.Node.Value, valuePattern) {
// results.Set(el.Key, el.Value)
// }
// } else {
errInChild := findMatchingChildren(d, results, candidate, pathNode.Lhs, valuePattern) errInChild := findMatchingChildren(d, results, candidate, pathNode.Lhs, valuePattern)
if errInChild != nil { if errInChild != nil {
return nil, errInChild return nil, errInChild
} }
// }
} }
return results, nil return results, nil

View File

@ -16,7 +16,7 @@ type Token struct {
OperationType OperationType OperationType OperationType
Value interface{} Value interface{}
StringValue string StringValue string
AgainstSelf bool PrefixSelf bool
CheckForPreTraverse bool // this token can sometimes have the traverse '.' missing in frnot of it CheckForPreTraverse bool // this token can sometimes have the traverse '.' missing in frnot of it
// e.g. a[1] should really be a.[1] // e.g. a[1] should really be a.[1]
@ -37,13 +37,13 @@ func pathToken(wrapped bool) lex.Action {
func opToken(op OperationType, againstSelf bool) lex.Action { func opToken(op OperationType, againstSelf bool) lex.Action {
return func(s *lex.Scanner, m *machines.Match) (interface{}, error) { return func(s *lex.Scanner, m *machines.Match) (interface{}, error) {
value := string(m.Bytes) value := string(m.Bytes)
return &Token{PathElementType: Operation, OperationType: op, Value: value, StringValue: value, AgainstSelf: againstSelf}, nil return &Token{PathElementType: Operation, OperationType: op, Value: value, StringValue: value, PrefixSelf: againstSelf}, nil
} }
} }
func literalToken(pType PathElementType, literal string, checkForPre bool, checkForPost bool) lex.Action { func literalToken(pType PathElementType, literal string, checkForPre bool, checkForPost bool, againstSelf bool) lex.Action {
return func(s *lex.Scanner, m *machines.Match) (interface{}, error) { return func(s *lex.Scanner, m *machines.Match) (interface{}, error) {
return &Token{PathElementType: pType, Value: literal, StringValue: literal, CheckForPreTraverse: checkForPre, CheckForPostTraverse: checkForPost}, nil return &Token{PathElementType: pType, Value: literal, StringValue: literal, CheckForPreTraverse: checkForPre, CheckForPostTraverse: checkForPost, PrefixSelf: againstSelf}, nil
} }
} }
@ -68,12 +68,13 @@ func arrayIndextoken(wrapped bool, checkForPre bool, checkForPost bool) lex.Acti
// Creates the lexer object and compiles the NFA. // Creates the lexer object and compiles the NFA.
func initLexer() (*lex.Lexer, error) { func initLexer() (*lex.Lexer, error) {
lexer := lex.NewLexer() lexer := lex.NewLexer()
lexer.Add([]byte(`\(`), literalToken(OpenBracket, "(", true, false)) lexer.Add([]byte(`\(`), literalToken(OpenBracket, "(", true, false, false))
lexer.Add([]byte(`\)`), literalToken(CloseBracket, ")", false, true)) lexer.Add([]byte(`\)`), literalToken(CloseBracket, ")", false, true, false))
lexer.Add([]byte(`\.\s*\)`), literalToken(CloseBracket, ")", false, true, true))
lexer.Add([]byte(`\[\+\]`), literalToken(PathKey, "[+]", true, true)) lexer.Add([]byte(`\[\+\]`), literalToken(PathKey, "[+]", true, true, false))
lexer.Add([]byte(`\[\*\]`), literalToken(PathKey, "[*]", true, true)) lexer.Add([]byte(`\[\*\]`), literalToken(PathKey, "[*]", true, true, false))
lexer.Add([]byte(`\*\*`), literalToken(PathKey, "**", false, false)) lexer.Add([]byte(`\*\*`), literalToken(PathKey, "**", false, false, false))
lexer.Add([]byte(`([Oo][Rr])`), opToken(Or, false)) lexer.Add([]byte(`([Oo][Rr])`), opToken(Or, false))
lexer.Add([]byte(`([Aa][Nn][Dd])`), opToken(And, false)) lexer.Add([]byte(`([Aa][Nn][Dd])`), opToken(And, false))
@ -143,7 +144,7 @@ func (p *pathTokeniser) Tokenise(path string) ([]*Token, error) {
(tokens[index-1].PathElementType == PathKey || tokens[index-1].PathElementType == CloseBracket) { (tokens[index-1].PathElementType == PathKey || tokens[index-1].PathElementType == CloseBracket) {
postProcessedTokens = append(postProcessedTokens, &Token{PathElementType: Operation, OperationType: Traverse, Value: "."}) postProcessedTokens = append(postProcessedTokens, &Token{PathElementType: Operation, OperationType: Traverse, Value: "."})
} }
if token.PathElementType == Operation && token.AgainstSelf { if token.PrefixSelf {
postProcessedTokens = append(postProcessedTokens, &Token{PathElementType: SelfReference, Value: "SELF"}) postProcessedTokens = append(postProcessedTokens, &Token{PathElementType: SelfReference, Value: "SELF"})
} }