Skip to content

Commit 19d003e

Browse files
committed
improve lexer error with correct source locations and preview
1 parent 5761d24 commit 19d003e

6 files changed

Lines changed: 61 additions & 50 deletions

File tree

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package graphql.parser;
2+
3+
import graphql.Internal;
4+
import graphql.language.SourceLocation;
5+
import org.antlr.v4.runtime.Token;
6+
7+
import java.util.List;
8+
9+
@Internal
10+
public class AntlrHelper {
11+
12+
public static SourceLocation createSourceLocation(MultiSourceReader multiSourceReader, int antrlLine, int charPositionInLine) {
13+
// multi source reader lines are 0 based while Antler lines are 1's based
14+
//
15+
// Antler columns ironically are 0 based - go figure!
16+
//
17+
int tokenLine = antrlLine - 1;
18+
MultiSourceReader.SourceAndLine sourceAndLine = multiSourceReader.getSourceAndLineFromOverallLine(tokenLine);
19+
//
20+
// graphql spec says line numbers and columns start at 1
21+
int line = sourceAndLine.getLine() + 1;
22+
int column = charPositionInLine + 1;
23+
return new SourceLocation(line, column, sourceAndLine.getSourceName());
24+
25+
}
26+
27+
public static SourceLocation createSourceLocation(MultiSourceReader multiSourceReader, Token token) {
28+
return AntlrHelper.createSourceLocation(multiSourceReader, token.getLine(), token.getCharPositionInLine());
29+
}
30+
31+
32+
/* grabs 3 lines before and after the syntax error */
33+
public static String createPreview(MultiSourceReader multiSourceReader, int antrlLine) {
34+
int line = antrlLine - 1;
35+
StringBuilder sb = new StringBuilder();
36+
int startLine = line - 3;
37+
int endLine = line + 3;
38+
List<String> lines = multiSourceReader.getData();
39+
for (int i = 0; i < lines.size(); i++) {
40+
if (i >= startLine && i <= endLine) {
41+
sb.append(lines.get(i)).append('\n');
42+
}
43+
}
44+
return sb.toString();
45+
46+
}
47+
48+
}

‎src/main/java/graphql/parser/ExtendedBailStrategy.java‎

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
package graphql.parser;
22

3+
import graphql.Internal;
34
import graphql.language.SourceLocation;
45
import org.antlr.v4.runtime.BailErrorStrategy;
56
import org.antlr.v4.runtime.Parser;
67
import org.antlr.v4.runtime.RecognitionException;
78
import org.antlr.v4.runtime.Token;
89
import org.antlr.v4.runtime.misc.ParseCancellationException;
910

10-
import java.util.List;
11-
12-
import static graphql.parser.SourceLocationHelper.mkSourceLocation;
13-
11+
@Internal
1412
public class ExtendedBailStrategy extends BailErrorStrategy {
1513
private final MultiSourceReader multiSourceReader;
1614

@@ -37,8 +35,8 @@ public Token recoverInline(Parser recognizer) throws RecognitionException {
3735
}
3836

3937
InvalidSyntaxException mkMoreTokensException(Token token) {
40-
SourceLocation sourceLocation = mkSourceLocation(multiSourceReader, token);
41-
String sourcePreview = mkPreview(token);
38+
SourceLocation sourceLocation = AntlrHelper.createSourceLocation(multiSourceReader, token);
39+
String sourcePreview = AntlrHelper.createPreview(multiSourceReader, token.getLine());
4240
return new InvalidSyntaxException(sourceLocation,
4341
"There are more tokens in the query that have not been consumed",
4442
sourcePreview, token.getText(), null);
@@ -51,26 +49,11 @@ private InvalidSyntaxException mkException(Parser recognizer, RecognitionExcepti
5149
SourceLocation sourceLocation = null;
5250
Token currentToken = recognizer.getCurrentToken();
5351
if (currentToken != null) {
54-
sourceLocation = mkSourceLocation(multiSourceReader, currentToken);
52+
sourceLocation = AntlrHelper.createSourceLocation(multiSourceReader, currentToken);
5553
offendingToken = currentToken.getText();
56-
sourcePreview = mkPreview(currentToken);
54+
sourcePreview = AntlrHelper.createPreview(multiSourceReader, currentToken.getLine());
5755
}
5856
return new InvalidSyntaxException(sourceLocation, null, sourcePreview, offendingToken, cause);
5957
}
6058

61-
/* grabs 3 lines before and after the syntax error */
62-
private String mkPreview(Token token) {
63-
int line = token.getLine() - 1;
64-
StringBuilder sb = new StringBuilder();
65-
int startLine = line - 3;
66-
int endLine = line + 3;
67-
List<String> lines = multiSourceReader.getData();
68-
for (int i = 0; i < lines.size(); i++) {
69-
if (i >= startLine && i <= endLine) {
70-
sb.append(lines.get(i)).append('\n');
71-
}
72-
}
73-
return sb.toString();
74-
}
75-
7659
}

‎src/main/java/graphql/parser/GraphqlAntlrToLanguage.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,7 @@ protected Description newDescription(GraphqlParser.DescriptionContext descriptio
810810
}
811811

812812
protected SourceLocation getSourceLocation(Token token) {
813-
return SourceLocationHelper.mkSourceLocation(multiSourceReader, token);
813+
return AntlrHelper.createSourceLocation(multiSourceReader, token);
814814
}
815815

816816
protected SourceLocation getSourceLocation(ParserRuleContext parserRuleContext) {

‎src/main/java/graphql/parser/Parser.java‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ public Document parseDocument(Reader reader) throws InvalidSyntaxException {
5959
lexer.addErrorListener(new BaseErrorListener() {
6060
@Override
6161
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
62-
throw new InvalidSyntaxException(new SourceLocation(line, charPositionInLine), "Invalid syntax: " + msg, null, null, null);
62+
SourceLocation sourceLocation = AntlrHelper.createSourceLocation(multiSourceReader, line, charPositionInLine);
63+
String preview = AntlrHelper.createPreview(multiSourceReader, line);
64+
throw new InvalidSyntaxException(sourceLocation, "Invalid syntax: " + msg, preview, null, null);
6365
}
6466
});
6567

‎src/main/java/graphql/parser/SourceLocationHelper.java‎

Lines changed: 0 additions & 25 deletions
This file was deleted.

‎src/test/groovy/graphql/parser/ParserTest.groovy‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,5 +747,8 @@ triple3 : """edge cases \\""" "" " \\"" \\" edge cases"""
747747
then:
748748
def e = thrown(InvalidSyntaxException)
749749
e.message.contains("Invalid syntax")
750+
e.sourcePreview == input + "\n"
751+
e.location.line == 3
752+
e.location.column == 20
750753
}
751754
}

0 commit comments

Comments
 (0)