Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.apollographql.apollo3.ast.gql.kt Maven / Gradle / Ivy
package com.apollographql.apollo3.ast
/**
* The GraphQL AST definition
*
* This is all in one file so we can use sealed classes. Extensions are in gqlxyz.kt
*/
/**
* A node in the GraphQL AST.
*
* The structure of the different nodes matches closely the one of the GraphQL specification
* (https://spec.graphql.org/June2018/#sec-Appendix-Grammar-Summary.Document)
*
* Compared to the Antlr [com.apollographql.apollo3.compiler.parser.antlr.GraphQLParser.DocumentContext], a GQLDocument
* is a lot simpler and allows for easy modifying a document (using [GQLNode.transform]()) and outputing them to a [okio.BufferedSink].
*
* Whitespace tokens are not mapped to GQLNodes so some formatting will be lost during modification
*/
interface GQLNode {
val sourceLocation: SourceLocation
/**
* The children of this node.
*
* Terminal nodes won't have any children.
*/
val children: List
/**
* Write the node to the given writer
*
* The general convention is that [GQLNode] should output their trailing line if they know
* they will need one
*/
fun write(writer: SDLWriter)
/**
* Internal-only. Copies this code using the given children
*
* To transform an AST, use [GQLNode.transform] instead
*/
fun copyWithNewChildren(container: NodeContainer): GQLNode
}
fun GQLNode.transform(block: (GQLNode) -> GQLNode?): GQLNode? {
val newChildren = children.mapNotNull {
it.transform(block)
}
return block(this)?.run {
val container = NodeContainer(newChildren)
copyWithNewChildren(container).also {
container.assert()
}
}
}
/**
* A [GQLNode] that has a name
*/
interface GQLNamed {
val name: String
}
/**
* A [GQLNode] that has a description
*/
interface GQLDescribed {
val description: String?
}
interface GQLDefinition : GQLNode
interface GQLTypeSystemExtension : GQLNode
interface GQLTypeExtension : GQLTypeSystemExtension, GQLNamed
sealed class GQLSelection : GQLNode
/**
* The top level node in a GraphQL document. This can be a schema document or an executable document
* (or something else if need be)
*
* See [parseAsGQLDocument] for how to obtain a [GQLDocument].
*/
data class GQLDocument(
val definitions: List,
val filePath: String?,
) : GQLNode {
override val sourceLocation: SourceLocation = SourceLocation(0, 0, filePath)
override val children = definitions
override fun write(writer: SDLWriter) {
definitions.join(writer = writer, separator = "\n")
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return GQLDocument(
definitions = container.take(),
filePath = filePath
)
}
companion object
}
data class GQLOperationDefinition(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val operationType: String,
val name: String?,
val variableDefinitions: List,
val directives: List,
val selectionSet: GQLSelectionSet,
override val description: String?,
) : GQLDefinition, GQLDescribed {
override val children = variableDefinitions + directives + selectionSet
override fun write(writer: SDLWriter) {
with(writer) {
write(operationType)
if (name != null) {
write(" ")
write(name)
if (variableDefinitions.isNotEmpty()) {
variableDefinitions.join(writer = writer, separator = ", ", prefix = "(", postfix = ")")
}
}
if (directives.isNotEmpty()) {
write(" ")
directives.join(writer)
}
if (selectionSet.selections.isNotEmpty()) {
write(" ")
selectionSet.write(writer)
}
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
variableDefinitions = container.take(),
directives = container.take(),
selectionSet = container.take().single(),
)
}
}
data class GQLFragmentDefinition(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
override val name: String,
val directives: List,
val typeCondition: GQLNamedType,
val selectionSet: GQLSelectionSet,
override val description: String?,
) : GQLDefinition, GQLNamed, GQLDescribed {
override val children = directives + selectionSet + typeCondition
override fun write(writer: SDLWriter) {
with(writer) {
write("fragment $name on ${typeCondition.name}")
if (directives.isNotEmpty()) {
write(" ")
directives.join(writer)
}
if (selectionSet.selections.isNotEmpty()) {
write(" ")
selectionSet.write(writer)
}
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
directives = container.take(),
typeCondition = container.take().single(),
selectionSet = container.take().single(),
)
}
}
data class GQLSchemaDefinition(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val description: String?,
val directives: List,
val rootOperationTypeDefinitions: List,
) : GQLDefinition {
override val children = directives + rootOperationTypeDefinitions
override fun write(writer: SDLWriter) {
with(writer) {
writeDescription(description)
if (directives.isNotEmpty()) {
directives.join(writer)
write(" ")
}
write("schema ")
write("{\n")
indent()
rootOperationTypeDefinitions.join(writer, separator = "",)
unindent()
write("}\n")
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
directives = container.take(),
rootOperationTypeDefinitions = container.take()
)
}
}
sealed class GQLTypeDefinition : GQLDefinition, GQLNamed, GQLDescribed {
fun isBuiltIn(): Boolean = builtInTypes.contains(this.name)
/**
* This duplicates some of what's in "builtins.graphqls" but it's easier to access
*/
private companion object {
val builtInTypes: Set = setOf(
"Int",
"Float",
"String",
"Boolean",
"ID",
"__Schema",
"__Type",
"__Field",
"__InputValue",
"__EnumValue",
"__TypeKind",
"__Directive",
"__DirectiveLocation"
)
}
}
data class GQLInterfaceTypeDefinition(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
override val description: String?,
override val name: String,
val implementsInterfaces: List,
val directives: List,
val fields: List,
) : GQLTypeDefinition() {
override val children: List = directives + fields
override fun write(writer: SDLWriter) {
with(writer) {
writeDescription(description)
write("interface $name")
if (implementsInterfaces.isNotEmpty()) {
write(" implements ")
write(implementsInterfaces.joinToString(" "))
}
if (directives.isNotEmpty()) {
write(" ")
directives.join(writer)
}
if (fields.isNotEmpty()) {
write(" ")
write("{\n")
indent()
fields.join(writer, separator = "\n\n")
unindent()
write("\n}\n")
}
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
directives = container.take(),
fields = container.take()
)
}
}
data class GQLObjectTypeDefinition(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
override val description: String?,
override val name: String,
val implementsInterfaces: List,
val directives: List,
val fields: List,
) : GQLTypeDefinition() {
override val children: List = directives + fields
override fun write(writer: SDLWriter) {
with(writer) {
writeDescription(description)
write("type $name")
if (implementsInterfaces.isNotEmpty()) {
write(" implements ")
write(implementsInterfaces.joinToString(" "))
}
if (directives.isNotEmpty()) {
write(" ")
directives.join(writer)
}
if (fields.isNotEmpty()) {
write(" ")
write("{\n")
indent()
fields.join(writer, separator = "\n\n")
unindent()
write("\n}\n")
}
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
directives = container.take(),
fields = container.take()
)
}
}
data class GQLInputObjectTypeDefinition(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
override val description: String?,
override val name: String,
val directives: List,
val inputFields: List,
) : GQLTypeDefinition() {
override val children: List = directives + inputFields
override fun write(writer: SDLWriter) {
with(writer) {
writeDescription(description)
write("input $name")
if (directives.isNotEmpty()) {
write(" ")
directives.join(writer)
}
if (inputFields.isNotEmpty()) {
write(" ")
write("{\n")
indent()
inputFields.join(writer, separator = "\n")
unindent()
write("}\n")
}
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
directives = container.take(),
inputFields = container.take()
)
}
}
data class GQLScalarTypeDefinition(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
override val description: String?,
override val name: String,
val directives: List,
) : GQLTypeDefinition() {
override val children = directives
override fun write(writer: SDLWriter) {
with(writer) {
writeDescription(description)
write("scalar $name")
if (directives.isNotEmpty()) {
write(" ")
directives.join(writer)
}
write("\n")
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
directives = container.take()
)
}
}
data class GQLEnumTypeDefinition(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
override val description: String?,
override val name: String,
val directives: List,
val enumValues: List,
) : GQLTypeDefinition() {
override val children: List = directives + enumValues
override fun write(writer: SDLWriter) {
with(writer) {
writeDescription(description)
write("enum $name")
if (directives.isNotEmpty()) {
write(" ")
directives.join(writer)
}
if (enumValues.isNotEmpty()) {
write(" ")
write("{\n")
indent()
enumValues.join(writer, separator = "\n",)
unindent()
write("}\n")
}
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
directives = container.take(),
enumValues = container.take()
)
}
}
data class GQLUnionTypeDefinition(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
override val description: String?,
override val name: String,
val directives: List,
val memberTypes: List,
) : GQLTypeDefinition() {
override val children: List = directives + memberTypes
override fun write(writer: SDLWriter) {
with(writer) {
writeDescription(description)
write("union $name")
if (directives.isNotEmpty()) {
write(" ")
directives.join(writer)
}
write(" = ")
memberTypes.join(writer, separator = "|")
write("\n")
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
directives = container.take(),
memberTypes = container.take()
)
}
}
data class GQLDirectiveDefinition(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val description: String?,
override val name: String,
val arguments: List,
val repeatable: Boolean,
val locations: List,
) : GQLDefinition, GQLNamed {
override val children: List = arguments
override fun write(writer: SDLWriter) {
with(writer) {
writeDescription(description)
write("directive @$name")
if (arguments.isNotEmpty()) {
write(" ")
arguments.join(writer, prefix = "(", separator = ", ", postfix = ")") {
it.write(writer, true)
}
}
if (repeatable) {
write(" repeatable")
}
write(" on ${locations.joinToString("|")}")
write("\n")
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
arguments = container.take(),
)
}
fun isBuiltIn(): Boolean = builtInDirectives.contains(this.name)
companion object {
val builtInDirectives: Set = setOf(
"include",
"skip",
"deprecated",
)
}
}
data class GQLSchemaExtension(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val directives: List,
val operationTypesDefinition: List,
) : GQLDefinition, GQLTypeSystemExtension {
override val children = directives + operationTypesDefinition
override fun write(writer: SDLWriter) {
TODO("Not yet implemented")
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
directives = container.take(),
operationTypesDefinition = container.take()
)
}
}
data class GQLEnumTypeExtension(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
override val name: String,
val directives: List,
val enumValues: List,
) : GQLDefinition, GQLTypeExtension {
override val children: List = directives + enumValues
override fun write(writer: SDLWriter) {
TODO("Not yet implemented")
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
directives = container.take(),
enumValues = container.take()
)
}
}
data class GQLObjectTypeExtension(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
override val name: String,
val implementsInterfaces: List,
val directives: List,
val fields: List,
) : GQLDefinition, GQLTypeExtension {
override val children: List = directives + fields
override fun write(writer: SDLWriter) {
TODO("Not yet implemented")
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
directives = container.take(),
fields = container.take()
)
}
}
data class GQLInputObjectTypeExtension(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
override val name: String,
val directives: List,
val inputFields: List,
) : GQLDefinition, GQLTypeExtension {
override val children: List = directives + inputFields
override fun write(writer: SDLWriter) {
TODO("Not yet implemented")
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
directives = container.take(),
inputFields = container.take()
)
}
}
data class GQLScalarTypeExtension(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
override val name: String,
val directives: List,
) : GQLDefinition, GQLTypeExtension {
override val children = directives
override fun write(writer: SDLWriter) {
TODO("Not yet implemented")
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
directives = container.take()
)
}
}
data class GQLInterfaceTypeExtension(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
override val name: String,
val implementsInterfaces: List,
val fields: List,
) : GQLDefinition, GQLTypeExtension, GQLNamed {
override val children = fields
override fun write(writer: SDLWriter) {
TODO("Not yet implemented")
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
fields = container.take()
)
}
}
data class GQLUnionTypeExtension(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
override val name: String,
val directives: List,
val memberTypes: List,
) : GQLDefinition, GQLTypeExtension {
override val children: List = directives + memberTypes
override fun write(writer: SDLWriter) {
TODO("Not yet implemented")
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
directives = container.take(),
memberTypes = container.take()
)
}
}
data class GQLEnumValueDefinition(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val description: String?,
override val name: String,
val directives: List,
) : GQLNode, GQLNamed {
override val children = directives
override fun write(writer: SDLWriter) {
with(writer) {
writeDescription(description)
write(name)
if (directives.isNotEmpty()) {
write(" ")
directives.join(writer)
}
write("\n")
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
directives = container.take()
)
}
}
data class GQLFieldDefinition(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val description: String?,
override val name: String,
val arguments: List,
val type: GQLType,
val directives: List,
) : GQLNode, GQLNamed {
override val children: List = directives + arguments
override fun write(writer: SDLWriter) {
with(writer) {
writeDescription(description)
write(name)
if (arguments.isNotEmpty()) {
arguments.join(writer, prefix = "(", separator = ", ", postfix = ")") {
it.write(writer, true)
}
}
write(": ")
type.write(writer)
if (directives.isNotEmpty()) {
write(" ")
directives.join(writer)
}
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
directives = container.take(),
arguments = container.take()
)
}
}
data class GQLInputValueDefinition(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val description: String?,
override val name: String,
val directives: List,
val type: GQLType,
val defaultValue: GQLValue?,
) : GQLNode, GQLNamed {
override val children = directives
/**
* @param inline whether the input value definition is used inline (for an example a field argument)
* or as a block (for an example for input fields)
*/
fun write(writer: SDLWriter, inline: Boolean) {
with(writer) {
if (inline) {
writeInlineString(description)
if (description != null) {
write(" ")
}
} else {
writeDescription(description)
}
write("$name: ")
type.write(writer)
if (defaultValue != null) {
write(" = ")
defaultValue.write(writer)
}
if (directives.isNotEmpty()) {
write(" ")
directives.join(writer)
}
if (!inline) {
write("\n")
}
}
}
override fun write(writer: SDLWriter) {
write(writer, false)
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
directives = container.take()
)
}
}
/**
* A variable definition is very similar to an InputValue definition except it doesn't
* have a description
*/
data class GQLVariableDefinition(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val name: String,
val type: GQLType,
val defaultValue: GQLValue?,
val directives: List,
) : GQLNode {
override val children = listOfNotNull(defaultValue) + directives
override fun write(writer: SDLWriter) {
with(writer) {
write("${'$'}$name: ")
type.write(writer)
if (defaultValue != null) {
write(" = ")
defaultValue.write(writer)
write(" ")
}
// TODO("support variable directives")
// directives.join(writer)
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
directives = container.take(),
defaultValue = container.takeSingle()
)
}
}
data class GQLOperationTypeDefinition(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val operationType: String,
val namedType: String,
) : GQLNode {
override val children = emptyList()
override fun write(writer: SDLWriter) {
with(writer) {
write("$operationType: $namedType\n")
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return this
}
}
data class GQLDirective(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
override val name: String,
val arguments: GQLArguments?,
) : GQLNode, GQLNamed {
override val children = listOfNotNull(arguments)
override fun write(writer: SDLWriter) {
with(writer) {
write("@$name")
arguments?.write(writer)
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
arguments = container.takeSingle()
)
}
}
data class GQLObjectField(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val name: String,
val value: GQLValue,
) : GQLNode {
override val children = listOf(value)
override fun write(writer: SDLWriter) {
with(writer) {
write("$name: ")
value.write(writer)
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
value = container.takeSingle()!!
)
}
}
data class GQLArgument(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val name: String,
val value: GQLValue,
) : GQLNode {
override val children = listOf(value)
override fun write(writer: SDLWriter) {
with(writer) {
write("$name: ")
value.write(writer)
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
value = container.takeSingle()!!
)
}
}
data class GQLSelectionSet(
val selections: List,
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
) : GQLNode {
override val children = selections
override fun write(writer: SDLWriter) {
with(writer) {
write("{\n")
indent()
selections.join(writer, separator = "")
unindent()
write("}\n")
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
selections = container.take()
)
}
}
data class GQLArguments(
val arguments: List,
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
) : GQLNode {
override val children: List = arguments
override fun write(writer: SDLWriter) {
arguments.join(writer, prefix = "(", separator = ", ", postfix = ")")
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
arguments = container.take()
)
}
}
data class GQLField(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val alias: String?,
val name: String,
val arguments: GQLArguments?,
val directives: List,
val selectionSet: GQLSelectionSet?,
) : GQLSelection() {
override val children: List = listOfNotNull(selectionSet) + listOfNotNull(arguments) + directives
override fun write(writer: SDLWriter) {
with(writer) {
if (alias != null) {
write("$alias: ")
}
write(name)
arguments?.write(writer)
if (directives.isNotEmpty()) {
write(" ")
directives.join(writer)
}
if (selectionSet != null) {
write(" ")
selectionSet.write(writer)
} else {
write("\n")
}
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
selectionSet = container.takeSingle(),
arguments = container.takeSingle(),
directives = container.take()
)
}
}
data class GQLInlineFragment(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val typeCondition: GQLNamedType,
val directives: List,
val selectionSet: GQLSelectionSet,
) : GQLSelection() {
override val children = directives + selectionSet + typeCondition
override fun write(writer: SDLWriter) {
with(writer) {
write("... on ${typeCondition.name}")
if (directives.isNotEmpty()) {
write(" ")
directives.join(writer)
}
if (selectionSet.selections.isNotEmpty()) {
write(" ")
selectionSet.write(writer)
}
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
directives = container.take(),
selectionSet = container.takeSingle()!!,
typeCondition = container.takeSingle()!!
)
}
}
data class GQLFragmentSpread(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val name: String,
val directives: List,
) : GQLSelection() {
override val children = directives
override fun write(writer: SDLWriter) {
with(writer) {
write("...${name}")
if (directives.isNotEmpty()) {
write(" ")
directives.join(writer)
}
write("\n")
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
directives = container.take()
)
}
}
sealed class GQLType : GQLNode
data class GQLNamedType(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
override val name: String,
) : GQLType(), GQLNamed {
override val children = emptyList()
override fun write(writer: SDLWriter) {
with(writer) {
write(name)
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return this
}
}
data class GQLNonNullType(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val type: GQLType,
) : GQLType() {
override val children = listOf(type)
override fun write(writer: SDLWriter) {
with(writer) {
type.write(writer)
write("!")
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
type = container.takeSingle()!!
)
}
}
data class GQLListType(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val type: GQLType,
) : GQLType() {
override val children = listOf(type)
override fun write(writer: SDLWriter) {
with(writer) {
write("[")
type.write(writer)
write("]")
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
type = container.takeSingle()!!
)
}
}
sealed class GQLValue : GQLNode
data class GQLVariableValue(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val name: String,
) : GQLValue() {
override val children = emptyList()
override fun write(writer: SDLWriter) {
with(writer) {
write("${'$'}$name")
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return this
}
}
data class GQLIntValue(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val value: Int,
) : GQLValue() {
override val children = emptyList()
override fun write(writer: SDLWriter) {
with(writer) {
write(value.toString())
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return this
}
}
data class GQLFloatValue(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val value: Double,
) : GQLValue() {
override val children = emptyList()
override fun write(writer: SDLWriter) {
with(writer) {
write(value.toString())
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return this
}
}
data class GQLStringValue(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val value: String,
) : GQLValue() {
override val children = emptyList()
override fun write(writer: SDLWriter) {
with(writer) {
write("\"${value.encodeToGraphQLSingleQuoted()}\"")
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return this
}
}
data class GQLBooleanValue(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val value: Boolean,
) : GQLValue() {
override val children = emptyList()
override fun write(writer: SDLWriter) {
with(writer) {
write(value.toString())
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return this
}
}
data class GQLEnumValue(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val value: String,
) : GQLValue() {
override val children = emptyList()
override fun write(writer: SDLWriter) {
with(writer) {
write(value)
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return this
}
}
data class GQLListValue(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val values: List,
) : GQLValue() {
override val children = values
override fun write(writer: SDLWriter) {
with(writer) {
write("[")
values.join(writer, ",")
write("]")
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
values = container.take()
)
}
}
data class GQLObjectValue(
override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN,
val fields: List,
) : GQLValue() {
override val children = fields
override fun write(writer: SDLWriter) {
with(writer) {
write("{\n")
indent()
fields.join(writer = writer, "\n")
unindent()
write("\n}\n")
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return copy(
fields = container.take()
)
}
}
data class GQLNullValue(override val sourceLocation: SourceLocation = SourceLocation.UNKNOWN) : GQLValue() {
override val children = emptyList()
override fun write(writer: SDLWriter) {
with(writer) {
write("null")
}
}
override fun copyWithNewChildren(container: NodeContainer): GQLNode {
return this
}
}
private fun List.join(
writer: SDLWriter,
separator: String = " ",
prefix: String = "",
postfix: String = "",
block: (T) -> Unit = {it.write(writer)}
) {
writer.write(prefix)
forEachIndexed { index, t ->
block(t)
if (index < size - 1) {
writer.write(separator)
}
}
writer.write(postfix)
}
enum class GQLDirectiveLocation {
QUERY,
MUTATION,
SUBSCRIPTION,
FIELD,
FRAGMENT_DEFINITION,
FRAGMENT_SPREAD,
INLINE_FRAGMENT,
VARIABLE_DEFINITION,
SCHEMA,
SCALAR,
OBJECT,
FIELD_DEFINITION,
ARGUMENT_DEFINITION,
INTERFACE,
UNION,
ENUM,
ENUM_VALUE,
INPUT_OBJECT,
INPUT_FIELD_DEFINITION,
}
@Suppress("UNCHECKED_CAST")
class NodeContainer(nodes: List) {
var remainingNodes = nodes
inline fun take(): List {
val (ret, rem) = remainingNodes.partition { it is T }
remainingNodes = rem
return ret as List
}
inline fun takeSingle(): T? {
val (ret, rem) = remainingNodes.partition { it is T }
remainingNodes = rem
check(ret.size <= 1)
return ret.firstOrNull() as T?
}
fun assert() {
check(remainingNodes.isEmpty()) {
"Remaining nodes: $remainingNodes"
}
}
}