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

Validate Typed operations and subqueries #500

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
171 changes: 112 additions & 59 deletions gen/rules/src/main/scala/clue/gen/GraphQLGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,75 @@ class GraphQLGen(config: GraphQLGenConfig)
newLineIndent + lines.replaceAll("\\n", newLineIndent)
}

private object GraphQLAnnotated {
def unapply(tree: Tree): Option[(List[Mod], String, Template)] = tree match {
case Defn.Trait(
mods @ GraphQLAnnotation(_),
templateName,
Nil,
_,
template
) =>
Some((mods, templateName.value, template))

case Defn.Class(
mods @ GraphQLAnnotation(_),
templateName,
Nil,
_,
template
) =>
Some((mods, templateName.value, template))

case Defn.Object(
mods @ GraphQLAnnotation(_),
name,
template
) =>
Some((mods, name.value, template))

case _ => None
}
}

private def isGraphQLOperation(inits: List[Init]) =
inits.exists {
case Init(Type.Apply(Type.Name("GraphQLOperation"), _), _, _) => true
case _ => false
}

private def isGraphQLOperationTyped(inits: List[Init]) =
inits.exists {
case Init(Type.Apply(
Type.Select(Term.Name("GraphQLOperation"), Type.Name("Typed")),
_
),
_,
_
) =>
true
case _ => false
}

private def isGraphQLSubquery(inits: List[Init]) =
inits.exists {
case Init(Type.Apply(Type.Name("GraphQLSubquery"), _), _, _) => true
case _ => false
}

private def isGraphQLSubqueryTyped(inits: List[Init]) =
inits.exists {
case Init(Type.Apply(
Type.Select(Term.Name("GraphQLSubquery"), Type.Name("Typed")),
_
),
_,
_
) =>
true
case _ => false
}

override def fix(implicit doc: SemanticDocument): Patch = {
val importPatch: List[IO[Patch]] =
doc.tokens.collect {
Expand All @@ -42,18 +111,6 @@ class GraphQLGen(config: GraphQLGenConfig)
val genPatch: List[IO[Patch]] =
doc.tree
.collect {
case obj @ Defn.Object(
GraphQLAnnotation(_),
name,
template
) => // Annotated objects are copied as-is
// TODO: We should be able to validate the query!
IO.pure(
Patch.replaceTree(
obj,
indented(obj)(q"object $name $template".toString)
) + Patch.removeGlobalImport(GraphQLAnnotation.symbol)
)
case obj @ Defn.Object(
GraphQLStubAnnotation(_),
_,
Expand Down Expand Up @@ -87,18 +144,11 @@ class GraphQLGen(config: GraphQLGenConfig)
)
) + Patch.removeGlobalImport(GraphQLSchemaAnnotation.symbol)
}
case obj @ Defn.Trait(
mods @ GraphQLAnnotation(_),
templateName,
Nil,
_,
case obj @ GraphQLAnnotated(
mods,
objName,
Template(early, inits, self, stats)
) if inits.exists {
case Init(Type.Apply(Type.Name("GraphQLOperation"), _), _, _) => true
case _ => false
} =>
val objName = templateName.value

) if isGraphQLOperation(inits) || isGraphQLOperationTyped(inits) =>
extractSchemaType(inits) match {
case None =>
abort(
Expand Down Expand Up @@ -126,17 +176,22 @@ class GraphQLGen(config: GraphQLGenConfig)
) >> IO {
val operation = queryResult.toOption.get

// Modifications to add the missing definitions.
val modObjDefs = scala.Function.chain(
List(
addImports(schemaType.value),
addVars(schema, operation, config),
addData(schema, operation, config, document.subqueries),
addVarEncoder,
addDataDecoder,
addConvenienceMethod(schemaType, operation, objName)
)
)
val typed = isGraphQLOperationTyped(inits)

val modObjDefs =
if (typed) // everything is already defined
identity[List[Stat]](_)
else // Modifications to add the missing definitions.
scala.Function.chain(
List(
addImports(schemaType.value),
addVars(schema, operation, config),
addData(schema, operation, config, document.subqueries),
addVarEncoder,
addDataDecoder,
addConvenienceMethod(schemaType, operation, objName)
)
)

val newMods = GraphQLAnnotation.removeFrom(mods)

Expand All @@ -155,18 +210,11 @@ class GraphQLGen(config: GraphQLGenConfig)
}
}
}
case obj @ Defn.Class(
case obj @ GraphQLAnnotated(
mods @ GraphQLAnnotation(_),
templateName,
Nil,
_,
objName,
Template(early, inits, self, stats)
) if inits.exists {
case Init(Type.Apply(Type.Name("GraphQLSubquery"), _), _, _) => true
case _ => false
} =>
val objName = templateName.value

) if isGraphQLSubquery(inits) || isGraphQLSubqueryTyped(inits) =>
extractSchemaAndRootTypes(inits) match {
case None =>
abort(
Expand Down Expand Up @@ -194,21 +242,26 @@ class GraphQLGen(config: GraphQLGenConfig)
) >> IO {
val operation = queryResult.toOption.get

// Modifications to add the missing definitions.
val modObjDefs = scala.Function.chain(
List(
addImports(schemaType.value),
addData(
schema,
operation,
config,
subquery.subqueries,
schema.types.find(_.name == rootTypeName)
),
addDataDecoder,
addConvenienceMethod(schemaType, operation, objName)
)
)
val typed = isGraphQLSubqueryTyped(inits)

val modObjDefs =
if (typed) // everything is already defined
identity[List[Stat]](_)
else // Modifications to add the missing definitions.
scala.Function.chain(
List(
addImports(schemaType.value),
addData(
schema,
operation,
config,
subquery.subqueries,
schema.types.find(_.name == rootTypeName)
),
addDataDecoder,
addConvenienceMethod(schemaType, operation, objName)
)
)

val newMods = GraphQLAnnotation.removeFrom(mods).filterNot {
case Mod.Abstract() => true
Expand Down
2 changes: 1 addition & 1 deletion gen/rules/src/main/scala/clue/gen/QueryGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ trait QueryGen extends Generator {
protected def extractSchemaAndRootTypes(list: List[Init]): Option[(Type.Name, String)] =
list.collect {
case Init(
Type.Apply(Type.Name("GraphQLSubquery"), List(tpe @ Type.Name(_))),
Type.Apply(_, (tpe @ Type.Name(_)) :: _),
_,
List(List(Lit.String(rootType)))
) =>
Expand Down