///|
/// 1-based source position in a GraphQL document.
pub(all) struct Pos {
line : Int32
column : Int32
} derive(Eq, Debug)
///|
/// Error raised by tokenizer, query parser, and schema parser.
///
/// Each parse error carries the source position where parsing failed.
pub(all) suberror ParseError {
GraphQLParseError(String, Pos)
} derive(Eq)
///|
/// Render a parse error with line and column context.
pub fn ParseError::to_string(self : ParseError) -> String {
match self {
GraphQLParseError(message, { line, column, }) =>
"graphql parse error at \{line}:\{column}: \{message}"
}
}
///|
pub impl Show for ParseError with fn output(self : ParseError, logger : &Logger) -> Unit {
logger.write_string(self.to_string())
}
///|
fn[T] parse_error(message : String, position : Pos) -> T raise ParseError {
raise GraphQLParseError(message, position)
}
///|
/// Integer literal wrapper.
///
/// GraphQL integer literals are parsed as `Int64` so tooling can preserve the
/// full accepted input range before application-level coercion.
pub(all) struct Number {
value : Int64
} derive(Eq, Debug)
///|
/// Return the parsed integer literal as `Int64`.
pub fn Number::as_int64(self : Number) -> Int64 {
self.value
}
///|
/// GraphQL type reference used by variable, field, and input definitions.
pub(all) enum GqlType {
NamedType(String)
ListType(GqlType)
NonNullType(GqlType)
} derive(Eq, Debug)
///|
/// GraphQL literal or variable value.
///
/// This representation preserves GraphQL-specific distinctions such as enum
/// values versus strings and variables versus their eventual runtime values.
pub(all) enum Value {
Variable(String)
IntValue(Number)
FloatValue(Double)
StringValue(String)
BooleanValue(Bool)
NullValue
EnumValue(String)
ListValue(Array[Value])
ObjectValue(Array[(String, Value)])
} derive(Eq, Debug)
///|
/// GraphQL directive use with parsed arguments.
pub(all) struct Directive {
position : Pos
name : String
arguments : Array[(String, Value)]
} derive(Eq, Debug)
///|
/// Parsed executable GraphQL document.
pub(all) struct QueryDocument {
definitions : Array[QueryDefinition]
} derive(Eq, Debug)
///|
/// Top-level executable document definition.
pub(all) enum QueryDefinition {
OperationDefinition(OperationDefinition)
FragmentDefinition(FragmentDefinition)
} derive(Eq, Debug)
///|
/// GraphQL operation definition, including shorthand selection-set operations.
pub(all) enum OperationDefinition {
SelectionSetOperation(SelectionSet)
QueryOperation(Query)
MutationOperation(Mutation)
SubscriptionOperation(Subscription)
} derive(Eq, Debug)
///|
/// Named fragment definition.
pub(all) struct FragmentDefinition {
position : Pos
name : String
type_condition : TypeCondition
directives : Array[Directive]
selection_set : SelectionSet
} derive(Eq, Debug)
///|
/// Parsed `query` operation.
pub(all) struct Query {
position : Pos
name : String?
variable_definitions : Array[VariableDefinition]
directives : Array[Directive]
selection_set : SelectionSet
} derive(Eq, Debug)
///|
/// Parsed `mutation` operation.
pub(all) struct Mutation {
position : Pos
name : String?
variable_definitions : Array[VariableDefinition]
directives : Array[Directive]
selection_set : SelectionSet
} derive(Eq, Debug)
///|
/// Parsed `subscription` operation.
pub(all) struct Subscription {
position : Pos
name : String?
variable_definitions : Array[VariableDefinition]
directives : Array[Directive]
selection_set : SelectionSet
} derive(Eq, Debug)
///|
/// Non-empty selection set with start and end source positions.
pub(all) struct SelectionSet {
span : (Pos, Pos)
items : Array[Selection]
} derive(Eq, Debug)
///|
/// Variable declaration from an operation definition.
pub(all) struct VariableDefinition {
position : Pos
name : String
var_type : GqlType
default_value : Value?
} derive(Eq, Debug)
///|
/// GraphQL field, fragment spread, or inline fragment selection.
pub(all) enum Selection {
FieldSelection(Field)
FragmentSpreadSelection(FragmentSpread)
InlineFragmentSelection(InlineFragment)
} derive(Eq, Debug)
///|
/// Field selection with optional alias, arguments, directives, and nested
/// selection set.
pub(all) struct Field {
position : Pos
field_alias : String?
name : String
arguments : Array[(String, Value)]
directives : Array[Directive]
selection_set : SelectionSet
} derive(Eq, Debug)
///|
/// Reference to a named fragment.
pub(all) struct FragmentSpread {
position : Pos
fragment_name : String
directives : Array[Directive]
} derive(Eq, Debug)
///|
/// Fragment type condition.
pub(all) enum TypeCondition {
On(String)
} derive(Eq, Debug)
///|
/// Inline fragment with optional type condition.
pub(all) struct InlineFragment {
position : Pos
type_condition : TypeCondition?
directives : Array[Directive]
selection_set : SelectionSet
} derive(Eq, Debug)
///|
/// Parsed GraphQL schema document.
pub(all) struct SchemaDocument {
definitions : Array[SchemaDefinition]
} derive(Eq, Debug)
///|
/// Top-level SDL definition.
pub(all) enum SchemaDefinition {
SchemaDef(SchemaDefinitionData)
TypeDef(TypeDefinition)
TypeExt(TypeExtension)
DirectiveDef(DirectiveDefinition)
} derive(Eq, Debug)
///|
/// Explicit `schema { ... }` root operation mapping.
pub(all) struct SchemaDefinitionData {
position : Pos
directives : Array[Directive]
query : String?
mutation : String?
subscription : String?
} derive(Eq, Debug)
///|
/// SDL type definition.
pub(all) enum TypeDefinition {
ScalarTypeDef(ScalarType)
ObjectTypeDef(ObjectType)
InterfaceTypeDef(InterfaceType)
UnionTypeDef(UnionType)
EnumTypeDef(EnumType)
InputObjectTypeDef(InputObjectType)
} derive(Eq, Debug)
///|
/// SDL type extension.
pub(all) enum TypeExtension {
ScalarTypeExt(ScalarTypeExtension)
ObjectTypeExt(ObjectTypeExtension)
InterfaceTypeExt(InterfaceTypeExtension)
UnionTypeExt(UnionTypeExtension)
EnumTypeExt(EnumTypeExtension)
InputObjectTypeExt(InputObjectTypeExtension)
} derive(Eq, Debug)
///|
/// SDL scalar type definition.
pub(all) struct ScalarType {
position : Pos
description : String?
name : String
directives : Array[Directive]
} derive(Eq, Debug)
///|
/// SDL scalar type extension.
pub(all) struct ScalarTypeExtension {
position : Pos
name : String
directives : Array[Directive]
} derive(Eq, Debug)
///|
/// SDL object type definition.
pub(all) struct ObjectType {
position : Pos
description : String?
name : String
implements_interfaces : Array[String]
directives : Array[Directive]
fields : Array[SchemaField]
} derive(Eq, Debug)
///|
/// SDL object type extension.
pub(all) struct ObjectTypeExtension {
position : Pos
name : String
implements_interfaces : Array[String]
directives : Array[Directive]
fields : Array[SchemaField]
} derive(Eq, Debug)
///|
/// SDL object or interface field definition.
pub(all) struct SchemaField {
position : Pos
description : String?
name : String
arguments : Array[InputValue]
field_type : GqlType
directives : Array[Directive]
} derive(Eq, Debug)
///|
/// SDL input field or argument definition.
pub(all) struct InputValue {
position : Pos
description : String?
name : String
value_type : GqlType
default_value : Value?
directives : Array[Directive]
} derive(Eq, Debug)
///|
/// SDL interface type definition.
pub(all) struct InterfaceType {
position : Pos
description : String?
name : String
implements_interfaces : Array[String]
directives : Array[Directive]
fields : Array[SchemaField]
} derive(Eq, Debug)
///|
/// SDL interface type extension.
pub(all) struct InterfaceTypeExtension {
position : Pos
name : String
implements_interfaces : Array[String]
directives : Array[Directive]
fields : Array[SchemaField]
} derive(Eq, Debug)
///|
/// SDL union type definition.
pub(all) struct UnionType {
position : Pos
description : String?
name : String
directives : Array[Directive]
types : Array[String]
} derive(Eq, Debug)
///|
/// SDL union type extension.
pub(all) struct UnionTypeExtension {
position : Pos
name : String
directives : Array[Directive]
types : Array[String]
} derive(Eq, Debug)
///|
/// SDL enum type definition.
pub(all) struct EnumType {
position : Pos
description : String?
name : String
directives : Array[Directive]
values : Array[EnumValue]
} derive(Eq, Debug)
///|
/// SDL enum value definition.
pub(all) struct EnumValue {
position : Pos
description : String?
name : String
directives : Array[Directive]
} derive(Eq, Debug)
///|
/// SDL enum type extension.
pub(all) struct EnumTypeExtension {
position : Pos
name : String
directives : Array[Directive]
values : Array[EnumValue]
} derive(Eq, Debug)
///|
/// SDL input object type definition.
pub(all) struct InputObjectType {
position : Pos
description : String?
name : String
directives : Array[Directive]
fields : Array[InputValue]
} derive(Eq, Debug)
///|
/// SDL input object type extension.
pub(all) struct InputObjectTypeExtension {
position : Pos
name : String
directives : Array[Directive]
fields : Array[InputValue]
} derive(Eq, Debug)
///|
/// GraphQL directive location.
pub(all) enum DirectiveLocation {
LocationQuery
LocationMutation
LocationSubscription
LocationField
LocationFragmentDefinition
LocationFragmentSpread
LocationInlineFragment
LocationSchema
LocationScalar
LocationObject
LocationFieldDefinition
LocationArgumentDefinition
LocationInterface
LocationUnion
LocationEnum
LocationEnumValue
LocationInputObject
LocationInputFieldDefinition
LocationVariableDefinition
} derive(Eq, Debug)
///|
/// SDL directive definition.
pub(all) struct DirectiveDefinition {
position : Pos
description : String?
name : String
arguments : Array[InputValue]
repeatable : Bool
locations : Array[DirectiveLocation]
} derive(Eq, Debug)
///|
/// Return the canonical GraphQL spec name for a directive location.
pub fn DirectiveLocation::as_string(self : DirectiveLocation) -> String {
match self {
LocationQuery => "QUERY"
LocationMutation => "MUTATION"
LocationSubscription => "SUBSCRIPTION"
LocationField => "FIELD"
LocationFragmentDefinition => "FRAGMENT_DEFINITION"
LocationFragmentSpread => "FRAGMENT_SPREAD"
LocationInlineFragment => "INLINE_FRAGMENT"
LocationSchema => "SCHEMA"
LocationScalar => "SCALAR"
LocationObject => "OBJECT"
LocationFieldDefinition => "FIELD_DEFINITION"
LocationArgumentDefinition => "ARGUMENT_DEFINITION"
LocationInterface => "INTERFACE"
LocationUnion => "UNION"
LocationEnum => "ENUM"
LocationEnumValue => "ENUM_VALUE"
LocationInputObject => "INPUT_OBJECT"
LocationInputFieldDefinition => "INPUT_FIELD_DEFINITION"
LocationVariableDefinition => "VARIABLE_DEFINITION"
}
}
///|
/// Return true when this location belongs to executable GraphQL documents.
pub fn DirectiveLocation::is_query(self : DirectiveLocation) -> Bool {
match self {
LocationQuery
| LocationMutation
| LocationSubscription
| LocationField
| LocationFragmentDefinition
| LocationFragmentSpread
| LocationInlineFragment => true
LocationSchema
| LocationScalar
| LocationObject
| LocationFieldDefinition
| LocationArgumentDefinition
| LocationInterface
| LocationUnion
| LocationEnum
| LocationEnumValue
| LocationInputObject
| LocationInputFieldDefinition
| LocationVariableDefinition => false
}
}
///|
/// Return true when this location belongs to GraphQL SDL.
pub fn DirectiveLocation::is_schema(self : DirectiveLocation) -> Bool {
!self.is_query()
}
///|
fn parse_directive_location(
value : String,
position : Pos,
) -> DirectiveLocation raise ParseError {
match value {
"QUERY" => LocationQuery
"MUTATION" => LocationMutation
"SUBSCRIPTION" => LocationSubscription
"FIELD" => LocationField
"FRAGMENT_DEFINITION" => LocationFragmentDefinition
"FRAGMENT_SPREAD" => LocationFragmentSpread
"INLINE_FRAGMENT" => LocationInlineFragment
"SCHEMA" => LocationSchema
"SCALAR" => LocationScalar
"OBJECT" => LocationObject
"FIELD_DEFINITION" => LocationFieldDefinition
"ARGUMENT_DEFINITION" => LocationArgumentDefinition
"INTERFACE" => LocationInterface
"UNION" => LocationUnion
"ENUM" => LocationEnum
"ENUM_VALUE" => LocationEnumValue
"INPUT_OBJECT" => LocationInputObject
"INPUT_FIELD_DEFINITION" => LocationInputFieldDefinition
"VARIABLE_DEFINITION" => LocationVariableDefinition
_ => parse_error("invalid directive location \{value}", position)
}
}
///|
/// Pretty-printer options for parsed query and schema documents.
pub(all) struct Style {
indent : Int32
multiline_arguments : Bool
} derive(Eq, Debug)
///|
/// Default formatting style: two-space indentation and inline arguments.
pub fn Style::default() -> Style {
{ indent: 2, multiline_arguments: false, }
}
///|
/// Return a copy of the style with a new indentation width.
pub fn Style::with_indent(self : Style, indent : Int32) -> Style {
{ ..self, indent, }
}
///|
/// Return a copy of the style with multiline argument formatting toggled.
pub fn Style::with_multiline_arguments(
self : Style,
multiline_arguments : Bool,
) -> Style {
{ ..self, multiline_arguments, }
}