This commit is contained in:
Mike Farah 2023-04-08 20:17:13 +10:00
parent 66ab916c6b
commit 6e3f1d959e
10 changed files with 83 additions and 65 deletions

View File

@ -218,6 +218,19 @@ func (n *CandidateNode) CopyChildren() []*CandidateNode {
}
func (n *CandidateNode) Copy() *CandidateNode {
return n.doCopy(true)
}
func (n *CandidateNode) CopyWithoutContent() *CandidateNode {
return n.doCopy(false)
}
func (n *CandidateNode) doCopy(cloneContent bool) *CandidateNode {
var content []*CandidateNode
if cloneContent {
content = n.CopyChildren()
}
return &CandidateNode{
Kind: n.Kind,
Style: n.Style,
@ -229,7 +242,7 @@ func (n *CandidateNode) Copy() *CandidateNode {
// ok not to clone this,
// as its a reference to somewhere else.
Alias: n.Alias,
Content: n.CopyChildren(),
Content: content,
HeadComment: n.HeadComment,
LineComment: n.LineComment,

View File

@ -3,8 +3,6 @@ package yqlib
import (
"container/list"
"fmt"
yaml "gopkg.in/yaml.v3"
)
func columnOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@ -14,8 +12,11 @@ func columnOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
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.Node.Column), Tag: "!!int"}
result := candidate.CreateReplacement(node)
result := candidate.CreateReplacement()
result.Kind = ScalarNode
result.Value = fmt.Sprintf("%v", candidate.Column)
result.Tag = "!!int"
results.PushBack(result)
}

View File

@ -5,8 +5,6 @@ import (
"bytes"
"container/list"
"regexp"
yaml "gopkg.in/yaml.v3"
)
type commentOpPreferences struct {
@ -35,7 +33,7 @@ func assignCommentsOperator(d *dataTreeNavigator, context Context, expressionNod
}
if rhs.MatchingNodes.Front() != nil {
comment = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
comment = rhs.MatchingNodes.Front().Value.(*CandidateNode).Value
}
}
@ -49,25 +47,25 @@ func assignCommentsOperator(d *dataTreeNavigator, context Context, expressionNod
}
if rhs.MatchingNodes.Front() != nil {
comment = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
comment = rhs.MatchingNodes.Front().Value.(*CandidateNode).Value
}
}
log.Debugf("Setting comment of : %v", candidate.GetKey())
if preferences.LineComment {
candidate.Node.LineComment = comment
candidate.LineComment = comment
}
if preferences.HeadComment {
candidate.Node.HeadComment = comment
candidate.HeadComment = comment
candidate.LeadingContent = "" // clobber the leading content, if there was any.
}
if preferences.FootComment && candidate.Node.Kind == yaml.DocumentNode && comment != "" {
if preferences.FootComment && candidate.Kind == DocumentNode && comment != "" {
candidate.TrailingContent = "# " + comment
} else if preferences.FootComment && candidate.Node.Kind == yaml.DocumentNode {
} else if preferences.FootComment && candidate.Kind == DocumentNode {
candidate.TrailingContent = comment
} else if preferences.FootComment && candidate.Node.Kind != yaml.DocumentNode {
candidate.Node.FootComment = comment
} else if preferences.FootComment && candidate.Kind != DocumentNode {
candidate.FootComment = comment
candidate.TrailingContent = ""
}
@ -91,7 +89,7 @@ func getCommentsOperator(d *dataTreeNavigator, context Context, expressionNode *
candidate := el.Value.(*CandidateNode)
comment := ""
if preferences.LineComment {
comment = candidate.Node.LineComment
comment = candidate.LineComment
} else if preferences.HeadComment && candidate.LeadingContent != "" {
var chompRegexp = regexp.MustCompile(`\n$`)
var output bytes.Buffer
@ -106,11 +104,11 @@ func getCommentsOperator(d *dataTreeNavigator, context Context, expressionNode *
comment = output.String()
comment = chompRegexp.ReplaceAllString(comment, "")
} else if preferences.HeadComment {
comment = candidate.Node.HeadComment
} else if preferences.FootComment && candidate.Node.Kind == yaml.DocumentNode && candidate.TrailingContent != "" {
comment = candidate.HeadComment
} else if preferences.FootComment && candidate.Kind == DocumentNode && candidate.TrailingContent != "" {
comment = candidate.TrailingContent
} else if preferences.FootComment {
comment = candidate.Node.FootComment
comment = candidate.FootComment
}
comment = startCommentCharaterRegExp.ReplaceAllString(comment, "")
comment = subsequentCommentCharaterRegExp.ReplaceAllString(comment, "\n")

View File

@ -2,8 +2,6 @@ package yqlib
import (
"container/list"
"gopkg.in/yaml.v3"
)
func createMapOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@ -36,7 +34,11 @@ func createMapOperator(d *dataTreeNavigator, context Context, expressionNode *Ex
sequences.PushBack(sequenceNode)
}
return context.SingleChildContext(&CandidateNode{Node: listToNodeSeq(sequences), Document: document, Path: path}), nil
node := listToNodeSeq(sequences)
node.Document = document
node.Path = path
return context.SingleChildContext(node), nil
}
@ -53,33 +55,37 @@ func sequenceFor(d *dataTreeNavigator, context Context, matchingNode *CandidateN
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"}
node := CandidateNode{Kind: MappingNode, Tag: "!!map"}
log.Debugf("LHS:", NodeToString(lhs))
log.Debugf("RHS:", NodeToString(rhs))
node.Content = []*yaml.Node{
unwrapDoc(lhs.Node),
unwrapDoc(rhs.Node),
node.Content = []*CandidateNode{
lhs.unwrapDocument(),
rhs.unwrapDocument(),
}
node.Document = document
node.Path = path
return &CandidateNode{Node: &node, Document: document, Path: path}, nil
return &node, nil
}, false)
if err != nil {
return nil, err
}
innerList := listToNodeSeq(mapPairs.MatchingNodes)
innerList.Style = yaml.FlowStyle
return &CandidateNode{Node: innerList, Document: document, Path: path}, nil
innerList.Style = FlowStyle
innerList.Document = document
innerList.Path = path
return innerList, nil
}
// NOTE: here the document index gets dropped so we
// no longer know where the node originates from.
func listToNodeSeq(list *list.List) *yaml.Node {
node := yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
func listToNodeSeq(list *list.List) *CandidateNode {
node := CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
for entry := list.Front(); entry != nil; entry = entry.Next() {
entryCandidate := entry.Value.(*CandidateNode)
log.Debugf("Collecting %v into sequence", NodeToString(entryCandidate))
node.Content = append(node.Content, entryCandidate.Node)
node.Content = append(node.Content, entryCandidate)
}
return &node
}

View File

@ -17,7 +17,7 @@ func evalOperator(d *dataTreeNavigator, context Context, expressionNode *Express
for pathExpStrEntry := pathExpStrResults.MatchingNodes.Front(); pathExpStrEntry != nil; pathExpStrEntry = pathExpStrEntry.Next() {
expressionStrCandidate := pathExpStrEntry.Value.(*CandidateNode)
expressions[expIndex], err = ExpressionParser.ParseExpression(expressionStrCandidate.Node.Value)
expressions[expIndex], err = ExpressionParser.ParseExpression(expressionStrCandidate.Value)
if err != nil {
return Context{}, err
}

View File

@ -25,7 +25,7 @@ func filterOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
if err != nil {
return Context{}, err
}
collected.Node.Style = unwrapDoc(candidate.Node).Style
collected.Style = candidate.unwrapDocument().Style
results.PushBack(collected)
}
return context.ChildContext(results), nil

View File

@ -3,8 +3,6 @@ package yqlib
import (
"container/list"
"fmt"
yaml "gopkg.in/yaml.v3"
)
func lengthOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@ -13,25 +11,27 @@ func lengthOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
targetNode := unwrapDoc(candidate.Node)
targetNode := candidate.unwrapDocument()
var length int
switch targetNode.Kind {
case yaml.ScalarNode:
case ScalarNode:
if targetNode.Tag == "!!null" {
length = 0
} else {
length = len(targetNode.Value)
}
case yaml.MappingNode:
case MappingNode:
length = len(targetNode.Content) / 2
case yaml.SequenceNode:
case SequenceNode:
length = len(targetNode.Content)
default:
length = 0
}
node := &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", length), Tag: "!!int"}
result := candidate.CreateReplacement(node)
result := candidate.CreateReplacement()
result.Kind = ScalarNode
result.Value = fmt.Sprintf("%v", length)
result.Tag = "!!int"
results.PushBack(result)
}

View File

@ -3,8 +3,6 @@ package yqlib
import (
"container/list"
"fmt"
yaml "gopkg.in/yaml.v3"
)
func lineOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@ -14,8 +12,10 @@ func lineOperator(d *dataTreeNavigator, context Context, expressionNode *Express
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.Node.Line), Tag: "!!int"}
result := candidate.CreateReplacement(node)
result := candidate.CreateReplacement()
result.Kind = ScalarNode
result.Value = fmt.Sprintf("%v", candidate.Line)
result.Tag = "!!int"
results.PushBack(result)
}

View File

@ -54,7 +54,7 @@ func mapOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi
if err != nil {
return Context{}, err
}
collected.Node.Style = unwrapDoc(candidate.Node).Style
collected.Style = candidate.unwrapDocument().Style
results.PushBack(collected)

View File

@ -3,33 +3,31 @@ package yqlib
import (
"container/list"
"fmt"
yaml "gopkg.in/yaml.v3"
)
func pickMap(original *yaml.Node, indices *yaml.Node) *yaml.Node {
func pickMap(original *CandidateNode, indices *CandidateNode) *CandidateNode {
filteredContent := make([]*yaml.Node, 0)
filteredContent := make([]*CandidateNode, 0)
for index := 0; index < len(indices.Content); index = index + 1 {
keyToFind := indices.Content[index]
indexInMap := findKeyInMap(original, keyToFind)
if indexInMap > -1 {
clonedKey := deepClone(original.Content[indexInMap])
clonedValue := deepClone(original.Content[indexInMap+1])
clonedKey := original.Content[indexInMap].Copy()
clonedValue := original.Content[indexInMap+1].Copy()
filteredContent = append(filteredContent, clonedKey, clonedValue)
}
}
newNode := deepCloneNoContent(original)
newNode := original.CopyWithoutContent()
newNode.Content = filteredContent
return newNode
}
func pickSequence(original *yaml.Node, indices *yaml.Node) (*yaml.Node, error) {
func pickSequence(original *CandidateNode, indices *CandidateNode) (*CandidateNode, error) {
filteredContent := make([]*yaml.Node, 0)
filteredContent := make([]*CandidateNode, 0)
for index := 0; index < len(indices.Content); index = index + 1 {
indexInArray, err := parseInt(indices.Content[index].Value)
if err != nil {
@ -37,11 +35,11 @@ func pickSequence(original *yaml.Node, indices *yaml.Node) (*yaml.Node, error) {
}
if indexInArray > -1 && indexInArray < len(original.Content) {
filteredContent = append(filteredContent, deepClone(original.Content[indexInArray]))
filteredContent = append(filteredContent, original.Content[indexInArray].Copy())
}
}
newNode := deepCloneNoContent(original)
newNode := original.CopyWithoutContent()
newNode.Content = filteredContent
return newNode, nil
@ -55,21 +53,21 @@ func pickOperator(d *dataTreeNavigator, context Context, expressionNode *Express
if err != nil {
return Context{}, err
}
indicesToPick := &yaml.Node{}
indicesToPick := &CandidateNode{}
if contextIndicesToPick.MatchingNodes.Len() > 0 {
indicesToPick = contextIndicesToPick.MatchingNodes.Front().Value.(*CandidateNode).Node
indicesToPick = contextIndicesToPick.MatchingNodes.Front().Value.(*CandidateNode)
}
var results = list.New()
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
node := unwrapDoc(candidate.Node)
node := candidate.unwrapDocument()
var replacement *yaml.Node
if node.Kind == yaml.MappingNode {
var replacement *CandidateNode
if node.Kind == MappingNode {
replacement = pickMap(node, indicesToPick)
} else if node.Kind == yaml.SequenceNode {
} else if node.Kind == SequenceNode {
replacement, err = pickSequence(node, indicesToPick)
if err != nil {
return Context{}, err
@ -79,7 +77,9 @@ func pickOperator(d *dataTreeNavigator, context Context, expressionNode *Express
return Context{}, fmt.Errorf("cannot pick indicies from type %v (%v)", node.Tag, candidate.GetNicePath())
}
results.PushBack(candidate.CreateReplacementWithDocWrappers(replacement))
replacement.LeadingContent = candidate.LeadingContent
replacement.TrailingContent = candidate.TrailingContent
results.PushBack(replacement)
}
return context.ChildContext(results), nil