Skip to content

Commit fb53067

Browse files
committed
parsing: Improve Parsing error handling
Use antlr BailErrorStrategy to cancel immediately if any syntax problem is detected Removed ErrorListener, because its not called anymore
1 parent 78af222 commit fb53067

4 files changed

Lines changed: 51 additions & 25 deletions

File tree

src/main/java/graphql/GraphQL.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@
1010
import graphql.validation.ValidationError;
1111
import graphql.validation.Validator;
1212
import org.antlr.v4.runtime.RecognitionException;
13+
import org.antlr.v4.runtime.misc.ParseCancellationException;
1314
import org.slf4j.Logger;
1415
import org.slf4j.LoggerFactory;
1516

1617
import java.util.Arrays;
1718
import java.util.Collections;
1819
import java.util.List;
1920
import java.util.Map;
20-
import java.util.concurrent.ExecutorService;
2121

2222
import static graphql.Assert.assertNotNull;
2323

@@ -62,8 +62,9 @@ public ExecutionResult execute(String requestString, String operationName, Objec
6262
Document document;
6363
try {
6464
document = parser.parseDocument(requestString);
65-
} catch (RecognitionException e) {
66-
SourceLocation sourceLocation = new SourceLocation(e.getOffendingToken().getLine(), e.getOffendingToken().getCharPositionInLine());
65+
} catch (ParseCancellationException e) {
66+
RecognitionException recognitionException = (RecognitionException) e.getCause();
67+
SourceLocation sourceLocation = new SourceLocation(recognitionException.getOffendingToken().getLine(), recognitionException.getOffendingToken().getCharPositionInLine());
6768
InvalidSyntaxError invalidSyntaxError = new InvalidSyntaxError(sourceLocation);
6869
return new ExecutionResultImpl(Arrays.asList(invalidSyntaxError));
6970
}

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

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
import graphql.language.Document;
44
import graphql.parser.antlr.GraphqlLexer;
55
import graphql.parser.antlr.GraphqlParser;
6-
import org.antlr.v4.runtime.*;
6+
import org.antlr.v4.runtime.ANTLRInputStream;
7+
import org.antlr.v4.runtime.BailErrorStrategy;
8+
import org.antlr.v4.runtime.CommonTokenStream;
79
import org.antlr.v4.runtime.atn.PredictionMode;
810
import org.slf4j.Logger;
911
import org.slf4j.LoggerFactory;
@@ -21,30 +23,13 @@ public Document parseDocument(String input) {
2123

2224
GraphqlParser parser = new GraphqlParser(tokens);
2325
parser.removeErrorListeners();
24-
parser.addErrorListener(new ErrorListener());
2526
parser.getInterpreter().setPredictionMode(PredictionMode.SLL);
26-
parser.setErrorHandler(new ErrorStrategy());
27+
parser.setErrorHandler(new BailErrorStrategy());
2728
GraphqlParser.DocumentContext document = parser.document();
2829

2930

3031
GraphqlAntlrToLanguage antlrToLanguage = new GraphqlAntlrToLanguage();
3132
antlrToLanguage.visitDocument(document);
3233
return antlrToLanguage.result;
3334
}
34-
35-
private class ErrorStrategy extends DefaultErrorStrategy {
36-
37-
@Override
38-
public void recover(org.antlr.v4.runtime.Parser recognizer, RecognitionException e) {
39-
throw e;
40-
}
41-
}
42-
43-
private class ErrorListener extends BaseErrorListener {
44-
@Override
45-
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
46-
log.error("graphql syntax error: line " + line + ":" + charPositionInLine + " " + msg);
47-
}
48-
}
49-
5035
}

src/test/groovy/graphql/GraphQLTest.groovy

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,21 @@ class GraphQLTest extends Specification {
110110
errors[0].errorType == ErrorType.InvalidSyntax
111111
errors[0].sourceLocations == [new SourceLocation(1, 8)]
112112
}
113+
114+
def "query with invalid syntax 2"() {
115+
given:
116+
GraphQLSchema schema = newSchema().query(
117+
newObject()
118+
.name("RootQueryType")
119+
.build()
120+
).build()
121+
122+
when:
123+
def errors = new GraphQL(schema).execute('{ hello[](() }').errors
124+
125+
then:
126+
errors.size() == 1
127+
errors[0].errorType == ErrorType.InvalidSyntax
128+
errors[0].sourceLocations == [new SourceLocation(1, 7)]
129+
}
113130
}

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

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package graphql.parser
22

33
import graphql.language.*
4+
import org.antlr.v4.runtime.misc.ParseCancellationException
45
import spock.lang.Specification
56
import spock.lang.Unroll
67

@@ -64,7 +65,7 @@ class ParserTest extends Specification {
6465
when:
6566
Document document = new Parser().parseDocument(input)
6667
then:
67-
isEqual(document,expectedResult)
68+
isEqual(document, expectedResult)
6869

6970
}
7071

@@ -142,7 +143,7 @@ class ParserTest extends Specification {
142143

143144
then:
144145
document.definitions.size() == 2
145-
isEqual(document.definitions[0],queryDefinition)
146+
isEqual(document.definitions[0], queryDefinition)
146147
isEqual(document.definitions[1], fragmentDefinition)
147148
}
148149

@@ -310,7 +311,7 @@ class ParserTest extends Specification {
310311
Field helloField = document.definitions[0].selectionSet.selections[0]
311312

312313
then:
313-
isEqual(helloField,new Field("hello", [new Argument("arg", new StringValue("hello, world"))]))
314+
isEqual(helloField, new Field("hello", [new Argument("arg", new StringValue("hello, world"))]))
314315
}
315316

316317
@Unroll
@@ -338,4 +339,26 @@ class ParserTest extends Specification {
338339

339340
}
340341

342+
def "extraneous input is an excpetion"() {
343+
given:
344+
def input = """
345+
mutation event(\$var: SomeType[]!) { res: update(arg: \$var) {id} }
346+
"""
347+
when:
348+
new Parser().parseDocument(input)
349+
then:
350+
thrown(ParseCancellationException)
351+
}
352+
353+
def "invalid syntax is an error"() {
354+
given:
355+
def input = """
356+
mutation event(() }
357+
"""
358+
when:
359+
new Parser().parseDocument(input)
360+
then:
361+
thrown(ParseCancellationException)
362+
}
363+
341364
}

0 commit comments

Comments
 (0)