aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/graphql-go/graphql/gqlerrors/syntax.go
blob: abad6ade0cf73b3e7424ef2f8a12cb3429a570aa (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package gqlerrors

import (
	"fmt"
	"regexp"
	"strings"

	"github.com/graphql-go/graphql/language/ast"
	"github.com/graphql-go/graphql/language/location"
	"github.com/graphql-go/graphql/language/source"
)

func NewSyntaxError(s *source.Source, position int, description string) *Error {
	l := location.GetLocation(s, position)
	return NewError(
		fmt.Sprintf("Syntax Error %s (%d:%d) %s\n\n%s", s.Name, l.Line, l.Column, description, highlightSourceAtLocation(s, l)),
		[]ast.Node{},
		"",
		s,
		[]int{position},
		nil,
	)
}

// printCharCode here is slightly different from lexer.printCharCode()
func printCharCode(code rune) string {
	// print as ASCII for printable range
	if code >= 0x0020 {
		return fmt.Sprintf(`%c`, code)
	}
	// Otherwise print the escaped form. e.g. `"\\u0007"`
	return fmt.Sprintf(`\u%04X`, code)
}
func printLine(str string) string {
	strSlice := []string{}
	for _, runeValue := range str {
		strSlice = append(strSlice, printCharCode(runeValue))
	}
	return fmt.Sprintf(`%s`, strings.Join(strSlice, ""))
}
func highlightSourceAtLocation(s *source.Source, l location.SourceLocation) string {
	line := l.Line
	prevLineNum := fmt.Sprintf("%d", (line - 1))
	lineNum := fmt.Sprintf("%d", line)
	nextLineNum := fmt.Sprintf("%d", (line + 1))
	padLen := len(nextLineNum)
	lines := regexp.MustCompile("\r\n|[\n\r]").Split(string(s.Body), -1)
	var highlight string
	if line >= 2 {
		highlight += fmt.Sprintf("%s: %s\n", lpad(padLen, prevLineNum), printLine(lines[line-2]))
	}
	highlight += fmt.Sprintf("%s: %s\n", lpad(padLen, lineNum), printLine(lines[line-1]))
	for i := 1; i < (2 + padLen + l.Column); i++ {
		highlight += " "
	}
	highlight += "^\n"
	if line < len(lines) {
		highlight += fmt.Sprintf("%s: %s\n", lpad(padLen, nextLineNum), printLine(lines[line]))
	}
	return highlight
}

func lpad(l int, s string) string {
	var r string
	for i := 1; i < (l - len(s) + 1); i++ {
		r += " "
	}
	return r + s
}