mirror of
https://github.com/mikefarah/yq.git
synced 2024-12-19 20:19:04 +00:00
Pass context through operators
Allows more sophisticated functionality
This commit is contained in:
parent
3bae44be68
commit
c6efd5519b
@ -1,4 +1,6 @@
|
||||
a: simple # just the best
|
||||
b: [1, 2]
|
||||
c:
|
||||
test: 1
|
||||
a:
|
||||
key1: "value1"
|
||||
key2: 2.6
|
||||
ab:
|
||||
key1: 6
|
||||
key2: "h"
|
@ -39,7 +39,11 @@ func (e *allAtOnceEvaluator) EvaluateCandidateNodes(expression string, inputCand
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return e.treeNavigator.GetMatchingNodes(inputCandidates, node)
|
||||
context, err := e.treeNavigator.GetMatchingNodes(Context{MatchingNodes: inputCandidates}, node)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return context.MatchingNodes, nil
|
||||
}
|
||||
|
||||
func (e *allAtOnceEvaluator) EvaluateFiles(expression string, filenames []string, printer Printer) error {
|
||||
|
18
pkg/yqlib/context.go
Normal file
18
pkg/yqlib/context.go
Normal file
@ -0,0 +1,18 @@
|
||||
package yqlib
|
||||
|
||||
import "container/list"
|
||||
|
||||
type Context struct {
|
||||
MatchingNodes *list.List
|
||||
Variables map[string]*list.List
|
||||
}
|
||||
|
||||
func (n *Context) SingleChildContext(candidate *CandidateNode) Context {
|
||||
elMap := list.New()
|
||||
elMap.PushBack(candidate)
|
||||
return Context{MatchingNodes: elMap, Variables: n.Variables}
|
||||
}
|
||||
|
||||
func (n *Context) ChildContext(results *list.List) Context {
|
||||
return Context{MatchingNodes: results, Variables: n.Variables}
|
||||
}
|
@ -3,16 +3,14 @@ package yqlib
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"container/list"
|
||||
|
||||
logging "gopkg.in/op/go-logging.v1"
|
||||
)
|
||||
|
||||
type DataTreeNavigator interface {
|
||||
// given a list of CandidateEntities and a expressionNode,
|
||||
// this will process the list against the given expressionNode and return
|
||||
// a new list of matching candidates
|
||||
GetMatchingNodes(matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error)
|
||||
// given the context and a expressionNode,
|
||||
// this will process the against the given expressionNode and return
|
||||
// a new context of matching candidates
|
||||
GetMatchingNodes(context Context, expressionNode *ExpressionNode) (Context, error)
|
||||
}
|
||||
|
||||
type dataTreeNavigator struct {
|
||||
@ -22,22 +20,22 @@ func NewDataTreeNavigator() DataTreeNavigator {
|
||||
return &dataTreeNavigator{}
|
||||
}
|
||||
|
||||
func (d *dataTreeNavigator) GetMatchingNodes(matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func (d *dataTreeNavigator) GetMatchingNodes(context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
if expressionNode == nil {
|
||||
log.Debugf("getMatchingNodes - nothing to do")
|
||||
return matchingNodes, nil
|
||||
return context, nil
|
||||
}
|
||||
log.Debugf("Processing Op: %v", expressionNode.Operation.toString())
|
||||
if log.IsEnabledFor(logging.DEBUG) {
|
||||
for el := matchingNodes.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
log.Debug(NodeToString(el.Value.(*CandidateNode)))
|
||||
}
|
||||
}
|
||||
log.Debug(">>")
|
||||
handler := expressionNode.Operation.OperationType.Handler
|
||||
if handler != nil {
|
||||
return handler(d, matchingNodes, expressionNode)
|
||||
return handler(d, context, expressionNode)
|
||||
}
|
||||
return nil, fmt.Errorf("Unknown operator %v", expressionNode.Operation.OperationType)
|
||||
return Context{}, fmt.Errorf("Unknown operator %v", expressionNode.Operation.OperationType)
|
||||
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package yqlib
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"container/list"
|
||||
"strconv"
|
||||
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
@ -15,12 +14,12 @@ func createAddOp(lhs *ExpressionNode, rhs *ExpressionNode) *ExpressionNode {
|
||||
Rhs: rhs}
|
||||
}
|
||||
|
||||
func addAssignOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func addAssignOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
assignmentOp := &Operation{OperationType: assignOpType}
|
||||
assignmentOp.UpdateAssign = false
|
||||
|
||||
assignmentOpNode := &ExpressionNode{Operation: assignmentOp, Lhs: expressionNode.Lhs, Rhs: createAddOp(expressionNode.Lhs, expressionNode.Rhs)}
|
||||
return d.GetMatchingNodes(matchingNodes, assignmentOpNode)
|
||||
return d.GetMatchingNodes(context, assignmentOpNode)
|
||||
}
|
||||
|
||||
func toNodes(candidate *CandidateNode) []*yaml.Node {
|
||||
@ -37,13 +36,13 @@ func toNodes(candidate *CandidateNode) []*yaml.Node {
|
||||
|
||||
}
|
||||
|
||||
func addOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func addOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("Add operator")
|
||||
|
||||
return crossFunction(d, matchingNodes, expressionNode, add)
|
||||
return crossFunction(d, context, expressionNode, add)
|
||||
}
|
||||
|
||||
func add(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
func add(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
lhs.Node = unwrapDoc(lhs.Node)
|
||||
rhs.Node = unwrapDoc(rhs.Node)
|
||||
|
||||
|
@ -1,18 +1,14 @@
|
||||
package yqlib
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
)
|
||||
|
||||
// corssFunction no matches
|
||||
// can boolean use crossfunction
|
||||
|
||||
func alternativeOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func alternativeOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("-- alternative")
|
||||
return crossFunction(d, matchingNodes, expressionNode, alternativeFunc)
|
||||
return crossFunction(d, context, expressionNode, alternativeFunc)
|
||||
}
|
||||
|
||||
func alternativeFunc(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
func alternativeFunc(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
lhs.Node = unwrapDoc(lhs.Node)
|
||||
rhs.Node = unwrapDoc(rhs.Node)
|
||||
log.Debugf("Alternative LHS: %v", lhs.Node.Tag)
|
||||
|
@ -6,146 +6,146 @@ import (
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func assignAliasOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func assignAliasOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
|
||||
log.Debugf("AssignAlias operator!")
|
||||
|
||||
aliasName := ""
|
||||
if !expressionNode.Operation.UpdateAssign {
|
||||
rhs, err := d.GetMatchingNodes(matchingNodes, expressionNode.Rhs)
|
||||
rhs, err := d.GetMatchingNodes(context, expressionNode.Rhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
if rhs.Front() != nil {
|
||||
aliasName = rhs.Front().Value.(*CandidateNode).Node.Value
|
||||
if rhs.MatchingNodes.Front() != nil {
|
||||
aliasName = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
|
||||
}
|
||||
}
|
||||
|
||||
lhs, err := d.GetMatchingNodes(matchingNodes, expressionNode.Lhs)
|
||||
lhs, err := d.GetMatchingNodes(context, expressionNode.Lhs)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
for el := lhs.Front(); el != nil; el = el.Next() {
|
||||
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
log.Debugf("Setting aliasName : %v", candidate.GetKey())
|
||||
|
||||
if expressionNode.Operation.UpdateAssign {
|
||||
rhs, err := d.GetMatchingNodes(nodeToMap(candidate), expressionNode.Rhs)
|
||||
rhs, err := d.GetMatchingNodes(context.SingleChildContext(candidate), expressionNode.Rhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
if rhs.Front() != nil {
|
||||
aliasName = rhs.Front().Value.(*CandidateNode).Node.Value
|
||||
if rhs.MatchingNodes.Front() != nil {
|
||||
aliasName = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
|
||||
}
|
||||
}
|
||||
|
||||
candidate.Node.Kind = yaml.AliasNode
|
||||
candidate.Node.Value = aliasName
|
||||
}
|
||||
return matchingNodes, nil
|
||||
return context, nil
|
||||
}
|
||||
|
||||
func getAliasOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func getAliasOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("GetAlias operator!")
|
||||
var results = list.New()
|
||||
|
||||
for el := matchingNodes.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
node := &yaml.Node{Kind: yaml.ScalarNode, Value: candidate.Node.Value, Tag: "!!str"}
|
||||
result := candidate.CreateChild(nil, node)
|
||||
results.PushBack(result)
|
||||
}
|
||||
return results, nil
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
||||
func assignAnchorOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func assignAnchorOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
|
||||
log.Debugf("AssignAnchor operator!")
|
||||
|
||||
anchorName := ""
|
||||
if !expressionNode.Operation.UpdateAssign {
|
||||
rhs, err := d.GetMatchingNodes(matchingNodes, expressionNode.Rhs)
|
||||
rhs, err := d.GetMatchingNodes(context, expressionNode.Rhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
if rhs.Front() != nil {
|
||||
anchorName = rhs.Front().Value.(*CandidateNode).Node.Value
|
||||
if rhs.MatchingNodes.Front() != nil {
|
||||
anchorName = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
|
||||
}
|
||||
}
|
||||
|
||||
lhs, err := d.GetMatchingNodes(matchingNodes, expressionNode.Lhs)
|
||||
lhs, err := d.GetMatchingNodes(context, expressionNode.Lhs)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
for el := lhs.Front(); el != nil; el = el.Next() {
|
||||
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
log.Debugf("Setting anchorName of : %v", candidate.GetKey())
|
||||
|
||||
if expressionNode.Operation.UpdateAssign {
|
||||
rhs, err := d.GetMatchingNodes(nodeToMap(candidate), expressionNode.Rhs)
|
||||
rhs, err := d.GetMatchingNodes(context.SingleChildContext(candidate), expressionNode.Rhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
if rhs.Front() != nil {
|
||||
anchorName = rhs.Front().Value.(*CandidateNode).Node.Value
|
||||
if rhs.MatchingNodes.Front() != nil {
|
||||
anchorName = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
|
||||
}
|
||||
}
|
||||
|
||||
candidate.Node.Anchor = anchorName
|
||||
}
|
||||
return matchingNodes, nil
|
||||
return context, nil
|
||||
}
|
||||
|
||||
func getAnchorOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func getAnchorOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("GetAnchor operator!")
|
||||
var results = list.New()
|
||||
|
||||
for el := matchingNodes.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
anchor := candidate.Node.Anchor
|
||||
node := &yaml.Node{Kind: yaml.ScalarNode, Value: anchor, Tag: "!!str"}
|
||||
result := candidate.CreateChild(nil, node)
|
||||
results.PushBack(result)
|
||||
}
|
||||
return results, nil
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
||||
func explodeOperator(d *dataTreeNavigator, matchMap *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func explodeOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("-- ExplodeOperation")
|
||||
|
||||
for el := matchMap.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
|
||||
rhs, err := d.GetMatchingNodes(nodeToMap(candidate), expressionNode.Rhs)
|
||||
rhs, err := d.GetMatchingNodes(context.SingleChildContext(candidate), expressionNode.Rhs)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
for childEl := rhs.Front(); childEl != nil; childEl = childEl.Next() {
|
||||
err = explodeNode(childEl.Value.(*CandidateNode).Node)
|
||||
for childEl := rhs.MatchingNodes.Front(); childEl != nil; childEl = childEl.Next() {
|
||||
err = explodeNode(childEl.Value.(*CandidateNode).Node, context)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return matchMap, nil
|
||||
return context, nil
|
||||
}
|
||||
|
||||
func explodeNode(node *yaml.Node) error {
|
||||
func explodeNode(node *yaml.Node, context Context) error {
|
||||
node.Anchor = ""
|
||||
switch node.Kind {
|
||||
case yaml.SequenceNode, yaml.DocumentNode:
|
||||
for index, contentNode := range node.Content {
|
||||
log.Debugf("exploding index %v", index)
|
||||
errorInContent := explodeNode(contentNode)
|
||||
errorInContent := explodeNode(contentNode, context)
|
||||
if errorInContent != nil {
|
||||
return errorInContent
|
||||
}
|
||||
@ -169,7 +169,7 @@ func explodeNode(node *yaml.Node) error {
|
||||
valueNode := node.Content[index+1]
|
||||
log.Debugf("traversing %v", keyNode.Value)
|
||||
if keyNode.Value != "<<" {
|
||||
err := overrideEntry(node, keyNode, valueNode, index, newContent)
|
||||
err := overrideEntry(node, keyNode, valueNode, index, context.ChildContext(newContent))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -178,14 +178,14 @@ func explodeNode(node *yaml.Node) error {
|
||||
log.Debugf("an alias merge list!")
|
||||
for index := 0; index < len(valueNode.Content); index = index + 1 {
|
||||
aliasNode := valueNode.Content[index]
|
||||
err := applyAlias(node, aliasNode.Alias, index, newContent)
|
||||
err := applyAlias(node, aliasNode.Alias, index, context.ChildContext(newContent))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Debugf("an alias merge!")
|
||||
err := applyAlias(node, valueNode.Alias, index, newContent)
|
||||
err := applyAlias(node, valueNode.Alias, index, context.ChildContext(newContent))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -205,7 +205,7 @@ func explodeNode(node *yaml.Node) error {
|
||||
}
|
||||
}
|
||||
|
||||
func applyAlias(node *yaml.Node, alias *yaml.Node, aliasIndex int, newContent *list.List) error {
|
||||
func applyAlias(node *yaml.Node, alias *yaml.Node, aliasIndex int, newContent Context) error {
|
||||
if alias == nil {
|
||||
return nil
|
||||
}
|
||||
@ -221,15 +221,15 @@ func applyAlias(node *yaml.Node, alias *yaml.Node, aliasIndex int, newContent *l
|
||||
return nil
|
||||
}
|
||||
|
||||
func overrideEntry(node *yaml.Node, key *yaml.Node, value *yaml.Node, startIndex int, newContent *list.List) error {
|
||||
func overrideEntry(node *yaml.Node, key *yaml.Node, value *yaml.Node, startIndex int, newContent Context) error {
|
||||
|
||||
err := explodeNode(value)
|
||||
err := explodeNode(value, newContent)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for newEl := newContent.Front(); newEl != nil; newEl = newEl.Next() {
|
||||
for newEl := newContent.MatchingNodes.Front(); newEl != nil; newEl = newEl.Next() {
|
||||
valueEl := newEl.Next() // move forward twice
|
||||
keyNode := newEl.Value.(*yaml.Node)
|
||||
log.Debugf("checking new content %v:%v", keyNode.Value, valueEl.Value.(*yaml.Node).Value)
|
||||
@ -250,12 +250,12 @@ func overrideEntry(node *yaml.Node, key *yaml.Node, value *yaml.Node, startIndex
|
||||
}
|
||||
}
|
||||
|
||||
err = explodeNode(key)
|
||||
err = explodeNode(key, newContent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Debugf("adding %v:%v", key.Value, value.Value)
|
||||
newContent.PushBack(key)
|
||||
newContent.PushBack(value)
|
||||
newContent.MatchingNodes.PushBack(key)
|
||||
newContent.MatchingNodes.PushBack(value)
|
||||
return nil
|
||||
}
|
||||
|
@ -1,30 +1,28 @@
|
||||
package yqlib
|
||||
|
||||
import "container/list"
|
||||
|
||||
func assignUpdateOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
lhs, err := d.GetMatchingNodes(matchingNodes, expressionNode.Lhs)
|
||||
func assignUpdateOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
lhs, err := d.GetMatchingNodes(context, expressionNode.Lhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
var rhs *list.List
|
||||
var rhs Context
|
||||
if !expressionNode.Operation.UpdateAssign {
|
||||
rhs, err = d.GetMatchingNodes(matchingNodes, expressionNode.Rhs)
|
||||
rhs, err = d.GetMatchingNodes(context, expressionNode.Rhs)
|
||||
}
|
||||
|
||||
for el := lhs.Front(); el != nil; el = el.Next() {
|
||||
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
|
||||
if expressionNode.Operation.UpdateAssign {
|
||||
rhs, err = d.GetMatchingNodes(nodeToMap(candidate), expressionNode.Rhs)
|
||||
rhs, err = d.GetMatchingNodes(context.SingleChildContext(candidate), expressionNode.Rhs)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
// grab the first value
|
||||
first := rhs.Front()
|
||||
first := rhs.MatchingNodes.Front()
|
||||
|
||||
if first != nil {
|
||||
rhsCandidate := first.Value.(*CandidateNode)
|
||||
@ -33,30 +31,30 @@ func assignUpdateOperator(d *dataTreeNavigator, matchingNodes *list.List, expres
|
||||
}
|
||||
}
|
||||
|
||||
return matchingNodes, nil
|
||||
return context, nil
|
||||
}
|
||||
|
||||
// does not update content or values
|
||||
func assignAttributesOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
lhs, err := d.GetMatchingNodes(matchingNodes, expressionNode.Lhs)
|
||||
func assignAttributesOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
lhs, err := d.GetMatchingNodes(context, expressionNode.Lhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
for el := lhs.Front(); el != nil; el = el.Next() {
|
||||
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
|
||||
rhs, err := d.GetMatchingNodes(nodeToMap(candidate), expressionNode.Rhs)
|
||||
rhs, err := d.GetMatchingNodes(context.SingleChildContext(candidate), expressionNode.Rhs)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
// grab the first value
|
||||
first := rhs.Front()
|
||||
first := rhs.MatchingNodes.Front()
|
||||
|
||||
if first != nil {
|
||||
candidate.UpdateAttributesFrom(first.Value.(*CandidateNode))
|
||||
}
|
||||
}
|
||||
return matchingNodes, nil
|
||||
return context, nil
|
||||
}
|
||||
|
@ -25,8 +25,8 @@ func isTruthy(c *CandidateNode) (bool, error) {
|
||||
|
||||
type boolOp func(bool, bool) bool
|
||||
|
||||
func performBoolOp(op boolOp) func(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
return func(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
func performBoolOp(op boolOp) func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
return func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
lhs.Node = unwrapDoc(lhs.Node)
|
||||
rhs.Node = unwrapDoc(rhs.Node)
|
||||
|
||||
@ -44,35 +44,35 @@ func performBoolOp(op boolOp) func(d *dataTreeNavigator, lhs *CandidateNode, rhs
|
||||
}
|
||||
}
|
||||
|
||||
func orOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func orOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("-- orOp")
|
||||
return crossFunction(d, matchingNodes, expressionNode, performBoolOp(
|
||||
return crossFunction(d, context, expressionNode, performBoolOp(
|
||||
func(b1 bool, b2 bool) bool {
|
||||
return b1 || b2
|
||||
}))
|
||||
}
|
||||
|
||||
func andOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func andOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("-- AndOp")
|
||||
return crossFunction(d, matchingNodes, expressionNode, performBoolOp(
|
||||
return crossFunction(d, context, expressionNode, performBoolOp(
|
||||
func(b1 bool, b2 bool) bool {
|
||||
return b1 && b2
|
||||
}))
|
||||
}
|
||||
|
||||
func notOperator(d *dataTreeNavigator, matchMap *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func notOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("-- notOperation")
|
||||
var results = list.New()
|
||||
|
||||
for el := matchMap.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
log.Debug("notOperation checking %v", candidate)
|
||||
truthy, errDecoding := isTruthy(candidate)
|
||||
if errDecoding != nil {
|
||||
return nil, errDecoding
|
||||
return Context{}, errDecoding
|
||||
}
|
||||
result := createBooleanCandidate(candidate, !truthy)
|
||||
results.PushBack(result)
|
||||
}
|
||||
return results, nil
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
@ -6,21 +6,21 @@ import (
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func collectOperator(d *dataTreeNavigator, matchMap *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func collectOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("-- collectOperation")
|
||||
|
||||
if matchMap.Len() == 0 {
|
||||
if context.MatchingNodes.Len() == 0 {
|
||||
node := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq", Value: "[]"}
|
||||
candidate := &CandidateNode{Node: node}
|
||||
return nodeToMap(candidate), nil
|
||||
return context.SingleChildContext(candidate), nil
|
||||
}
|
||||
|
||||
var results = list.New()
|
||||
|
||||
node := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
|
||||
var collectC *CandidateNode
|
||||
if matchMap.Front() != nil {
|
||||
collectC = matchMap.Front().Value.(*CandidateNode).CreateChild(nil, node)
|
||||
if context.MatchingNodes.Front() != nil {
|
||||
collectC = context.MatchingNodes.Front().Value.(*CandidateNode).CreateChild(nil, node)
|
||||
if len(collectC.Path) > 0 {
|
||||
collectC.Path = collectC.Path[:len(collectC.Path)-1]
|
||||
}
|
||||
@ -28,7 +28,7 @@ func collectOperator(d *dataTreeNavigator, matchMap *list.List, expressionNode *
|
||||
collectC = &CandidateNode{Node: node}
|
||||
}
|
||||
|
||||
for el := matchMap.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
log.Debugf("Collecting %v", NodeToString(candidate))
|
||||
node.Content = append(node.Content, unwrapDoc(candidate.Node))
|
||||
@ -36,5 +36,5 @@ func collectOperator(d *dataTreeNavigator, matchMap *list.List, expressionNode *
|
||||
|
||||
results.PushBack(collectC)
|
||||
|
||||
return results, nil
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
@ -17,22 +17,22 @@ import (
|
||||
...
|
||||
*/
|
||||
|
||||
func collectObjectOperator(d *dataTreeNavigator, matchMap *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func collectObjectOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("-- collectObjectOperation")
|
||||
|
||||
if matchMap.Len() == 0 {
|
||||
if context.MatchingNodes.Len() == 0 {
|
||||
node := &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map", Value: "{}"}
|
||||
candidate := &CandidateNode{Node: node}
|
||||
return nodeToMap(candidate), nil
|
||||
return context.SingleChildContext(candidate), nil
|
||||
}
|
||||
first := matchMap.Front().Value.(*CandidateNode)
|
||||
first := context.MatchingNodes.Front().Value.(*CandidateNode)
|
||||
var rotated []*list.List = make([]*list.List, len(first.Node.Content))
|
||||
|
||||
for i := 0; i < len(first.Node.Content); i++ {
|
||||
rotated[i] = list.New()
|
||||
}
|
||||
|
||||
for el := matchMap.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidateNode := el.Value.(*CandidateNode)
|
||||
for i := 0; i < len(first.Node.Content); i++ {
|
||||
rotated[i].PushBack(candidateNode.CreateChild(i, candidateNode.Node.Content[i]))
|
||||
@ -41,59 +41,59 @@ func collectObjectOperator(d *dataTreeNavigator, matchMap *list.List, expression
|
||||
|
||||
newObject := list.New()
|
||||
for i := 0; i < len(first.Node.Content); i++ {
|
||||
additions, err := collect(d, list.New(), rotated[i])
|
||||
additions, err := collect(d, context.ChildContext(list.New()), rotated[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
newObject.PushBackList(additions)
|
||||
newObject.PushBackList(additions.MatchingNodes)
|
||||
}
|
||||
|
||||
return newObject, nil
|
||||
return context.ChildContext(newObject), nil
|
||||
|
||||
}
|
||||
|
||||
func collect(d *dataTreeNavigator, aggregate *list.List, remainingMatches *list.List) (*list.List, error) {
|
||||
func collect(d *dataTreeNavigator, context Context, remainingMatches *list.List) (Context, error) {
|
||||
if remainingMatches.Len() == 0 {
|
||||
return aggregate, nil
|
||||
return context, nil
|
||||
}
|
||||
|
||||
candidate := remainingMatches.Remove(remainingMatches.Front()).(*CandidateNode)
|
||||
|
||||
splatted, err := splat(d, nodeToMap(candidate),
|
||||
splatted, err := splat(d, context.SingleChildContext(candidate),
|
||||
traversePreferences{DontFollowAlias: true, IncludeMapKeys: false})
|
||||
|
||||
for splatEl := splatted.Front(); splatEl != nil; splatEl = splatEl.Next() {
|
||||
for splatEl := splatted.MatchingNodes.Front(); splatEl != nil; splatEl = splatEl.Next() {
|
||||
splatEl.Value.(*CandidateNode).Path = nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
if aggregate.Len() == 0 {
|
||||
if context.MatchingNodes.Len() == 0 {
|
||||
return collect(d, splatted, remainingMatches)
|
||||
}
|
||||
|
||||
newAgg := list.New()
|
||||
|
||||
for el := aggregate.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
aggCandidate := el.Value.(*CandidateNode)
|
||||
for splatEl := splatted.Front(); splatEl != nil; splatEl = splatEl.Next() {
|
||||
for splatEl := splatted.MatchingNodes.Front(); splatEl != nil; splatEl = splatEl.Next() {
|
||||
splatCandidate := splatEl.Value.(*CandidateNode)
|
||||
newCandidate, err := aggCandidate.Copy()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
newCandidate.Path = nil
|
||||
|
||||
newCandidate, err = multiply(multiplyPreferences{AppendArrays: false})(d, newCandidate, splatCandidate)
|
||||
newCandidate, err = multiply(multiplyPreferences{AppendArrays: false})(d, context, newCandidate, splatCandidate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
newAgg.PushBack(newCandidate)
|
||||
}
|
||||
}
|
||||
return collect(d, newAgg, remainingMatches)
|
||||
return collect(d, context.ChildContext(newAgg), remainingMatches)
|
||||
|
||||
}
|
||||
|
@ -13,41 +13,41 @@ type commentOpPreferences struct {
|
||||
FootComment bool
|
||||
}
|
||||
|
||||
func assignCommentsOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func assignCommentsOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
|
||||
log.Debugf("AssignComments operator!")
|
||||
|
||||
lhs, err := d.GetMatchingNodes(matchingNodes, expressionNode.Lhs)
|
||||
lhs, err := d.GetMatchingNodes(context, expressionNode.Lhs)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
preferences := expressionNode.Operation.Preferences.(commentOpPreferences)
|
||||
|
||||
comment := ""
|
||||
if !expressionNode.Operation.UpdateAssign {
|
||||
rhs, err := d.GetMatchingNodes(matchingNodes, expressionNode.Rhs)
|
||||
rhs, err := d.GetMatchingNodes(context, expressionNode.Rhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
if rhs.Front() != nil {
|
||||
comment = rhs.Front().Value.(*CandidateNode).Node.Value
|
||||
if rhs.MatchingNodes.Front() != nil {
|
||||
comment = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
|
||||
}
|
||||
}
|
||||
|
||||
for el := lhs.Front(); el != nil; el = el.Next() {
|
||||
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
|
||||
if expressionNode.Operation.UpdateAssign {
|
||||
rhs, err := d.GetMatchingNodes(nodeToMap(candidate), expressionNode.Rhs)
|
||||
rhs, err := d.GetMatchingNodes(context.SingleChildContext(candidate), expressionNode.Rhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
if rhs.Front() != nil {
|
||||
comment = rhs.Front().Value.(*CandidateNode).Node.Value
|
||||
if rhs.MatchingNodes.Front() != nil {
|
||||
comment = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,15 +63,15 @@ func assignCommentsOperator(d *dataTreeNavigator, matchingNodes *list.List, expr
|
||||
}
|
||||
|
||||
}
|
||||
return matchingNodes, nil
|
||||
return context, nil
|
||||
}
|
||||
|
||||
func getCommentsOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func getCommentsOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
preferences := expressionNode.Operation.Preferences.(commentOpPreferences)
|
||||
log.Debugf("GetComments operator!")
|
||||
var results = list.New()
|
||||
|
||||
for el := matchingNodes.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
comment := ""
|
||||
if preferences.LineComment {
|
||||
@ -87,5 +87,5 @@ func getCommentsOperator(d *dataTreeNavigator, matchingNodes *list.List, express
|
||||
result := candidate.CreateChild(nil, node)
|
||||
results.PushBack(result)
|
||||
}
|
||||
return results, nil
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func createMapOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func createMapOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("-- createMapOperation")
|
||||
|
||||
//each matchingNodes entry should turn into a sequence of keys to create.
|
||||
@ -18,29 +18,29 @@ func createMapOperator(d *dataTreeNavigator, matchingNodes *list.List, expressio
|
||||
|
||||
sequences := list.New()
|
||||
|
||||
if matchingNodes.Len() > 0 {
|
||||
if context.MatchingNodes.Len() > 0 {
|
||||
|
||||
for matchingNodeEl := matchingNodes.Front(); matchingNodeEl != nil; matchingNodeEl = matchingNodeEl.Next() {
|
||||
for matchingNodeEl := context.MatchingNodes.Front(); matchingNodeEl != nil; matchingNodeEl = matchingNodeEl.Next() {
|
||||
matchingNode := matchingNodeEl.Value.(*CandidateNode)
|
||||
sequenceNode, err := sequenceFor(d, matchingNode, expressionNode)
|
||||
sequenceNode, err := sequenceFor(d, context, matchingNode, expressionNode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
sequences.PushBack(sequenceNode)
|
||||
}
|
||||
} else {
|
||||
sequenceNode, err := sequenceFor(d, nil, expressionNode)
|
||||
sequenceNode, err := sequenceFor(d, context, nil, expressionNode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
sequences.PushBack(sequenceNode)
|
||||
}
|
||||
|
||||
return nodeToMap(&CandidateNode{Node: listToNodeSeq(sequences), Document: document, Path: path}), nil
|
||||
return context.SingleChildContext(&CandidateNode{Node: listToNodeSeq(sequences), Document: document, Path: path}), nil
|
||||
|
||||
}
|
||||
|
||||
func sequenceFor(d *dataTreeNavigator, matchingNode *CandidateNode, expressionNode *ExpressionNode) (*CandidateNode, error) {
|
||||
func sequenceFor(d *dataTreeNavigator, context Context, matchingNode *CandidateNode, expressionNode *ExpressionNode) (*CandidateNode, error) {
|
||||
var path []interface{}
|
||||
var document uint = 0
|
||||
var matches = list.New()
|
||||
@ -48,11 +48,11 @@ func sequenceFor(d *dataTreeNavigator, matchingNode *CandidateNode, expressionNo
|
||||
if matchingNode != nil {
|
||||
path = matchingNode.Path
|
||||
document = matchingNode.Document
|
||||
matches = nodeToMap(matchingNode)
|
||||
matches.PushBack(matchingNode)
|
||||
}
|
||||
|
||||
mapPairs, err := crossFunction(d, matches, expressionNode,
|
||||
func(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
mapPairs, err := crossFunction(d, context.ChildContext(matches), expressionNode,
|
||||
func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
node := yaml.Node{Kind: yaml.MappingNode, Tag: "!!map"}
|
||||
log.Debugf("LHS:", NodeToString(lhs))
|
||||
log.Debugf("RHS:", NodeToString(rhs))
|
||||
@ -67,7 +67,7 @@ func sequenceFor(d *dataTreeNavigator, matchingNode *CandidateNode, expressionNo
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
innerList := listToNodeSeq(mapPairs)
|
||||
innerList := listToNodeSeq(mapPairs.MatchingNodes)
|
||||
innerList.Style = yaml.FlowStyle
|
||||
return &CandidateNode{Node: innerList, Document: document, Path: path}, nil
|
||||
}
|
||||
|
@ -1,21 +1,20 @@
|
||||
package yqlib
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func deleteChildOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func deleteChildOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
|
||||
nodesToDelete, err := d.GetMatchingNodes(matchingNodes, expressionNode.Rhs)
|
||||
nodesToDelete, err := d.GetMatchingNodes(context, expressionNode.Rhs)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
for el := nodesToDelete.Front(); el != nil; el = el.Next() {
|
||||
for el := nodesToDelete.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
|
||||
deleteImmediateChildOp := &Operation{
|
||||
@ -28,26 +27,26 @@ func deleteChildOperator(d *dataTreeNavigator, matchingNodes *list.List, express
|
||||
Rhs: createTraversalTree(candidate.Path[0:len(candidate.Path)-1], traversePreferences{}),
|
||||
}
|
||||
|
||||
_, err := d.GetMatchingNodes(matchingNodes, deleteImmediateChildOpNode)
|
||||
_, err := d.GetMatchingNodes(context, deleteImmediateChildOpNode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
}
|
||||
return matchingNodes, nil
|
||||
return context, nil
|
||||
}
|
||||
|
||||
func deleteImmediateChildOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
parents, err := d.GetMatchingNodes(matchingNodes, expressionNode.Rhs)
|
||||
func deleteImmediateChildOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
parents, err := d.GetMatchingNodes(context, expressionNode.Rhs)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
childPath := expressionNode.Operation.Value
|
||||
|
||||
log.Debug("childPath to remove %v", childPath)
|
||||
|
||||
for el := parents.Front(); el != nil; el = el.Next() {
|
||||
for el := parents.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
parent := el.Value.(*CandidateNode)
|
||||
parentNode := unwrapDoc(parent.Node)
|
||||
if parentNode.Kind == yaml.MappingNode {
|
||||
@ -55,11 +54,11 @@ func deleteImmediateChildOperator(d *dataTreeNavigator, matchingNodes *list.List
|
||||
} else if parentNode.Kind == yaml.SequenceNode {
|
||||
deleteFromArray(parent, childPath)
|
||||
} else {
|
||||
return nil, fmt.Errorf("Cannot delete nodes from parent of tag %v", parentNode.Tag)
|
||||
return Context{}, fmt.Errorf("Cannot delete nodes from parent of tag %v", parentNode.Tag)
|
||||
}
|
||||
|
||||
}
|
||||
return matchingNodes, nil
|
||||
return context, nil
|
||||
}
|
||||
|
||||
func deleteFromMap(candidate *CandidateNode, childPath interface{}) {
|
||||
|
@ -7,14 +7,14 @@ import (
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func getDocumentIndexOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func getDocumentIndexOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
var results = list.New()
|
||||
|
||||
for el := matchingNodes.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
node := &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", candidate.Document), Tag: "!!int"}
|
||||
scalar := candidate.CreateChild(nil, node)
|
||||
results.PushBack(scalar)
|
||||
}
|
||||
return results, nil
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package yqlib
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
@ -13,7 +12,7 @@ type envOpPreferences struct {
|
||||
StringValue bool
|
||||
}
|
||||
|
||||
func envOperator(d *dataTreeNavigator, matchMap *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func envOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
envName := expressionNode.Operation.CandidateNode.Node.Value
|
||||
log.Debug("EnvOperator, env name:", envName)
|
||||
|
||||
@ -29,13 +28,13 @@ func envOperator(d *dataTreeNavigator, matchMap *list.List, expressionNode *Expr
|
||||
Value: rawValue,
|
||||
}
|
||||
} else if rawValue == "" {
|
||||
return nil, fmt.Errorf("Value for env variable '%v' not provided in env()", envName)
|
||||
return Context{}, fmt.Errorf("Value for env variable '%v' not provided in env()", envName)
|
||||
} else {
|
||||
var dataBucket yaml.Node
|
||||
decoder := yaml.NewDecoder(strings.NewReader(rawValue))
|
||||
errorReading := decoder.Decode(&dataBucket)
|
||||
if errorReading != nil {
|
||||
return nil, errorReading
|
||||
return Context{}, errorReading
|
||||
}
|
||||
//first node is a doc
|
||||
node = unwrapDoc(&dataBucket)
|
||||
@ -46,5 +45,5 @@ func envOperator(d *dataTreeNavigator, matchMap *list.List, expressionNode *Expr
|
||||
|
||||
target := &CandidateNode{Node: node}
|
||||
|
||||
return nodeToMap(target), nil
|
||||
return context.SingleChildContext(target), nil
|
||||
}
|
||||
|
@ -1,15 +1,11 @@
|
||||
package yqlib
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
)
|
||||
|
||||
func equalsOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func equalsOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("-- equalsOperation")
|
||||
return crossFunction(d, matchingNodes, expressionNode, isEquals)
|
||||
return crossFunction(d, context, expressionNode, isEquals)
|
||||
}
|
||||
|
||||
func isEquals(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
func isEquals(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
value := false
|
||||
|
||||
lhsNode := unwrapDoc(lhs.Node)
|
||||
|
@ -7,32 +7,32 @@ import (
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func getFilenameOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func getFilenameOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("GetFilename")
|
||||
|
||||
var results = list.New()
|
||||
|
||||
for el := matchingNodes.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
node := &yaml.Node{Kind: yaml.ScalarNode, Value: candidate.Filename, Tag: "!!str"}
|
||||
result := candidate.CreateChild(nil, node)
|
||||
results.PushBack(result)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
||||
func getFileIndexOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func getFileIndexOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("GetFileIndex")
|
||||
|
||||
var results = list.New()
|
||||
|
||||
for el := matchingNodes.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
node := &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", candidate.FileIndex), Tag: "!!int"}
|
||||
result := candidate.CreateChild(nil, node)
|
||||
results.PushBack(result)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
@ -7,20 +7,20 @@ import (
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func hasOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func hasOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
|
||||
log.Debugf("-- hasOperation")
|
||||
var results = list.New()
|
||||
|
||||
rhs, err := d.GetMatchingNodes(matchingNodes, expressionNode.Rhs)
|
||||
wanted := rhs.Front().Value.(*CandidateNode).Node
|
||||
rhs, err := d.GetMatchingNodes(context, expressionNode.Rhs)
|
||||
wanted := rhs.MatchingNodes.Front().Value.(*CandidateNode).Node
|
||||
wantedKey := wanted.Value
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
for el := matchingNodes.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
|
||||
// grab the first value
|
||||
@ -41,7 +41,7 @@ func hasOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode
|
||||
if wanted.Tag == "!!int" {
|
||||
var number, errParsingInt = strconv.ParseInt(wantedKey, 10, 64) // nolint
|
||||
if errParsingInt != nil {
|
||||
return nil, errParsingInt
|
||||
return Context{}, errParsingInt
|
||||
}
|
||||
candidateHasKey = int64(len(contents)) > number
|
||||
}
|
||||
@ -50,5 +50,5 @@ func hasOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode
|
||||
results.PushBack(createBooleanCandidate(candidate, false))
|
||||
}
|
||||
}
|
||||
return results, nil
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
@ -7,12 +7,12 @@ import (
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func keysOperator(d *dataTreeNavigator, matchMap *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func keysOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("-- keysOperator")
|
||||
|
||||
var results = list.New()
|
||||
|
||||
for el := matchMap.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
node := unwrapDoc(candidate.Node)
|
||||
var targetNode *yaml.Node
|
||||
@ -21,14 +21,14 @@ func keysOperator(d *dataTreeNavigator, matchMap *list.List, expressionNode *Exp
|
||||
} else if node.Kind == yaml.SequenceNode {
|
||||
targetNode = getIndicies(node)
|
||||
} else {
|
||||
return nil, fmt.Errorf("Cannot get keys of %v, keys only works for maps and arrays", node.Tag)
|
||||
return Context{}, fmt.Errorf("Cannot get keys of %v, keys only works for maps and arrays", node.Tag)
|
||||
}
|
||||
|
||||
result := candidate.CreateChild(nil, targetNode)
|
||||
results.PushBack(result)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
||||
func getMapKeys(node *yaml.Node) *yaml.Node {
|
||||
|
@ -7,11 +7,11 @@ import (
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func lengthOperator(d *dataTreeNavigator, matchMap *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func lengthOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("-- lengthOperation")
|
||||
var results = list.New()
|
||||
|
||||
for el := matchMap.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
targetNode := unwrapDoc(candidate.Node)
|
||||
var length int
|
||||
@ -35,5 +35,5 @@ func lengthOperator(d *dataTreeNavigator, matchMap *list.List, expressionNode *E
|
||||
results.PushBack(result)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
@ -9,77 +9,18 @@ import (
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type crossFunctionCalculation func(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error)
|
||||
|
||||
func doCrossFunc(d *dataTreeNavigator, contextList *list.List, expressionNode *ExpressionNode, calculation crossFunctionCalculation) (*list.List, error) {
|
||||
var results = list.New()
|
||||
lhs, err := d.GetMatchingNodes(contextList, expressionNode.Lhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Debugf("crossFunction LHS len: %v", lhs.Len())
|
||||
|
||||
rhs, err := d.GetMatchingNodes(contextList, expressionNode.Rhs)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for el := lhs.Front(); el != nil; el = el.Next() {
|
||||
lhsCandidate := el.Value.(*CandidateNode)
|
||||
|
||||
for rightEl := rhs.Front(); rightEl != nil; rightEl = rightEl.Next() {
|
||||
log.Debugf("Applying calc")
|
||||
rhsCandidate := rightEl.Value.(*CandidateNode)
|
||||
resultCandidate, err := calculation(d, lhsCandidate, rhsCandidate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
results.PushBack(resultCandidate)
|
||||
}
|
||||
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func crossFunction(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode, calculation crossFunctionCalculation) (*list.List, error) {
|
||||
var results = list.New()
|
||||
|
||||
var evaluateAllTogether = true
|
||||
for matchEl := matchingNodes.Front(); matchEl != nil; matchEl = matchEl.Next() {
|
||||
evaluateAllTogether = evaluateAllTogether && matchEl.Value.(*CandidateNode).EvaluateTogether
|
||||
if !evaluateAllTogether {
|
||||
break
|
||||
}
|
||||
}
|
||||
if evaluateAllTogether {
|
||||
return doCrossFunc(d, matchingNodes, expressionNode, calculation)
|
||||
}
|
||||
|
||||
for matchEl := matchingNodes.Front(); matchEl != nil; matchEl = matchEl.Next() {
|
||||
contextList := nodeToMap(matchEl.Value.(*CandidateNode))
|
||||
innerResults, err := doCrossFunc(d, contextList, expressionNode, calculation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
results.PushBackList(innerResults)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
type multiplyPreferences struct {
|
||||
AppendArrays bool
|
||||
TraversePrefs traversePreferences
|
||||
}
|
||||
|
||||
func multiplyOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func multiplyOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("-- MultiplyOperator")
|
||||
return crossFunction(d, matchingNodes, expressionNode, multiply(expressionNode.Operation.Preferences.(multiplyPreferences)))
|
||||
return crossFunction(d, context, expressionNode, multiply(expressionNode.Operation.Preferences.(multiplyPreferences)))
|
||||
}
|
||||
|
||||
func multiply(preferences multiplyPreferences) func(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
return func(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
func multiply(preferences multiplyPreferences) func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
return func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
lhs.Node = unwrapDoc(lhs.Node)
|
||||
rhs.Node = unwrapDoc(rhs.Node)
|
||||
log.Debugf("Multipling LHS: %v", lhs.Node.Tag)
|
||||
@ -89,11 +30,11 @@ func multiply(preferences multiplyPreferences) func(d *dataTreeNavigator, lhs *C
|
||||
(lhs.Node.Kind == yaml.SequenceNode && rhs.Node.Kind == yaml.SequenceNode) {
|
||||
|
||||
var newBlank = lhs.CreateChild(nil, &yaml.Node{})
|
||||
var newThing, err = mergeObjects(d, newBlank, lhs, multiplyPreferences{})
|
||||
var newThing, err = mergeObjects(d, context, newBlank, lhs, multiplyPreferences{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mergeObjects(d, newThing, rhs, preferences)
|
||||
return mergeObjects(d, context, newThing, rhs, preferences)
|
||||
} else if lhs.Node.Tag == "!!int" && rhs.Node.Tag == "!!int" {
|
||||
return multiplyIntegers(lhs, rhs)
|
||||
}
|
||||
@ -119,14 +60,14 @@ func multiplyIntegers(lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, e
|
||||
return target, nil
|
||||
}
|
||||
|
||||
func mergeObjects(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode, preferences multiplyPreferences) (*CandidateNode, error) {
|
||||
func mergeObjects(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode, preferences multiplyPreferences) (*CandidateNode, error) {
|
||||
shouldAppendArrays := preferences.AppendArrays
|
||||
var results = list.New()
|
||||
|
||||
// shouldn't recurse arrays if appending
|
||||
prefs := recursiveDescentPreferences{RecurseArray: !shouldAppendArrays,
|
||||
TraversePreferences: traversePreferences{DontFollowAlias: true}}
|
||||
err := recursiveDecent(d, results, nodeToMap(rhs), prefs)
|
||||
err := recursiveDecent(d, results, context.SingleChildContext(rhs), prefs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -137,7 +78,7 @@ func mergeObjects(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode,
|
||||
}
|
||||
|
||||
for el := results.Front(); el != nil; el = el.Next() {
|
||||
err := applyAssignment(d, pathIndexToStartFrom, lhs, el.Value.(*CandidateNode), preferences)
|
||||
err := applyAssignment(d, context, pathIndexToStartFrom, lhs, el.Value.(*CandidateNode), preferences)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -145,7 +86,7 @@ func mergeObjects(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode,
|
||||
return lhs, nil
|
||||
}
|
||||
|
||||
func applyAssignment(d *dataTreeNavigator, pathIndexToStartFrom int, lhs *CandidateNode, rhs *CandidateNode, preferences multiplyPreferences) error {
|
||||
func applyAssignment(d *dataTreeNavigator, context Context, pathIndexToStartFrom int, lhs *CandidateNode, rhs *CandidateNode, preferences multiplyPreferences) error {
|
||||
shouldAppendArrays := preferences.AppendArrays
|
||||
log.Debugf("merge - applyAssignment lhs %v, rhs: %v", NodeToString(lhs), NodeToString(rhs))
|
||||
|
||||
@ -162,7 +103,7 @@ func applyAssignment(d *dataTreeNavigator, pathIndexToStartFrom int, lhs *Candid
|
||||
|
||||
assignmentOpNode := &ExpressionNode{Operation: assignmentOp, Lhs: createTraversalTree(lhsPath, preferences.TraversePrefs), Rhs: &ExpressionNode{Operation: rhsOp}}
|
||||
|
||||
_, err := d.GetMatchingNodes(nodeToMap(lhs), assignmentOpNode)
|
||||
_, err := d.GetMatchingNodes(context.SingleChildContext(lhs), assignmentOpNode)
|
||||
|
||||
return err
|
||||
}
|
||||
|
@ -16,12 +16,12 @@ func createPathNodeFor(pathElement interface{}) *yaml.Node {
|
||||
}
|
||||
}
|
||||
|
||||
func getPathOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func getPathOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("GetPath")
|
||||
|
||||
var results = list.New()
|
||||
|
||||
for el := matchingNodes.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
node := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
|
||||
|
||||
@ -35,5 +35,5 @@ func getPathOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionN
|
||||
results.PushBack(result)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
@ -1,11 +1,18 @@
|
||||
package yqlib
|
||||
|
||||
import "container/list"
|
||||
func pipeOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
|
||||
func pipeOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
lhs, err := d.GetMatchingNodes(matchingNodes, expressionNode.Lhs)
|
||||
//lhs may update the variable context, we should pass that into the RHS
|
||||
// BUT we still return the original context back (see jq)
|
||||
// https://stedolan.github.io/jq/manual/#Variable/SymbolicBindingOperator:...as$identifier|...
|
||||
|
||||
lhs, err := d.GetMatchingNodes(context, expressionNode.Lhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
return d.GetMatchingNodes(lhs, expressionNode.Rhs)
|
||||
rhs, err := d.GetMatchingNodes(lhs, expressionNode.Rhs)
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
return context.ChildContext(rhs.MatchingNodes), nil
|
||||
}
|
||||
|
@ -11,20 +11,20 @@ type recursiveDescentPreferences struct {
|
||||
RecurseArray bool
|
||||
}
|
||||
|
||||
func recursiveDescentOperator(d *dataTreeNavigator, matchMap *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func recursiveDescentOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
var results = list.New()
|
||||
|
||||
preferences := expressionNode.Operation.Preferences.(recursiveDescentPreferences)
|
||||
err := recursiveDecent(d, results, matchMap, preferences)
|
||||
err := recursiveDecent(d, results, context, preferences)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
return results, nil
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
||||
func recursiveDecent(d *dataTreeNavigator, results *list.List, matchMap *list.List, preferences recursiveDescentPreferences) error {
|
||||
for el := matchMap.Front(); el != nil; el = el.Next() {
|
||||
func recursiveDecent(d *dataTreeNavigator, results *list.List, context Context, preferences recursiveDescentPreferences) error {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
|
||||
candidate.Node = unwrapDoc(candidate.Node)
|
||||
@ -35,7 +35,7 @@ func recursiveDecent(d *dataTreeNavigator, results *list.List, matchMap *list.Li
|
||||
if candidate.Node.Kind != yaml.AliasNode && len(candidate.Node.Content) > 0 &&
|
||||
(preferences.RecurseArray || candidate.Node.Kind != yaml.SequenceNode) {
|
||||
|
||||
children, err := splat(d, nodeToMap(candidate), preferences.TraversePreferences)
|
||||
children, err := splat(d, context.SingleChildContext(candidate), preferences.TraversePreferences)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -4,28 +4,28 @@ import (
|
||||
"container/list"
|
||||
)
|
||||
|
||||
func selectOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func selectOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
|
||||
log.Debugf("-- selectOperation")
|
||||
var results = list.New()
|
||||
|
||||
for el := matchingNodes.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
|
||||
rhs, err := d.GetMatchingNodes(nodeToMap(candidate), expressionNode.Rhs)
|
||||
rhs, err := d.GetMatchingNodes(context.SingleChildContext(candidate), expressionNode.Rhs)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
// grab the first value
|
||||
first := rhs.Front()
|
||||
first := rhs.MatchingNodes.Front()
|
||||
|
||||
if first != nil {
|
||||
result := first.Value.(*CandidateNode)
|
||||
includeResult, errDecoding := isTruthy(result)
|
||||
if errDecoding != nil {
|
||||
return nil, errDecoding
|
||||
return Context{}, errDecoding
|
||||
}
|
||||
|
||||
if includeResult {
|
||||
@ -33,5 +33,5 @@ func selectOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNo
|
||||
}
|
||||
}
|
||||
}
|
||||
return results, nil
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
package yqlib
|
||||
|
||||
import "container/list"
|
||||
|
||||
func selfOperator(d *dataTreeNavigator, matchMap *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
return matchMap, nil
|
||||
func selfOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
return context, nil
|
||||
}
|
||||
|
@ -1,33 +1,32 @@
|
||||
package yqlib
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
"sort"
|
||||
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func sortKeysOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func sortKeysOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
|
||||
for el := matchingNodes.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
rhs, err := d.GetMatchingNodes(nodeToMap(candidate), expressionNode.Rhs)
|
||||
rhs, err := d.GetMatchingNodes(context.SingleChildContext(candidate), expressionNode.Rhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
for childEl := rhs.Front(); childEl != nil; childEl = childEl.Next() {
|
||||
for childEl := rhs.MatchingNodes.Front(); childEl != nil; childEl = childEl.Next() {
|
||||
node := unwrapDoc(childEl.Value.(*CandidateNode).Node)
|
||||
if node.Kind == yaml.MappingNode {
|
||||
sortKeys(node)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return matchingNodes, nil
|
||||
return context, nil
|
||||
}
|
||||
|
||||
func sortKeys(node *yaml.Node) {
|
||||
|
@ -1,18 +1,14 @@
|
||||
package yqlib
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
)
|
||||
|
||||
func splitDocumentOperator(d *dataTreeNavigator, matchMap *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func splitDocumentOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("-- splitDocumentOperator")
|
||||
|
||||
var index uint = 0
|
||||
for el := matchMap.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
candidate.Document = index
|
||||
index = index + 1
|
||||
}
|
||||
|
||||
return matchMap, nil
|
||||
return context, nil
|
||||
}
|
||||
|
@ -8,32 +8,32 @@ import (
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func joinStringOperator(d *dataTreeNavigator, matchMap *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func joinStringOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("-- joinStringOperator")
|
||||
joinStr := ""
|
||||
|
||||
rhs, err := d.GetMatchingNodes(matchMap, expressionNode.Rhs)
|
||||
rhs, err := d.GetMatchingNodes(context, expressionNode.Rhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
if rhs.Front() != nil {
|
||||
joinStr = rhs.Front().Value.(*CandidateNode).Node.Value
|
||||
if rhs.MatchingNodes.Front() != nil {
|
||||
joinStr = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
|
||||
}
|
||||
|
||||
var results = list.New()
|
||||
|
||||
for el := matchMap.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
node := unwrapDoc(candidate.Node)
|
||||
if node.Kind != yaml.SequenceNode {
|
||||
return nil, fmt.Errorf("Cannot join with %v, can only join arrays of scalars", node.Tag)
|
||||
return Context{}, fmt.Errorf("Cannot join with %v, can only join arrays of scalars", node.Tag)
|
||||
}
|
||||
targetNode := join(node.Content, joinStr)
|
||||
result := candidate.CreateChild(nil, targetNode)
|
||||
results.PushBack(result)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
||||
func join(content []*yaml.Node, joinStr string) *yaml.Node {
|
||||
@ -49,35 +49,35 @@ func join(content []*yaml.Node, joinStr string) *yaml.Node {
|
||||
return &yaml.Node{Kind: yaml.ScalarNode, Value: strings.Join(stringsToJoin, joinStr), Tag: "!!str"}
|
||||
}
|
||||
|
||||
func splitStringOperator(d *dataTreeNavigator, matchMap *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func splitStringOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("-- splitStringOperator")
|
||||
splitStr := ""
|
||||
|
||||
rhs, err := d.GetMatchingNodes(matchMap, expressionNode.Rhs)
|
||||
rhs, err := d.GetMatchingNodes(context, expressionNode.Rhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
if rhs.Front() != nil {
|
||||
splitStr = rhs.Front().Value.(*CandidateNode).Node.Value
|
||||
if rhs.MatchingNodes.Front() != nil {
|
||||
splitStr = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
|
||||
}
|
||||
|
||||
var results = list.New()
|
||||
|
||||
for el := matchMap.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
node := unwrapDoc(candidate.Node)
|
||||
if node.Tag == "!!null" {
|
||||
continue
|
||||
}
|
||||
if node.Tag != "!!str" {
|
||||
return nil, fmt.Errorf("Cannot split %v, can only split strings", node.Tag)
|
||||
return Context{}, fmt.Errorf("Cannot split %v, can only split strings", node.Tag)
|
||||
}
|
||||
targetNode := split(node.Value, splitStr)
|
||||
result := candidate.CreateChild(nil, targetNode)
|
||||
results.PushBack(result)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
||||
func split(value string, spltStr string) *yaml.Node {
|
||||
|
@ -26,43 +26,43 @@ func parseStyle(customStyle string) (yaml.Style, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func assignStyleOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func assignStyleOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
|
||||
log.Debugf("AssignStyleOperator: %v")
|
||||
var style yaml.Style
|
||||
if !expressionNode.Operation.UpdateAssign {
|
||||
rhs, err := d.GetMatchingNodes(matchingNodes, expressionNode.Rhs)
|
||||
rhs, err := d.GetMatchingNodes(context, expressionNode.Rhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
if rhs.Front() != nil {
|
||||
style, err = parseStyle(rhs.Front().Value.(*CandidateNode).Node.Value)
|
||||
if rhs.MatchingNodes.Front() != nil {
|
||||
style, err = parseStyle(rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lhs, err := d.GetMatchingNodes(matchingNodes, expressionNode.Lhs)
|
||||
lhs, err := d.GetMatchingNodes(context, expressionNode.Lhs)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
for el := lhs.Front(); el != nil; el = el.Next() {
|
||||
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
log.Debugf("Setting style of : %v", candidate.GetKey())
|
||||
if expressionNode.Operation.UpdateAssign {
|
||||
rhs, err := d.GetMatchingNodes(nodeToMap(candidate), expressionNode.Rhs)
|
||||
rhs, err := d.GetMatchingNodes(context.SingleChildContext(candidate), expressionNode.Rhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
if rhs.Front() != nil {
|
||||
style, err = parseStyle(rhs.Front().Value.(*CandidateNode).Node.Value)
|
||||
if rhs.MatchingNodes.Front() != nil {
|
||||
style, err = parseStyle(rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -70,15 +70,15 @@ func assignStyleOperator(d *dataTreeNavigator, matchingNodes *list.List, express
|
||||
candidate.Node.Style = style
|
||||
}
|
||||
|
||||
return matchingNodes, nil
|
||||
return context, nil
|
||||
}
|
||||
|
||||
func getStyleOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func getStyleOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("GetStyleOperator")
|
||||
|
||||
var results = list.New()
|
||||
|
||||
for el := matchingNodes.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
var style string
|
||||
switch candidate.Node.Style {
|
||||
@ -104,5 +104,5 @@ func getStyleOperator(d *dataTreeNavigator, matchingNodes *list.List, expression
|
||||
results.PushBack(result)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
@ -6,58 +6,58 @@ import (
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func assignTagOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func assignTagOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
|
||||
log.Debugf("AssignTagOperator: %v")
|
||||
tag := ""
|
||||
|
||||
if !expressionNode.Operation.UpdateAssign {
|
||||
rhs, err := d.GetMatchingNodes(matchingNodes, expressionNode.Rhs)
|
||||
rhs, err := d.GetMatchingNodes(context, expressionNode.Rhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
if rhs.Front() != nil {
|
||||
tag = rhs.Front().Value.(*CandidateNode).Node.Value
|
||||
if rhs.MatchingNodes.Front() != nil {
|
||||
tag = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
|
||||
}
|
||||
}
|
||||
|
||||
lhs, err := d.GetMatchingNodes(matchingNodes, expressionNode.Lhs)
|
||||
lhs, err := d.GetMatchingNodes(context, expressionNode.Lhs)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
for el := lhs.Front(); el != nil; el = el.Next() {
|
||||
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
log.Debugf("Setting tag of : %v", candidate.GetKey())
|
||||
if expressionNode.Operation.UpdateAssign {
|
||||
rhs, err := d.GetMatchingNodes(nodeToMap(candidate), expressionNode.Rhs)
|
||||
rhs, err := d.GetMatchingNodes(context.SingleChildContext(candidate), expressionNode.Rhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
if rhs.Front() != nil {
|
||||
tag = rhs.Front().Value.(*CandidateNode).Node.Value
|
||||
if rhs.MatchingNodes.Front() != nil {
|
||||
tag = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
|
||||
}
|
||||
}
|
||||
unwrapDoc(candidate.Node).Tag = tag
|
||||
}
|
||||
|
||||
return matchingNodes, nil
|
||||
return context, nil
|
||||
}
|
||||
|
||||
func getTagOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func getTagOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("GetTagOperator")
|
||||
|
||||
var results = list.New()
|
||||
|
||||
for el := matchingNodes.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
node := &yaml.Node{Kind: yaml.ScalarNode, Value: unwrapDoc(candidate.Node).Tag, Tag: "!!str"}
|
||||
result := candidate.CreateChild(nil, node)
|
||||
results.PushBack(result)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
@ -15,23 +15,23 @@ type traversePreferences struct {
|
||||
DontAutoCreate bool // by default, we automatically create entries on the fly.
|
||||
}
|
||||
|
||||
func splat(d *dataTreeNavigator, matches *list.List, prefs traversePreferences) (*list.List, error) {
|
||||
return traverseNodesWithArrayIndices(matches, make([]*yaml.Node, 0), prefs)
|
||||
func splat(d *dataTreeNavigator, context Context, prefs traversePreferences) (Context, error) {
|
||||
return traverseNodesWithArrayIndices(context, make([]*yaml.Node, 0), prefs)
|
||||
}
|
||||
|
||||
func traversePathOperator(d *dataTreeNavigator, matchMap *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func traversePathOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("-- Traversing")
|
||||
var matchingNodeMap = list.New()
|
||||
var matches = list.New()
|
||||
|
||||
for el := matchMap.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
newNodes, err := traverse(d, el.Value.(*CandidateNode), expressionNode.Operation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
matchingNodeMap.PushBackList(newNodes)
|
||||
matches.PushBackList(newNodes)
|
||||
}
|
||||
|
||||
return matchingNodeMap, nil
|
||||
return context.ChildContext(matches), nil
|
||||
}
|
||||
|
||||
func traverse(d *dataTreeNavigator, matchingNode *CandidateNode, operation *Operation) (*list.List, error) {
|
||||
@ -74,30 +74,30 @@ func traverse(d *dataTreeNavigator, matchingNode *CandidateNode, operation *Oper
|
||||
}
|
||||
}
|
||||
|
||||
func traverseArrayOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func traverseArrayOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
// rhs is a collect expression that will yield indexes to retreive of the arrays
|
||||
|
||||
rhs, err := d.GetMatchingNodes(matchingNodes, expressionNode.Rhs)
|
||||
rhs, err := d.GetMatchingNodes(context, expressionNode.Rhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
var indicesToTraverse = rhs.Front().Value.(*CandidateNode).Node.Content
|
||||
return traverseNodesWithArrayIndices(matchingNodes, indicesToTraverse, traversePreferences{})
|
||||
var indicesToTraverse = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Content
|
||||
return traverseNodesWithArrayIndices(context, indicesToTraverse, traversePreferences{})
|
||||
}
|
||||
|
||||
func traverseNodesWithArrayIndices(matchingNodes *list.List, indicesToTraverse []*yaml.Node, prefs traversePreferences) (*list.List, error) {
|
||||
func traverseNodesWithArrayIndices(context Context, indicesToTraverse []*yaml.Node, prefs traversePreferences) (Context, error) {
|
||||
var matchingNodeMap = list.New()
|
||||
for el := matchingNodes.Front(); el != nil; el = el.Next() {
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
newNodes, err := traverseArrayIndices(candidate, indicesToTraverse, prefs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
matchingNodeMap.PushBackList(newNodes)
|
||||
}
|
||||
|
||||
return matchingNodeMap, nil
|
||||
return context.ChildContext(matchingNodeMap), nil
|
||||
}
|
||||
|
||||
func traverseArrayIndices(matchingNode *CandidateNode, indicesToTraverse []*yaml.Node, prefs traversePreferences) (*list.List, error) { // call this if doc / alias like the other traverse
|
||||
|
@ -1,19 +1,17 @@
|
||||
package yqlib
|
||||
|
||||
import "container/list"
|
||||
|
||||
func unionOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
lhs, err := d.GetMatchingNodes(matchingNodes, expressionNode.Lhs)
|
||||
func unionOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
lhs, err := d.GetMatchingNodes(context, expressionNode.Lhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
rhs, err := d.GetMatchingNodes(matchingNodes, expressionNode.Rhs)
|
||||
rhs, err := d.GetMatchingNodes(context, expressionNode.Rhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Context{}, err
|
||||
}
|
||||
for el := rhs.Front(); el != nil; el = el.Next() {
|
||||
for el := rhs.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
node := el.Value.(*CandidateNode)
|
||||
lhs.PushBack(node)
|
||||
lhs.MatchingNodes.PushBack(node)
|
||||
}
|
||||
return lhs, nil
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
package yqlib
|
||||
|
||||
import "container/list"
|
||||
|
||||
func valueOperator(d *dataTreeNavigator, matchMap *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
func valueOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debug("value = %v", expressionNode.Operation.CandidateNode.Node.Value)
|
||||
return nodeToMap(expressionNode.Operation.CandidateNode), nil
|
||||
return context.SingleChildContext(expressionNode.Operation.CandidateNode), nil
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type operatorHandler func(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error)
|
||||
type operatorHandler func(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error)
|
||||
|
||||
func unwrapDoc(node *yaml.Node) *yaml.Node {
|
||||
if node.Kind == yaml.DocumentNode {
|
||||
@ -16,8 +16,67 @@ func unwrapDoc(node *yaml.Node) *yaml.Node {
|
||||
return node
|
||||
}
|
||||
|
||||
func emptyOperator(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode) (*list.List, error) {
|
||||
return list.New(), nil
|
||||
func emptyOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
context.MatchingNodes = list.New()
|
||||
return context, nil
|
||||
}
|
||||
|
||||
type crossFunctionCalculation func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error)
|
||||
|
||||
func doCrossFunc(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode, calculation crossFunctionCalculation) (Context, error) {
|
||||
var results = list.New()
|
||||
lhs, err := d.GetMatchingNodes(context, expressionNode.Lhs)
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
log.Debugf("crossFunction LHS len: %v", lhs.MatchingNodes.Len())
|
||||
|
||||
rhs, err := d.GetMatchingNodes(context, expressionNode.Rhs)
|
||||
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
lhsCandidate := el.Value.(*CandidateNode)
|
||||
|
||||
for rightEl := rhs.MatchingNodes.Front(); rightEl != nil; rightEl = rightEl.Next() {
|
||||
log.Debugf("Applying calc")
|
||||
rhsCandidate := rightEl.Value.(*CandidateNode)
|
||||
resultCandidate, err := calculation(d, context, lhsCandidate, rhsCandidate)
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
results.PushBack(resultCandidate)
|
||||
}
|
||||
|
||||
}
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
||||
func crossFunction(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode, calculation crossFunctionCalculation) (Context, error) {
|
||||
var results = list.New()
|
||||
|
||||
var evaluateAllTogether = true
|
||||
for matchEl := context.MatchingNodes.Front(); matchEl != nil; matchEl = matchEl.Next() {
|
||||
evaluateAllTogether = evaluateAllTogether && matchEl.Value.(*CandidateNode).EvaluateTogether
|
||||
if !evaluateAllTogether {
|
||||
break
|
||||
}
|
||||
}
|
||||
if evaluateAllTogether {
|
||||
return doCrossFunc(d, context, expressionNode, calculation)
|
||||
}
|
||||
|
||||
for matchEl := context.MatchingNodes.Front(); matchEl != nil; matchEl = matchEl.Next() {
|
||||
innerResults, err := doCrossFunc(d, context.SingleChildContext(matchEl.Value.(*CandidateNode)), expressionNode, calculation)
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
results.PushBackList(innerResults.MatchingNodes)
|
||||
}
|
||||
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
||||
func createBooleanCandidate(owner *CandidateNode, value bool) *CandidateNode {
|
||||
@ -29,12 +88,6 @@ func createBooleanCandidate(owner *CandidateNode, value bool) *CandidateNode {
|
||||
return owner.CreateChild(nil, node)
|
||||
}
|
||||
|
||||
func nodeToMap(candidate *CandidateNode) *list.List {
|
||||
elMap := list.New()
|
||||
elMap.PushBack(candidate)
|
||||
return elMap
|
||||
}
|
||||
|
||||
func createTraversalTree(path []interface{}, traversePrefs traversePreferences) *ExpressionNode {
|
||||
if len(path) == 0 {
|
||||
return &ExpressionNode{Operation: &Operation{OperationType: selfReferenceOpType}}
|
||||
|
@ -27,7 +27,6 @@ type expressionScenario struct {
|
||||
}
|
||||
|
||||
func testScenario(t *testing.T, s *expressionScenario) {
|
||||
var results *list.List
|
||||
var err error
|
||||
|
||||
node, err := NewExpressionParser().ParseExpression(s.expression)
|
||||
@ -66,13 +65,13 @@ func testScenario(t *testing.T, s *expressionScenario) {
|
||||
os.Setenv("myenv", s.environmentVariable)
|
||||
}
|
||||
|
||||
results, err = NewDataTreeNavigator().GetMatchingNodes(inputs, node)
|
||||
context, err := NewDataTreeNavigator().GetMatchingNodes(Context{MatchingNodes: inputs}, node)
|
||||
|
||||
if err != nil {
|
||||
t.Error(fmt.Errorf("%v: %v", err, s.expression))
|
||||
return
|
||||
}
|
||||
test.AssertResultComplexWithContext(t, s.expected, resultsToString(results), fmt.Sprintf("exp: %v\ndoc: %v", s.expression, s.document))
|
||||
test.AssertResultComplexWithContext(t, s.expected, resultsToString(context.MatchingNodes), fmt.Sprintf("exp: %v\ndoc: %v", s.expression, s.document))
|
||||
}
|
||||
|
||||
func resultsToString(results *list.List) []string {
|
||||
@ -252,12 +251,12 @@ func documentOutput(t *testing.T, w *bufio.Writer, s expressionScenario, formatt
|
||||
|
||||
}
|
||||
|
||||
results, err := NewDataTreeNavigator().GetMatchingNodes(inputs, node)
|
||||
context, err := NewDataTreeNavigator().GetMatchingNodes(Context{MatchingNodes: inputs}, node)
|
||||
if err != nil {
|
||||
t.Error(err, s.expression)
|
||||
}
|
||||
|
||||
err = printer.PrintResults(results)
|
||||
err = printer.PrintResults(context.MatchingNodes)
|
||||
if err != nil {
|
||||
t.Error(err, s.expression)
|
||||
}
|
||||
|
@ -74,14 +74,14 @@ func (p *resultsPrinter) safelyFlush(writer *bufio.Writer) {
|
||||
|
||||
func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error {
|
||||
log.Debug("PrintResults for %v matches", matchingNodes.Len())
|
||||
var err error
|
||||
if p.outputToJSON {
|
||||
explodeOp := Operation{OperationType: explodeOpType}
|
||||
explodeNode := ExpressionNode{Operation: &explodeOp}
|
||||
matchingNodes, err = p.treeNavigator.GetMatchingNodes(matchingNodes, &explodeNode)
|
||||
context, err := p.treeNavigator.GetMatchingNodes(Context{MatchingNodes: matchingNodes}, &explodeNode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
matchingNodes = context.MatchingNodes
|
||||
}
|
||||
|
||||
bufferedWriter := bufio.NewWriter(p.writer)
|
||||
|
@ -3,6 +3,7 @@ package yqlib
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"container/list"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@ -16,6 +17,12 @@ a: apple
|
||||
a: coconut
|
||||
`
|
||||
|
||||
func nodeToList(candidate *CandidateNode) *list.List {
|
||||
elMap := list.New()
|
||||
elMap.PushBack(candidate)
|
||||
return elMap
|
||||
}
|
||||
|
||||
func TestPrinterMultipleDocsInSequence(t *testing.T) {
|
||||
var output bytes.Buffer
|
||||
var writer = bufio.NewWriter(&output)
|
||||
@ -27,13 +34,13 @@ func TestPrinterMultipleDocsInSequence(t *testing.T) {
|
||||
}
|
||||
|
||||
el := inputs.Front()
|
||||
sample1 := nodeToMap(el.Value.(*CandidateNode))
|
||||
sample1 := nodeToList(el.Value.(*CandidateNode))
|
||||
|
||||
el = el.Next()
|
||||
sample2 := nodeToMap(el.Value.(*CandidateNode))
|
||||
sample2 := nodeToList(el.Value.(*CandidateNode))
|
||||
|
||||
el = el.Next()
|
||||
sample3 := nodeToMap(el.Value.(*CandidateNode))
|
||||
sample3 := nodeToList(el.Value.(*CandidateNode))
|
||||
|
||||
err = printer.PrintResults(sample1)
|
||||
if err != nil {
|
||||
@ -68,19 +75,19 @@ func TestPrinterMultipleFilesInSequence(t *testing.T) {
|
||||
elNode := el.Value.(*CandidateNode)
|
||||
elNode.Document = 0
|
||||
elNode.FileIndex = 0
|
||||
sample1 := nodeToMap(elNode)
|
||||
sample1 := nodeToList(elNode)
|
||||
|
||||
el = el.Next()
|
||||
elNode = el.Value.(*CandidateNode)
|
||||
elNode.Document = 0
|
||||
elNode.FileIndex = 1
|
||||
sample2 := nodeToMap(elNode)
|
||||
sample2 := nodeToList(elNode)
|
||||
|
||||
el = el.Next()
|
||||
elNode = el.Value.(*CandidateNode)
|
||||
elNode.Document = 0
|
||||
elNode.FileIndex = 2
|
||||
sample3 := nodeToMap(elNode)
|
||||
sample3 := nodeToList(elNode)
|
||||
|
||||
err = printer.PrintResults(sample1)
|
||||
if err != nil {
|
||||
|
@ -41,11 +41,11 @@ func (s *streamEvaluator) EvaluateNew(expression string, printer Printer) error
|
||||
inputList := list.New()
|
||||
inputList.PushBack(candidateNode)
|
||||
|
||||
matches, errorParsing := s.treeNavigator.GetMatchingNodes(inputList, node)
|
||||
result, errorParsing := s.treeNavigator.GetMatchingNodes(Context{MatchingNodes: inputList}, node)
|
||||
if errorParsing != nil {
|
||||
return errorParsing
|
||||
}
|
||||
return printer.PrintResults(matches)
|
||||
return printer.PrintResults(result.MatchingNodes)
|
||||
}
|
||||
|
||||
func (s *streamEvaluator) EvaluateFiles(expression string, filenames []string, printer Printer) error {
|
||||
@ -97,11 +97,11 @@ func (s *streamEvaluator) Evaluate(filename string, reader io.Reader, node *Expr
|
||||
inputList := list.New()
|
||||
inputList.PushBack(candidateNode)
|
||||
|
||||
matches, errorParsing := s.treeNavigator.GetMatchingNodes(inputList, node)
|
||||
result, errorParsing := s.treeNavigator.GetMatchingNodes(Context{MatchingNodes: inputList}, node)
|
||||
if errorParsing != nil {
|
||||
return errorParsing
|
||||
}
|
||||
err := printer.PrintResults(matches)
|
||||
err := printer.PrintResults(result.MatchingNodes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user