Skip to content

Commit 7a5bdcf

Browse files
authored
Merge pull request #419 from Netflix/feature/codegen-syntax-insight
2 parents 74c7be2 + ce469e5 commit 7a5bdcf

File tree

2 files changed

+97
-14
lines changed
  • graphql-dgs-codegen-core/src

2 files changed

+97
-14
lines changed

graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/CodeGen.kt

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@ import com.netflix.graphql.dgs.codegen.generators.shared.excludeSchemaTypeExtens
3434
import com.squareup.javapoet.JavaFile
3535
import com.squareup.kotlinpoet.FileSpec
3636
import graphql.language.*
37+
import graphql.parser.InvalidSyntaxException
3738
import graphql.parser.MultiSourceReader
3839
import graphql.parser.Parser
3940
import graphql.parser.ParserOptions
4041
import java.io.File
42+
import java.io.Reader
4143
import java.nio.file.Path
4244
import java.nio.file.Paths
4345

@@ -97,28 +99,41 @@ class CodeGen(private val config: CodeGenConfig) {
9799
builder.maxTokens(SDL_MAX_ALLOWED_SCHEMA_TOKENS)
98100
}
99101
val parser = Parser()
100-
val readerBuilder = MultiSourceReader.newMultiSourceReader()
101-
102-
val schemaFiles = config.schemaFiles.sorted()
103-
.flatMap { it.walkTopDown() }
104-
.filter { it.isFile }
105102

106-
for (schemaFile in schemaFiles) {
107-
schemaFile.appendText("\n")
108-
readerBuilder.reader(schemaFile.reader(), schemaFile.name)
109-
}
110-
111-
for (schema in config.schemas) {
112-
readerBuilder.string(schema, null)
113-
}
103+
val readerBuilder = MultiSourceReader.newMultiSourceReader()
104+
val debugReaderBuilder = MultiSourceReader.newMultiSourceReader()
114105

106+
loadSchemaReaders(readerBuilder, debugReaderBuilder)
115107
val document = readerBuilder.build().use { reader ->
116-
parser.parseDocument(reader, options)
108+
try {
109+
parser.parseDocument(reader, options)
110+
} catch (exception: InvalidSyntaxException) {
111+
throw CodeGenSchemaParsingException(debugReaderBuilder.build(), exception)
112+
}
117113
}
118114

119115
return document
120116
}
121117

118+
/**
119+
* Loads the given [MultiSourceReader.Builder] references with the sources that will be used to provide
120+
* the schema information for the parser.
121+
*/
122+
private fun loadSchemaReaders(vararg readerBuilders: MultiSourceReader.Builder) {
123+
readerBuilders.forEach { rb ->
124+
val schemaFiles = config.schemaFiles.sorted()
125+
.flatMap { it.walkTopDown() }
126+
.filter { it.isFile }
127+
for (schemaFile in schemaFiles) {
128+
rb.string("\n", "codegen")
129+
rb.reader(schemaFile.reader(), schemaFile.name)
130+
}
131+
for (schema in config.schemas) {
132+
rb.string(schema, null)
133+
}
134+
}
135+
}
136+
122137
private fun generateJava(): CodeGenResult {
123138
val definitions = document.definitions
124139
// data types
@@ -618,3 +633,30 @@ fun Type<*>.findBaseTypeDefinition(): TypeDefinition<*>? {
618633
}
619634
}
620635
}
636+
637+
class CodeGenSchemaParsingException(
638+
schemaReader: Reader,
639+
invalidSyntaxException: InvalidSyntaxException
640+
) : RuntimeException(buildMessage(schemaReader, invalidSyntaxException), invalidSyntaxException) {
641+
companion object {
642+
private fun buildMessage(
643+
schemaReader: Reader,
644+
invalidSyntaxException: InvalidSyntaxException
645+
): String {
646+
schemaReader.use { reader ->
647+
return """
648+
|Unable to parse the schema...
649+
|${invalidSyntaxException.message}
650+
|
651+
|Schema Section:
652+
|>>>
653+
|${invalidSyntaxException.sourcePreview}
654+
|<<<
655+
|
656+
|Full Schema:
657+
|${reader.readText()}
658+
""".trimMargin()
659+
}
660+
}
661+
}
662+
}

graphql-dgs-codegen-core/src/test/kotlin/com/netflix/graphql/dgs/codegen/CodeGenTest.kt

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import com.squareup.javapoet.ClassName
2323
import com.squareup.javapoet.JavaFile
2424
import com.squareup.javapoet.ParameterizedTypeName
2525
import com.squareup.javapoet.WildcardTypeName
26+
import org.assertj.core.api.Assertions
2627
import org.assertj.core.api.Assertions.assertThat
2728
import org.junit.jupiter.api.Nested
2829
import org.junit.jupiter.api.Test
@@ -36,6 +37,46 @@ import java.util.stream.Stream
3637

3738
class CodeGenTest {
3839

40+
@Test
41+
fun `When the schema fails to parse, is able to print the error message along with the schema`() {
42+
val schema = """
43+
type Query {
44+
people: [Person]
45+
}
46+
type Person {
47+
firstname: String
48+
lastname: String
49+
}
50+
type Mutation {
51+
""".trimIndent()
52+
53+
Assertions.assertThatThrownBy {
54+
CodeGen(CodeGenConfig(schemas = setOf(schema), packageName = basePackageName)).generate()
55+
}.isInstanceOf(CodeGenSchemaParsingException::class.java)
56+
.hasMessageContainingAll(
57+
"Invalid Syntax : offending token '<EOF>' at line 8 column 16",
58+
"""
59+
|Schema Section:
60+
|>>>
61+
| firstname: String
62+
| lastname: String
63+
|}
64+
|type Mutation {
65+
|
66+
""".trimMargin(),
67+
"""Full Schema:
68+
|type Query {
69+
| people: [Person]
70+
|}
71+
|type Person {
72+
| firstname: String
73+
| lastname: String
74+
|}
75+
|type Mutation {
76+
""".trimMargin()
77+
)
78+
}
79+
3980
@Test
4081
fun generateDataClassWithStringProperties() {
4182
val schema = """

0 commit comments

Comments
 (0)