Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement parsing of multi-line schema item descriptions #48

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion language/lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const (
BOOL // true, false
NULL // null

MULTILINE_STRING // """abc\ndef"""
)

func (tokenType TokenType) String() string {
Expand Down Expand Up @@ -111,6 +112,8 @@ func (tokenType TokenType) String() string {
return "Boolean"
case NULL:
return "null"
case MULTILINE_STRING:
return "MultilineString"
default:
return "Unknown"
}
Expand Down Expand Up @@ -197,6 +200,9 @@ func (lexer *Lexer) Emit(tokenType TokenType) {
panic(err)
}
}
if tokenType == MULTILINE_STRING {
value = value[3 : len(value)-3]
}
lexer.Tokens <- Token{tokenType, value, startPos, endPos}
lexer.Start = lexer.Pos
lexer.Width = 0
Expand Down Expand Up @@ -351,6 +357,9 @@ func LexText(lexer *Lexer) StateFn {
lexer.Backup()
return LexComment
case rn == '"':
if lexer.AcceptString("\"\"") {
return LexMultilineQuote
}
lexer.Backup()
return LexQuote
case rn == '.':
Expand Down Expand Up @@ -421,7 +430,10 @@ func LexComment(lexer *Lexer) StateFn {
}
for {
switch rn := lexer.Next(); rn {
case -1, '\u000A', '\u000D':
case -1:
lexer.Backup()
return LexText
case '\u000A', '\u000D':
if rn == '\u000D' && lexer.Peek() == '\u000A' {
lexer.Next()
}
Expand All @@ -438,6 +450,27 @@ func LexComment(lexer *Lexer) StateFn {
return LexText
}

func LexMultilineQuote(lexer *Lexer) StateFn {
for {
switch rn := lexer.Next(); rn {
case -1, '\u000A', '\u000D':
if rn == '\u000D' && lexer.Peek() == '\u000A' {
lexer.Next()
}
lexer.Line += 1
lexer.Column = 1
continue
case '"':
if lexer.AcceptString("\"\"") {
lexer.Emit(MULTILINE_STRING)
return LexText
}
return lexer.Errorf(`GraphQL Syntax Error (%d:%d) Invalid multiline description`, lexer.Line, lexer.Column-1)
}
}
return LexText
}

func LexQuote(lexer *Lexer) StateFn {
quote := lexer.Next()
index := 1
Expand Down
26 changes: 18 additions & 8 deletions language/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,19 +112,29 @@ func (parser *Parser) description() (string, error) {
text := ""
isBody := false
token := parser.lookahead
for token.Type == DESCRIPTION {
text += strings.Trim(token.Val[2:], " ")
if isBody {
text += " "
} else {
isBody = true
switch token.Type {
case STRING:
for token.Type == STRING {
text += strings.Trim(token.Val, " ")
if isBody {
text += " "
} else {
isBody = true
}
err := parser.match(STRING)
if err != nil {
return text, err
}
token = parser.lookahead
}
err := parser.match(DESCRIPTION)
case MULTILINE_STRING:
err := parser.match(MULTILINE_STRING)
if err != nil {
return text, err
}
token = parser.lookahead
text = strings.Trim(token.Val, "\n")
}

return text, nil
}

Expand Down
35 changes: 35 additions & 0 deletions language/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1367,6 +1367,41 @@ input Hello {
})
So(err, ShouldNotEqual, nil)
})

Convey("multiline descriptions", func() {
result, err = parser.Parse(&ParseParams{
Source: `
# Comment
"""
Multiline Description on Scalar
Line 2
"""
scalar Scalar

"""
Multiline Description on Object
Line 2
"""
type Object {
"""
Multiline Description on Field
Line 2
"""
field: String!
}
`,
})
So(err, ShouldEqual, nil)

scalar := result.Definitions[0].(*ScalarTypeDefinition)
object := result.Definitions[1].(*ObjectTypeDefinition)
field := object.Fields[0]

So(scalar.Description, ShouldEqual, "Multiline Description on Scalar\nLine 2")
So(object.Description, ShouldEqual, "Multiline Description on Object\nLine 2")
So(field.Description, ShouldEqual, "\tMultiline Description on Field\n\tLine 2\n\t")
})

})

}