Skip to content

Commit 03ffdf2

Browse files
authored
More Apollo AST APIs (#5104)
* Add String.parseAsGQLDocument(), File.parseAsGQLDocument() and Path.parseAsGQLDocument() * promote String.toSchema
1 parent 01a097b commit 03ffdf2

File tree

24 files changed

+157
-108
lines changed

24 files changed

+157
-108
lines changed

libraries/apollo-ast/api/apollo-ast.api

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,17 @@
11
public final class com/apollographql/apollo3/ast/ApolloParser {
2+
public static final fun parseAsGQLDocument (Ljava/io/File;Lcom/apollographql/apollo3/ast/ParserOptions;)Lcom/apollographql/apollo3/ast/GQLResult;
3+
public static final fun parseAsGQLDocument (Ljava/lang/String;Lcom/apollographql/apollo3/ast/ParserOptions;)Lcom/apollographql/apollo3/ast/GQLResult;
4+
public static final fun parseAsGQLDocument (Lokio/Path;Lcom/apollographql/apollo3/ast/ParserOptions;)Lcom/apollographql/apollo3/ast/GQLResult;
5+
public static synthetic fun parseAsGQLDocument$default (Ljava/io/File;Lcom/apollographql/apollo3/ast/ParserOptions;ILjava/lang/Object;)Lcom/apollographql/apollo3/ast/GQLResult;
6+
public static synthetic fun parseAsGQLDocument$default (Ljava/lang/String;Lcom/apollographql/apollo3/ast/ParserOptions;ILjava/lang/Object;)Lcom/apollographql/apollo3/ast/GQLResult;
7+
public static synthetic fun parseAsGQLDocument$default (Lokio/Path;Lcom/apollographql/apollo3/ast/ParserOptions;ILjava/lang/Object;)Lcom/apollographql/apollo3/ast/GQLResult;
8+
public static final fun parseAsGQLSelections (Ljava/lang/String;Lcom/apollographql/apollo3/ast/ParserOptions;)Lcom/apollographql/apollo3/ast/GQLResult;
9+
public static synthetic fun parseAsGQLSelections$default (Ljava/lang/String;Lcom/apollographql/apollo3/ast/ParserOptions;ILjava/lang/Object;)Lcom/apollographql/apollo3/ast/GQLResult;
10+
public static final fun parseAsGQLType (Ljava/lang/String;Lcom/apollographql/apollo3/ast/ParserOptions;)Lcom/apollographql/apollo3/ast/GQLResult;
11+
public static synthetic fun parseAsGQLType$default (Ljava/lang/String;Lcom/apollographql/apollo3/ast/ParserOptions;ILjava/lang/Object;)Lcom/apollographql/apollo3/ast/GQLResult;
12+
public static final fun parseAsGQLValue (Ljava/lang/String;Lcom/apollographql/apollo3/ast/ParserOptions;)Lcom/apollographql/apollo3/ast/GQLResult;
13+
public static synthetic fun parseAsGQLValue$default (Ljava/lang/String;Lcom/apollographql/apollo3/ast/ParserOptions;ILjava/lang/Object;)Lcom/apollographql/apollo3/ast/GQLResult;
14+
public static final fun toSchema (Ljava/lang/String;)Lcom/apollographql/apollo3/ast/Schema;
215
}
316

417
public final class com/apollographql/apollo3/ast/Check_key_fieldsKt {

libraries/apollo-ast/src/commonMain/kotlin/com/apollographql/apollo3/ast/Schema.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ class Schema internal constructor(
217217
@ApolloInternal
218218
fun fromMap(map: Map<String, Any>): Schema {
219219
return Schema(
220-
definitions = Buffer().writeUtf8(map["sdl"] as String).parseAsGQLDocument().getOrThrow().definitions,
220+
definitions = (map["sdl"] as String).parseAsGQLDocument().getOrThrow().definitions,
221221
keyFields = (map["keyFields"]!! as Map<String, Collection<String>>).mapValues { it.value.toSet() },
222222
foreignNames = map["foreignNames"]!! as Map<String, String>,
223223
directivesToStrip = map["directivesToStrip"]!! as List<String>,

libraries/apollo-ast/src/commonMain/kotlin/com/apollographql/apollo3/ast/api.kt

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
1+
@file:JvmMultifileClass
12
@file:JvmName("ApolloParser")
23

34
package com.apollographql.apollo3.ast
45

6+
import com.apollographql.apollo3.annotations.ApolloDeprecatedSince
57
import com.apollographql.apollo3.annotations.ApolloExperimental
68
import com.apollographql.apollo3.annotations.ApolloInternal
79
import com.apollographql.apollo3.ast.internal.ExecutableValidationScope
810
import com.apollographql.apollo3.ast.internal.LexerException
911
import com.apollographql.apollo3.ast.internal.Parser
1012
import com.apollographql.apollo3.ast.internal.ParserException
1113
import com.apollographql.apollo3.ast.internal.validateSchema
14+
import okio.Buffer
1215
import okio.BufferedSource
16+
import okio.Path
17+
import okio.buffer
1318
import okio.use
19+
import kotlin.jvm.JvmMultifileClass
1420
import kotlin.jvm.JvmName
1521

1622
/**
@@ -21,6 +27,8 @@ import kotlin.jvm.JvmName
2127
@ApolloExperimental
2228
fun BufferedSource.toSchema(filePath: String? = null): Schema = parseAsGQLDocument(filePath).getOrThrow().validateAsSchema().getOrThrow()
2329

30+
fun String.toSchema(): Schema = parseAsGQLDocument().getOrThrow().validateAsSchema().getOrThrow()
31+
2432
/**
2533
* Parses the source to a List<[GQLDefinition]>, throwing on parsing or validation errors.
2634
*
@@ -37,8 +45,12 @@ fun BufferedSource.toExecutableDefinitions(
3745
.getOrThrow()
3846

3947
private fun <T : Any> BufferedSource.parseInternal(filePath: String?, withSourceLocation: Boolean, block: Parser.() -> T): GQLResult<T> {
48+
return this.use { readUtf8() }.parseInternal(filePath, withSourceLocation, block)
49+
}
50+
51+
private fun <T : Any> String.parseInternal(filePath: String?, withSourceLocation: Boolean, block: Parser.() -> T): GQLResult<T> {
4052
return try {
41-
GQLResult(Parser(this.use { it.readUtf8() }, withSourceLocation, filePath).block(), emptyList())
53+
GQLResult(Parser(this, withSourceLocation, filePath).block(), emptyList())
4254
} catch (e: ParserException) {
4355
GQLResult(
4456
null,
@@ -75,6 +87,8 @@ private fun <T : Any> BufferedSource.parseInternal(filePath: String?, withSource
7587
}
7688

7789
class ParserOptions(
90+
@Deprecated("This is used as a fallback the time to stabilize the new parser but will be removed")
91+
@ApolloDeprecatedSince(ApolloDeprecatedSince.Version.v4_0_0)
7892
val useAntlr: Boolean = false,
7993
val allowEmptyDocuments: Boolean = true,
8094
val withSourceLocation: Boolean = true,
@@ -84,10 +98,47 @@ class ParserOptions(
8498
}
8599
}
86100

87-
expect internal fun parseDocumentWithAntlr(source: BufferedSource, filePath: String?): GQLResult<GQLDocument>
88-
expect internal fun parseValueWithAntlr(source: BufferedSource, filePath: String?): GQLResult<GQLValue>
89-
expect internal fun parseTypeWithAntlr(source: BufferedSource, filePath: String?): GQLResult<GQLType>
90-
expect internal fun parseSelectionsWithAntlr(source: BufferedSource, filePath: String?): GQLResult<List<GQLSelection>>
101+
internal expect fun parseDocumentWithAntlr(source: BufferedSource, filePath: String?): GQLResult<GQLDocument>
102+
internal expect fun parseValueWithAntlr(source: BufferedSource, filePath: String?): GQLResult<GQLValue>
103+
internal expect fun parseTypeWithAntlr(source: BufferedSource, filePath: String?): GQLResult<GQLType>
104+
internal expect fun parseSelectionsWithAntlr(source: BufferedSource, filePath: String?): GQLResult<List<GQLSelection>>
105+
106+
fun String.parseAsGQLDocument(options: ParserOptions = ParserOptions.Default): GQLResult<GQLDocument> {
107+
@Suppress("DEPRECATION")
108+
return if (options.useAntlr) {
109+
Buffer().writeUtf8(this).parseAsGQLDocument(options = options)
110+
} else {
111+
parseInternal(null, options.withSourceLocation) { parseDocument(options.allowEmptyDocuments) }
112+
}
113+
}
114+
fun String.parseAsGQLValue(options: ParserOptions = ParserOptions.Default): GQLResult<GQLValue> {
115+
@Suppress("DEPRECATION")
116+
return if (options.useAntlr) {
117+
Buffer().writeUtf8(this).parseAsGQLValue(options = options)
118+
} else {
119+
parseInternal(null, options.withSourceLocation) { parseValue() }
120+
}
121+
}
122+
fun String.parseAsGQLType(options: ParserOptions = ParserOptions.Default): GQLResult<GQLType> {
123+
@Suppress("DEPRECATION")
124+
return if (options.useAntlr) {
125+
Buffer().writeUtf8(this).parseAsGQLType(options = options)
126+
} else {
127+
parseInternal(null, options.withSourceLocation) { parseType() }
128+
}
129+
}
130+
fun String.parseAsGQLSelections(options: ParserOptions = ParserOptions.Default): GQLResult<List<GQLSelection>> {
131+
@Suppress("DEPRECATION")
132+
return if (options.useAntlr) {
133+
Buffer().writeUtf8(this).parseAsGQLSelections(options = options)
134+
} else {
135+
parseInternal(null, options.withSourceLocation) { parseSelections() }
136+
}
137+
}
138+
139+
fun Path.parseAsGQLDocument(options: ParserOptions = ParserOptions.Default): GQLResult<GQLDocument> {
140+
return HOST_FILESYSTEM.source(this).buffer().parseAsGQLDocument(filePath = toString(), options = options)
141+
}
91142

92143
/**
93144
* Parses the source to a [GQLDocument], validating the syntax but not the contents of the document.
@@ -101,6 +152,7 @@ expect internal fun parseSelectionsWithAntlr(source: BufferedSource, filePath: S
101152
*/
102153
@ApolloExperimental
103154
fun BufferedSource.parseAsGQLDocument(filePath: String? = null, options: ParserOptions = ParserOptions.Default): GQLResult<GQLDocument> {
155+
@Suppress("DEPRECATION")
104156
return if (options.useAntlr) {
105157
parseDocumentWithAntlr(this, filePath)
106158
} else {
@@ -115,6 +167,7 @@ fun BufferedSource.parseAsGQLDocument(filePath: String? = null, options: ParserO
115167
*/
116168
@ApolloExperimental
117169
fun BufferedSource.parseAsGQLValue(filePath: String? = null, options: ParserOptions = ParserOptions.Default): GQLResult<GQLValue> {
170+
@Suppress("DEPRECATION")
118171
return if (options.useAntlr) {
119172
parseValueWithAntlr(this, filePath)
120173
} else {
@@ -129,6 +182,7 @@ fun BufferedSource.parseAsGQLValue(filePath: String? = null, options: ParserOpti
129182
*/
130183
@ApolloExperimental
131184
fun BufferedSource.parseAsGQLType(filePath: String? = null, options: ParserOptions = ParserOptions.Default): GQLResult<GQLType> {
185+
@Suppress("DEPRECATION")
132186
return if (options.useAntlr) {
133187
parseTypeWithAntlr(this, filePath)
134188
} else {
@@ -146,6 +200,7 @@ fun BufferedSource.parseAsGQLSelections(
146200
filePath: String? = null,
147201
options: ParserOptions = ParserOptions.Default,
148202
): GQLResult<List<GQLSelection>> {
203+
@Suppress("DEPRECATION")
149204
return if (options.useAntlr) {
150205
parseSelectionsWithAntlr(this, filePath)
151206
} else {

libraries/apollo-ast/src/commonMain/kotlin/com/apollographql/apollo3/ast/gqldocument.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ fun apolloDefinitions(version: String): List<GQLDefinition> {
4343
}
4444

4545
private fun definitionsFromString(string: String): List<GQLDefinition> {
46-
return Buffer().writeUtf8(string)
47-
.parseAsGQLDocument(null)
46+
return string
47+
.parseAsGQLDocument()
4848
.getOrThrow()
4949
.definitions
5050
}

libraries/apollo-ast/src/commonMain/kotlin/com/apollographql/apollo3/ast/gqltypedefinition.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package com.apollographql.apollo3.ast
22

33
import com.apollographql.apollo3.annotations.ApolloInternal
44
import com.apollographql.apollo3.ast.Schema.Companion.NONNULL
5-
import com.apollographql.apollo3.ast.internal.buffer
65

76
// 5.5.2.3 Fragment spread is possible
87
internal fun GQLTypeDefinition.sharesPossibleTypesWith(other: GQLTypeDefinition, schema: Schema): Boolean {
@@ -27,7 +26,7 @@ fun GQLTypeDefinition.isFieldNonNull(fieldName: String, schema: Schema? = null):
2726

2827
val stringValue = (directive.arguments.first().value as GQLStringValue).value
2928

30-
val selections = stringValue.buffer().parseAsGQLSelections().getOrThrow()
29+
val selections = stringValue.parseAsGQLSelections().getOrThrow()
3130

3231
return selections.filterIsInstance<GQLField>()
3332
.map { it.name }

libraries/apollo-ast/src/commonMain/kotlin/com/apollographql/apollo3/ast/internal/SchemaValidationScope.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ private fun List<GQLDirective>.extractFields(argumentName: String): Set<String>
502502

503503
val selectionSet = (value as? GQLStringValue)?.value ?: return@flatMap emptyList()
504504

505-
selectionSet.buffer().parseAsGQLSelections().getOrThrow().map { gqlSelection ->
505+
selectionSet.parseAsGQLSelections().getOrThrow().map { gqlSelection ->
506506
// No need to check here, this should be done during validation
507507
(gqlSelection as GQLField).name
508508
}

libraries/apollo-ast/src/commonMain/kotlin/com/apollographql/apollo3/ast/internal/ValidationCommon.kt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ import com.apollographql.apollo3.ast.findDeprecationReason
3737
import com.apollographql.apollo3.ast.isVariableUsageAllowed
3838
import com.apollographql.apollo3.ast.parseAsGQLSelections
3939
import com.apollographql.apollo3.ast.pretty
40-
import okio.Buffer
4140

4241
interface IssuesScope {
4342
val issues: MutableList<Issue>
@@ -186,7 +185,7 @@ internal fun ValidationScope.extraValidateNonNullDirective(directive: GQLDirecti
186185
)
187186
val stringValue = (directive.arguments.first().value as GQLStringValue).value
188187

189-
val selections = stringValue.buffer().parseAsGQLSelections().getOrThrow()
188+
val selections = stringValue.parseAsGQLSelections().getOrThrow()
190189

191190
val badSelection = selections.firstOrNull { it !is GQLField }
192191
check(badSelection == null) {
@@ -207,7 +206,7 @@ internal fun ValidationScope.extraValidateNonNullDirective(directive: GQLDirecti
207206
* Extra Apollo-specific validation for @typePolicy
208207
*/
209208
internal fun ValidationScope.extraValidateTypePolicyDirective(directive: GQLDirective) {
210-
(directive.arguments.first().value as GQLStringValue).value.buffer().parseAsGQLSelections().getOrThrow().forEach {
209+
(directive.arguments.first().value as GQLStringValue).value.parseAsGQLSelections().getOrThrow().forEach {
211210
if (it !is GQLField) {
212211
registerIssue("Fragments are not supported in @$TYPE_POLICY directives", it.sourceLocation)
213212
} else if (it.selections.isNotEmpty()) {
@@ -216,8 +215,6 @@ internal fun ValidationScope.extraValidateTypePolicyDirective(directive: GQLDire
216215
}
217216
}
218217

219-
internal fun String.buffer() = Buffer().writeUtf8(this)
220-
221218
private fun ValidationScope.validateArgument(
222219
argument: GQLArgument,
223220
inputValueDefinitions: List<GQLInputValueDefinition>,

libraries/apollo-ast/src/commonMain/kotlin/com/apollographql/apollo3/ast/introspection/introspection_to_schema.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,13 @@ import com.apollographql.apollo3.ast.GQLStringValue
3232
import com.apollographql.apollo3.ast.GQLType
3333
import com.apollographql.apollo3.ast.GQLUnionTypeDefinition
3434
import com.apollographql.apollo3.ast.GQLValue
35-
import com.apollographql.apollo3.ast.HOST_FILESYSTEM
3635
import com.apollographql.apollo3.ast.Schema
3736
import com.apollographql.apollo3.ast.SourceLocation
3837
import com.apollographql.apollo3.ast.parseAsGQLDocument
3938
import com.apollographql.apollo3.ast.parseAsGQLValue
40-
import com.apollographql.apollo3.ast.toSchema
4139
import com.apollographql.apollo3.ast.validateAsSchema
4240
import okio.Buffer
4341
import okio.Path
44-
import okio.buffer
4542
import kotlin.jvm.JvmMultifileClass
4643
import kotlin.jvm.JvmName
4744

@@ -344,7 +341,7 @@ fun Path.toSchemaGQLDocument(): GQLDocument {
344341
return if (name.endsWith("json")) {
345342
toIntrospectionSchema().toGQLDocument(filePath = name)
346343
} else {
347-
HOST_FILESYSTEM.source(this).buffer().parseAsGQLDocument(this.toString()).getOrThrow()
344+
parseAsGQLDocument().getOrThrow()
348345
}
349346
}
350347

libraries/apollo-ast/src/commonTest/kotlin/com/apollographql/apollo3/graphql/ast/test/ParserTest.kt

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@ import com.apollographql.apollo3.ast.GQLFieldDefinition
55
import com.apollographql.apollo3.ast.GQLObjectTypeDefinition
66
import com.apollographql.apollo3.ast.GQLOperationDefinition
77
import com.apollographql.apollo3.ast.GQLStringValue
8-
import com.apollographql.apollo3.ast.GQLTypeDefinition
9-
import com.apollographql.apollo3.ast.SourceLocation
10-
import com.apollographql.apollo3.ast.internal.buffer
118
import com.apollographql.apollo3.ast.parseAsGQLDocument
129
import com.apollographql.apollo3.ast.parseAsGQLValue
1310
import kotlin.test.Test
@@ -23,7 +20,6 @@ class ParserTest {
2320
query Test { field }
2421
ab bc
2522
""".trimIndent()
26-
.buffer()
2723
.parseAsGQLDocument()
2824
.getOrThrow()
2925
fail("An exception was expected")
@@ -39,14 +35,13 @@ class ParserTest {
3935
query Test { field }
4036
# comment after
4137
""".trimIndent()
42-
.buffer()
4338
.parseAsGQLDocument()
4439
.getOrThrow()
4540
}
4641

4742
@Test
4843
fun blockString() {
49-
val value = "\"\"\" \\\"\"\" \"\"\"".buffer().parseAsGQLValue().getOrThrow()
44+
val value = "\"\"\" \\\"\"\" \"\"\"".parseAsGQLValue().getOrThrow()
5045

5146
assertEquals(" \"\"\" ", (value as GQLStringValue).value)
5247
}
@@ -58,7 +53,7 @@ class ParserTest {
5853
" \n" +
5954
" second line\n" +
6055
" \n" +
61-
"\"\"\"").buffer().parseAsGQLValue().getOrThrow()
56+
"\"\"\"").parseAsGQLValue().getOrThrow()
6257

6358
assertEquals("first line\n \nsecond line", (value as GQLStringValue).value)
6459
}
@@ -76,7 +71,6 @@ query Test {
7671
)
7772
}
7873
""".trimIndent()
79-
.buffer()
8074
.parseAsGQLDocument()
8175
.getOrThrow()
8276
.definitions
@@ -101,7 +95,6 @@ query Test {
10195
fieldA: String
10296
}
10397
""".trimIndent()
104-
.buffer()
10598
.parseAsGQLDocument()
10699
.getOrThrow()
107100
.definitions

libraries/apollo-ast/src/commonTest/kotlin/com/apollographql/apollo3/graphql/ast/test/SDLWriterTest.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package com.apollographql.apollo3.graphql.ast.test
22

33
import com.apollographql.apollo3.ast.SDLWriter
44
import com.apollographql.apollo3.ast.Schema
5-
import com.apollographql.apollo3.ast.internal.buffer
65
import com.apollographql.apollo3.ast.parseAsGQLDocument
76
import com.apollographql.apollo3.ast.toSchema
87
import com.apollographql.apollo3.ast.toUtf8
@@ -44,7 +43,7 @@ class SDLWriterTest {
4443
4544
""".trimIndent()
4645

47-
val schema: Schema = schemaString.buffer().toSchema()
46+
val schema: Schema = schemaString.toSchema()
4847
val writerBuffer = Buffer()
4948
val sdlWriter = SDLWriter(writerBuffer, " ")
5049
sdlWriter.write(schema.toGQLDocument())
@@ -107,11 +106,11 @@ class SDLWriterTest {
107106
108107
""".trimIndent()
109108

110-
val expected = Buffer().writeUtf8(schemaString).parseAsGQLDocument().getOrThrow()
109+
val expected = schemaString.parseAsGQLDocument().getOrThrow()
111110

112111
val serialized = expected.toUtf8()
113112

114-
Buffer().writeUtf8(serialized).parseAsGQLDocument().getOrThrow()
113+
serialized.parseAsGQLDocument().getOrThrow()
115114
// Enable when we have hashCode and equals on GQLNode
116115
//assertEquals(expected.removeLocation(), actual.removeLocation())
117116
}

0 commit comments

Comments
 (0)