syntax.go

 1package gqlerrors
 2
 3import (
 4	"fmt"
 5	"regexp"
 6	"strings"
 7
 8	"github.com/graphql-go/graphql/language/ast"
 9	"github.com/graphql-go/graphql/language/location"
10	"github.com/graphql-go/graphql/language/source"
11)
12
13func NewSyntaxError(s *source.Source, position int, description string) *Error {
14	l := location.GetLocation(s, position)
15	return NewError(
16		fmt.Sprintf("Syntax Error %s (%d:%d) %s\n\n%s", s.Name, l.Line, l.Column, description, highlightSourceAtLocation(s, l)),
17		[]ast.Node{},
18		"",
19		s,
20		[]int{position},
21		nil,
22	)
23}
24
25// printCharCode here is slightly different from lexer.printCharCode()
26func printCharCode(code rune) string {
27	// print as ASCII for printable range
28	if code >= 0x0020 {
29		return fmt.Sprintf(`%c`, code)
30	}
31	// Otherwise print the escaped form. e.g. `"\\u0007"`
32	return fmt.Sprintf(`\u%04X`, code)
33}
34func printLine(str string) string {
35	strSlice := []string{}
36	for _, runeValue := range str {
37		strSlice = append(strSlice, printCharCode(runeValue))
38	}
39	return fmt.Sprintf(`%s`, strings.Join(strSlice, ""))
40}
41func highlightSourceAtLocation(s *source.Source, l location.SourceLocation) string {
42	line := l.Line
43	prevLineNum := fmt.Sprintf("%d", (line - 1))
44	lineNum := fmt.Sprintf("%d", line)
45	nextLineNum := fmt.Sprintf("%d", (line + 1))
46	padLen := len(nextLineNum)
47	lines := regexp.MustCompile("\r\n|[\n\r]").Split(string(s.Body), -1)
48	var highlight string
49	if line >= 2 {
50		highlight += fmt.Sprintf("%s: %s\n", lpad(padLen, prevLineNum), printLine(lines[line-2]))
51	}
52	highlight += fmt.Sprintf("%s: %s\n", lpad(padLen, lineNum), printLine(lines[line-1]))
53	for i := 1; i < (2 + padLen + l.Column); i++ {
54		highlight += " "
55	}
56	highlight += "^\n"
57	if line < len(lines) {
58		highlight += fmt.Sprintf("%s: %s\n", lpad(padLen, nextLineNum), printLine(lines[line]))
59	}
60	return highlight
61}
62
63func lpad(l int, s string) string {
64	var r string
65	for i := 1; i < (l - len(s) + 1); i++ {
66		r += " "
67	}
68	return r + s
69}