Extracted out is path expression checking logic

This commit is contained in:
Mike Farah 2020-01-11 19:30:27 +11:00
parent 2d237e7e8e
commit 35fd5b7ae4
8 changed files with 21 additions and 9 deletions

View File

@ -2,7 +2,6 @@ package yqlib
import (
"strconv"
"strings"
errors "github.com/pkg/errors"
yaml "gopkg.in/yaml.v3"
@ -70,7 +69,7 @@ func (n *navigator) recurse(value *yaml.Node, head string, tail []string, pathSt
return n.recurseMap(value, head, tail, pathStack)
case yaml.SequenceNode:
log.Debug("its a sequence of %v things!", len(value.Content))
if head == "*" || head == "**" || strings.Contains(head, "==") {
if n.navigationStrategy.GetPathParser().IsPathExpression(head) {
return n.splatArray(value, head, tail, pathStack)
} else if head == "+" {
return n.appendArray(value, head, tail, pathStack)
@ -117,7 +116,7 @@ func (n *navigator) recurseMap(value *yaml.Node, head string, tail []string, pat
return errorVisiting
}
if traversedEntry || head == "*" || head == "**" || !n.navigationStrategy.AutoCreateMap(NewNodeContext(value, head, tail, pathStack)) {
if traversedEntry || n.navigationStrategy.GetPathParser().IsPathExpression(head) || !n.navigationStrategy.AutoCreateMap(NewNodeContext(value, head, tail, pathStack)) {
return nil
}

View File

@ -10,6 +10,7 @@ func DeleteNavigationStrategy(pathElementToDelete string) NavigationStrategy {
parser := NewPathParser()
return &NavigationStrategyImpl{
visitedNodes: []*NodeContext{},
pathParser: parser,
followAlias: func(nodeContext NodeContext) bool {
return false
},

View File

@ -3,6 +3,7 @@ package yqlib
func FilterMatchingNodesNavigationStrategy(value string) NavigationStrategy {
return &NavigationStrategyImpl{
visitedNodes: []*NodeContext{},
pathParser: NewPathParser(),
followAlias: func(nodeContext NodeContext) bool {
return true
},

View File

@ -74,7 +74,8 @@ func guessKind(head string, tail []string, guess yaml.Kind) yaml.Kind {
if tail[0] == "+" || errorParsingInt == nil {
return yaml.SequenceNode
}
if (tail[0] == "*" || tail[0] == "**" || head == "**") && (guess == yaml.SequenceNode || guess == yaml.MappingNode) {
pathParser := NewPathParser()
if (pathParser.IsPathExpression(tail[0]) || head == "**") && (guess == yaml.SequenceNode || guess == yaml.MappingNode) {
return guess
}
if guess == yaml.AliasNode {

View File

@ -36,6 +36,7 @@ type NavigationStrategy interface {
ShouldTraverse(nodeContext NodeContext, nodeKey string) bool
GetVisitedNodes() []*NodeContext
DebugVisitedNodes()
GetPathParser() PathParser
}
type NavigationStrategyImpl struct {
@ -44,6 +45,11 @@ type NavigationStrategyImpl struct {
visit func(nodeContext NodeContext) error
shouldVisitExtraFn func(nodeContext NodeContext) bool
visitedNodes []*NodeContext
pathParser PathParser
}
func (ns *NavigationStrategyImpl) GetPathParser() PathParser {
return ns.pathParser
}
func (ns *NavigationStrategyImpl) GetVisitedNodes() []*NodeContext {
@ -68,10 +74,8 @@ func (ns *NavigationStrategyImpl) ShouldTraverse(nodeContext NodeContext, nodeKe
return false
}
parser := NewPathParser()
return (nodeKey == "<<" && ns.FollowAlias(nodeContext)) || (nodeKey != "<<" &&
parser.MatchesNextPathElement(nodeContext, nodeKey))
ns.pathParser.MatchesNextPathElement(nodeContext, nodeKey))
}
func (ns *NavigationStrategyImpl) shouldVisit(nodeContext NodeContext) bool {
@ -88,11 +92,10 @@ func (ns *NavigationStrategyImpl) shouldVisit(nodeContext NodeContext) bool {
nodeKey := fmt.Sprintf("%v", pathStack[len(pathStack)-1])
log.Debug("nodeKey: %v, nodeContext.Head: %v", nodeKey, nodeContext.Head)
parser := NewPathParser()
// only visit aliases if its an exact match
return ((nodeKey == "<<" && nodeContext.Head == "<<") || (nodeKey != "<<" &&
parser.MatchesNextPathElement(nodeContext, nodeKey))) && (ns.shouldVisitExtraFn == nil || ns.shouldVisitExtraFn(nodeContext))
ns.pathParser.MatchesNextPathElement(nodeContext, nodeKey))) && (ns.shouldVisitExtraFn == nil || ns.shouldVisitExtraFn(nodeContext))
}
func (ns *NavigationStrategyImpl) Visit(nodeContext NodeContext) error {

View File

@ -8,6 +8,7 @@ import (
type PathParser interface {
ParsePath(path string) []string
MatchesNextPathElement(nodeContext NodeContext, nodeKey string) bool
IsPathExpression(pathElement string) bool
}
type pathParser struct{}
@ -16,6 +17,10 @@ func NewPathParser() PathParser {
return &pathParser{}
}
func (p *pathParser) IsPathExpression(pathElement string) bool {
return pathElement == "*" || pathElement == "**" || strings.Contains(pathElement, "==")
}
/**
* node: node that we may traverse/visit
* head: path element expression to match against

View File

@ -3,6 +3,7 @@ package yqlib
func ReadNavigationStrategy() NavigationStrategy {
return &NavigationStrategyImpl{
visitedNodes: []*NodeContext{},
pathParser: NewPathParser(),
followAlias: func(nodeContext NodeContext) bool {
return true
},

View File

@ -3,6 +3,7 @@ package yqlib
func UpdateNavigationStrategy(updateCommand UpdateCommand, autoCreate bool) NavigationStrategy {
return &NavigationStrategyImpl{
visitedNodes: []*NodeContext{},
pathParser: NewPathParser(),
followAlias: func(nodeContext NodeContext) bool {
return false
},