mirror of
https://github.com/mikefarah/yq.git
synced 2025-01-13 20:15:57 +00:00
wip
This commit is contained in:
parent
6a891e5239
commit
8fef31b417
@ -35,6 +35,13 @@ func createIntegerScalarNode(num int) *CandidateNode {
|
||||
}
|
||||
}
|
||||
|
||||
func createStringScalarNode(stringValue string) *CandidateNode {
|
||||
var node = &CandidateNode{Kind: ScalarNode}
|
||||
node.Value = stringValue
|
||||
node.Tag = "!!str"
|
||||
return node
|
||||
}
|
||||
|
||||
func createScalarNode(value interface{}, stringValue string) *CandidateNode {
|
||||
var node = &CandidateNode{Kind: ScalarNode}
|
||||
node.Value = stringValue
|
||||
@ -137,36 +144,37 @@ func (n *CandidateNode) guessTagFromCustomType() string {
|
||||
log.Debug("guessTagFromCustomType: could not guess underlying tag type %v", errorReading)
|
||||
return n.Tag
|
||||
}
|
||||
guessedTag := unwrapDoc(dataBucket).Tag
|
||||
guessedTag := dataBucket.unwrapDocument().Tag
|
||||
log.Info("im guessing the tag %v is a %v", n.Tag, guessedTag)
|
||||
return guessedTag
|
||||
}
|
||||
|
||||
func (n *CandidateNode) CreateChildInMap(key *CandidateNode) *CandidateNode {
|
||||
var value interface{}
|
||||
if key != nil {
|
||||
value = key.Value
|
||||
}
|
||||
return &CandidateNode{
|
||||
Path: n.createChildPath(value),
|
||||
Parent: n,
|
||||
Key: key,
|
||||
Document: n.Document,
|
||||
Filename: n.Filename,
|
||||
FileIndex: n.FileIndex,
|
||||
}
|
||||
}
|
||||
// func (n *CandidateNode) CreateChildInMap(key *CandidateNode) *CandidateNode {
|
||||
// var value interface{}
|
||||
// if key != nil {
|
||||
// value = key.Value
|
||||
// }
|
||||
// return &CandidateNode{
|
||||
// Path: n.createChildPath(value),
|
||||
// Parent: n,
|
||||
// Key: key,
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
// Document: n.Document,
|
||||
// Filename: n.Filename,
|
||||
// FileIndex: n.FileIndex,
|
||||
// }
|
||||
// }
|
||||
|
||||
// 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() *CandidateNode {
|
||||
return &CandidateNode{
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
|
||||
logging "gopkg.in/op/go-logging.v1"
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type DataTreeNavigator interface {
|
||||
@ -13,7 +12,7 @@ type DataTreeNavigator interface {
|
||||
// a new context of matching candidates
|
||||
GetMatchingNodes(context Context, expressionNode *ExpressionNode) (Context, error)
|
||||
|
||||
DeeplyAssign(context Context, path []interface{}, rhsNode *yaml.Node) error
|
||||
DeeplyAssign(context Context, rhsNode *CandidateNode) error
|
||||
}
|
||||
|
||||
type dataTreeNavigator struct {
|
||||
@ -23,12 +22,7 @@ func NewDataTreeNavigator() DataTreeNavigator {
|
||||
return &dataTreeNavigator{}
|
||||
}
|
||||
|
||||
func (d *dataTreeNavigator) DeeplyAssign(context Context, path []interface{}, rhsNode *yaml.Node) error {
|
||||
|
||||
rhsCandidateNode := &CandidateNode{
|
||||
Path: path,
|
||||
Node: rhsNode,
|
||||
}
|
||||
func (d *dataTreeNavigator) DeeplyAssign(context Context, rhsCandidateNode *CandidateNode) error {
|
||||
|
||||
assignmentOp := &Operation{OperationType: assignOpType, Preferences: assignPreferences{}}
|
||||
|
||||
@ -36,7 +30,7 @@ func (d *dataTreeNavigator) DeeplyAssign(context Context, path []interface{}, rh
|
||||
|
||||
assignmentOpNode := &ExpressionNode{
|
||||
Operation: assignmentOp,
|
||||
LHS: createTraversalTree(path, traversePreferences{}, false),
|
||||
LHS: createTraversalTree(rhsCandidateNode.Path, traversePreferences{}, false),
|
||||
RHS: &ExpressionNode{Operation: rhsOp},
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,6 @@ import (
|
||||
"encoding/base64"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type base64Padder struct {
|
||||
@ -70,11 +68,5 @@ func (dec *base64Decoder) Decode() (*CandidateNode, error) {
|
||||
}
|
||||
}
|
||||
dec.readAnything = true
|
||||
return &CandidateNode{
|
||||
Node: &yaml.Node{
|
||||
Kind: yaml.ScalarNode,
|
||||
Tag: "!!str",
|
||||
Value: buf.String(),
|
||||
},
|
||||
}, nil
|
||||
return createStringScalarNode(buf.String()), nil
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
"io"
|
||||
|
||||
"github.com/dimchansky/utfbom"
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type csvObjectDecoder struct {
|
||||
@ -28,7 +27,7 @@ func (dec *csvObjectDecoder) Init(reader io.Reader) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dec *csvObjectDecoder) convertToYamlNode(content string) *yaml.Node {
|
||||
func (dec *csvObjectDecoder) convertToNode(content string) *CandidateNode {
|
||||
node, err := parseSnippet(content)
|
||||
if err != nil {
|
||||
return createScalarNode(content, content)
|
||||
@ -36,14 +35,14 @@ func (dec *csvObjectDecoder) convertToYamlNode(content string) *yaml.Node {
|
||||
return node
|
||||
}
|
||||
|
||||
func (dec *csvObjectDecoder) createObject(headerRow []string, contentRow []string) *yaml.Node {
|
||||
objectNode := &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map"}
|
||||
func (dec *csvObjectDecoder) createObject(headerRow []string, contentRow []string) *CandidateNode {
|
||||
objectNode := &CandidateNode{Kind: MappingNode, Tag: "!!map"}
|
||||
|
||||
for i, header := range headerRow {
|
||||
objectNode.Content = append(
|
||||
objectNode.Content,
|
||||
createScalarNode(header, header),
|
||||
dec.convertToYamlNode(contentRow[i]))
|
||||
dec.convertToNode(contentRow[i]))
|
||||
}
|
||||
return objectNode
|
||||
}
|
||||
@ -58,7 +57,7 @@ func (dec *csvObjectDecoder) Decode() (*CandidateNode, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rootArray := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
|
||||
rootArray := &CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
|
||||
|
||||
contentRow, err := dec.reader.Read()
|
||||
|
||||
@ -73,9 +72,7 @@ func (dec *csvObjectDecoder) Decode() (*CandidateNode, error) {
|
||||
}
|
||||
|
||||
return &CandidateNode{
|
||||
Node: &yaml.Node{
|
||||
Kind: yaml.DocumentNode,
|
||||
Content: []*yaml.Node{rootArray},
|
||||
},
|
||||
Kind: DocumentNode,
|
||||
Content: []*CandidateNode{rootArray},
|
||||
}, nil
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/magiconair/properties"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type propertiesDecoder struct {
|
||||
@ -52,16 +51,14 @@ func (dec *propertiesDecoder) applyPropertyComments(context Context, path []inte
|
||||
assignmentOp := &Operation{OperationType: assignOpType, Preferences: assignPreferences{}}
|
||||
|
||||
rhsCandidateNode := &CandidateNode{
|
||||
Path: path,
|
||||
Node: &yaml.Node{
|
||||
Tag: "!!str",
|
||||
Value: fmt.Sprintf("%v", path[len(path)-1]),
|
||||
HeadComment: dec.processComment(strings.Join(comments, "\n")),
|
||||
Kind: yaml.ScalarNode,
|
||||
},
|
||||
Path: path,
|
||||
Tag: "!!str",
|
||||
Value: fmt.Sprintf("%v", path[len(path)-1]),
|
||||
HeadComment: dec.processComment(strings.Join(comments, "\n")),
|
||||
Kind: ScalarNode,
|
||||
}
|
||||
|
||||
rhsCandidateNode.Node.Tag = guessTagFromCustomType(rhsCandidateNode.Node)
|
||||
rhsCandidateNode.Tag = rhsCandidateNode.guessTagFromCustomType()
|
||||
|
||||
rhsOp := &Operation{OperationType: referenceOpType, CandidateNode: rhsCandidateNode}
|
||||
|
||||
@ -87,15 +84,11 @@ func (dec *propertiesDecoder) applyProperty(context Context, properties *propert
|
||||
}
|
||||
}
|
||||
|
||||
rhsNode := &yaml.Node{
|
||||
Value: value,
|
||||
Tag: "!!str",
|
||||
Kind: yaml.ScalarNode,
|
||||
}
|
||||
rhsNode := createStringScalarNode(value)
|
||||
rhsNode.Tag = rhsNode.guessTagFromCustomType()
|
||||
rhsNode.Path = path
|
||||
|
||||
rhsNode.Tag = guessTagFromCustomType(rhsNode)
|
||||
|
||||
return dec.d.DeeplyAssign(context, path, rhsNode)
|
||||
return dec.d.DeeplyAssign(context, rhsNode)
|
||||
}
|
||||
|
||||
func (dec *propertiesDecoder) Decode() (*CandidateNode, error) {
|
||||
@ -118,10 +111,8 @@ func (dec *propertiesDecoder) Decode() (*CandidateNode, error) {
|
||||
properties.DisableExpansion = true
|
||||
|
||||
rootMap := &CandidateNode{
|
||||
Node: &yaml.Node{
|
||||
Kind: yaml.MappingNode,
|
||||
Tag: "!!map",
|
||||
},
|
||||
Kind: MappingNode,
|
||||
Tag: "!!map",
|
||||
}
|
||||
|
||||
context := Context{}
|
||||
@ -136,10 +127,8 @@ func (dec *propertiesDecoder) Decode() (*CandidateNode, error) {
|
||||
dec.finished = true
|
||||
|
||||
return &CandidateNode{
|
||||
Node: &yaml.Node{
|
||||
Kind: yaml.DocumentNode,
|
||||
Content: []*yaml.Node{rootMap.Node},
|
||||
},
|
||||
Kind: DocumentNode,
|
||||
Content: []*CandidateNode{rootMap},
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import (
|
||||
"time"
|
||||
|
||||
toml "github.com/pelletier/go-toml/v2/unstable"
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type tomlDecoder struct {
|
||||
@ -37,10 +36,9 @@ func (dec *tomlDecoder) Init(reader io.Reader) error {
|
||||
}
|
||||
dec.parser.Reset(buf.Bytes())
|
||||
dec.rootMap = &CandidateNode{
|
||||
Node: &yaml.Node{
|
||||
Kind: yaml.MappingNode,
|
||||
Tag: "!!map",
|
||||
}}
|
||||
Kind: MappingNode,
|
||||
Tag: "!!map",
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -64,10 +62,12 @@ func (dec *tomlDecoder) processKeyValueIntoMap(rootMap *CandidateNode, tomlNode
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
valueNode.Path = path
|
||||
|
||||
context := Context{}
|
||||
context = context.SingleChildContext(rootMap)
|
||||
|
||||
return dec.d.DeeplyAssign(context, path, valueNode)
|
||||
return dec.d.DeeplyAssign(context, valueNode)
|
||||
}
|
||||
|
||||
func (dec *tomlDecoder) decodeKeyValuesIntoMap(rootMap *CandidateNode, tomlNode *toml.Node) (bool, error) {
|
||||
@ -95,8 +95,8 @@ func (dec *tomlDecoder) decodeKeyValuesIntoMap(rootMap *CandidateNode, tomlNode
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (dec *tomlDecoder) createInlineTableMap(tomlNode *toml.Node) (*yaml.Node, error) {
|
||||
content := make([]*yaml.Node, 0)
|
||||
func (dec *tomlDecoder) createInlineTableMap(tomlNode *toml.Node) (*CandidateNode, error) {
|
||||
content := make([]*CandidateNode, 0)
|
||||
log.Debug("!! createInlineTableMap")
|
||||
|
||||
iterator := tomlNode.Children()
|
||||
@ -107,28 +107,26 @@ func (dec *tomlDecoder) createInlineTableMap(tomlNode *toml.Node) (*yaml.Node, e
|
||||
}
|
||||
|
||||
keyValues := &CandidateNode{
|
||||
Node: &yaml.Node{
|
||||
Kind: yaml.MappingNode,
|
||||
Tag: "!!map",
|
||||
},
|
||||
Kind: MappingNode,
|
||||
Tag: "!!map",
|
||||
}
|
||||
|
||||
if err := dec.processKeyValueIntoMap(keyValues, child); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
content = append(content, keyValues.Node.Content...)
|
||||
content = append(content, keyValues.Content...)
|
||||
}
|
||||
|
||||
return &yaml.Node{
|
||||
Kind: yaml.MappingNode,
|
||||
return &CandidateNode{
|
||||
Kind: MappingNode,
|
||||
Tag: "!!map",
|
||||
Content: content,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (dec *tomlDecoder) createArray(tomlNode *toml.Node) (*yaml.Node, error) {
|
||||
content := make([]*yaml.Node, 0)
|
||||
func (dec *tomlDecoder) createArray(tomlNode *toml.Node) (*CandidateNode, error) {
|
||||
content := make([]*CandidateNode, 0)
|
||||
iterator := tomlNode.Children()
|
||||
for iterator.Next() {
|
||||
child := iterator.Node()
|
||||
@ -139,43 +137,43 @@ func (dec *tomlDecoder) createArray(tomlNode *toml.Node) (*yaml.Node, error) {
|
||||
content = append(content, yamlNode)
|
||||
}
|
||||
|
||||
return &yaml.Node{
|
||||
Kind: yaml.SequenceNode,
|
||||
return &CandidateNode{
|
||||
Kind: SequenceNode,
|
||||
Tag: "!!seq",
|
||||
Content: content,
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
func (dec *tomlDecoder) createStringScalar(tomlNode *toml.Node) (*yaml.Node, error) {
|
||||
func (dec *tomlDecoder) createStringScalar(tomlNode *toml.Node) (*CandidateNode, error) {
|
||||
content := string(tomlNode.Data)
|
||||
return createScalarNode(content, content), nil
|
||||
}
|
||||
|
||||
func (dec *tomlDecoder) createBoolScalar(tomlNode *toml.Node) (*yaml.Node, error) {
|
||||
func (dec *tomlDecoder) createBoolScalar(tomlNode *toml.Node) (*CandidateNode, error) {
|
||||
content := string(tomlNode.Data)
|
||||
return createScalarNode(content == "true", content), nil
|
||||
}
|
||||
|
||||
func (dec *tomlDecoder) createIntegerScalar(tomlNode *toml.Node) (*yaml.Node, error) {
|
||||
func (dec *tomlDecoder) createIntegerScalar(tomlNode *toml.Node) (*CandidateNode, error) {
|
||||
content := string(tomlNode.Data)
|
||||
_, num, err := parseInt64(content)
|
||||
return createScalarNode(num, content), err
|
||||
}
|
||||
|
||||
func (dec *tomlDecoder) createDateTimeScalar(tomlNode *toml.Node) (*yaml.Node, error) {
|
||||
func (dec *tomlDecoder) createDateTimeScalar(tomlNode *toml.Node) (*CandidateNode, error) {
|
||||
content := string(tomlNode.Data)
|
||||
val, err := parseDateTime(time.RFC3339, content)
|
||||
return createScalarNode(val, content), err
|
||||
}
|
||||
|
||||
func (dec *tomlDecoder) createFloatScalar(tomlNode *toml.Node) (*yaml.Node, error) {
|
||||
func (dec *tomlDecoder) createFloatScalar(tomlNode *toml.Node) (*CandidateNode, error) {
|
||||
content := string(tomlNode.Data)
|
||||
num, err := strconv.ParseFloat(content, 64)
|
||||
return createScalarNode(num, content), err
|
||||
}
|
||||
|
||||
func (dec *tomlDecoder) decodeNode(tomlNode *toml.Node) (*yaml.Node, error) {
|
||||
func (dec *tomlDecoder) decodeNode(tomlNode *toml.Node) (*CandidateNode, error) {
|
||||
switch tomlNode.Kind {
|
||||
case toml.Key, toml.String:
|
||||
return dec.createStringScalar(tomlNode)
|
||||
@ -241,15 +239,13 @@ func (dec *tomlDecoder) Decode() (*CandidateNode, error) {
|
||||
// must have finished
|
||||
dec.finished = true
|
||||
|
||||
if len(dec.rootMap.Node.Content) == 0 {
|
||||
if len(dec.rootMap.Content) == 0 {
|
||||
return nil, io.EOF
|
||||
}
|
||||
|
||||
return &CandidateNode{
|
||||
Node: &yaml.Node{
|
||||
Kind: yaml.DocumentNode,
|
||||
Content: []*yaml.Node{dec.rootMap.Node},
|
||||
},
|
||||
Kind: DocumentNode,
|
||||
Content: []*CandidateNode{dec.rootMap},
|
||||
}, deferredError
|
||||
|
||||
}
|
||||
@ -259,9 +255,9 @@ func (dec *tomlDecoder) processTopLevelNode(currentNode *toml.Node) (bool, error
|
||||
var err error
|
||||
log.Debug("!!!!!!!!!!!!Going to process %v state is current %v", currentNode.Kind, NodeToString(dec.rootMap))
|
||||
if currentNode.Kind == toml.Table {
|
||||
runAgainstCurrentExp, err = dec.processTable((currentNode))
|
||||
runAgainstCurrentExp, err = dec.processTable(currentNode)
|
||||
} else if currentNode.Kind == toml.ArrayTable {
|
||||
runAgainstCurrentExp, err = dec.processArrayTable((currentNode))
|
||||
runAgainstCurrentExp, err = dec.processArrayTable(currentNode)
|
||||
} else {
|
||||
runAgainstCurrentExp, err = dec.decodeKeyValuesIntoMap(dec.rootMap, currentNode)
|
||||
}
|
||||
@ -281,10 +277,9 @@ func (dec *tomlDecoder) processTable(currentNode *toml.Node) (bool, error) {
|
||||
}
|
||||
|
||||
tableNodeValue := &CandidateNode{
|
||||
Node: &yaml.Node{
|
||||
Kind: yaml.MappingNode,
|
||||
Tag: "!!map",
|
||||
},
|
||||
Kind: MappingNode,
|
||||
Tag: "!!map",
|
||||
Path: fullPath,
|
||||
}
|
||||
|
||||
tableValue := dec.parser.Expression()
|
||||
@ -301,21 +296,19 @@ func (dec *tomlDecoder) processTable(currentNode *toml.Node) (bool, error) {
|
||||
c := Context{}
|
||||
|
||||
c = c.SingleChildContext(dec.rootMap)
|
||||
err = dec.d.DeeplyAssign(c, fullPath, tableNodeValue.Node)
|
||||
err = dec.d.DeeplyAssign(c, tableNodeValue)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return runAgainstCurrentExp, nil
|
||||
}
|
||||
|
||||
func (dec *tomlDecoder) arrayAppend(context Context, path []interface{}, rhsNode *yaml.Node) error {
|
||||
func (dec *tomlDecoder) arrayAppend(context Context, path []interface{}, rhsNode *CandidateNode) error {
|
||||
rhsCandidateNode := &CandidateNode{
|
||||
Path: path,
|
||||
Node: &yaml.Node{
|
||||
Kind: yaml.SequenceNode,
|
||||
Tag: "!!seq",
|
||||
Content: []*yaml.Node{rhsNode},
|
||||
},
|
||||
Path: path,
|
||||
Kind: SequenceNode,
|
||||
Tag: "!!seq",
|
||||
Content: []*CandidateNode{rhsNode},
|
||||
}
|
||||
|
||||
assignmentOp := &Operation{OperationType: addAssignOpType}
|
||||
@ -346,10 +339,9 @@ func (dec *tomlDecoder) processArrayTable(currentNode *toml.Node) (bool, error)
|
||||
}
|
||||
|
||||
tableNodeValue := &CandidateNode{
|
||||
Node: &yaml.Node{
|
||||
Kind: yaml.MappingNode,
|
||||
Tag: "!!map",
|
||||
},
|
||||
Kind: MappingNode,
|
||||
Tag: "!!map",
|
||||
Path: fullPath,
|
||||
}
|
||||
|
||||
tableValue := dec.parser.Expression()
|
||||
@ -363,7 +355,7 @@ func (dec *tomlDecoder) processArrayTable(currentNode *toml.Node) (bool, error)
|
||||
c = c.SingleChildContext(dec.rootMap)
|
||||
|
||||
// += function
|
||||
err = dec.arrayAppend(c, fullPath, tableNodeValue.Node)
|
||||
err = dec.arrayAppend(c, fullPath, tableNodeValue)
|
||||
|
||||
return runAgainstCurrentExp, err
|
||||
}
|
||||
|
@ -130,44 +130,65 @@ func (dec *yamlDecoder) convertStyle(oStyle yaml.Style) Style {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (dec *yamlDecoder) ConvertToCandidateNode(yamlNode *yaml.Node) *CandidateNode {
|
||||
kids := make([]*CandidateNode, len(yamlNode.Content))
|
||||
for i, v := range yamlNode.Content {
|
||||
kids[i] = dec.ConvertToCandidateNode(v)
|
||||
}
|
||||
func (dec *yamlDecoder) ConvertToCandidateNode(parent *CandidateNode, path []interface{}, yamlNode *yaml.Node) *CandidateNode {
|
||||
|
||||
return &CandidateNode{
|
||||
candidateNode := &CandidateNode{
|
||||
Kind: dec.convertKind(yamlNode.Kind),
|
||||
Style: dec.convertStyle(yamlNode.Style),
|
||||
|
||||
Tag: yamlNode.Tag,
|
||||
Value: yamlNode.Value,
|
||||
Anchor: yamlNode.Anchor,
|
||||
Alias: dec.ConvertToCandidateNode(yamlNode.Alias),
|
||||
Content: kids,
|
||||
Tag: yamlNode.Tag,
|
||||
Value: yamlNode.Value,
|
||||
Anchor: yamlNode.Anchor,
|
||||
|
||||
// not sure on this - check
|
||||
Alias: dec.ConvertToCandidateNode(parent, path, yamlNode.Alias),
|
||||
|
||||
HeadComment: yamlNode.HeadComment,
|
||||
LineComment: yamlNode.LineComment,
|
||||
FootComment: yamlNode.FootComment,
|
||||
Path: path,
|
||||
|
||||
// Parent: yamlNode.Parent,
|
||||
// Key: yamlNode.Key,
|
||||
Parent: parent,
|
||||
|
||||
// LeadingContent: yamlNode.LeadingContent,
|
||||
// TrailingContent: yamlNode.TrailingContent,
|
||||
|
||||
// Path: yamlNode.Path,
|
||||
// Document: yamlNode.Document,
|
||||
// Filename: yamlNode.Filename,
|
||||
Document: parent.Document,
|
||||
Filename: parent.Filename,
|
||||
|
||||
Line: yamlNode.Line,
|
||||
Column: yamlNode.Column,
|
||||
|
||||
// FileIndex: yamlNode.FileIndex,
|
||||
// EvaluateTogether: yamlNode.EvaluateTogether,
|
||||
// IsMapKey: yamlNode.IsMapKey,
|
||||
FileIndex: parent.FileIndex,
|
||||
}
|
||||
|
||||
kids := make([]*CandidateNode, len(yamlNode.Content))
|
||||
|
||||
if yamlNode.Kind == yaml.MappingNode {
|
||||
// children are key, values
|
||||
for i := 0; i < len(yamlNode.Content); i = i + 2 {
|
||||
key := yamlNode.Content[i]
|
||||
value := yamlNode.Content[i+1]
|
||||
|
||||
childPath := parent.createChildPath(key.Value)
|
||||
keyNode := dec.ConvertToCandidateNode(parent, childPath, key)
|
||||
keyNode.IsMapKey = true
|
||||
|
||||
valueNode := dec.ConvertToCandidateNode(parent, childPath, value)
|
||||
valueNode.Key = keyNode
|
||||
|
||||
kids[i] = keyNode
|
||||
kids[i+1] = valueNode
|
||||
}
|
||||
} else {
|
||||
// its just an normal array
|
||||
for i, v := range yamlNode.Content {
|
||||
childPath := parent.createChildPath(i)
|
||||
kids[i] = dec.ConvertToCandidateNode(parent, childPath, v)
|
||||
}
|
||||
}
|
||||
|
||||
candidateNode.Content = kids
|
||||
|
||||
return candidateNode
|
||||
|
||||
}
|
||||
|
||||
func (dec *yamlDecoder) Decode() (*CandidateNode, error) {
|
||||
@ -190,7 +211,7 @@ func (dec *yamlDecoder) Decode() (*CandidateNode, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
candidateNode := dec.ConvertToCandidateNode(&dataBucket)
|
||||
candidateNode := dec.ConvertToCandidateNode(&CandidateNode{}, make([]interface{}, 0), &dataBucket)
|
||||
|
||||
if dec.leadingContent != "" {
|
||||
candidateNode.LeadingContent = dec.leadingContent
|
||||
|
@ -258,10 +258,10 @@ func guessTagFromCustomType(node *yaml.Node) string {
|
||||
return guessedTag
|
||||
}
|
||||
|
||||
func parseSnippet(value string) (*yaml.Node, error) {
|
||||
func parseSnippet(value string) (*CandidateNode, error) {
|
||||
if value == "" {
|
||||
return &yaml.Node{
|
||||
Kind: yaml.ScalarNode,
|
||||
return &CandidateNode{
|
||||
Kind: ScalarNode,
|
||||
Tag: "!!null",
|
||||
}, nil
|
||||
}
|
||||
@ -274,10 +274,10 @@ func parseSnippet(value string) (*yaml.Node, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(parsedNode.Node.Content) == 0 {
|
||||
if len(parsedNode.Content) == 0 {
|
||||
return nil, fmt.Errorf("bad data")
|
||||
}
|
||||
result := unwrapDoc(parsedNode.Node)
|
||||
result := parsedNode.unwrapDocument()
|
||||
result.Line = 0
|
||||
result.Column = 0
|
||||
return result, err
|
||||
@ -382,13 +382,6 @@ func parseInt(numberString string) (int, error) {
|
||||
return int(parsed), err
|
||||
}
|
||||
|
||||
func createStringScalarNode(stringValue string) *yaml.Node {
|
||||
var node = &yaml.Node{Kind: yaml.ScalarNode}
|
||||
node.Value = stringValue
|
||||
node.Tag = "!!str"
|
||||
return node
|
||||
}
|
||||
|
||||
func headAndLineComment(node *yaml.Node) string {
|
||||
return headComment(node) + lineComment(node)
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/elliotchance/orderedmap"
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type traversePreferences struct {
|
||||
@ -17,7 +16,7 @@ type traversePreferences struct {
|
||||
}
|
||||
|
||||
func splat(context Context, prefs traversePreferences) (Context, error) {
|
||||
return traverseNodesWithArrayIndices(context, make([]*yaml.Node, 0), prefs)
|
||||
return traverseNodesWithArrayIndices(context, make([]*CandidateNode, 0), prefs)
|
||||
}
|
||||
|
||||
func traversePathOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
@ -37,39 +36,38 @@ func traversePathOperator(d *dataTreeNavigator, context Context, expressionNode
|
||||
|
||||
func traverse(context Context, matchingNode *CandidateNode, operation *Operation) (*list.List, error) {
|
||||
log.Debug("Traversing %v", NodeToString(matchingNode))
|
||||
value := matchingNode.Node
|
||||
|
||||
if value.Tag == "!!null" && operation.Value != "[]" && !context.DontAutoCreate {
|
||||
if matchingNode.Tag == "!!null" && operation.Value != "[]" && !context.DontAutoCreate {
|
||||
log.Debugf("Guessing kind")
|
||||
// we must have added this automatically, lets guess what it should be now
|
||||
switch operation.Value.(type) {
|
||||
case int, int64:
|
||||
log.Debugf("probably an array")
|
||||
value.Kind = yaml.SequenceNode
|
||||
matchingNode.Kind = SequenceNode
|
||||
default:
|
||||
log.Debugf("probably a map")
|
||||
value.Kind = yaml.MappingNode
|
||||
matchingNode.Kind = MappingNode
|
||||
}
|
||||
value.Tag = ""
|
||||
matchingNode.Tag = ""
|
||||
}
|
||||
|
||||
switch value.Kind {
|
||||
case yaml.MappingNode:
|
||||
log.Debug("its a map with %v entries", len(value.Content)/2)
|
||||
switch matchingNode.Kind {
|
||||
case MappingNode:
|
||||
log.Debug("its a map with %v entries", len(matchingNode.Content)/2)
|
||||
return traverseMap(context, matchingNode, createStringScalarNode(operation.StringValue), operation.Preferences.(traversePreferences), false)
|
||||
|
||||
case yaml.SequenceNode:
|
||||
log.Debug("its a sequence of %v things!", len(value.Content))
|
||||
case SequenceNode:
|
||||
log.Debug("its a sequence of %v things!", len(matchingNode.Content))
|
||||
return traverseArray(matchingNode, operation, operation.Preferences.(traversePreferences))
|
||||
|
||||
case yaml.AliasNode:
|
||||
case AliasNode:
|
||||
log.Debug("its an alias!")
|
||||
matchingNode.Node = matchingNode.Node.Alias
|
||||
matchingNode = matchingNode.Alias
|
||||
return traverse(context, matchingNode, operation)
|
||||
case yaml.DocumentNode:
|
||||
case DocumentNode:
|
||||
log.Debug("digging into doc node")
|
||||
|
||||
return traverse(context, matchingNode.CreateChildInMap(nil, matchingNode.Node.Content[0]), operation)
|
||||
return traverse(context, matchingNode.Content[0], operation)
|
||||
default:
|
||||
return list.New(), nil
|
||||
}
|
||||
@ -103,7 +101,7 @@ func traverseArrayOperator(d *dataTreeNavigator, context Context, expressionNode
|
||||
if expressionNode.Operation.Preferences != nil {
|
||||
prefs = expressionNode.Operation.Preferences.(traversePreferences)
|
||||
}
|
||||
var indicesToTraverse = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Content
|
||||
var indicesToTraverse = rhs.MatchingNodes.Front().Value.(*CandidateNode).Content
|
||||
|
||||
log.Debugf("indicesToTraverse %v", len(indicesToTraverse))
|
||||
|
||||
@ -115,7 +113,7 @@ func traverseArrayOperator(d *dataTreeNavigator, context Context, expressionNode
|
||||
return context.ChildContext(result.MatchingNodes), nil
|
||||
}
|
||||
|
||||
func traverseNodesWithArrayIndices(context Context, indicesToTraverse []*yaml.Node, prefs traversePreferences) (Context, error) {
|
||||
func traverseNodesWithArrayIndices(context Context, indicesToTraverse []*CandidateNode, prefs traversePreferences) (Context, error) {
|
||||
var matchingNodeMap = list.New()
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
@ -129,34 +127,33 @@ func traverseNodesWithArrayIndices(context Context, indicesToTraverse []*yaml.No
|
||||
return context.ChildContext(matchingNodeMap), nil
|
||||
}
|
||||
|
||||
func traverseArrayIndices(context Context, matchingNode *CandidateNode, indicesToTraverse []*yaml.Node, prefs traversePreferences) (*list.List, error) { // call this if doc / alias like the other traverse
|
||||
node := matchingNode.Node
|
||||
if node.Tag == "!!null" {
|
||||
func traverseArrayIndices(context Context, matchingNode *CandidateNode, indicesToTraverse []*CandidateNode, prefs traversePreferences) (*list.List, error) { // call this if doc / alias like the other traverse
|
||||
if matchingNode.Tag == "!!null" {
|
||||
log.Debugf("OperatorArrayTraverse got a null - turning it into an empty array")
|
||||
// auto vivification
|
||||
node.Tag = ""
|
||||
node.Kind = yaml.SequenceNode
|
||||
matchingNode.Tag = ""
|
||||
matchingNode.Kind = SequenceNode
|
||||
//check that the indices are numeric, if not, then we should create an object
|
||||
if len(indicesToTraverse) != 0 && indicesToTraverse[0].Tag != "!!int" {
|
||||
node.Kind = yaml.MappingNode
|
||||
matchingNode.Kind = MappingNode
|
||||
}
|
||||
}
|
||||
|
||||
if node.Kind == yaml.AliasNode {
|
||||
matchingNode.Node = node.Alias
|
||||
if matchingNode.Kind == AliasNode {
|
||||
matchingNode = matchingNode.Alias
|
||||
return traverseArrayIndices(context, matchingNode, indicesToTraverse, prefs)
|
||||
} else if node.Kind == yaml.SequenceNode {
|
||||
} else if matchingNode.Kind == SequenceNode {
|
||||
return traverseArrayWithIndices(matchingNode, indicesToTraverse, prefs)
|
||||
} else if node.Kind == yaml.MappingNode {
|
||||
} else if matchingNode.Kind == MappingNode {
|
||||
return traverseMapWithIndices(context, matchingNode, indicesToTraverse, prefs)
|
||||
} else if node.Kind == yaml.DocumentNode {
|
||||
return traverseArrayIndices(context, matchingNode.CreateChildInMap(nil, matchingNode.Node.Content[0]), indicesToTraverse, prefs)
|
||||
} else if matchingNode.Kind == DocumentNode {
|
||||
return traverseArrayIndices(context, matchingNode.Content[0], indicesToTraverse, prefs)
|
||||
}
|
||||
log.Debugf("OperatorArrayTraverse skipping %v as its a %v", matchingNode, node.Tag)
|
||||
log.Debugf("OperatorArrayTraverse skipping %v as its a %v", matchingNode, matchingNode.Tag)
|
||||
return list.New(), nil
|
||||
}
|
||||
|
||||
func traverseMapWithIndices(context Context, candidate *CandidateNode, indices []*yaml.Node, prefs traversePreferences) (*list.List, error) {
|
||||
func traverseMapWithIndices(context Context, candidate *CandidateNode, indices []*CandidateNode, prefs traversePreferences) (*list.List, error) {
|
||||
if len(indices) == 0 {
|
||||
return traverseMap(context, candidate, createStringScalarNode(""), prefs, true)
|
||||
}
|
||||
@ -175,15 +172,15 @@ func traverseMapWithIndices(context Context, candidate *CandidateNode, indices [
|
||||
return matchingNodeMap, nil
|
||||
}
|
||||
|
||||
func traverseArrayWithIndices(candidate *CandidateNode, indices []*yaml.Node, prefs traversePreferences) (*list.List, error) {
|
||||
func traverseArrayWithIndices(candidate *CandidateNode, indices []*CandidateNode, prefs traversePreferences) (*list.List, error) {
|
||||
log.Debug("traverseArrayWithIndices")
|
||||
var newMatches = list.New()
|
||||
node := unwrapDoc(candidate.Node)
|
||||
node := candidate.unwrapDocument()
|
||||
if len(indices) == 0 {
|
||||
log.Debug("splatting")
|
||||
var index int
|
||||
for index = 0; index < len(node.Content); index = index + 1 {
|
||||
newMatches.PushBack(candidate.CreateChildInArray(index, node.Content[index]))
|
||||
newMatches.PushBack(node.Content[index])
|
||||
}
|
||||
return newMatches, nil
|
||||
|
||||
@ -206,7 +203,7 @@ func traverseArrayWithIndices(candidate *CandidateNode, indices []*yaml.Node, pr
|
||||
node.Style = 0
|
||||
}
|
||||
|
||||
node.Content = append(node.Content, &yaml.Node{Tag: "!!null", Kind: yaml.ScalarNode, Value: "null"})
|
||||
node.Content = append(node.Content, &CandidateNode{Tag: "!!null", Kind: ScalarNode, Value: "null"})
|
||||
contentLength = len(node.Content)
|
||||
}
|
||||
|
||||
@ -218,16 +215,16 @@ func traverseArrayWithIndices(candidate *CandidateNode, indices []*yaml.Node, pr
|
||||
return nil, fmt.Errorf("index [%v] out of range, array size is %v", index, contentLength)
|
||||
}
|
||||
|
||||
newMatches.PushBack(candidate.CreateChildInArray(index, node.Content[indexToUse]))
|
||||
newMatches.PushBack(node.Content[indexToUse])
|
||||
}
|
||||
return newMatches, nil
|
||||
}
|
||||
|
||||
func keyMatches(key *yaml.Node, wantedKey string) bool {
|
||||
func keyMatches(key *CandidateNode, wantedKey string) bool {
|
||||
return matchKey(key.Value, wantedKey)
|
||||
}
|
||||
|
||||
func traverseMap(context Context, matchingNode *CandidateNode, keyNode *yaml.Node, prefs traversePreferences, splat bool) (*list.List, error) {
|
||||
func traverseMap(context Context, matchingNode *CandidateNode, keyNode *CandidateNode, prefs traversePreferences, splat bool) (*list.List, error) {
|
||||
var newMatches = orderedmap.NewOrderedMap()
|
||||
err := doTraverseMap(newMatches, matchingNode, keyNode.Value, prefs, splat)
|
||||
|
||||
@ -238,26 +235,21 @@ func traverseMap(context Context, matchingNode *CandidateNode, keyNode *yaml.Nod
|
||||
if !splat && !prefs.DontAutoCreate && !context.DontAutoCreate && newMatches.Len() == 0 {
|
||||
log.Debugf("no matches, creating one")
|
||||
//no matches, create one automagically
|
||||
valueNode := &yaml.Node{Tag: "!!null", Kind: yaml.ScalarNode, Value: "null"}
|
||||
valueNode := &CandidateNode{Tag: "!!null", Kind: ScalarNode, Value: "null"}
|
||||
|
||||
node := matchingNode.Node
|
||||
|
||||
if len(node.Content) == 0 {
|
||||
node.Style = 0
|
||||
if len(matchingNode.Content) == 0 {
|
||||
matchingNode.Style = 0
|
||||
}
|
||||
|
||||
node.Content = append(node.Content, keyNode, valueNode)
|
||||
matchingNode.Content = append(matchingNode.Content, keyNode, valueNode)
|
||||
|
||||
if prefs.IncludeMapKeys {
|
||||
log.Debug("including key")
|
||||
candidateNode := matchingNode.CreateChildInMap(keyNode, keyNode)
|
||||
candidateNode.IsMapKey = true
|
||||
newMatches.Set(fmt.Sprintf("keyOf-%v", candidateNode.GetKey()), candidateNode)
|
||||
newMatches.Set(keyNode.GetKey(), keyNode)
|
||||
}
|
||||
if !prefs.DontIncludeMapValues {
|
||||
log.Debug("including value")
|
||||
candidateNode := matchingNode.CreateChildInMap(keyNode, valueNode)
|
||||
newMatches.Set(candidateNode.GetKey(), candidateNode)
|
||||
newMatches.Set(valueNode.GetKey(), valueNode)
|
||||
}
|
||||
}
|
||||
|
||||
@ -270,14 +262,12 @@ func traverseMap(context Context, matchingNode *CandidateNode, keyNode *yaml.Nod
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func doTraverseMap(newMatches *orderedmap.OrderedMap, candidate *CandidateNode, wantedKey string, prefs traversePreferences, splat bool) error {
|
||||
func doTraverseMap(newMatches *orderedmap.OrderedMap, node *CandidateNode, wantedKey string, prefs traversePreferences, splat bool) error {
|
||||
// value.Content is a concatenated array of key, value,
|
||||
// so keys are in the even indices, values in odd.
|
||||
// merge aliases are defined first, but we only want to traverse them
|
||||
// if we don't find a match directly on this node first.
|
||||
|
||||
node := candidate.Node
|
||||
|
||||
var contents = node.Content
|
||||
for index := 0; index < len(contents); index = index + 2 {
|
||||
key := contents[index]
|
||||
@ -287,7 +277,7 @@ func doTraverseMap(newMatches *orderedmap.OrderedMap, candidate *CandidateNode,
|
||||
//skip the 'merge' tag, find a direct match first
|
||||
if key.Tag == "!!merge" && !prefs.DontFollowAlias {
|
||||
log.Debug("Merge anchor")
|
||||
err := traverseMergeAnchor(newMatches, candidate, value, wantedKey, prefs, splat)
|
||||
err := traverseMergeAnchor(newMatches, node, value, wantedKey, prefs, splat)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -295,14 +285,11 @@ func doTraverseMap(newMatches *orderedmap.OrderedMap, candidate *CandidateNode,
|
||||
log.Debug("MATCHED")
|
||||
if prefs.IncludeMapKeys {
|
||||
log.Debug("including key")
|
||||
candidateNode := candidate.CreateChildInMap(key, key)
|
||||
candidateNode.IsMapKey = true
|
||||
newMatches.Set(fmt.Sprintf("keyOf-%v", candidateNode.GetKey()), candidateNode)
|
||||
newMatches.Set(key.GetKey(), key)
|
||||
}
|
||||
if !prefs.DontIncludeMapValues {
|
||||
log.Debug("including value")
|
||||
candidateNode := candidate.CreateChildInMap(key, value)
|
||||
newMatches.Set(candidateNode.GetKey(), candidateNode)
|
||||
newMatches.Set(value.GetKey(), value)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -310,15 +297,15 @@ func doTraverseMap(newMatches *orderedmap.OrderedMap, candidate *CandidateNode,
|
||||
return nil
|
||||
}
|
||||
|
||||
func traverseMergeAnchor(newMatches *orderedmap.OrderedMap, originalCandidate *CandidateNode, value *yaml.Node, wantedKey string, prefs traversePreferences, splat bool) error {
|
||||
func traverseMergeAnchor(newMatches *orderedmap.OrderedMap, originalCandidate *CandidateNode, value *CandidateNode, wantedKey string, prefs traversePreferences, splat bool) error {
|
||||
switch value.Kind {
|
||||
case yaml.AliasNode:
|
||||
if value.Alias.Kind != yaml.MappingNode {
|
||||
case AliasNode:
|
||||
if value.Alias.Kind != MappingNode {
|
||||
return fmt.Errorf("can only use merge anchors with maps (!!map), but got %v", value.Alias.Tag)
|
||||
}
|
||||
candidateNode := originalCandidate.CreateReplacement(value.Alias)
|
||||
return doTraverseMap(newMatches, candidateNode, wantedKey, prefs, splat)
|
||||
case yaml.SequenceNode:
|
||||
// candidateNode := originalCandidate.CreateReplacement(value.Alias)
|
||||
return doTraverseMap(newMatches, value.Alias, wantedKey, prefs, splat)
|
||||
case SequenceNode:
|
||||
for _, childValue := range value.Content {
|
||||
err := traverseMergeAnchor(newMatches, originalCandidate, childValue, wantedKey, prefs, splat)
|
||||
if err != nil {
|
||||
@ -331,6 +318,6 @@ func traverseMergeAnchor(newMatches *orderedmap.OrderedMap, originalCandidate *C
|
||||
|
||||
func traverseArray(candidate *CandidateNode, operation *Operation, prefs traversePreferences) (*list.List, error) {
|
||||
log.Debug("operation Value %v", operation.Value)
|
||||
indices := []*yaml.Node{{Value: operation.StringValue}}
|
||||
indices := []*CandidateNode{{Value: operation.StringValue}}
|
||||
return traverseArrayWithIndices(candidate, indices, prefs)
|
||||
}
|
||||
|
@ -94,6 +94,30 @@ var tomlScenarios = []formatScenario{
|
||||
expected: "person:\n name: hello\n address: 12 cat st\n",
|
||||
scenarioType: "decode",
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
description: "Parse: include key information",
|
||||
input: "person.name = \"hello\"\nperson.address = \"12 cat st\"\n",
|
||||
expression: ".person.name | key",
|
||||
expected: "name\n",
|
||||
scenarioType: "roundtrip",
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
description: "Parse: include parent information",
|
||||
input: "person.name = \"hello\"\nperson.address = \"12 cat st\"\n",
|
||||
expression: ".person.name | parent",
|
||||
expected: "person\n",
|
||||
scenarioType: "decode",
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
description: "Parse: include path information",
|
||||
input: "person.name = \"hello\"\nperson.address = \"12 cat st\"\n",
|
||||
expression: ".person.name | path",
|
||||
expected: "- person\n- name\n",
|
||||
scenarioType: "decode",
|
||||
},
|
||||
{
|
||||
description: "Encode: Scalar",
|
||||
input: "person.name = \"hello\"\nperson.address = \"12 cat st\"\n",
|
||||
|
Loading…
Reference in New Issue
Block a user