2323import java .util .List ;
2424import java .util .function .BiFunction ;
2525
26+ /**
27+ * This can parse graphql syntax, both Query syntax and Schema Definition Language (SDL) syntax, into an
28+ * Abstract Syntax Tree (AST) represented by a {@link Document}
29+ * <p>
30+ * You should not generally need to call this class as the {@link graphql.GraphQL} code sets this up for you
31+ * but if you are doing specific graphql utilities this class is essential.
32+ *
33+ * Graphql syntax has a series of characters, such as spaces, new lines and commas that are not considered relevant
34+ * to the syntax. However they can be captured and associated with the AST elements they belong to.
35+ *
36+ * This costs more memory but for certain use cases (like editors) this maybe be useful. We have chosen to no capture
37+ * ignored characters by default but you can turn this on, either per parse or statically for the whole JVM
38+ * via {@link #setCaptureIgnoredChars(boolean)}
39+ *
40+ * @see graphql.language.IgnoredChar
41+ */
2642@ PublicApi
2743public class Parser {
2844
45+ private static boolean captureIgnoredChars = false ;
2946
30- public static Document parse (String input ) {
47+ /**
48+ * By default the Parser will not capture ignored characters. A static holds this default
49+ * value in a JVM wide basis.
50+ *
51+ * Significant memory savings can be made if we do NOT capture ignored characters,
52+ * especially in SDL parsing.
53+ *
54+ * @return the static default value on whether to capture ignored chars
55+ *
56+ * @see graphql.language.IgnoredChar
57+ */
58+ public static boolean getCaptureIgnoredChars () {
59+ return captureIgnoredChars ;
60+ }
61+
62+ /**
63+ * By default the Parser will not capture ignored characters. A static holds this default
64+ * value in a JVM wide basis.
65+ *
66+ * Significant memory savings can be made if we do NOT capture ignored characters,
67+ * especially in SDL parsing. So we have set this to false by default.
68+ *
69+ * This static can be set to true to allow the behavior of version 16.x or before.
70+ *
71+ * @param flag - whether to capture ignored characters in AST elements or not
72+ *
73+ * @see graphql.language.IgnoredChar
74+ */
75+ public static void setCaptureIgnoredChars (boolean flag ) {
76+ captureIgnoredChars = flag ;
77+ }
78+
79+ /**
80+ * Parses a string input into a graphql AST {@link Document}
81+ *
82+ * @param input the input to parse
83+ *
84+ * @return an AST {@link Document}
85+ *
86+ * @throws InvalidSyntaxException if the input is not valid graphql syntax
87+ */
88+ public static Document parse (String input ) throws InvalidSyntaxException {
3189 return new Parser ().parseDocument (input );
3290 }
3391
34- public static Value <?> parseValue (String input ) {
92+ /**
93+ * Parses a string input into a graphql AST {@link Value}
94+ *
95+ * @param input the input to parse
96+ *
97+ * @return an AST {@link Value}
98+ *
99+ * @throws InvalidSyntaxException if the input is not valid graphql syntax
100+ */
101+ public static Value <?> parseValue (String input ) throws InvalidSyntaxException {
35102 return new Parser ().parseValueImpl (input );
36103 }
37104
105+ /**
106+ * Parses a string input into a graphql AST {@link Document}
107+ *
108+ * @param input the input to parse
109+ *
110+ * @return an AST {@link Document}
111+ *
112+ * @throws InvalidSyntaxException if the input is not valid graphql syntax
113+ */
38114 public Document parseDocument (String input ) throws InvalidSyntaxException {
39115 return parseDocument (input , null );
40116 }
41117
118+ /**
119+ * Parses a string input into a graphql AST {@link Document}
120+ *
121+ * @param input the input to parse
122+ * @param sourceName - the name to attribute to the input text in {@link SourceLocation#getSourceName()}
123+ *
124+ * @return an AST {@link Document}
125+ *
126+ * @throws InvalidSyntaxException if the input is not valid graphql syntax
127+ */
42128 public Document parseDocument (String input , String sourceName ) throws InvalidSyntaxException {
43129 MultiSourceReader multiSourceReader = MultiSourceReader .newMultiSourceReader ()
44130 .string (input , sourceName )
@@ -47,29 +133,76 @@ public Document parseDocument(String input, String sourceName) throws InvalidSyn
47133 return parseDocument (multiSourceReader );
48134 }
49135
50- public Document parseDocument (Reader reader ) {
136+ /**
137+ * Parses a string input into a graphql AST {@link Document}
138+ *
139+ * @param input the input to parse
140+ * @param captureIgnoredChars whether to capture characters that are otherwise ignored in graphql syntax against
141+ * each AST element
142+ *
143+ * @return an AST {@link Document}
144+ *
145+ * @throws InvalidSyntaxException if the input is not valid graphql syntax
146+ */
147+ public Document parseDocument (String input , boolean captureIgnoredChars ) throws InvalidSyntaxException {
148+ MultiSourceReader multiSourceReader = MultiSourceReader .newMultiSourceReader ()
149+ .string (input , null )
150+ .trackData (true )
151+ .build ();
152+ return parseDocument (multiSourceReader , captureIgnoredChars );
153+ }
154+
155+ /**
156+ * Parses reader input into a graphql AST {@link Document}
157+ *
158+ * @param reader the reader input to parse
159+ *
160+ * @return an AST {@link Document}
161+ *
162+ * @throws InvalidSyntaxException if the input is not valid graphql syntax
163+ */
164+ public Document parseDocument (Reader reader ) throws InvalidSyntaxException {
165+ return parseDocumentImpl (reader , null );
166+ }
167+
168+ /**
169+ * Parses reader input into a graphql AST {@link Document}
170+ *
171+ * @param reader the reader input to parse
172+ * @param captureIgnoredChars whether to capture characters that are otherwise ignored in graphql syntax against
173+ * each AST element
174+ *
175+ * @return an AST {@link Document}
176+ *
177+ * @throws InvalidSyntaxException if the input is not valid graphql syntax
178+ */
179+ public Document parseDocument (Reader reader , boolean captureIgnoredChars ) throws InvalidSyntaxException {
180+ return parseDocumentImpl (reader , captureIgnoredChars );
181+ }
182+
183+ private Document parseDocumentImpl (Reader reader , Boolean captureIgnoredChars ) throws InvalidSyntaxException {
51184 BiFunction <GraphqlParser , GraphqlAntlrToLanguage , Object []> nodeFunction = (parser , toLanguage ) -> {
52185 GraphqlParser .DocumentContext documentContext = parser .document ();
53186 Document doc = toLanguage .createDocument (documentContext );
54187 return new Object []{documentContext , doc };
55188 };
56- return (Document ) parseImpl (reader , nodeFunction );
189+ return (Document ) parseImpl (reader , nodeFunction , captureIgnoredChars );
57190 }
58191
59- private Value <?> parseValueImpl (String input ) {
192+ private Value <?> parseValueImpl (String input ) throws InvalidSyntaxException {
60193 BiFunction <GraphqlParser , GraphqlAntlrToLanguage , Object []> nodeFunction = (parser , toLanguage ) -> {
61194 GraphqlParser .ValueContext documentContext = parser .value ();
62- Value value = toLanguage .createValue (documentContext );
195+ Value <?> value = toLanguage .createValue (documentContext );
63196 return new Object []{documentContext , value };
64197 };
65198 MultiSourceReader multiSourceReader = MultiSourceReader .newMultiSourceReader ()
66199 .string (input , null )
67200 .trackData (true )
68201 .build ();
69- return (Value <?>) parseImpl (multiSourceReader , nodeFunction );
202+ return (Value <?>) parseImpl (multiSourceReader , nodeFunction , null );
70203 }
71204
72- private Node parseImpl (Reader reader , BiFunction <GraphqlParser , GraphqlAntlrToLanguage , Object []> nodeFunction ) throws InvalidSyntaxException {
205+ private Node <?> parseImpl (Reader reader , BiFunction <GraphqlParser , GraphqlAntlrToLanguage , Object []> nodeFunction , Boolean captureIgnoredChars ) throws InvalidSyntaxException {
73206 MultiSourceReader multiSourceReader ;
74207 if (reader instanceof MultiSourceReader ) {
75208 multiSourceReader = (MultiSourceReader ) reader ;
@@ -104,10 +237,14 @@ public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int
104237 ExtendedBailStrategy bailStrategy = new ExtendedBailStrategy (multiSourceReader );
105238 parser .setErrorHandler (bailStrategy );
106239
240+ // preserve old protected call semantics - remove at some point
107241 GraphqlAntlrToLanguage toLanguage = getAntlrToLanguage (tokens , multiSourceReader );
242+ if (toLanguage == null ) {
243+ toLanguage = getAntlrToLanguage (tokens , multiSourceReader , captureIgnoredChars );
244+ }
108245 Object [] contextAndNode = nodeFunction .apply (parser , toLanguage );
109246 ParserRuleContext parserRuleContext = (ParserRuleContext ) contextAndNode [0 ];
110- Node node = (Node ) contextAndNode [1 ];
247+ Node <?> node = (Node <?> ) contextAndNode [1 ];
111248
112249 Token stop = parserRuleContext .getStop ();
113250 List <Token > allTokens = tokens .getTokens ();
@@ -133,8 +270,24 @@ public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int
133270 * @param multiSourceReader the source of the query document
134271 *
135272 * @return a new GraphqlAntlrToLanguage instance
273+ *
274+ * @deprecated - really should use {@link #getAntlrToLanguage(CommonTokenStream, MultiSourceReader, Boolean)}
136275 */
276+ @ Deprecated
137277 protected GraphqlAntlrToLanguage getAntlrToLanguage (CommonTokenStream tokens , MultiSourceReader multiSourceReader ) {
138- return new GraphqlAntlrToLanguage (tokens , multiSourceReader );
278+ return null ;
279+ }
280+
281+ /**
282+ * Allows you to override the ANTLR to AST code.
283+ *
284+ * @param tokens the token stream
285+ * @param multiSourceReader the source of the query document
286+ * @param captureIgnoredChars - whether ignored characters should be captured in the AST elements
287+ *
288+ * @return a new GraphqlAntlrToLanguage instance
289+ */
290+ protected GraphqlAntlrToLanguage getAntlrToLanguage (CommonTokenStream tokens , MultiSourceReader multiSourceReader , Boolean captureIgnoredChars ) {
291+ return new GraphqlAntlrToLanguage (tokens , multiSourceReader , captureIgnoredChars );
139292 }
140293}
0 commit comments