Skip to content

Commit

Permalink
Captured position of operation input schemas
Browse files Browse the repository at this point in the history
  • Loading branch information
Baccata committed May 10, 2024
1 parent 5a42b24 commit 3849b3b
Showing 1 changed file with 35 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def derivedSchemaImpl[T: Type](using q: Quotes): Expr[Schema[T]] = {
val name = stringFromSingleton[name]
val elemSchemas = summonSchemas[T, elementTypes]
val labels = stringsFromTupleOfSingletons[elementLabels]
val structHints = maybeAddDocs(hintsForType[T], docs.map(_.main))
val structHints = hintsForType[T].maybeAddDocs(docs.map(_.main))
val fieldDocs = docs.map(_.params).getOrElse(Map.empty)
val fieldHints = fieldHintsMap[T](fieldDocs)
val defaults = defaultValues[T]
Expand Down Expand Up @@ -103,7 +103,7 @@ def derivedSchemaImpl[T: Type](using q: Quotes): Expr[Schema[T]] = {
}
} =>
val maybeEnumSchemaExpr = enumSchemaExpression[T, elementTypes]
val shapeHints = maybeAddDocs(hintsForType[T], docs.map(_.main))
val shapeHints = hintsForType[T].maybeAddDocs(docs.map(_.main))
val name = stringFromSingleton[name]
maybeEnumSchemaExpr match {
case Some(enumSchemaExpr) =>
Expand Down Expand Up @@ -135,13 +135,10 @@ def derivedAPIImpl[T: Type, F[_]: Type](
val tpe = TypeRepr.of[T]
val cls = tpe.classSymbol
val serviceDocs: Option[String] = cls.flatMap(_.docstring).map(Docs.parse).map(_.main)
val serviceHints = maybeAddDocs(hintsForType[T], serviceDocs).maybeAddPos(cls)
val serviceHints = hintsForType[T].maybeAddDocs(serviceDocs).maybeAddPos(cls)
val methodDocs = cls.toList.flatMap(_.declarations.flatMap {
sym => sym.docstring.map(docs => sym.name -> Docs.parse(docs))
}).toMap
val methodSymbols = cls.toList.flatMap(_.declarations.map {
sym => sym.name -> sym
}).toMap

mirror match {
case '{
Expand All @@ -154,7 +151,13 @@ def derivedAPIImpl[T: Type, F[_]: Type](
} =>
val serviceNamespace = stringFromSingleton[ns]
val serviceName = stringFromSingleton[label]
val opSchemas = operationSchemasExpression[operations, operationLabels, F](serviceNamespace, serviceName, methodDocs, methodSymbols)
val methodSymbols = cls.toList.flatMap(_.declarations.map {
sym => sym.name -> sym
}).toMap
val methodParamSymbols = cls.toList.flatMap(_.declarations.map {
sym => sym.name -> sym.paramSymss.flatten // curried methods get caught by `InterfaceMirror`
}).toMap
val opSchemas = operationSchemasExpression[operations, operationLabels, F](serviceNamespace, serviceName, methodDocs, methodSymbols, methodParamSymbols)
'{
new DynamicAPI[T] {
type Effect[I, E, O, SI, SO] = F[O]
Expand Down Expand Up @@ -308,16 +311,16 @@ private def operationHints(annotations: List[Expr[Any]])(using Quotes): Expr[Hin
}
.getOrElse('{ Hints.empty })

private def paramHintsMap(annotations: List[List[Expr[Any]]], labels: List[String], paramDocs: Map[String, String])(using
Quotes
): Map[String, Expr[Hints]] = {
private def paramHintsMap(using Quotes)
(annotations: List[List[Expr[Any]]], labels: List[String], paramDocs: Map[String, String], paramSymbols: List[quotes.reflect.Symbol]): Map[String, Expr[Hints]] = {
annotations
.zip(labels)
.map { case (paramAnnotations, paramName) =>
.zipWithIndex
.map { case ((paramAnnotations, paramName), index) =>
val hintsExpr = paramAnnotations
.collectFirst { case '{ $smithyAnnotation: HintsProvider } => '{ $smithyAnnotation.hints } }
.getOrElse('{ Hints.empty })
paramName -> maybeAddDocs(hintsExpr, paramDocs.get(paramName), member = true)
paramName -> hintsExpr.maybeAddDocs(paramDocs.get(paramName), member = true).maybeAddPos(Some(paramSymbols(index)), member = true)
}
.toMap
}
Expand All @@ -344,16 +347,17 @@ private def errorUnionRepr[U : Type](using quotes: Quotes) : quotes.reflect.Type
}
}

private def maybeAddDocs(expr: Expr[Hints], docs: Option[String], member: Boolean = false)(using Quotes): Expr[Hints] = {
docs match {
case Some(doc) if member => '{ $expr.addMemberHints(smithy.api.Documentation(${Expr(doc)}))}
case Some(doc) => '{ $expr.addTargetHints(smithy.api.Documentation(${Expr(doc)}))}
case None => expr
extension(expr: Expr[Hints]){

private[internals] def maybeAddDocs(using Quotes)(docs: Option[String], member: Boolean = false): Expr[Hints] = {
docs match {
case Some(doc) if member => '{ $expr.addMemberHints(smithy.api.Documentation(${Expr(doc)}))}
case Some(doc) => '{ $expr.addTargetHints(smithy.api.Documentation(${Expr(doc)}))}
case None => expr
}
}
}

extension(expr: Expr[Hints]){
private[internals] def maybeAddPos(using Quotes)(symbol: Option[quotes.reflect.Symbol]) : Expr[Hints] = {
private[internals] def maybeAddPos(using Quotes)(symbol: Option[quotes.reflect.Symbol], member: Boolean = false) : Expr[Hints] = {
symbol.flatMap(_.pos) match {
case None => expr
case Some(pos) =>
Expand All @@ -368,7 +372,8 @@ extension(expr: Expr[Hints]){
endColumn = ${Expr(pos.endColumn)}
) : Hints.Binding
}
'{$expr.add($sourceLoc)}
if (member) '{$expr.addMemberHints($sourceLoc)}
else '{$expr.addTargetHints($sourceLoc)}
}
}
}
Expand All @@ -394,7 +399,7 @@ private def fieldHintsMap[T: Type](docs: Map[String, String])(using
.map { sym =>
val hintsExprs = sym.annotations.flatMap(maybeSmithyAnnotation)
val hintsExpr = Expr.ofSeq(hintsExprs)
sym.name -> maybeAddDocs('{ $hintsExpr.map(_.hints).fold(Hints.empty)(_ ++ _) }, docs.get(sym.name), member = true)
sym.name -> '{ $hintsExpr.map(_.hints).fold(Hints.empty)(_ ++ _) }.maybeAddDocs(docs.get(sym.name), member = true)
}
.toMap
}
Expand All @@ -403,7 +408,8 @@ private def operationSchemasExpression[Ts: Type, OpLabels: Type, F[_]: Type](usi
serviceNamespace: String,
serviceName: String,
methodDocs: Map[String, Docs],
methodSymbols: Map[String, quotes.reflect.Symbol]
methodSymbols: Map[String, quotes.reflect.Symbol],
methodParamSymbols: Map[String, List[quotes.reflect.Symbol]]
): Expr[List[OperationSchema[?, ?, ?, ?, ?]]] = {
val expressionList = typesFromTuple[Ts]
.zip(stringsFromTupleOfSingletons[OpLabels])
Expand All @@ -423,10 +429,11 @@ private def operationSchemasExpression[Ts: Type, OpLabels: Type, F[_]: Type](usi
val opDocs = methodDocs.get(opName).map(_.main)
val outputDocs = Expr(methodDocs.get(opName).flatMap(_.output))
val methodSymbol = methodSymbols.get(opName)
val opHints = maybeAddDocs(operationHints(opAnnotations), opDocs).maybeAddPos(methodSymbol)
val opHints = operationHints(opAnnotations).maybeAddDocs(opDocs).maybeAddPos(methodSymbol)
val paramDocs = methodDocs.get(opName).map(_.params).getOrElse(Map.empty)
val paramSymbols = methodParamSymbols.get(opName).getOrElse(List.empty)
val paramAnnotations = extractAnnotationsFromTuple[inputAnnotations]
val fieldHints = paramHintsMap(paramAnnotations, labels, paramDocs)
val fieldHints = paramHintsMap(paramAnnotations, labels, paramDocs, paramSymbols)
val defaults = Map.empty[String, Expr[Any]]
val fieldsExpr = fieldsExpression[inputTypes](paramSchemas, labels, fieldHints, defaults)
val errorSchemas = summonSchemas[errorTypes, errorTypes]
Expand All @@ -435,12 +442,13 @@ private def operationSchemasExpression[Ts: Type, OpLabels: Type, F[_]: Type](usi
val nestedNs = Expr(serviceNamespace + "." + uncapitalise(serviceName))
val opInputNameExpr = Expr(opName + "Input")
val opOutputNameExpr = Expr(opName + "Output")
val inputSchemaHints = '{Hints(ShapeId("smithy.api", "input") -> Document.obj())}.maybeAddPos(methodSymbol)
val inputSchema = '{
val fields = $fieldsExpr.toVector
Schema
.struct(fields)(seq => Tuple.fromArray(seq.toArray).asInstanceOf[inputTypes])
.withId($nestedNs, $opInputNameExpr)
.addHints(ShapeId("smithy.api", "input") -> Document.obj())
.addHints($inputSchemaHints)
}
val outputSchema = '{ summonInline[Schema[outputType]].compile(wrapOutputSchema(ShapeId($nestedNs, $opOutputNameExpr), $outputDocs))}
val opSchemaWithoutError = '{
Expand Down Expand Up @@ -608,7 +616,7 @@ private def enumValueExpression[Enum: Type](memberType: Type[?], index: Int)(usi

ev match {
case '{$mirror: Mirror.Singleton {type MirroredLabel = label}} => Some{
val hintsExpr = maybeAddDocs(hintsFor(TypeRepr.of[mt].termSymbol), docs.map(_.main))
val hintsExpr = hintsFor(TypeRepr.of[mt].termSymbol).maybeAddDocs(docs.map(_.main))
val labelExpr = Expr(stringFromSingleton[label])
val indexExpr = Expr(index)
'{
Expand Down

0 comments on commit 3849b3b

Please sign in to comment.