goccy wip

This commit is contained in:
Mike Farah 2023-10-06 10:36:28 +11:00
parent 7afe3e90ee
commit f3743204ed
4 changed files with 118 additions and 35 deletions

View File

@ -1 +1,2 @@
a: the cute cat wrote a long sentence that wasn't wrapped at all. the cute cat wrote a long sentence that wasn't wrapped at all. a: #things
meow

View File

@ -2,22 +2,53 @@ package yqlib
import ( import (
"fmt" "fmt"
"strings"
yaml "github.com/goccy/go-yaml"
"github.com/goccy/go-yaml/ast" "github.com/goccy/go-yaml/ast"
goccyToken "github.com/goccy/go-yaml/token" goccyToken "github.com/goccy/go-yaml/token"
) )
func (o *CandidateNode) goccyDecodeIntoChild(childNode ast.Node, anchorMap map[string]*CandidateNode) (*CandidateNode, error) { func (o *CandidateNode) goccyDecodeIntoChild(childNode ast.Node, cm yaml.CommentMap) (*CandidateNode, error) {
newChild := o.CreateChild() newChild := o.CreateChild()
err := newChild.UnmarshalGoccyYAML(childNode, anchorMap) err := newChild.UnmarshalGoccyYAML(childNode, cm)
return newChild, err return newChild, err
} }
func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, anchorMap map[string]*CandidateNode) error { func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap) error {
log.Debugf("UnmarshalYAML %v", node) log.Debugf("UnmarshalYAML %v", node)
log.Debugf("UnmarshalYAML %v", node.Type().String()) log.Debugf("UnmarshalYAML %v", node.Type().String())
log.Debugf("UnmarshalYAML Value: %v", node.String()) log.Debugf("UnmarshalYAML Node Value: %v", node.String())
log.Debugf("UnmarshalYAML Node GetComment: %v", node.GetComment())
if node.GetComment() != nil {
commentMapComments := cm[node.GetPath()]
for _, comment := range node.GetComment().Comments {
// need to use the comment map to find the position :/
log.Debugf("%v has a comment of [%v]", node.GetPath(), comment.Token.Value)
for _, commentMapComment := range commentMapComments {
commentMapValue := strings.Join(commentMapComment.Texts, "\n")
if commentMapValue == comment.Token.Value {
log.Debug("found a matching entry in comment map")
// we found the comment in the comment map,
// now we can process the position
switch commentMapComment.Position {
case yaml.CommentHeadPosition:
o.HeadComment = comment.String()
log.Debug("its a head comment %v", comment.String())
case yaml.CommentLinePosition:
o.LineComment = comment.String()
log.Debug("its a line comment %v", comment.String())
case yaml.CommentFootPosition:
o.FootComment = comment.String()
log.Debug("its a foot comment %v", comment.String())
}
}
}
}
}
o.Value = node.String() o.Value = node.String()
switch node.Type() { switch node.Type() {
@ -43,40 +74,46 @@ func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, anchorMap map[string]*
o.Tag = "!!str" o.Tag = "!!str"
o.Style = LiteralStyle o.Style = LiteralStyle
astLiteral := node.(*ast.LiteralNode) astLiteral := node.(*ast.LiteralNode)
log.Debugf("astLiteral.Start.Type %v", astLiteral.Start.Type)
if astLiteral.Start.Type == goccyToken.FoldedType { if astLiteral.Start.Type == goccyToken.FoldedType {
log.Debugf("folded Type %v", astLiteral.Start.Type)
o.Style = FoldedStyle o.Style = FoldedStyle
} }
log.Debug("startvalue: %v ", node.(*ast.LiteralNode).Start.Value) log.Debug("start value: %v ", node.(*ast.LiteralNode).Start.Value)
log.Debug("startvalue: %v ", node.(*ast.LiteralNode).Start.Type) log.Debug("start value: %v ", node.(*ast.LiteralNode).Start.Type)
// TODO: here I could put the original value with line breaks
// to solve the multiline > problem
o.Value = astLiteral.Value.Value o.Value = astLiteral.Value.Value
case ast.TagType: case ast.TagType:
o.UnmarshalGoccyYAML(node.(*ast.TagNode).Value, anchorMap) o.UnmarshalGoccyYAML(node.(*ast.TagNode).Value, cm)
o.Tag = node.(*ast.TagNode).Start.Value o.Tag = node.(*ast.TagNode).Start.Value
case ast.MappingValueType, ast.MappingType: case ast.MappingType:
log.Debugf("UnmarshalYAML - a mapping node") log.Debugf("UnmarshalYAML - a mapping node")
o.Kind = MappingNode o.Kind = MappingNode
o.Tag = "!!map" o.Tag = "!!map"
if node.Type() == ast.MappingType { mappingNode := node.(*ast.MappingNode)
if mappingNode.IsFlowStyle {
o.Style = FlowStyle o.Style = FlowStyle
} }
for _, mappingValueNode := range mappingNode.Values {
astMapIter := node.(ast.MapNode).MapRange() err := o.goccyProcessMappingValueNode(mappingValueNode, cm)
for astMapIter.Next() {
log.Debug("UnmarshalYAML map entry %v", astMapIter.Key().String())
keyNode, err := o.goccyDecodeIntoChild(astMapIter.Key(), anchorMap)
if err != nil { if err != nil {
return err return ast.ErrInvalidAnchorName
} }
}
keyNode.IsMapKey = true if mappingNode.FootComment != nil {
log.Debug("UnmarshalYAML map value %v", astMapIter.Value().String()) log.Debugf("mapping node has a foot comment of: %v", mappingNode.FootComment)
valueNode, err := o.goccyDecodeIntoChild(astMapIter.Value(), anchorMap) o.FootComment = mappingNode.FootComment.String()
if err != nil { }
return err case ast.MappingValueType:
} log.Debugf("UnmarshalYAML - a mapping node")
o.Kind = MappingNode
o.Content = append(o.Content, keyNode, valueNode) o.Tag = "!!map"
mappingValueNode := node.(*ast.MappingValueNode)
err := o.goccyProcessMappingValueNode(mappingValueNode, cm)
if err != nil {
return ast.ErrInvalidAnchorName
} }
case ast.SequenceType: case ast.SequenceType:
log.Debugf("UnmarshalYAML - a sequence node") log.Debugf("UnmarshalYAML - a sequence node")
@ -95,7 +132,7 @@ func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, anchorMap map[string]*
keyNode.Kind = ScalarNode keyNode.Kind = ScalarNode
keyNode.Value = fmt.Sprintf("%v", i) keyNode.Value = fmt.Sprintf("%v", i)
valueNode, err := o.goccyDecodeIntoChild(astSeq[i], anchorMap) valueNode, err := o.goccyDecodeIntoChild(astSeq[i], cm)
if err != nil { if err != nil {
return err return err
} }
@ -110,3 +147,26 @@ func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, anchorMap map[string]*
log.Debugf("KIND: %v", o.Kind) log.Debugf("KIND: %v", o.Kind)
return nil return nil
} }
func (o *CandidateNode) goccyProcessMappingValueNode(mappingEntry *ast.MappingValueNode, cm yaml.CommentMap) error {
log.Debug("UnmarshalYAML MAP KEY entry %v", mappingEntry.Key)
keyNode, err := o.goccyDecodeIntoChild(mappingEntry.Key, cm)
if err != nil {
return err
}
keyNode.IsMapKey = true
log.Debug("UnmarshalYAML MAP VALUE entry %v", mappingEntry.Value)
valueNode, err := o.goccyDecodeIntoChild(mappingEntry.Value, cm)
if err != nil {
return err
}
if mappingEntry.FootComment != nil {
valueNode.FootComment = mappingEntry.FootComment.String()
}
o.Content = append(o.Content, keyNode, valueNode)
return nil
}

View File

@ -11,6 +11,7 @@ import (
type goccyYamlDecoder struct { type goccyYamlDecoder struct {
decoder yaml.Decoder decoder yaml.Decoder
cm yaml.CommentMap
} }
func NewGoccyYAMLDecoder() Decoder { func NewGoccyYAMLDecoder() Decoder {
@ -18,7 +19,8 @@ func NewGoccyYAMLDecoder() Decoder {
} }
func (dec *goccyYamlDecoder) Init(reader io.Reader) error { func (dec *goccyYamlDecoder) Init(reader io.Reader) error {
dec.decoder = *yaml.NewDecoder(reader) dec.cm = yaml.CommentMap{}
dec.decoder = *yaml.NewDecoder(reader, yaml.CommentToMap(dec.cm))
return nil return nil
} }
@ -28,15 +30,11 @@ func (dec *goccyYamlDecoder) Decode() (*CandidateNode, error) {
err := dec.decoder.Decode(&ast) err := dec.decoder.Decode(&ast)
if err != nil { if err != nil {
log.Debug("badasda: %v", err)
return nil, err return nil, err
} }
log.Debug("ASTasdasdadasd: %v", ast.Type().String())
candidateNode := &CandidateNode{} candidateNode := &CandidateNode{}
candidateNode.UnmarshalGoccyYAML(ast, nil) candidateNode.UnmarshalGoccyYAML(ast, dec.cm)
return candidateNode, nil return candidateNode, nil
} }

View File

@ -32,6 +32,12 @@ var goccyYamlFormatScenarios = []formatScenario{
// expected: "{mike: 3}\n", // expected: "{mike: 3}\n",
// }, // },
// { // {
// description: "basic - map multiple entries",
// skipDoc: true,
// input: "mike: 3\nfred: 12\n",
// expected: "mike: 3\nfred: 12\n",
// },
// {
// description: "basic - 3.1", // description: "basic - 3.1",
// skipDoc: true, // skipDoc: true,
// input: "{\nmike: 3\n}", // input: "{\nmike: 3\n}",
@ -91,11 +97,29 @@ var goccyYamlFormatScenarios = []formatScenario{
// input: "a: |-\n meow\n", // input: "a: |-\n meow\n",
// expected: "a: |-\n meow\n", // expected: "a: |-\n meow\n",
// }, // },
// {
// description: "basic - line comment",
// skipDoc: true,
// input: "a: meow # line comment\n",
// expected: "a: meow # line comment\n",
// },
// {
// description: "basic - line comment",
// skipDoc: true,
// input: "# head comment\na: #line comment\n meow\n",
// expected: "# head comment\na: meow #line comment\n", // go-yaml does this
// },
{ {
description: "basic - string block", description: "basic - foot comment",
skipDoc: true, skipDoc: true,
input: "a: >\n meow\n", input: "a: meow\n# foot comment\n",
expected: "a: >\n meow\n", expected: "a: meow\n# foot comment\n",
},
{
description: "basic - foot comment",
skipDoc: true,
input: "a: meow\nb: woof\n# foot comment\n",
expected: "a: meow\nb: woof\n# foot comment\n",
}, },
} }