summaryrefslogtreecommitdiffstats
path: root/dependencies/pkg/mod/github.com/goccy/go-yaml@v1.9.6/printer
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 12:36:04 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 12:36:04 +0000
commitb09c6d56832eb1718c07d74abf3bc6ae3fe4e030 (patch)
treed2caec2610d4ea887803ec9e9c3cd77136c448ba /dependencies/pkg/mod/github.com/goccy/go-yaml@v1.9.6/printer
parentInitial commit. (diff)
downloadicingadb-upstream.tar.xz
icingadb-upstream.zip
Adding upstream version 1.1.0.upstream/1.1.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dependencies/pkg/mod/github.com/goccy/go-yaml@v1.9.6/printer')
-rw-r--r--dependencies/pkg/mod/github.com/goccy/go-yaml@v1.9.6/printer/printer.go352
-rw-r--r--dependencies/pkg/mod/github.com/goccy/go-yaml@v1.9.6/printer/printer_test.go223
2 files changed, 575 insertions, 0 deletions
diff --git a/dependencies/pkg/mod/github.com/goccy/go-yaml@v1.9.6/printer/printer.go b/dependencies/pkg/mod/github.com/goccy/go-yaml@v1.9.6/printer/printer.go
new file mode 100644
index 0000000..d5e25dc
--- /dev/null
+++ b/dependencies/pkg/mod/github.com/goccy/go-yaml@v1.9.6/printer/printer.go
@@ -0,0 +1,352 @@
+package printer
+
+import (
+ "fmt"
+ "math"
+ "strings"
+
+ "github.com/fatih/color"
+ "github.com/goccy/go-yaml/ast"
+ "github.com/goccy/go-yaml/token"
+)
+
+// Property additional property set for each the token
+type Property struct {
+ Prefix string
+ Suffix string
+}
+
+// PrintFunc returns property instance
+type PrintFunc func() *Property
+
+// Printer create text from token collection or ast
+type Printer struct {
+ LineNumber bool
+ LineNumberFormat func(num int) string
+ MapKey PrintFunc
+ Anchor PrintFunc
+ Alias PrintFunc
+ Bool PrintFunc
+ String PrintFunc
+ Number PrintFunc
+}
+
+func defaultLineNumberFormat(num int) string {
+ return fmt.Sprintf("%2d | ", num)
+}
+
+func (p *Printer) property(tk *token.Token) *Property {
+ prop := &Property{}
+ switch tk.PreviousType() {
+ case token.AnchorType:
+ if p.Anchor != nil {
+ return p.Anchor()
+ }
+ return prop
+ case token.AliasType:
+ if p.Alias != nil {
+ return p.Alias()
+ }
+ return prop
+ }
+ switch tk.NextType() {
+ case token.MappingValueType:
+ if p.MapKey != nil {
+ return p.MapKey()
+ }
+ return prop
+ }
+ switch tk.Type {
+ case token.BoolType:
+ if p.Bool != nil {
+ return p.Bool()
+ }
+ return prop
+ case token.AnchorType:
+ if p.Anchor != nil {
+ return p.Anchor()
+ }
+ return prop
+ case token.AliasType:
+ if p.Anchor != nil {
+ return p.Alias()
+ }
+ return prop
+ case token.StringType, token.SingleQuoteType, token.DoubleQuoteType:
+ if p.String != nil {
+ return p.String()
+ }
+ return prop
+ case token.IntegerType, token.FloatType:
+ if p.Number != nil {
+ return p.Number()
+ }
+ return prop
+ default:
+ }
+ return prop
+}
+
+// PrintTokens create text from token collection
+func (p *Printer) PrintTokens(tokens token.Tokens) string {
+ if len(tokens) == 0 {
+ return ""
+ }
+ if p.LineNumber {
+ if p.LineNumberFormat == nil {
+ p.LineNumberFormat = defaultLineNumberFormat
+ }
+ }
+ texts := []string{}
+ lineNumber := tokens[0].Position.Line
+ for _, tk := range tokens {
+ lines := strings.Split(tk.Origin, "\n")
+ prop := p.property(tk)
+ header := ""
+ if p.LineNumber {
+ header = p.LineNumberFormat(lineNumber)
+ }
+ if len(lines) == 1 {
+ line := prop.Prefix + lines[0] + prop.Suffix
+ if len(texts) == 0 {
+ texts = append(texts, header+line)
+ lineNumber++
+ } else {
+ text := texts[len(texts)-1]
+ texts[len(texts)-1] = text + line
+ }
+ } else {
+ for idx, src := range lines {
+ if p.LineNumber {
+ header = p.LineNumberFormat(lineNumber)
+ }
+ line := prop.Prefix + src + prop.Suffix
+ if idx == 0 {
+ if len(texts) == 0 {
+ texts = append(texts, header+line)
+ lineNumber++
+ } else {
+ text := texts[len(texts)-1]
+ texts[len(texts)-1] = text + line
+ }
+ } else {
+ texts = append(texts, fmt.Sprintf("%s%s", header, line))
+ lineNumber++
+ }
+ }
+ }
+ }
+ return strings.Join(texts, "\n")
+}
+
+// PrintNode create text from ast.Node
+func (p *Printer) PrintNode(node ast.Node) []byte {
+ return []byte(fmt.Sprintf("%+v\n", node))
+}
+
+const escape = "\x1b"
+
+func format(attr color.Attribute) string {
+ return fmt.Sprintf("%s[%dm", escape, attr)
+}
+
+func (p *Printer) setDefaultColorSet() {
+ p.Bool = func() *Property {
+ return &Property{
+ Prefix: format(color.FgHiMagenta),
+ Suffix: format(color.Reset),
+ }
+ }
+ p.Number = func() *Property {
+ return &Property{
+ Prefix: format(color.FgHiMagenta),
+ Suffix: format(color.Reset),
+ }
+ }
+ p.MapKey = func() *Property {
+ return &Property{
+ Prefix: format(color.FgHiCyan),
+ Suffix: format(color.Reset),
+ }
+ }
+ p.Anchor = func() *Property {
+ return &Property{
+ Prefix: format(color.FgHiYellow),
+ Suffix: format(color.Reset),
+ }
+ }
+ p.Alias = func() *Property {
+ return &Property{
+ Prefix: format(color.FgHiYellow),
+ Suffix: format(color.Reset),
+ }
+ }
+ p.String = func() *Property {
+ return &Property{
+ Prefix: format(color.FgHiGreen),
+ Suffix: format(color.Reset),
+ }
+ }
+}
+
+func (p *Printer) PrintErrorMessage(msg string, isColored bool) string {
+ if isColored {
+ return fmt.Sprintf("%s%s%s",
+ format(color.FgHiRed),
+ msg,
+ format(color.Reset),
+ )
+ }
+ return msg
+}
+
+func (p *Printer) removeLeftSideNewLineChar(src string) string {
+ return strings.TrimLeft(strings.TrimLeft(strings.TrimLeft(src, "\r"), "\n"), "\r\n")
+}
+
+func (p *Printer) removeRightSideNewLineChar(src string) string {
+ return strings.TrimRight(strings.TrimRight(strings.TrimRight(src, "\r"), "\n"), "\r\n")
+}
+
+func (p *Printer) removeRightSideWhiteSpaceChar(src string) string {
+ return p.removeRightSideNewLineChar(strings.TrimRight(src, " "))
+}
+
+func (p *Printer) newLineCount(s string) int {
+ src := []rune(s)
+ size := len(src)
+ cnt := 0
+ for i := 0; i < size; i++ {
+ c := src[i]
+ switch c {
+ case '\r':
+ if i+1 < size && src[i+1] == '\n' {
+ i++
+ }
+ cnt++
+ case '\n':
+ cnt++
+ }
+ }
+ return cnt
+}
+
+func (p *Printer) isNewLineLastChar(s string) bool {
+ for i := len(s) - 1; i > 0; i-- {
+ c := s[i]
+ switch c {
+ case ' ':
+ continue
+ case '\n', '\r':
+ return true
+ }
+ break
+ }
+ return false
+}
+
+func (p *Printer) printBeforeTokens(tk *token.Token, minLine, extLine int) token.Tokens {
+ for {
+ if tk.Prev == nil {
+ break
+ }
+ if tk.Prev.Position.Line < minLine {
+ break
+ }
+ tk = tk.Prev
+ }
+ minTk := tk.Clone()
+ if minTk.Prev != nil {
+ // add white spaces to minTk by prev token
+ prev := minTk.Prev
+ whiteSpaceLen := len(prev.Origin) - len(strings.TrimRight(prev.Origin, " "))
+ minTk.Origin = strings.Repeat(" ", whiteSpaceLen) + minTk.Origin
+ }
+ minTk.Origin = p.removeLeftSideNewLineChar(minTk.Origin)
+ tokens := token.Tokens{minTk}
+ tk = minTk.Next
+ for tk != nil && tk.Position.Line <= extLine {
+ clonedTk := tk.Clone()
+ tokens.Add(clonedTk)
+ tk = clonedTk.Next
+ }
+ lastTk := tokens[len(tokens)-1]
+ trimmedOrigin := p.removeRightSideWhiteSpaceChar(lastTk.Origin)
+ suffix := lastTk.Origin[len(trimmedOrigin):]
+ lastTk.Origin = trimmedOrigin
+
+ if lastTk.Next != nil && len(suffix) > 1 {
+ next := lastTk.Next.Clone()
+ // add suffix to header of next token
+ if suffix[0] == '\n' || suffix[0] == '\r' {
+ suffix = suffix[1:]
+ }
+ next.Origin = suffix + next.Origin
+ lastTk.Next = next
+ }
+ return tokens
+}
+
+func (p *Printer) printAfterTokens(tk *token.Token, maxLine int) token.Tokens {
+ tokens := token.Tokens{}
+ if tk == nil {
+ return tokens
+ }
+ if tk.Position.Line > maxLine {
+ return tokens
+ }
+ minTk := tk.Clone()
+ minTk.Origin = p.removeLeftSideNewLineChar(minTk.Origin)
+ tokens.Add(minTk)
+ tk = minTk.Next
+ for tk != nil && tk.Position.Line <= maxLine {
+ clonedTk := tk.Clone()
+ tokens.Add(clonedTk)
+ tk = clonedTk.Next
+ }
+ return tokens
+}
+
+func (p *Printer) setupErrorTokenFormat(annotateLine int, isColored bool) {
+ prefix := func(annotateLine, num int) string {
+ if annotateLine == num {
+ return fmt.Sprintf("> %2d | ", num)
+ }
+ return fmt.Sprintf(" %2d | ", num)
+ }
+ p.LineNumber = true
+ p.LineNumberFormat = func(num int) string {
+ if isColored {
+ fn := color.New(color.Bold, color.FgHiWhite).SprintFunc()
+ return fn(prefix(annotateLine, num))
+ }
+ return prefix(annotateLine, num)
+ }
+ if isColored {
+ p.setDefaultColorSet()
+ }
+}
+
+func (p *Printer) PrintErrorToken(tk *token.Token, isColored bool) string {
+ errToken := tk
+ curLine := tk.Position.Line
+ curExtLine := curLine + p.newLineCount(p.removeLeftSideNewLineChar(tk.Origin))
+ if p.isNewLineLastChar(tk.Origin) {
+ // if last character ( exclude white space ) is new line character, ignore it.
+ curExtLine--
+ }
+
+ minLine := int(math.Max(float64(curLine-3), 1))
+ maxLine := curExtLine + 3
+ p.setupErrorTokenFormat(curLine, isColored)
+
+ beforeTokens := p.printBeforeTokens(tk, minLine, curExtLine)
+ lastTk := beforeTokens[len(beforeTokens)-1]
+ afterTokens := p.printAfterTokens(lastTk.Next, maxLine)
+
+ beforeSource := p.PrintTokens(beforeTokens)
+ prefixSpaceNum := len(fmt.Sprintf(" %2d | ", curLine))
+ annotateLine := strings.Repeat(" ", prefixSpaceNum+errToken.Position.Column-1) + "^"
+ afterSource := p.PrintTokens(afterTokens)
+ return fmt.Sprintf("%s\n%s\n%s", beforeSource, annotateLine, afterSource)
+}
diff --git a/dependencies/pkg/mod/github.com/goccy/go-yaml@v1.9.6/printer/printer_test.go b/dependencies/pkg/mod/github.com/goccy/go-yaml@v1.9.6/printer/printer_test.go
new file mode 100644
index 0000000..2afa74f
--- /dev/null
+++ b/dependencies/pkg/mod/github.com/goccy/go-yaml@v1.9.6/printer/printer_test.go
@@ -0,0 +1,223 @@
+package printer_test
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/goccy/go-yaml/lexer"
+ "github.com/goccy/go-yaml/printer"
+)
+
+func Test_Printer(t *testing.T) {
+ yml := `---
+text: aaaa
+text2: aaaa
+ bbbb
+ cccc
+ dddd
+ eeee
+text3: ffff
+ gggg
+ hhhh
+ iiii
+ jjjj
+bool: true
+number: 10
+anchor: &x 1
+alias: *x
+`
+ t.Run("print starting from tokens[3]", func(t *testing.T) {
+ tokens := lexer.Tokenize(yml)
+ var p printer.Printer
+ actual := "\n" + p.PrintErrorToken(tokens[3], false)
+ expect := `
+ 1 | ---
+> 2 | text: aaaa
+ ^
+ 3 | text2: aaaa
+ 4 | bbbb
+ 5 | cccc
+ 6 | dddd
+ 7 | eeee
+ 8 | `
+ if actual != expect {
+ t.Fatalf("unexpected output: expect:[%s]\n actual:[%s]", expect, actual)
+ }
+ })
+ t.Run("print starting from tokens[4]", func(t *testing.T) {
+ tokens := lexer.Tokenize(yml)
+ var p printer.Printer
+ actual := "\n" + p.PrintErrorToken(tokens[4], false)
+ expect := `
+ 1 | ---
+ 2 | text: aaaa
+> 3 | text2: aaaa
+ 4 | bbbb
+ 5 | cccc
+ 6 | dddd
+ 7 | eeee
+ ^
+`
+ if actual != expect {
+ t.Fatalf("unexpected output: expect:[%s]\n actual:[%s]", expect, actual)
+ }
+ })
+ t.Run("print starting from tokens[6]", func(t *testing.T) {
+ tokens := lexer.Tokenize(yml)
+ var p printer.Printer
+ actual := "\n" + p.PrintErrorToken(tokens[6], false)
+ expect := `
+ 1 | ---
+ 2 | text: aaaa
+> 3 | text2: aaaa
+ 4 | bbbb
+ 5 | cccc
+ 6 | dddd
+ 7 | eeee
+ ^
+ 8 | text3: ffff
+ 9 | gggg
+ 10 | hhhh
+ 11 | iiii
+ 12 | jjjj
+ 13 | `
+ if actual != expect {
+ t.Fatalf("unexpected output: expect:[%s]\n actual:[%s]", expect, actual)
+ }
+ })
+ t.Run("print error token with document header", func(t *testing.T) {
+ tokens := lexer.Tokenize(`---
+a:
+ b:
+ c:
+ d: e
+ f: g
+ h: i
+
+---
+`)
+ expect := `
+ 3 | b:
+ 4 | c:
+ 5 | d: e
+> 6 | f: g
+ ^
+ 7 | h: i
+ 8 |
+ 9 | ---`
+ var p printer.Printer
+ actual := "\n" + p.PrintErrorToken(tokens[12], false)
+ if actual != expect {
+ t.Fatalf("unexpected output: expect:[%s]\n actual:[%s]", expect, actual)
+ }
+ })
+ t.Run("output with color", func(t *testing.T) {
+ t.Run("token6", func(t *testing.T) {
+ tokens := lexer.Tokenize(yml)
+ var p printer.Printer
+ t.Logf("\n%s", p.PrintErrorToken(tokens[6], true))
+ })
+ t.Run("token9", func(t *testing.T) {
+ tokens := lexer.Tokenize(yml)
+ var p printer.Printer
+ t.Logf("\n%s", p.PrintErrorToken(tokens[9], true))
+ })
+ t.Run("token12", func(t *testing.T) {
+ tokens := lexer.Tokenize(yml)
+ var p printer.Printer
+ t.Logf("\n%s", p.PrintErrorToken(tokens[12], true))
+ })
+ })
+ t.Run("print error message", func(t *testing.T) {
+ var p printer.Printer
+ src := "message"
+ msg := p.PrintErrorMessage(src, false)
+ if msg != src {
+ t.Fatal("unexpected result")
+ }
+ p.PrintErrorMessage(src, true)
+ })
+}
+
+func TestPrinter_Anchor(t *testing.T) {
+ expected := `
+anchor: &x 1
+alias: *x`
+ tokens := lexer.Tokenize(expected)
+ var p printer.Printer
+ got := p.PrintTokens(tokens)
+ if expected != got {
+ t.Fatalf("unexpected output: expect:[%s]\n actual:[%s]", expected, got)
+ }
+}
+
+func Test_Printer_Multiline(t *testing.T) {
+ yml := `
+text1: 'aaaa
+ bbbb
+ cccc'
+text2: "ffff
+ gggg
+ hhhh"
+text3: hello
+`
+ tc := []struct {
+ token int
+ want string
+ }{
+ {
+ token: 2,
+ want: `
+> 2 | text1: 'aaaa
+ 3 | bbbb
+ 4 | cccc'
+ ^
+ 5 | text2: "ffff
+ 6 | gggg
+ 7 | hhhh"`,
+ },
+ {token: 3,
+ want: `
+ 2 | text1: 'aaaa
+ 3 | bbbb
+ 4 | cccc'
+> 5 | text2: "ffff
+ 6 | gggg
+ 7 | hhhh"
+ ^
+ 8 | text3: hello`,
+ },
+ {token: 5,
+ want: `
+ 2 | text1: 'aaaa
+ 3 | bbbb
+ 4 | cccc'
+> 5 | text2: "ffff
+ 6 | gggg
+ 7 | hhhh"
+ ^
+ 8 | text3: hello`,
+ },
+ {token: 6,
+ want: `
+ 5 | text2: "ffff
+ 6 | gggg
+ 7 | hhhh"
+> 8 | text3: hello
+ ^
+`,
+ },
+ }
+ for _, tt := range tc {
+ name := fmt.Sprintf("print starting from tokens[%d]", tt.token)
+ t.Run(name, func(t *testing.T) {
+ tokens := lexer.Tokenize(yml)
+ var p printer.Printer
+ got := "\n" + p.PrintErrorToken(tokens[tt.token], false)
+ want := tt.want
+ if got != want {
+ t.Fatalf("PrintErrorToken() got: %s\n want:%s\n", want, got)
+ }
+ })
+ }
+}