Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AST separation #777

Merged
merged 20 commits into from
Nov 10, 2021
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:
run: sbt ++${{ matrix.scala }} test

- name: Compress target directories
run: tar cf targets.tar target modules/core/target modules/benchmarks/target project/target
run: tar cf targets.tar target modules/ast/target modules/core/target modules/benchmarks/target project/target

- name: Upload target directories
uses: actions/upload-artifact@v2
Expand Down
10 changes: 5 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# folders
.bsp
.idea
target
lib
classes
.bsp/
.idea/
target/
lib/
classes/

# files
*.iml
Expand Down
147 changes: 145 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -165,22 +165,165 @@ ThisBuild / mimaBinaryIssueFilters ++= Seq(
"sangria.execution.ExecutionPath.productElementName"),
ProblemFilters.exclude[IncompatibleMethTypeProblem]("sangria.execution.ExecutionPath.this"),
ProblemFilters.exclude[DirectMissingMethodProblem]("sangria.execution.ExecutionPath.this"),
ProblemFilters.exclude[MissingTypesProblem]("sangria.execution.ExecutionPath$")
ProblemFilters.exclude[MissingTypesProblem]("sangria.execution.ExecutionPath$"),

// removed the `ast` package to its own library
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.Argument"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.Argument$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.AstLocation"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.AstLocation$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.AstNode"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.AstNode$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.BigDecimalValue"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.BigDecimalValue$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.BigIntValue"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.BigIntValue$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.BooleanValue"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.BooleanValue$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.Comment"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.Comment$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.ConditionalFragment"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.Definition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.Directive"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.Directive$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.DirectiveDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.DirectiveDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.DirectiveLocation"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.DirectiveLocation$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.Document"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.Document$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.EnumTypeDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.EnumTypeDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.EnumTypeExtensionDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.EnumTypeExtensionDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.EnumValue"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.EnumValue$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.EnumValueDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.EnumValueDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.Field"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.Field$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.FieldDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.FieldDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.FloatValue"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.FloatValue$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.FragmentDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.FragmentDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.FragmentSpread"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.FragmentSpread$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.InlineFragment"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.InlineFragment$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.InputDocument"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.InputDocument$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.InputObjectTypeDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.InputObjectTypeDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.InputObjectTypeExtensionDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.InputObjectTypeExtensionDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.InputValueDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.InputValueDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.IntValue"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.IntValue$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.InterfaceTypeDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.InterfaceTypeDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.InterfaceTypeExtensionDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.InterfaceTypeExtensionDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.ListType"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.ListType$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.ListValue"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.ListValue$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.NameValue"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.NamedType"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.NamedType$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.NotNullType"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.NotNullType$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.NullValue"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.NullValue$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.ObjectField"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.ObjectField$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.ObjectLikeTypeExtensionDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.ObjectTypeDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.ObjectTypeDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.ObjectTypeExtensionDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.ObjectTypeExtensionDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.ObjectValue"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.ObjectValue$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.OperationDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.OperationDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.OperationType"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.OperationType$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.OperationType$Mutation$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.OperationType$Query$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.OperationType$Subscription$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.OperationTypeDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.OperationTypeDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.ScalarTypeDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.ScalarTypeDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.ScalarTypeExtensionDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.ScalarTypeExtensionDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.ScalarValue"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.SchemaAstNode"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.SchemaDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.SchemaDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.SchemaExtensionDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.SchemaExtensionDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.Selection"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.SelectionContainer"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.StringValue"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.StringValue$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.Type"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.TypeDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.TypeExtensionDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.TypeSystemDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.TypeSystemExtensionDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.UnionTypeDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.UnionTypeDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.UnionTypeExtensionDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.UnionTypeExtensionDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.Value"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.VariableDefinition"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.VariableDefinition$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.VariableValue"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.VariableValue$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.WithArguments"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.WithComments"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.WithDescription"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.WithDirectives"),
ProblemFilters.exclude[MissingClassProblem]("sangria.ast.WithTrailingComments"),
ProblemFilters.exclude[MissingClassProblem]("sangria.parser.AggregateSourceMapper"),
ProblemFilters.exclude[MissingClassProblem]("sangria.parser.AggregateSourceMapper$"),
ProblemFilters.exclude[MissingClassProblem]("sangria.parser.DefaultSourceMapper"),
ProblemFilters.exclude[MissingClassProblem]("sangria.parser.SourceMapper"),

// added type annotation
ProblemFilters.exclude[IncompatibleResultTypeProblem](
"sangria.renderer.QueryRenderer.renderCommentLines"),
ProblemFilters.exclude[IncompatibleResultTypeProblem](
"sangria.renderer.QueryRenderer.renderCommentLines")
)

lazy val root = project
.in(file("."))
.withId("sangria-root")
.aggregate(core, benchmarks)
.aggregate(ast, core, benchmarks)
.settings(inThisBuild(projectInfo))
.settings(
scalacSettings ++ shellSettings ++ noPublishSettings
)
.disablePlugins(MimaPlugin)

lazy val ast = project
.in(file("modules/ast"))
.withId("sangria-ast")
.settings(scalacSettings ++ shellSettings)
.settings(
name := "sangria-ast",
description := "Scala GraphQL AST representation"
)
.disablePlugins(MimaPlugin)

lazy val core = project
.in(file("modules/core"))
.withId("sangria-core")
.dependsOn(ast)
.settings(scalacSettings ++ shellSettings)
.settings(
name := "sangria",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,11 @@
package sangria.ast

import sangria.execution.InputDocumentMaterializer
import sangria.marshalling.{FromInput, InputUnmarshaller}
import sangria.parser.{AggregateSourceMapper, DeliveryScheme, SourceMapper}
import sangria.renderer.QueryRenderer
import sangria.validation.DocumentAnalyzer
import sangria.schema.{InputType, Schema}
import sangria.validation.TypeInfo
import sangria.visitor._

import scala.collection.immutable.ListMap

/** A complete GraphQL request operated on by a GraphQL service.
*
* @param definitions
* The definitions, which primarily constitute the document.
* @param sourceMapper
*
* @see
* [[https://spec.graphql.org/June2018/#Document]]
Expand Down Expand Up @@ -73,15 +63,6 @@ case class Document(
*/
def +(other: Document): Document = merge(other)

lazy val analyzer: DocumentAnalyzer = DocumentAnalyzer(this)

lazy val separateOperations: Map[Option[String], Document] = analyzer.separateOperations

def separateOperation(definition: OperationDefinition): Document =
analyzer.separateOperation(definition)
def separateOperation(operationName: Option[String]): Option[Document] =
analyzer.separateOperation(operationName)

override def equals(other: Any): Boolean = other match {
case that: Document =>
that.canEqual(this) &&
Expand Down Expand Up @@ -141,39 +122,9 @@ case class InputDocument(
*/
def +(other: InputDocument): InputDocument = merge(other)

def to[T](
schema: Schema[_, _],
inputType: InputType[T]
)(implicit fromInput: FromInput[T], scheme: DeliveryScheme[Vector[T]]): scheme.Result =
InputDocumentMaterializer.to(schema, this, inputType)

def to[T, Vars](
schema: Schema[_, _],
inputType: InputType[T],
variables: Vars
)(implicit
iu: InputUnmarshaller[Vars],
fromInput: FromInput[T],
scheme: DeliveryScheme[Vector[T]]): scheme.Result =
InputDocumentMaterializer.to(schema, this, inputType, variables)

def to[T](inputType: InputType[T])(implicit
fromInput: FromInput[T],
scheme: DeliveryScheme[Vector[T]]): scheme.Result =
InputDocumentMaterializer.to(this, inputType)

def to[T, Vars](
inputType: InputType[T],
variables: Vars = InputUnmarshaller.emptyMapVars
)(implicit
iu: InputUnmarshaller[Vars],
fromInput: FromInput[T],
scheme: DeliveryScheme[Vector[T]]): scheme.Result =
InputDocumentMaterializer.to(this, inputType, variables)

override def equals(other: Any): Boolean = other match {
case that: InputDocument =>
(that.canEqual(this)) &&
that.canEqual(this) &&
values == that.values &&
location == that.location
case _ => false
Expand All @@ -184,7 +135,7 @@ case class InputDocument(
}

object InputDocument {
def merge(documents: Traversable[InputDocument]): InputDocument =
def merge(documents: Iterable[InputDocument]): InputDocument =
InputDocument(documents.toVector.flatMap(_.values))
}

Expand Down Expand Up @@ -396,9 +347,7 @@ case class Argument(
* [[https://spec.graphql.org/June2018/#Value]]
* @group value
*/
sealed trait Value extends AstNode with WithComments {
override def renderPretty: String = QueryRenderer.render(this, QueryRenderer.PrettyInput)
}
sealed trait Value extends AstNode with WithComments

/** @group scalar
*/
Expand Down Expand Up @@ -798,22 +747,6 @@ sealed trait AstNode {
/** Location at which this node lexically begins in the GraphQL request source code. */
def location: Option[AstLocation]
def cacheKeyHash: Int = System.identityHashCode(this)

def renderPretty: String = QueryRenderer.render(this, QueryRenderer.Pretty)
def renderCompact: String = QueryRenderer.render(this, QueryRenderer.Compact)

def visit(visitor: AstVisitor): this.type =
AstVisitor.visit(this, visitor)

def visit(onEnter: AstNode => VisitorCommand, onLeave: AstNode => VisitorCommand): this.type =
AstVisitor.visit(this, onEnter, onLeave)

def visitAstWithTypeInfo(schema: Schema[_, _])(visitorFn: TypeInfo => AstVisitor): this.type =
AstVisitor.visitAstWithTypeInfo[this.type](schema, this)(visitorFn)

def visitAstWithState[S](schema: Schema[_, _], state: S)(
visitorFn: (TypeInfo, S) => AstVisitor): S =
AstVisitor.visitAstWithState(schema, this, state)(visitorFn)
}

/** @group typesystem
Expand Down Expand Up @@ -847,16 +780,3 @@ sealed trait TypeExtensionDefinition extends TypeSystemExtensionDefinition with
sealed trait ObjectLikeTypeExtensionDefinition extends TypeExtensionDefinition {
def fields: Vector[FieldDefinition]
}

object AstNode {
def withoutAstLocations[T <: AstNode](node: T, stripComments: Boolean = false): T = {
val enterComment = (_: Comment) =>
if (stripComments) VisitorCommand.Delete else VisitorCommand.Continue

visit[AstNode](
node,
Visit[Comment](enterComment),
VisitAnyField[AstNode, Option[AstLocation]]((_, _) => VisitorCommand.Transform(None)))
.asInstanceOf[T]
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
package sangria.parser

import org.parboiled2.ParserInput
import sangria.ast.AstLocation
package sangria.ast

/** Set of functions that convert a [[AstLocation GraphQL source code location]] to human-readable
* strings.
Expand Down Expand Up @@ -30,15 +27,21 @@ trait SourceMapper {
def renderLinePosition(location: AstLocation, prefix: String = ""): String
}

/** [[SourceMapper]] for a single GraphQL document. */
class DefaultSourceMapper(val id: String, val parserInput: ParserInput) extends SourceMapper {
override lazy val source: String = parserInput.sliceString(0, parserInput.length)
trait SourceMapperInput {
def source: String
def getLine(line: Int): String
}

/** [[sangria.ast.SourceMapper]] for a single GraphQL document. */
class DefaultSourceMapper(val id: String, val sourceMapperInput: SourceMapperInput)
extends sangria.ast.SourceMapper {
override lazy val source: String = sourceMapperInput.source

override def renderLocation(location: AstLocation) =
s"(line ${location.line}, column ${location.column})"

override def renderLinePosition(location: AstLocation, prefix: String = ""): String =
parserInput
sourceMapperInput
.getLine(location.line)
.replace("\r", "") + "\n" + prefix + (" " * (location.column - 1)) + "^"
}
Expand Down
Loading