2020-11-03 23:48:43 +00:00
|
|
|
package yqlib
|
2020-10-13 01:51:37 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
|
2020-10-21 02:54:51 +00:00
|
|
|
"github.com/jinzhu/copier"
|
2020-10-13 01:51:37 +00:00
|
|
|
"gopkg.in/yaml.v3"
|
|
|
|
)
|
|
|
|
|
|
|
|
type CandidateNode struct {
|
|
|
|
Node *yaml.Node // the actual node
|
|
|
|
Path []interface{} /// the path we took to get to this node
|
|
|
|
Document uint // the document index of this node
|
2020-10-27 05:45:16 +00:00
|
|
|
Filename string
|
2020-10-13 01:51:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (n *CandidateNode) GetKey() string {
|
2020-10-30 01:00:48 +00:00
|
|
|
return fmt.Sprintf("%v - %v", n.Document, n.Path)
|
2020-10-13 01:51:37 +00:00
|
|
|
}
|
|
|
|
|
2020-11-13 03:07:11 +00:00
|
|
|
func (n *CandidateNode) Copy() (*CandidateNode, error) {
|
2020-10-21 02:54:51 +00:00
|
|
|
clone := &CandidateNode{}
|
2020-11-13 03:07:11 +00:00
|
|
|
err := copier.Copy(clone, n)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return clone, nil
|
2020-10-21 02:54:51 +00:00
|
|
|
}
|
|
|
|
|
2020-10-16 01:29:26 +00:00
|
|
|
// updates this candidate from the given candidate node
|
|
|
|
func (n *CandidateNode) UpdateFrom(other *CandidateNode) {
|
2020-10-19 05:36:46 +00:00
|
|
|
n.UpdateAttributesFrom(other)
|
2020-10-16 01:29:26 +00:00
|
|
|
n.Node.Content = other.Node.Content
|
|
|
|
n.Node.Value = other.Node.Value
|
2020-10-29 23:56:45 +00:00
|
|
|
n.Node.Alias = other.Node.Alias
|
2020-10-19 05:14:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (n *CandidateNode) UpdateAttributesFrom(other *CandidateNode) {
|
2020-10-19 05:36:46 +00:00
|
|
|
if n.Node.Kind != other.Node.Kind {
|
|
|
|
// clear out the contents when switching to a different type
|
|
|
|
// e.g. map to array
|
|
|
|
n.Node.Content = make([]*yaml.Node, 0)
|
|
|
|
n.Node.Value = ""
|
|
|
|
}
|
2020-10-16 01:29:26 +00:00
|
|
|
n.Node.Kind = other.Node.Kind
|
|
|
|
n.Node.Tag = other.Node.Tag
|
2020-10-28 00:34:01 +00:00
|
|
|
|
|
|
|
// merge will pickup the style of the new thing
|
|
|
|
// when autocreating nodes
|
|
|
|
if n.Node.Style == 0 {
|
|
|
|
n.Node.Style = other.Node.Style
|
|
|
|
}
|
2020-10-30 01:40:44 +00:00
|
|
|
n.Node.FootComment = n.Node.FootComment + other.Node.FootComment
|
|
|
|
n.Node.HeadComment = n.Node.HeadComment + other.Node.HeadComment
|
|
|
|
n.Node.LineComment = n.Node.LineComment + other.Node.LineComment
|
2020-10-16 01:29:26 +00:00
|
|
|
}
|
|
|
|
|
2020-10-13 01:51:37 +00:00
|
|
|
func (n *CandidateNode) PathStackToString() string {
|
|
|
|
return mergePathStackToString(n.Path)
|
|
|
|
}
|
|
|
|
|
|
|
|
func mergePathStackToString(pathStack []interface{}) string {
|
|
|
|
var sb strings.Builder
|
|
|
|
for index, path := range pathStack {
|
|
|
|
switch path.(type) {
|
|
|
|
case int, int64:
|
|
|
|
// if arrayMergeStrategy == AppendArrayMergeStrategy {
|
|
|
|
// sb.WriteString("[+]")
|
|
|
|
// } else {
|
|
|
|
sb.WriteString(fmt.Sprintf("[%v]", path))
|
|
|
|
// }
|
|
|
|
|
|
|
|
default:
|
|
|
|
s := fmt.Sprintf("%v", path)
|
|
|
|
var _, errParsingInt = strconv.ParseInt(s, 10, 64) // nolint
|
|
|
|
|
|
|
|
hasSpecial := strings.Contains(s, ".") || strings.Contains(s, "[") || strings.Contains(s, "]") || strings.Contains(s, "\"")
|
|
|
|
hasDoubleQuotes := strings.Contains(s, "\"")
|
|
|
|
wrappingCharacterStart := "\""
|
|
|
|
wrappingCharacterEnd := "\""
|
|
|
|
if hasDoubleQuotes {
|
|
|
|
wrappingCharacterStart = "("
|
|
|
|
wrappingCharacterEnd = ")"
|
|
|
|
}
|
|
|
|
if hasSpecial || errParsingInt == nil {
|
|
|
|
sb.WriteString(wrappingCharacterStart)
|
|
|
|
}
|
|
|
|
sb.WriteString(s)
|
|
|
|
if hasSpecial || errParsingInt == nil {
|
|
|
|
sb.WriteString(wrappingCharacterEnd)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if index < len(pathStack)-1 {
|
|
|
|
sb.WriteString(".")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return sb.String()
|
|
|
|
}
|