Skip to content

Commit 2fbb97f

Browse files
authored
Configure client generate parser options (#1586) (#1592)
* Configure client generate parser options * Fix star import failure from ktlint * Set defaults, update documentation, fix name of parser options class for maven plugin * Do not set default for parser options, use null to inherit default from graphql-java
1 parent 3d721c7 commit 2fbb97f

File tree

13 files changed

+275
-39
lines changed

13 files changed

+275
-39
lines changed

plugins/client/graphql-kotlin-client-generator/src/main/kotlin/com/expediagroup/graphql/plugin/client/generateClient.kt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@
1616

1717
package com.expediagroup.graphql.plugin.client
1818

19-
import com.expediagroup.graphql.plugin.client.generator.GraphQLClientGenerator
20-
import com.expediagroup.graphql.plugin.client.generator.GraphQLClientGeneratorConfig
2119
import com.expediagroup.graphql.plugin.client.generator.GraphQLScalar
2220
import com.expediagroup.graphql.plugin.client.generator.GraphQLSerializer
21+
import com.expediagroup.graphql.plugin.client.generator.GraphQLClientGeneratorConfig
22+
import com.expediagroup.graphql.plugin.client.generator.GraphQLClientGenerator
2323
import com.squareup.kotlinpoet.FileSpec
24+
import graphql.parser.ParserOptions
2425
import java.io.File
2526

2627
/**
@@ -33,15 +34,17 @@ fun generateClient(
3334
serializer: GraphQLSerializer = GraphQLSerializer.JACKSON,
3435
schemaPath: String,
3536
queries: List<File>,
36-
useOptionalInputWrapper: Boolean = false
37+
useOptionalInputWrapper: Boolean = false,
38+
parserOptions: ParserOptions.Builder.() -> Unit = {}
3739
): List<FileSpec> {
3840
val customScalars = customScalarsMap.associateBy { it.scalar }
3941
val config = GraphQLClientGeneratorConfig(
4042
packageName = packageName,
4143
allowDeprecated = allowDeprecated,
4244
customScalarMap = customScalars,
4345
serializer = serializer,
44-
useOptionalInputWrapper = useOptionalInputWrapper
46+
useOptionalInputWrapper = useOptionalInputWrapper,
47+
parserOptions = parserOptions
4548
)
4649
val generator = GraphQLClientGenerator(schemaPath, config)
4750
return generator.generate(queries)

plugins/client/graphql-kotlin-client-generator/src/main/kotlin/com/expediagroup/graphql/plugin/client/generator/GraphQLClientGenerator.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import com.squareup.kotlinpoet.TypeSpec
3333
import graphql.language.ObjectTypeDefinition
3434
import graphql.language.OperationDefinition
3535
import graphql.parser.Parser
36+
import graphql.parser.ParserOptions
3637
import graphql.schema.idl.SchemaParser
3738
import graphql.schema.idl.TypeDefinitionRegistry
3839
import kotlinx.serialization.Required
@@ -53,6 +54,7 @@ class GraphQLClientGenerator(
5354
private val sharedTypes: MutableMap<ClassName, List<TypeSpec>> = mutableMapOf()
5455
private var generateOptionalSerializer: Boolean = false
5556
private val graphQLSchema: TypeDefinitionRegistry
57+
private val parserOptions: ParserOptions = ParserOptions.newParserOptions().also { this.config.parserOptions(it) }.build()
5658

5759
init {
5860
graphQLSchema = parseSchema(schemaPath)
@@ -92,7 +94,7 @@ class GraphQLClientGenerator(
9294
*/
9395
internal fun generate(queryFile: File): List<FileSpec> {
9496
val queryConst = queryFile.readText().trim()
95-
val queryDocument = documentParser.parseDocument(queryConst)
97+
val queryDocument = documentParser.parseDocument(queryConst, parserOptions)
9698

9799
val operationDefinitions = queryDocument.definitions.filterIsInstance(OperationDefinition::class.java)
98100
if (operationDefinitions.size > 1) {

plugins/client/graphql-kotlin-client-generator/src/main/kotlin/com/expediagroup/graphql/plugin/client/generator/GraphQLClientGeneratorConfig.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.expediagroup.graphql.plugin.client.generator
1818

1919
import com.squareup.kotlinpoet.ClassName
20+
import graphql.parser.ParserOptions
2021

2122
/**
2223
* GraphQL client generator configuration.
@@ -31,7 +32,9 @@ data class GraphQLClientGeneratorConfig(
3132
/** Type of JSON serializer to be used. */
3233
val serializer: GraphQLSerializer = GraphQLSerializer.JACKSON,
3334
/** Explicit opt-in flag to enable support for optional inputs. */
34-
val useOptionalInputWrapper: Boolean = false
35+
val useOptionalInputWrapper: Boolean = false,
36+
/** Set parser options for processing GraphQL queries and schema definition language documents */
37+
val parserOptions: ParserOptions.Builder.() -> Unit = {}
3538
)
3639

3740
/**

plugins/graphql-kotlin-gradle-plugin/src/main/kotlin/com/expediagroup/graphql/plugin/gradle/GraphQLGradlePlugin.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ class GraphQLGradlePlugin : Plugin<Project> {
9393
generateClientTask.queryFiles.setFrom(extension.clientExtension.queryFiles)
9494
generateClientTask.serializer.convention(extension.clientExtension.serializer)
9595
generateClientTask.useOptionalInputWrapper.convention(extension.clientExtension.useOptionalInputWrapper)
96+
generateClientTask.parserOptions.convention(extension.clientExtension.parserOptions)
9697

9798
when {
9899
extension.clientExtension.endpoint != null -> {

plugins/graphql-kotlin-gradle-plugin/src/main/kotlin/com/expediagroup/graphql/plugin/gradle/GraphQLPluginExtension.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.expediagroup.graphql.plugin.gradle
1818

19+
import com.expediagroup.graphql.plugin.gradle.config.GraphQLParserOptions
1920
import com.expediagroup.graphql.plugin.gradle.config.GraphQLScalar
2021
import com.expediagroup.graphql.plugin.gradle.config.GraphQLSerializer
2122
import com.expediagroup.graphql.plugin.gradle.config.TimeoutConfiguration
@@ -84,6 +85,17 @@ open class GraphQLPluginClientExtension {
8485
fun timeout(action: Action<TimeoutConfiguration>) {
8586
action.execute(timeoutConfig)
8687
}
88+
89+
/** Configure options for parsing GraphQL queries and schema definition language documents. */
90+
internal val parserOptions: GraphQLParserOptions = GraphQLParserOptions()
91+
92+
/**
93+
* Configure options for parsing GraphQL queries and schema definition language documents. Settings
94+
* here override the defaults set by GraphQL Java.
95+
*/
96+
fun parserOptions(action: Action<GraphQLParserOptions>) {
97+
action.execute(parserOptions)
98+
}
8799
}
88100

89101
open class GraphQLPluginSchemaExtension {

plugins/graphql-kotlin-gradle-plugin/src/main/kotlin/com/expediagroup/graphql/plugin/gradle/actions/GenerateClientAction.kt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,24 @@ abstract class GenerateClientAction : WorkAction<GenerateClientParameters> {
3939
val queryFiles = parameters.queryFiles.get()
4040
val targetDirectory = parameters.targetDirectory.get()
4141
val useOptionalInputWrapper = parameters.useOptionalInputWrapper.get()
42+
val parserOptions = parameters.parserOptions.get()
4243

43-
generateClient(targetPackage, allowDeprecated, customScalarMap, serializer, schemaPath, queryFiles, useOptionalInputWrapper).forEach {
44+
generateClient(
45+
targetPackage,
46+
allowDeprecated,
47+
customScalarMap,
48+
serializer,
49+
schemaPath,
50+
queryFiles,
51+
useOptionalInputWrapper,
52+
parserOptions = {
53+
parserOptions.maxTokens?.let { maxTokens(it) }
54+
parserOptions.maxWhitespaceTokens?.let { maxWhitespaceTokens(it) }
55+
parserOptions.captureIgnoredChars?.let { captureIgnoredChars(it) }
56+
parserOptions.captureSourceLocation?.let { captureSourceLocation(it) }
57+
parserOptions.captureLineComments?.let { captureLineComments(it) }
58+
}
59+
).forEach {
4460
it.writeTo(targetDirectory)
4561
}
4662
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.expediagroup.graphql.plugin.gradle.config
2+
3+
import java.io.Serializable
4+
5+
/**
6+
* Configure options for parsing GraphQL queries and schema definition language documents. Settings
7+
* here override the defaults set by GraphQL Java.
8+
*/
9+
data class GraphQLParserOptions(
10+
/** Modify the maximum number of tokens read to prevent processing extremely large queries */
11+
var maxTokens: Int? = null,
12+
/** Modify the maximum number of whitespace tokens read to prevent processing extremely large queries */
13+
var maxWhitespaceTokens: Int? = null,
14+
/** Memory usage is significantly reduced by not capturing ignored characters, especially in SDL parsing. */
15+
var captureIgnoredChars: Boolean? = null,
16+
/** Single-line comments do not have any semantic meaning in GraphQL source documents and can be ignored */
17+
var captureLineComments: Boolean? = null,
18+
/** Memory usage is reduced by not setting SourceLocations on AST nodes, especially in SDL parsing. */
19+
var captureSourceLocation: Boolean? = null
20+
) : Serializable

plugins/graphql-kotlin-gradle-plugin/src/main/kotlin/com/expediagroup/graphql/plugin/gradle/parameters/GenerateClientParameters.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.expediagroup.graphql.plugin.gradle.parameters
1818

19+
import com.expediagroup.graphql.plugin.gradle.config.GraphQLParserOptions
1920
import com.expediagroup.graphql.plugin.gradle.config.GraphQLScalar
2021
import com.expediagroup.graphql.plugin.gradle.config.GraphQLSerializer
2122
import org.gradle.api.provider.ListProperty
@@ -44,4 +45,6 @@ interface GenerateClientParameters : WorkParameters {
4445
val targetDirectory: Property<File>
4546
/** Explicit opt-in flag to wrap nullable arguments in OptionalInput that supports both null and undefined values. */
4647
val useOptionalInputWrapper: Property<Boolean>
48+
/** Set parser options for processing GraphQL queries and schema definition language documents */
49+
val parserOptions: Property<GraphQLParserOptions>
4750
}

plugins/graphql-kotlin-gradle-plugin/src/main/kotlin/com/expediagroup/graphql/plugin/gradle/tasks/AbstractGenerateClientTask.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.expediagroup.graphql.plugin.gradle.tasks
1818

1919
import com.expediagroup.graphql.plugin.gradle.actions.GenerateClientAction
20+
import com.expediagroup.graphql.plugin.gradle.config.GraphQLParserOptions
2021
import com.expediagroup.graphql.plugin.gradle.config.GraphQLScalar
2122
import com.expediagroup.graphql.plugin.gradle.config.GraphQLSerializer
2223
import org.gradle.api.DefaultTask
@@ -117,6 +118,10 @@ abstract class AbstractGenerateClientTask : DefaultTask() {
117118
@Option(option = "useOptionalInputWrapper", description = "Opt-in flag to wrap nullable arguments in OptionalInput that supports both null and undefined.")
118119
val useOptionalInputWrapper: Property<Boolean> = project.objects.property(Boolean::class.java)
119120

121+
@Input
122+
@Optional
123+
val parserOptions: Property<GraphQLParserOptions> = project.objects.property(GraphQLParserOptions::class.java)
124+
120125
@OutputDirectory
121126
val outputDirectory: DirectoryProperty = project.objects.directoryProperty()
122127

@@ -131,6 +136,7 @@ abstract class AbstractGenerateClientTask : DefaultTask() {
131136
customScalars.convention(emptyList())
132137
serializer.convention(GraphQLSerializer.JACKSON)
133138
useOptionalInputWrapper.convention(false)
139+
parserOptions.convention(GraphQLParserOptions())
134140
}
135141

136142
@Suppress("EXPERIMENTAL_API_USAGE")
@@ -177,6 +183,7 @@ abstract class AbstractGenerateClientTask : DefaultTask() {
177183
parameters.queryFiles.set(targetQueryFiles)
178184
parameters.targetDirectory.set(targetDirectory)
179185
parameters.useOptionalInputWrapper.set(useOptionalInputWrapper)
186+
parameters.parserOptions.set(parserOptions)
180187
}
181188
workQueue.await()
182189
logger.debug("successfully generated GraphQL HTTP client")
@@ -191,6 +198,7 @@ abstract class AbstractGenerateClientTask : DefaultTask() {
191198
}
192199
logger.debug(" packageName = $packageName")
193200
logger.debug(" allowDeprecatedFields = $allowDeprecatedFields")
201+
logger.debug(" parserOptions = $parserOptions")
194202
logger.debug(" converters")
195203
customScalars.get().forEach { (customScalar, type, converter) ->
196204
logger.debug(" - custom scalar = $customScalar")

plugins/graphql-kotlin-maven-plugin/src/integration/generate-client/pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@
7878
<configuration>
7979
<packageName>com.expediagroup.graphql.plugin.generated</packageName>
8080
<schemaFile>schema.graphql</schemaFile>
81+
<parserOptions>
82+
<maxTokens>15000</maxTokens>
83+
<maxWhitespaceTokens>200000</maxWhitespaceTokens>
84+
<captureIgnoredChars>false</captureIgnoredChars>
85+
<captureLineComments>false</captureLineComments>
86+
<captureSourceLocation>true</captureSourceLocation>
87+
</parserOptions>
8188
</configuration>
8289
</execution>
8390
</executions>

plugins/graphql-kotlin-maven-plugin/src/main/kotlin/com/expediagroup/graphql/plugin/maven/GenerateClientAbstractMojo.kt

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,23 @@ abstract class GenerateClientAbstractMojo : AbstractMojo() {
7373
@Parameter(name = "customScalars")
7474
private var customScalars: List<CustomScalar> = mutableListOf()
7575

76+
/**
77+
* Configure options for parsing GraphQL queries and schema definition language documents. Settings
78+
* here override the defaults set by GraphQL Java.
79+
*
80+
* ```xml
81+
* <parserOptions>
82+
* <maxTokens>15000</maxTokens>
83+
* <maxWhitespaceTokens>200000</maxWhitespaceTokens>
84+
* <captureIgnoredChars>false</captureIgnoredChars>
85+
* <captureLineComments>false</captureLineComments>
86+
* <captureSourceLocation>true</captureSourceLocation>
87+
* </parserOptions>
88+
* ```
89+
*/
90+
@Parameter(name = "parserOptions")
91+
private var parserOptions: ParserOptions? = null
92+
7693
/**
7794
* Directory file containing GraphQL queries. Instead of specifying a directory you can also specify list of query file by using
7895
* [queryFiles] property instead.
@@ -116,7 +133,15 @@ abstract class GenerateClientAbstractMojo : AbstractMojo() {
116133

117134
logConfiguration(schemaPath, targetQueryFiles)
118135
val customGraphQLScalars = customScalars.map { GraphQLScalar(it.scalar, it.type, it.converter) }
119-
generateClient(packageName, allowDeprecatedFields, customGraphQLScalars, serializer, schemaPath, targetQueryFiles, useOptionalInputWrapper).forEach {
136+
generateClient(packageName, allowDeprecatedFields, customGraphQLScalars, serializer, schemaPath, targetQueryFiles, useOptionalInputWrapper, parserOptions = {
137+
parserOptions?.apply {
138+
maxTokens?.let { maxTokens(it) }
139+
maxWhitespaceTokens?.let { maxWhitespaceTokens(it) }
140+
captureIgnoredChars?.let { captureIgnoredChars(it) }
141+
captureLineComments?.let { captureLineComments(it) }
142+
captureSourceLocation?.let { captureSourceLocation(it) }
143+
}
144+
}).forEach {
120145
it.writeTo(outputDirectory)
121146
}
122147

@@ -149,6 +174,14 @@ abstract class GenerateClientAbstractMojo : AbstractMojo() {
149174
log.debug(" |- kotlin type = ${converterInfo.type}")
150175
log.debug(" |- converter = ${converterInfo.converter}")
151176
}
177+
parserOptions?.apply {
178+
log.debug(" parserOptions")
179+
maxTokens?.let { log.debug(" maxTokens = $it") }
180+
maxWhitespaceTokens?.let { log.debug(" maxWhitespaceTokens = $it") }
181+
captureIgnoredChars?.let { log.debug(" captureIgnoredChars = $it") }
182+
captureLineComments?.let { log.debug(" captureLineComments = $it") }
183+
captureSourceLocation?.let { log.debug(" captureSourceLocation = $it") }
184+
}
152185
log.debug("")
153186
log.debug("-- end GraphQL Client generator configuration --")
154187
}
@@ -177,3 +210,29 @@ class CustomScalar {
177210
@Parameter
178211
lateinit var converter: String
179212
}
213+
214+
/**
215+
* Configure options for parsing GraphQL queries and schema definition language documents. Settings
216+
* here override the defaults set by GraphQL Java.
217+
*/
218+
class ParserOptions {
219+
/** Modify the maximum number of tokens read to prevent processing extremely large queries */
220+
@Parameter
221+
var maxTokens: Int? = null
222+
223+
/** Modify the maximum number of whitespace tokens read to prevent processing extremely large queries */
224+
@Parameter
225+
var maxWhitespaceTokens: Int? = null
226+
227+
/** Memory usage is significantly reduced by not capturing ignored characters, especially in SDL parsing. */
228+
@Parameter
229+
var captureIgnoredChars: Boolean? = null
230+
231+
/** Single-line comments do not have any semantic meaning in GraphQL source documents and can be ignored */
232+
@Parameter
233+
var captureLineComments: Boolean? = null
234+
235+
/** Memory usage is reduced by not setting SourceLocations on AST nodes, especially in SDL parsing. */
236+
@Parameter
237+
var captureSourceLocation: Boolean? = null
238+
}

0 commit comments

Comments
 (0)