Skip to content
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