diff --git a/pkg/yqlib/candidate_node.go b/pkg/yqlib/candidate_node.go index 6f698c41..28f9635f 100644 --- a/pkg/yqlib/candidate_node.go +++ b/pkg/yqlib/candidate_node.go @@ -94,13 +94,17 @@ type CandidateNode struct { IsMapKey bool } -// func (n *CandidateNode) GetKey() string { -// keyPrefix := "" -// if n.IsMapKey { -// keyPrefix = "key-" -// } -// return fmt.Sprintf("%v%v - %v", keyPrefix, n.Document, n.Path) -// } +func (n *CandidateNode) GetKey() string { + keyPrefix := "" + if n.IsMapKey { + keyPrefix = "key-" + } + key := "" + if n.Key != nil { + key = n.Key.Value + } + return fmt.Sprintf("%v%v - %v", keyPrefix, n.Document, key) +} func (n *CandidateNode) unwrapDocument() *CandidateNode { if n.Kind == DocumentNode { @@ -196,29 +200,25 @@ func (n *CandidateNode) guessTagFromCustomType() string { // } // } -// func (n *CandidateNode) CreateChildInArray(index int) *CandidateNode { -// return &CandidateNode{ -// Path: n.createChildPath(index), -// Parent: n, -// Key: createIntegerScalarNode(index), -// Document: n.Document, -// Filename: n.Filename, -// FileIndex: n.FileIndex, -// } -// } - func (n *CandidateNode) CreateReplacement(kind Kind, tag string, value string) *CandidateNode { - return &CandidateNode{ - Parent: n.Parent, - Key: n.Key, - IsMapKey: n.IsMapKey, - Document: n.Document, - Filename: n.Filename, - FileIndex: n.FileIndex, - Kind: kind, - Tag: tag, - Value: value, + node := &CandidateNode{ + Kind: kind, + Tag: tag, + Value: value, } + n.CopyAsReplacement(node) + return node +} + +func (n *CandidateNode) CopyAsReplacement(replacement *CandidateNode) *CandidateNode { + copy := replacement.Copy() + copy.Parent = n.Parent + copy.Key = n.Key + copy.IsMapKey = n.IsMapKey + copy.Document = n.Document + copy.Filename = n.Filename + copy.FileIndex = n.FileIndex + return copy } func (n *CandidateNode) CreateReplacementWithDocWrappers(kind Kind, tag string, style Style) *CandidateNode { diff --git a/pkg/yqlib/lib.go b/pkg/yqlib/lib.go index 1e0f7733..b488725f 100644 --- a/pkg/yqlib/lib.go +++ b/pkg/yqlib/lib.go @@ -462,7 +462,7 @@ func NodeToString(node *CandidateNode) string { } else if node.Kind == AliasNode { tag = "alias" } - return fmt.Sprintf(`D%v, P%v, (%v)::%v`, node.Document, node.Path, tag, buf.String()) + return fmt.Sprintf(`D%v, P%v, (%v)::%v`, node.Document, node.GetNicePath(), tag, buf.String()) } func KindString(kind yaml.Kind) string { diff --git a/pkg/yqlib/operator_add.go b/pkg/yqlib/operator_add.go index d201f717..17e16a1b 100644 --- a/pkg/yqlib/operator_add.go +++ b/pkg/yqlib/operator_add.go @@ -48,10 +48,10 @@ func add(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *Candida lhsNode := lhs if lhsNode.Tag == "!!null" { - return lhs.CreateReplacement(rhs), nil + return lhs.CopyAsReplacement(rhs), nil } - target := lhs.CreateReplacement(&yaml{ + target := lhs.CopyAsReplacement(&CandidateNode{ Anchor: lhs.Anchor, }) diff --git a/pkg/yqlib/operator_collect_object.go b/pkg/yqlib/operator_collect_object.go index 0c4bb1a0..d767f7d7 100644 --- a/pkg/yqlib/operator_collect_object.go +++ b/pkg/yqlib/operator_collect_object.go @@ -35,7 +35,7 @@ func collectObjectOperator(d *dataTreeNavigator, originalContext Context, expres candidateNode := el.Value.(*CandidateNode) for i := 0; i < len(first.Content); i++ { - rotated[i].PushBack(candidateNode.CreateChildInArray(i, candidateNode.Content[i])) + rotated[i].PushBack(candidateNode.Content[i]) } } @@ -62,10 +62,6 @@ func collect(d *dataTreeNavigator, context Context, remainingMatches *list.List) splatted, err := splat(context.SingleChildContext(candidate), traversePreferences{DontFollowAlias: true, IncludeMapKeys: false}) - for splatEl := splatted.MatchingNodes.Front(); splatEl != nil; splatEl = splatEl.Next() { - splatEl.Value.(*CandidateNode).Path = nil - } - if err != nil { return Context{}, err } @@ -82,8 +78,6 @@ func collect(d *dataTreeNavigator, context Context, remainingMatches *list.List) splatCandidate := splatEl.Value.(*CandidateNode) newCandidate := aggCandidate.Copy() - newCandidate.Path = nil - newCandidate, err = multiply(multiplyPreferences{AppendArrays: false})(d, context, newCandidate, splatCandidate) if err != nil { return Context{}, err diff --git a/pkg/yqlib/operator_compare.go b/pkg/yqlib/operator_compare.go index b017bdc4..6311a8d5 100644 --- a/pkg/yqlib/operator_compare.go +++ b/pkg/yqlib/operator_compare.go @@ -40,9 +40,9 @@ func compare(prefs compareTypePref) func(d *dataTreeNavigator, context Context, return nil, fmt.Errorf("arrays not yet supported for comparison") default: if rhsU.Kind != ScalarNode { - return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhsU.Tag, rhs.Path, lhsU.Tag) + return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhsU.Tag, rhs.GetNicePath(), lhsU.Tag) } - target := lhs.CreateReplacement() + target := lhs.CopyWithoutContent() boolV, err := compareScalars(context, prefs, lhsU, rhsU) return createBooleanCandidate(target, boolV), err diff --git a/pkg/yqlib/operator_contains.go b/pkg/yqlib/operator_contains.go index d07a645e..9a0ba092 100644 --- a/pkg/yqlib/operator_contains.go +++ b/pkg/yqlib/operator_contains.go @@ -3,15 +3,13 @@ package yqlib import ( "fmt" "strings" - - yaml "gopkg.in/yaml.v3" ) func containsOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { return crossFunction(d, context.ReadOnlyClone(), expressionNode, containsWithNodes, false) } -func containsArrayElement(array *yaml.Node, item *yaml.Node) (bool, error) { +func containsArrayElement(array *CandidateNode, item *CandidateNode) (bool, error) { for index := 0; index < len(array.Content); index = index + 1 { containedInArray, err := contains(array.Content[index], item) if err != nil { @@ -24,8 +22,8 @@ func containsArrayElement(array *yaml.Node, item *yaml.Node) (bool, error) { return false, nil } -func containsArray(lhs *yaml.Node, rhs *yaml.Node) (bool, error) { - if rhs.Kind != yaml.SequenceNode { +func containsArray(lhs *CandidateNode, rhs *CandidateNode) (bool, error) { + if rhs.Kind != SequenceNode { return containsArrayElement(lhs, rhs) } for index := 0; index < len(rhs.Content); index = index + 1 { @@ -40,8 +38,8 @@ func containsArray(lhs *yaml.Node, rhs *yaml.Node) (bool, error) { return true, nil } -func containsObject(lhs *yaml.Node, rhs *yaml.Node) (bool, error) { - if rhs.Kind != yaml.MappingNode { +func containsObject(lhs *CandidateNode, rhs *CandidateNode) (bool, error) { + if rhs.Kind != MappingNode { return false, nil } for index := 0; index < len(rhs.Content); index = index + 2 { @@ -68,21 +66,21 @@ func containsObject(lhs *yaml.Node, rhs *yaml.Node) (bool, error) { return true, nil } -func containsScalars(lhs *yaml.Node, rhs *yaml.Node) (bool, error) { +func containsScalars(lhs *CandidateNode, rhs *CandidateNode) (bool, error) { if lhs.Tag == "!!str" { return strings.Contains(lhs.Value, rhs.Value), nil } return lhs.Value == rhs.Value, nil } -func contains(lhs *yaml.Node, rhs *yaml.Node) (bool, error) { +func contains(lhs *CandidateNode, rhs *CandidateNode) (bool, error) { switch lhs.Kind { - case yaml.MappingNode: + case MappingNode: return containsObject(lhs, rhs) - case yaml.SequenceNode: + case SequenceNode: return containsArray(lhs, rhs) - case yaml.ScalarNode: - if rhs.Kind != yaml.ScalarNode || lhs.Tag != rhs.Tag { + case ScalarNode: + if rhs.Kind != ScalarNode || lhs.Tag != rhs.Tag { return false, nil } if lhs.Tag == "!!null" { @@ -94,15 +92,15 @@ func contains(lhs *yaml.Node, rhs *yaml.Node) (bool, error) { return false, fmt.Errorf("%v not yet supported for contains", lhs.Tag) } -func containsWithNodes(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) { - lhs.Node = unwrapDoc(lhs.Node) - rhs.Node = unwrapDoc(rhs.Node) +func containsWithNodes(d *dataTreeNavigator, context Context, lhsW *CandidateNode, rhsW *CandidateNode) (*CandidateNode, error) { + lhs := lhsW.unwrapDocument() + rhs := rhsW.unwrapDocument() - if lhs.Node.Kind != rhs.Node.Kind { - return nil, fmt.Errorf("%v cannot check contained in %v", rhs.Node.Tag, lhs.Node.Tag) + if lhs.Kind != rhs.Kind { + return nil, fmt.Errorf("%v cannot check contained in %v", rhs.Tag, lhs.Tag) } - result, err := contains(lhs.Node, rhs.Node) + result, err := contains(lhs, rhs) if err != nil { return nil, err } diff --git a/pkg/yqlib/operator_delete.go b/pkg/yqlib/operator_delete.go index 1d0f4c56..882cb839 100644 --- a/pkg/yqlib/operator_delete.go +++ b/pkg/yqlib/operator_delete.go @@ -61,7 +61,7 @@ func deleteFromMap(candidate *CandidateNode, childPath interface{}) { shouldDelete := key.Value == childPath - log.Debugf("shouldDelete %v ? %v", value.ToDebugString(), shouldDelete) + log.Debugf("shouldDelete %v ? %v", NodeToString(value), shouldDelete) if !shouldDelete { newContents = append(newContents, key, value) diff --git a/pkg/yqlib/operator_divide.go b/pkg/yqlib/operator_divide.go index c3d5eb23..b6e8b59e 100644 --- a/pkg/yqlib/operator_divide.go +++ b/pkg/yqlib/operator_divide.go @@ -4,8 +4,6 @@ import ( "fmt" "strconv" "strings" - - yaml "gopkg.in/yaml.v3" ) func divideOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { @@ -14,46 +12,44 @@ func divideOperator(d *dataTreeNavigator, context Context, expressionNode *Expre return crossFunction(d, context.ReadOnlyClone(), expressionNode, divide, false) } -func divide(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) { - lhs.Node = unwrapDoc(lhs.Node) - rhs.Node = unwrapDoc(rhs.Node) +func divide(d *dataTreeNavigator, context Context, lhsW *CandidateNode, rhsW *CandidateNode) (*CandidateNode, error) { + lhs := lhsW.unwrapDocument() + rhs := rhsW.unwrapDocument() - lhsNode := lhs.Node - - if lhsNode.Tag == "!!null" { - return nil, fmt.Errorf("%v (%v) cannot be divided by %v (%v)", lhsNode.Tag, lhs.GetNicePath(), rhs.Node.Tag, rhs.GetNicePath()) + if lhs.Tag == "!!null" { + return nil, fmt.Errorf("%v (%v) cannot be divided by %v (%v)", lhs.Tag, lhs.GetNicePath(), rhs.Tag, rhs.GetNicePath()) } - target := &yaml.Node{} + target := lhs.CopyWithoutContent() - if lhsNode.Kind == yaml.ScalarNode && rhs.Node.Kind == yaml.ScalarNode { - if err := divideScalars(target, lhsNode, rhs.Node); err != nil { + if lhs.Kind == ScalarNode && rhs.Kind == ScalarNode { + if err := divideScalars(target, lhs, rhs); err != nil { return nil, err } } else { - return nil, fmt.Errorf("%v (%v) cannot be divided by %v (%v)", lhsNode.Tag, lhs.GetNicePath(), rhs.Node.Tag, rhs.GetNicePath()) + return nil, fmt.Errorf("%v (%v) cannot be divided by %v (%v)", lhs.Tag, lhs.GetNicePath(), rhs.Tag, rhs.GetNicePath()) } - return lhs.CreateReplacement(target), nil + return target, nil } -func divideScalars(target *yaml.Node, lhs *yaml.Node, rhs *yaml.Node) error { +func divideScalars(target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error { lhsTag := lhs.Tag - rhsTag := guessTagFromCustomType(rhs) + rhsTag := rhs.guessTagFromCustomType() lhsIsCustom := false if !strings.HasPrefix(lhsTag, "!!") { // custom tag - we have to have a guess - lhsTag = guessTagFromCustomType(lhs) + lhsTag = lhs.guessTagFromCustomType() lhsIsCustom = true } if lhsTag == "!!str" && rhsTag == "!!str" { - res := split(lhs.Value, rhs.Value) - target.Kind = res.Kind - target.Tag = res.Tag - target.Content = res.Content + tKind, tTag, res := split(lhs.Value, rhs.Value) + target.Kind = tKind + target.Tag = tTag + target.Content = res } else if (lhsTag == "!!int" || lhsTag == "!!float") && (rhsTag == "!!int" || rhsTag == "!!float") { - target.Kind = yaml.ScalarNode + target.Kind = ScalarNode target.Style = lhs.Style lhsNum, err := strconv.ParseFloat(lhs.Value, 64) diff --git a/pkg/yqlib/operator_encoder_decoder.go b/pkg/yqlib/operator_encoder_decoder.go index 3e8d8149..4a3c77cc 100644 --- a/pkg/yqlib/operator_encoder_decoder.go +++ b/pkg/yqlib/operator_encoder_decoder.go @@ -151,7 +151,6 @@ func decodeOperator(d *dataTreeNavigator, context Context, expressionNode *Expre } //first node is a doc node := decodedNode.unwrapDocument() - node.Path = candidate.Path node.Key = candidate.Key node.Parent = candidate.Parent node.Document = candidate.Document diff --git a/pkg/yqlib/operator_equals.go b/pkg/yqlib/operator_equals.go index d8dc788a..f668ebf5 100644 --- a/pkg/yqlib/operator_equals.go +++ b/pkg/yqlib/operator_equals.go @@ -1,7 +1,5 @@ package yqlib -import "gopkg.in/yaml.v3" - func equalsOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { log.Debugf("-- equalsOperation") return crossFunction(d, context, expressionNode, isEquals(false), true) @@ -16,7 +14,7 @@ func isEquals(flip bool) func(d *dataTreeNavigator, context Context, lhs *Candid return createBooleanCandidate(owner, !flip), nil } else if lhs == nil { log.Debugf("lhs nil, but rhs is not") - rhsNode := unwrapDoc(rhs.Node) + rhsNode := rhs.unwrapDocument() value := rhsNode.Tag == "!!null" if flip { value = !value @@ -24,7 +22,7 @@ func isEquals(flip bool) func(d *dataTreeNavigator, context Context, lhs *Candid return createBooleanCandidate(rhs, value), nil } else if rhs == nil { log.Debugf("lhs not nil, but rhs is") - lhsNode := unwrapDoc(lhs.Node) + lhsNode := lhs.unwrapDocument() value := lhsNode.Tag == "!!null" if flip { value = !value @@ -32,12 +30,12 @@ func isEquals(flip bool) func(d *dataTreeNavigator, context Context, lhs *Candid return createBooleanCandidate(lhs, value), nil } - lhsNode := unwrapDoc(lhs.Node) - rhsNode := unwrapDoc(rhs.Node) + lhsNode := lhs.unwrapDocument() + rhsNode := rhs.unwrapDocument() if lhsNode.Tag == "!!null" { value = (rhsNode.Tag == "!!null") - } else if lhsNode.Kind == yaml.ScalarNode && rhsNode.Kind == yaml.ScalarNode { + } else if lhsNode.Kind == ScalarNode && rhsNode.Kind == ScalarNode { value = matchKey(lhsNode.Value, rhsNode.Value) } log.Debugf("%v == %v ? %v", NodeToString(lhs), NodeToString(rhs), value) diff --git a/pkg/yqlib/operator_modulo.go b/pkg/yqlib/operator_modulo.go index ecb9b406..f5973f0a 100644 --- a/pkg/yqlib/operator_modulo.go +++ b/pkg/yqlib/operator_modulo.go @@ -5,8 +5,6 @@ import ( "math" "strconv" "strings" - - yaml "gopkg.in/yaml.v3" ) func moduloOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { @@ -15,41 +13,39 @@ func moduloOperator(d *dataTreeNavigator, context Context, expressionNode *Expre return crossFunction(d, context.ReadOnlyClone(), expressionNode, modulo, false) } -func modulo(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) { - lhs.Node = unwrapDoc(lhs.Node) - rhs.Node = unwrapDoc(rhs.Node) +func modulo(d *dataTreeNavigator, context Context, lhsW *CandidateNode, rhsW *CandidateNode) (*CandidateNode, error) { + lhs := lhsW.unwrapDocument() + rhs := rhsW.unwrapDocument() - lhsNode := lhs.Node - - if lhsNode.Tag == "!!null" { - return nil, fmt.Errorf("%v (%v) cannot modulo by %v (%v)", lhsNode.Tag, lhs.GetNicePath(), rhs.Node.Tag, rhs.GetNicePath()) + if lhs.Tag == "!!null" { + return nil, fmt.Errorf("%v (%v) cannot modulo by %v (%v)", lhs.Tag, lhs.GetNicePath(), rhs.Tag, rhs.GetNicePath()) } - target := &yaml.Node{} + target := lhs.CopyWithoutContent() - if lhsNode.Kind == yaml.ScalarNode && rhs.Node.Kind == yaml.ScalarNode { - if err := moduloScalars(target, lhsNode, rhs.Node); err != nil { + if lhs.Kind == ScalarNode && rhs.Kind == ScalarNode { + if err := moduloScalars(target, lhs, rhs); err != nil { return nil, err } } else { - return nil, fmt.Errorf("%v (%v) cannot modulo by %v (%v)", lhsNode.Tag, lhs.GetNicePath(), rhs.Node.Tag, rhs.GetNicePath()) + return nil, fmt.Errorf("%v (%v) cannot modulo by %v (%v)", lhs.Tag, lhs.GetNicePath(), rhs.Tag, rhs.GetNicePath()) } - return lhs.CreateReplacement(target), nil + return target, nil } -func moduloScalars(target *yaml.Node, lhs *yaml.Node, rhs *yaml.Node) error { +func moduloScalars(target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error { lhsTag := lhs.Tag - rhsTag := guessTagFromCustomType(rhs) + rhsTag := rhs.guessTagFromCustomType() lhsIsCustom := false if !strings.HasPrefix(lhsTag, "!!") { // custom tag - we have to have a guess - lhsTag = guessTagFromCustomType(lhs) + lhsTag = lhs.guessTagFromCustomType() lhsIsCustom = true } if lhsTag == "!!int" && rhsTag == "!!int" { - target.Kind = yaml.ScalarNode + target.Kind = ScalarNode target.Style = lhs.Style format, lhsNum, err := parseInt64(lhs.Value) @@ -68,7 +64,7 @@ func moduloScalars(target *yaml.Node, lhs *yaml.Node, rhs *yaml.Node) error { target.Tag = lhs.Tag target.Value = fmt.Sprintf(format, remainder) } else if (lhsTag == "!!int" || lhsTag == "!!float") && (rhsTag == "!!int" || rhsTag == "!!float") { - target.Kind = yaml.ScalarNode + target.Kind = ScalarNode target.Style = lhs.Style lhsNum, err := strconv.ParseFloat(lhs.Value, 64) diff --git a/pkg/yqlib/operator_multiply.go b/pkg/yqlib/operator_multiply.go index cf638015..b978fe41 100644 --- a/pkg/yqlib/operator_multiply.go +++ b/pkg/yqlib/operator_multiply.go @@ -7,7 +7,6 @@ import ( "strings" "github.com/jinzhu/copier" - yaml "gopkg.in/yaml.v3" ) type multiplyPreferences struct { @@ -38,15 +37,15 @@ func multiplyOperator(d *dataTreeNavigator, context Context, expressionNode *Exp func getComments(lhs *CandidateNode, rhs *CandidateNode) (leadingContent string, headComment string, footComment string) { leadingContent = rhs.LeadingContent - headComment = rhs.Node.HeadComment - footComment = rhs.Node.FootComment - if lhs.Node.HeadComment != "" || lhs.LeadingContent != "" { - headComment = lhs.Node.HeadComment + headComment = rhs.HeadComment + footComment = rhs.FootComment + if lhs.HeadComment != "" || lhs.LeadingContent != "" { + headComment = lhs.HeadComment leadingContent = lhs.LeadingContent } - if lhs.Node.FootComment != "" { - footComment = lhs.Node.FootComment + if lhs.FootComment != "" { + footComment = lhs.FootComment } return leadingContent, headComment, footComment } @@ -55,27 +54,27 @@ func multiply(preferences multiplyPreferences) func(d *dataTreeNavigator, contex return func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) { // need to do this before unWrapping the potential document node leadingContent, headComment, footComment := getComments(lhs, rhs) - lhs.Node = unwrapDoc(lhs.Node) - rhs.Node = unwrapDoc(rhs.Node) - log.Debugf("Multiplying LHS: %v", lhs.Node.Tag) - log.Debugf("- RHS: %v", rhs.Node.Tag) + lhs = lhs.unwrapDocument() + rhs = rhs.unwrapDocument() + log.Debugf("Multiplying LHS: %v", lhs.Tag) + log.Debugf("- RHS: %v", rhs.Tag) - if rhs.Node.Tag == "!!null" { - return lhs.Copy() + if rhs.Tag == "!!null" { + return lhs.Copy(), nil } - if (lhs.Node.Kind == yaml.MappingNode && rhs.Node.Kind == yaml.MappingNode) || - (lhs.Node.Tag == "!!null" && rhs.Node.Kind == yaml.MappingNode) || - (lhs.Node.Kind == yaml.SequenceNode && rhs.Node.Kind == yaml.SequenceNode) || - (lhs.Node.Tag == "!!null" && rhs.Node.Kind == yaml.SequenceNode) { + if (lhs.Kind == MappingNode && rhs.Kind == MappingNode) || + (lhs.Tag == "!!null" && rhs.Kind == MappingNode) || + (lhs.Kind == SequenceNode && rhs.Kind == SequenceNode) || + (lhs.Tag == "!!null" && rhs.Kind == SequenceNode) { var newBlank = CandidateNode{} err := copier.CopyWithOption(&newBlank, lhs, copier.Option{IgnoreEmpty: true, DeepCopy: true}) if err != nil { return nil, err } newBlank.LeadingContent = leadingContent - newBlank.Node.HeadComment = headComment - newBlank.Node.FootComment = footComment + newBlank.HeadComment = headComment + newBlank.FootComment = footComment return mergeObjects(d, context.WritableClone(), &newBlank, rhs, preferences) } @@ -84,12 +83,12 @@ func multiply(preferences multiplyPreferences) func(d *dataTreeNavigator, contex } func multiplyScalars(lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) { - lhsTag := lhs.Node.Tag - rhsTag := guessTagFromCustomType(rhs.Node) + lhsTag := lhs.Tag + rhsTag := rhs.guessTagFromCustomType() lhsIsCustom := false if !strings.HasPrefix(lhsTag, "!!") { // custom tag - we have to have a guess - lhsTag = guessTagFromCustomType(lhs.Node) + lhsTag = lhs.guessTagFromCustomType() lhsIsCustom = true } @@ -98,46 +97,46 @@ func multiplyScalars(lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, er } else if (lhsTag == "!!int" || lhsTag == "!!float") && (rhsTag == "!!int" || rhsTag == "!!float") { return multiplyFloats(lhs, rhs, lhsIsCustom) } - return nil, fmt.Errorf("Cannot multiply %v with %v", lhs.Node.Tag, rhs.Node.Tag) + return nil, fmt.Errorf("Cannot multiply %v with %v", lhs.Tag, rhs.Tag) } func multiplyFloats(lhs *CandidateNode, rhs *CandidateNode, lhsIsCustom bool) (*CandidateNode, error) { - target := lhs.CreateReplacement(&yaml.Node{}) - target.Node.Kind = yaml.ScalarNode - target.Node.Style = lhs.Node.Style + target := lhs.CopyWithoutContent() + target.Kind = ScalarNode + target.Style = lhs.Style if lhsIsCustom { - target.Node.Tag = lhs.Node.Tag + target.Tag = lhs.Tag } else { - target.Node.Tag = "!!float" + target.Tag = "!!float" } - lhsNum, err := strconv.ParseFloat(lhs.Node.Value, 64) + lhsNum, err := strconv.ParseFloat(lhs.Value, 64) if err != nil { return nil, err } - rhsNum, err := strconv.ParseFloat(rhs.Node.Value, 64) + rhsNum, err := strconv.ParseFloat(rhs.Value, 64) if err != nil { return nil, err } - target.Node.Value = fmt.Sprintf("%v", lhsNum*rhsNum) + target.Value = fmt.Sprintf("%v", lhsNum*rhsNum) return target, nil } func multiplyIntegers(lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) { - target := lhs.CreateReplacement(&yaml.Node{}) - target.Node.Kind = yaml.ScalarNode - target.Node.Style = lhs.Node.Style - target.Node.Tag = lhs.Node.Tag + target := lhs.CopyWithoutContent() + target.Kind = ScalarNode + target.Style = lhs.Style + target.Tag = lhs.Tag - format, lhsNum, err := parseInt64(lhs.Node.Value) + format, lhsNum, err := parseInt64(lhs.Value) if err != nil { return nil, err } - _, rhsNum, err := parseInt64(rhs.Node.Value) + _, rhsNum, err := parseInt64(rhs.Value) if err != nil { return nil, err } - target.Node.Value = fmt.Sprintf(format, lhsNum*rhsNum) + target.Value = fmt.Sprintf(format, lhsNum*rhsNum) return target, nil } @@ -156,12 +155,12 @@ func mergeObjects(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs var pathIndexToStartFrom int if results.Front() != nil { - pathIndexToStartFrom = len(results.Front().Value.(*CandidateNode).Path) + pathIndexToStartFrom = len(results.Front().Value.(*CandidateNode).GetPath()) } for el := results.Front(); el != nil; el = el.Next() { candidate := el.Value.(*CandidateNode) - if candidate.Node.Tag == "!!merge" { + if candidate.Tag == "!!merge" { continue } @@ -177,20 +176,20 @@ func applyAssignment(d *dataTreeNavigator, context Context, pathIndexToStartFrom shouldAppendArrays := preferences.AppendArrays log.Debugf("merge - applyAssignment lhs %v, rhs: %v", lhs.GetKey(), rhs.GetKey()) - lhsPath := rhs.Path[pathIndexToStartFrom:] + lhsPath := rhs.GetPath()[pathIndexToStartFrom:] log.Debugf("merge - lhsPath %v", lhsPath) assignmentOp := &Operation{OperationType: assignAttributesOpType, Preferences: preferences.AssignPrefs} - if shouldAppendArrays && rhs.Node.Kind == yaml.SequenceNode { + if shouldAppendArrays && rhs.Kind == SequenceNode { assignmentOp.OperationType = addAssignOpType log.Debugf("merge - assignmentOp.OperationType = addAssignOpType") - } else if !preferences.DeepMergeArrays && rhs.Node.Kind == yaml.SequenceNode || - (rhs.Node.Kind == yaml.ScalarNode || rhs.Node.Kind == yaml.AliasNode) { + } else if !preferences.DeepMergeArrays && rhs.Kind == SequenceNode || + (rhs.Kind == ScalarNode || rhs.Kind == AliasNode) { assignmentOp.OperationType = assignOpType assignmentOp.UpdateAssign = false - log.Debugf("merge - rhs.Node.Kind == yaml.SequenceNode: %v", rhs.Node.Kind == yaml.SequenceNode) - log.Debugf("merge - rhs.Node.Kind == yaml.ScalarNode: %v", rhs.Node.Kind == yaml.ScalarNode) - log.Debugf("merge - rhs.Node.Kind == yaml.AliasNode: %v", rhs.Node.Kind == yaml.AliasNode) + log.Debugf("merge - rhs.Kind == SequenceNode: %v", rhs.Kind == SequenceNode) + log.Debugf("merge - rhs.Kind == ScalarNode: %v", rhs.Kind == ScalarNode) + log.Debugf("merge - rhs.Kind == AliasNode: %v", rhs.Kind == AliasNode) log.Debugf("merge - assignmentOp.OperationType = assignOpType, no updateassign") } else { log.Debugf("merge - assignmentOp := &Operation{OperationType: assignAttributesOpType}") diff --git a/pkg/yqlib/operator_recursive_descent.go b/pkg/yqlib/operator_recursive_descent.go index bb583840..3300e5d8 100644 --- a/pkg/yqlib/operator_recursive_descent.go +++ b/pkg/yqlib/operator_recursive_descent.go @@ -2,8 +2,6 @@ package yqlib import ( "container/list" - - yaml "gopkg.in/yaml.v3" ) type recursiveDescentPreferences struct { @@ -25,15 +23,13 @@ func recursiveDescentOperator(d *dataTreeNavigator, context Context, expressionN func recursiveDecent(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) + candidate := el.Value.(*CandidateNode).unwrapDocument() log.Debugf("Recursive Decent, added %v", NodeToString(candidate)) results.PushBack(candidate) - if candidate.Node.Kind != yaml.AliasNode && len(candidate.Node.Content) > 0 && - (preferences.RecurseArray || candidate.Node.Kind != yaml.SequenceNode) { + if candidate.Kind != AliasNode && len(candidate.Content) > 0 && + (preferences.RecurseArray || candidate.Kind != SequenceNode) { children, err := splat(context.SingleChildContext(candidate), preferences.TraversePreferences) diff --git a/pkg/yqlib/operator_slice.go b/pkg/yqlib/operator_slice.go index e496cf93..7bf340a9 100644 --- a/pkg/yqlib/operator_slice.go +++ b/pkg/yqlib/operator_slice.go @@ -3,8 +3,6 @@ package yqlib import ( "container/list" "fmt" - - yaml "gopkg.in/yaml.v3" ) func getSliceNumber(d *dataTreeNavigator, context Context, node *CandidateNode, expressionNode *ExpressionNode) (int, error) { @@ -15,7 +13,7 @@ func getSliceNumber(d *dataTreeNavigator, context Context, node *CandidateNode, if result.MatchingNodes.Len() != 1 { return 0, fmt.Errorf("expected to find 1 number, got %v instead", result.MatchingNodes.Len()) } - return parseInt(result.MatchingNodes.Front().Value.(*CandidateNode).Node.Value) + return parseInt(result.MatchingNodes.Front().Value.(*CandidateNode).Value) } func sliceArrayOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { @@ -27,8 +25,7 @@ func sliceArrayOperator(d *dataTreeNavigator, context Context, expressionNode *E results := list.New() for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { - lhsNode := el.Value.(*CandidateNode) - original := unwrapDoc(lhsNode.Node) + lhsNode := el.Value.(*CandidateNode).unwrapDocument() firstNumber, err := getSliceNumber(d, context, lhsNode, expressionNode.LHS) @@ -37,7 +34,7 @@ func sliceArrayOperator(d *dataTreeNavigator, context Context, expressionNode *E } relativeFirstNumber := firstNumber if relativeFirstNumber < 0 { - relativeFirstNumber = len(original.Content) + firstNumber + relativeFirstNumber = len(lhsNode.Content) + firstNumber } secondNumber, err := getSliceNumber(d, context, lhsNode, expressionNode.RHS) @@ -47,24 +44,21 @@ func sliceArrayOperator(d *dataTreeNavigator, context Context, expressionNode *E relativeSecondNumber := secondNumber if relativeSecondNumber < 0 { - relativeSecondNumber = len(original.Content) + secondNumber - } else if relativeSecondNumber > len(original.Content) { - relativeSecondNumber = len(original.Content) + relativeSecondNumber = len(lhsNode.Content) + secondNumber + } else if relativeSecondNumber > len(lhsNode.Content) { + relativeSecondNumber = len(lhsNode.Content) } log.Debug("calculateIndicesToTraverse: slice from %v to %v", relativeFirstNumber, relativeSecondNumber) - var newResults []*yaml.Node + var newResults []*CandidateNode for i := relativeFirstNumber; i < relativeSecondNumber; i++ { - newResults = append(newResults, original.Content[i]) + newResults = append(newResults, lhsNode.Content[i]) } - slicedArrayNode := &yaml.Node{ - Kind: yaml.SequenceNode, - Tag: original.Tag, - Content: newResults, - } - results.PushBack(lhsNode.CreateReplacement(slicedArrayNode)) + sliceArrayNode := lhsNode.CreateReplacement(SequenceNode, lhsNode.Tag, "") + sliceArrayNode.Content = newResults + results.PushBack(sliceArrayNode) } diff --git a/pkg/yqlib/operator_subtract.go b/pkg/yqlib/operator_subtract.go index 90867d48..4ff9065a 100644 --- a/pkg/yqlib/operator_subtract.go +++ b/pkg/yqlib/operator_subtract.go @@ -5,8 +5,6 @@ import ( "strconv" "strings" "time" - - "gopkg.in/yaml.v3" ) func createSubtractOp(lhs *ExpressionNode, rhs *ExpressionNode) *ExpressionNode { @@ -26,50 +24,50 @@ func subtractOperator(d *dataTreeNavigator, context Context, expressionNode *Exp } func subtractArray(lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) { - newLHSArray := make([]*yaml.Node, 0) + newLHSArray := make([]*CandidateNode, 0) - for lindex := 0; lindex < len(lhs.Node.Content); lindex = lindex + 1 { + for lindex := 0; lindex < len(lhs.Content); lindex = lindex + 1 { shouldInclude := true - for rindex := 0; rindex < len(rhs.Node.Content) && shouldInclude; rindex = rindex + 1 { - if recursiveNodeEqual(lhs.Node.Content[lindex], rhs.Node.Content[rindex]) { + for rindex := 0; rindex < len(rhs.Content) && shouldInclude; rindex = rindex + 1 { + if recursiveNodeEqual(lhs.Content[lindex], rhs.Content[rindex]) { shouldInclude = false } } if shouldInclude { - newLHSArray = append(newLHSArray, lhs.Node.Content[lindex]) + newLHSArray = append(newLHSArray, lhs.Content[lindex]) } } - lhs.Node.Content = newLHSArray + lhs.Content = newLHSArray return lhs, nil } func subtract(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) { - lhs.Node = unwrapDoc(lhs.Node) - rhs.Node = unwrapDoc(rhs.Node) + lhs = lhs.unwrapDocument() + rhs = rhs.unwrapDocument() - lhsNode := lhs.Node + lhsNode := lhs if lhsNode.Tag == "!!null" { - return lhs.CreateReplacement(rhs.Node), nil + return lhs.CopyAsReplacement(rhs), nil } - target := lhs.CreateReplacement(&yaml.Node{}) + target := lhs.CopyWithoutContent() switch lhsNode.Kind { - case yaml.MappingNode: + case MappingNode: return nil, fmt.Errorf("maps not yet supported for subtraction") - case yaml.SequenceNode: - if rhs.Node.Kind != yaml.SequenceNode { - return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhs.Node.Tag, rhs.Path, lhsNode.Tag) + case SequenceNode: + if rhs.Kind != SequenceNode { + return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhs.Tag, rhs.GetNicePath(), lhsNode.Tag) } return subtractArray(lhs, rhs) - case yaml.ScalarNode: - if rhs.Node.Kind != yaml.ScalarNode { - return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhs.Node.Tag, rhs.Path, lhsNode.Tag) + case ScalarNode: + if rhs.Kind != ScalarNode { + return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhs.Tag, rhs.GetNicePath(), lhsNode.Tag) } - target.Node.Kind = yaml.ScalarNode - target.Node.Style = lhsNode.Style - if err := subtractScalars(context, target, lhsNode, rhs.Node); err != nil { + target.Kind = ScalarNode + target.Style = lhsNode.Style + if err := subtractScalars(context, target, lhsNode, rhs); err != nil { return nil, err } } @@ -77,19 +75,19 @@ func subtract(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *Ca return target, nil } -func subtractScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs *yaml.Node) error { +func subtractScalars(context Context, target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error { lhsTag := lhs.Tag rhsTag := rhs.Tag lhsIsCustom := false if !strings.HasPrefix(lhsTag, "!!") { // custom tag - we have to have a guess - lhsTag = guessTagFromCustomType(lhs) + lhsTag = lhs.guessTagFromCustomType() lhsIsCustom = true } if !strings.HasPrefix(rhsTag, "!!") { // custom tag - we have to have a guess - rhsTag = guessTagFromCustomType(rhs) + rhsTag = rhs.guessTagFromCustomType() } isDateTime := lhsTag == "!!timestamp" @@ -113,8 +111,8 @@ func subtractScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs return err } result := lhsNum - rhsNum - target.Node.Tag = lhs.Tag - target.Node.Value = fmt.Sprintf(format, result) + target.Tag = lhs.Tag + target.Value = fmt.Sprintf(format, result) } else if (lhsTag == "!!int" || lhsTag == "!!float") && (rhsTag == "!!int" || rhsTag == "!!float") { lhsNum, err := strconv.ParseFloat(lhs.Value, 64) if err != nil { @@ -126,11 +124,11 @@ func subtractScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs } result := lhsNum - rhsNum if lhsIsCustom { - target.Node.Tag = lhs.Tag + target.Tag = lhs.Tag } else { - target.Node.Tag = "!!float" + target.Tag = "!!float" } - target.Node.Value = fmt.Sprintf("%v", result) + target.Value = fmt.Sprintf("%v", result) } else { return fmt.Errorf("%v cannot be added to %v", lhs.Tag, rhs.Tag) } @@ -138,7 +136,7 @@ func subtractScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs return nil } -func subtractDateTime(layout string, target *CandidateNode, lhs *yaml.Node, rhs *yaml.Node) error { +func subtractDateTime(layout string, target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error { var durationStr string if strings.HasPrefix(rhs.Value, "-") { durationStr = rhs.Value[1:] @@ -157,6 +155,6 @@ func subtractDateTime(layout string, target *CandidateNode, lhs *yaml.Node, rhs } newTime := currentTime.Add(duration) - target.Node.Value = newTime.Format(layout) + target.Value = newTime.Format(layout) return nil } diff --git a/pkg/yqlib/operator_variables.go b/pkg/yqlib/operator_variables.go index 32248ffc..01a946ec 100644 --- a/pkg/yqlib/operator_variables.go +++ b/pkg/yqlib/operator_variables.go @@ -72,10 +72,7 @@ func variableLoopSingleChild(d *dataTreeNavigator, context Context, originalExp if prefs.IsReference { variableValue.PushBack(el.Value) } else { - candidateCopy, err := el.Value.(*CandidateNode).Copy() - if err != nil { - return Context{}, err - } + candidateCopy := el.Value.(*CandidateNode).Copy() variableValue.PushBack(candidateCopy) } newContext := context.ChildContext(context.MatchingNodes) diff --git a/pkg/yqlib/operators.go b/pkg/yqlib/operators.go index ea0574d6..21afe61e 100644 --- a/pkg/yqlib/operators.go +++ b/pkg/yqlib/operators.go @@ -37,10 +37,7 @@ func compoundAssignFunction(d *dataTreeNavigator, context Context, expressionNod for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() { candidate := el.Value.(*CandidateNode) - clone, err := candidate.Copy() - if err != nil { - return Context{}, err - } + clone := candidate.Copy() valueCopyExp := &ExpressionNode{Operation: &Operation{OperationType: referenceOpType, CandidateNode: clone}} valueExpression := &ExpressionNode{Operation: &Operation{OperationType: referenceOpType, CandidateNode: candidate}} @@ -187,8 +184,7 @@ func createBooleanCandidate(owner *CandidateNode, value bool) *CandidateNode { if !value { valString = "false" } - node := &yaml.Node{Kind: yaml.ScalarNode, Value: valString, Tag: "!!bool"} - return owner.CreateReplacement(node) + return owner.CreateReplacement(ScalarNode, "!!bool", valString) } func createTraversalTree(path []interface{}, traversePrefs traversePreferences, targetKey bool) *ExpressionNode { diff --git a/pkg/yqlib/printer.go b/pkg/yqlib/printer.go index a2d9f4ed..1c8d9779 100644 --- a/pkg/yqlib/printer.go +++ b/pkg/yqlib/printer.go @@ -7,8 +7,6 @@ import ( "fmt" "io" "regexp" - - yaml "gopkg.in/yaml.v3" ) type Printer interface { @@ -91,7 +89,7 @@ func (p *resultsPrinter) PrintedAnything() bool { return p.printedMatches } -func (p *resultsPrinter) printNode(node *yaml.Node, writer io.Writer) error { +func (p *resultsPrinter) printNode(node *CandidateNode, writer io.Writer) error { p.printedMatches = p.printedMatches || (node.Tag != "!!null" && (node.Tag != "!!bool" || node.Value != "false")) return p.encoder.Encode(writer, node) @@ -161,7 +159,7 @@ func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error { return err } - if err := p.printNode(mappedDoc.Node, destination); err != nil { + if err := p.printNode(mappedDoc, destination); err != nil { return err }