From ba0fa8632f29ecdd51efae1a560ad5a91c6cf4c8 Mon Sep 17 00:00:00 2001 From: Jeff Lewis Date: Wed, 9 Feb 2022 01:09:46 -0700 Subject: [PATCH] remove generation of redundant package imports (#102) --- build.sbt | 7 ++- .../src/smithy4s/codegen/Renderer.scala | 8 ++-- ...> smithy4s.example.imp.ImportService.json} | 18 ++++++++ .../example/error/NotFoundError.scala | 22 +++++++++ .../example/{ => imp}/ImportService.scala | 46 ++++++++++++++++--- .../src/smithy4s/example/imp/package.scala | 12 +++++ .../src/smithy4s/example/package.scala | 6 --- sampleSpecs/import.smithy | 6 ++- sampleSpecs/importerror.smithy | 7 +++ 9 files changed, 112 insertions(+), 20 deletions(-) rename modules/example/resources/{smithy4s.example.ImportService.json => smithy4s.example.imp.ImportService.json} (56%) create mode 100644 modules/example/src/smithy4s/example/error/NotFoundError.scala rename modules/example/src/smithy4s/example/{ => imp}/ImportService.scala (55%) create mode 100644 modules/example/src/smithy4s/example/imp/package.scala create mode 100644 sampleSpecs/importerror.smithy diff --git a/build.sbt b/build.sbt index 4dcb8e004..339b4db93 100644 --- a/build.sbt +++ b/build.sbt @@ -543,14 +543,17 @@ lazy val example = projectMatrix .settings( Compile / allowedNamespaces := Seq( "smithy4s.example", - "smithy4s.example.import_test" + "smithy4s.example.import_test", + "smithy4s.example.imp", + "smithy4s.example.error" ), smithySpecs := Seq( (ThisBuild / baseDirectory).value / "sampleSpecs" / "example.smithy", (ThisBuild / baseDirectory).value / "sampleSpecs" / "errors.smithy", (ThisBuild / baseDirectory).value / "sampleSpecs" / "streaming.smithy", (ThisBuild / baseDirectory).value / "sampleSpecs" / "operation.smithy", - (ThisBuild / baseDirectory).value / "sampleSpecs" / "import.smithy" + (ThisBuild / baseDirectory).value / "sampleSpecs" / "import.smithy", + (ThisBuild / baseDirectory).value / "sampleSpecs" / "importerror.smithy" ), Compile / resourceDirectory := (ThisBuild / baseDirectory).value / "modules" / "example" / "resources", isCE3 := true, diff --git a/modules/codegen/src/smithy4s/codegen/Renderer.scala b/modules/codegen/src/smithy4s/codegen/Renderer.scala index d82813517..9e29d9010 100644 --- a/modules/codegen/src/smithy4s/codegen/Renderer.scala +++ b/modules/codegen/src/smithy4s/codegen/Renderer.scala @@ -252,7 +252,6 @@ private[codegen] class Renderer(compilationUnit: CompilationUnit) { self => val params = if (op.input != Type.unit) { s"input: ${op.input.render}" } else "" - val opName = op.name val traitName = s"${serviceName}Operation" val input = @@ -400,9 +399,9 @@ private[codegen] class Renderer(compilationUnit: CompilationUnit) { self => block( s"def liftError(throwable: Throwable) : Option[$errorName] = throwable match" ) { - op.errors.collect { case Type.Ref(ns, name) => - ns -> s"case e: ${name} => Some($errorName.${name}Case(e))" - } ++ List("" -> "case _ => None") + op.errors.collect { case Type.Ref(_, name) => + s"case e: ${name} => Some($errorName.${name}Case(e))" + } ++ List("case _ => None") }, block( s"def unliftError(e: $errorName) : Throwable = e match" @@ -425,6 +424,7 @@ private[codegen] class Renderer(compilationUnit: CompilationUnit) { self => altName.dropWhile(_ == '_').capitalize + "Case" val caseNames = alts.map(_.name).map(caseName) val imports = alts.foldMap(_.tpe.imports) ++ syntaxImport + lines( s"sealed trait $name extends scala.Product with scala.Serializable", obj(name, ext = shapeTag(name))( diff --git a/modules/example/resources/smithy4s.example.ImportService.json b/modules/example/resources/smithy4s.example.imp.ImportService.json similarity index 56% rename from modules/example/resources/smithy4s.example.ImportService.json rename to modules/example/resources/smithy4s.example.imp.ImportService.json index 177cda605..dfe0bc1ab 100644 --- a/modules/example/resources/smithy4s.example.ImportService.json +++ b/modules/example/resources/smithy4s.example.imp.ImportService.json @@ -18,6 +18,16 @@ } } } + }, + "404": { + "description": "NotFoundError 404 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotFoundErrorResponseContent" + } + } + } } } } @@ -27,6 +37,14 @@ "schemas": { "ImportOperationOutputPayload": { "type": "string" + }, + "NotFoundErrorResponseContent": { + "type": "object", + "properties": { + "error": { + "type": "string" + } + } } } } diff --git a/modules/example/src/smithy4s/example/error/NotFoundError.scala b/modules/example/src/smithy4s/example/error/NotFoundError.scala new file mode 100644 index 000000000..a415fb4b3 --- /dev/null +++ b/modules/example/src/smithy4s/example/error/NotFoundError.scala @@ -0,0 +1,22 @@ +package smithy4s.example.error + +import smithy4s.syntax._ + +case class NotFoundError(error: Option[String] = None) extends Throwable { +} +object NotFoundError extends smithy4s.ShapeTag.Companion[NotFoundError] { + val id: smithy4s.ShapeId = smithy4s.ShapeId("smithy4s.example.error", "NotFoundError") + + val hints : smithy4s.Hints = smithy4s.Hints( + id, + smithy.api.Error.CLIENT, + smithy.api.HttpError(404), + ) + + val schema: smithy4s.Schema[NotFoundError] = struct( + string.optional[NotFoundError]("error", _.error), + ){ + NotFoundError.apply + }.withHints(hints) + implicit val staticSchema : schematic.Static[smithy4s.Schema[NotFoundError]] = schematic.Static(schema) +} \ No newline at end of file diff --git a/modules/example/src/smithy4s/example/ImportService.scala b/modules/example/src/smithy4s/example/imp/ImportService.scala similarity index 55% rename from modules/example/src/smithy4s/example/ImportService.scala rename to modules/example/src/smithy4s/example/imp/ImportService.scala index 5859053e5..9b15ec372 100644 --- a/modules/example/src/smithy4s/example/ImportService.scala +++ b/modules/example/src/smithy4s/example/imp/ImportService.scala @@ -1,16 +1,18 @@ -package smithy4s.example +package smithy4s.example.imp +import ImportServiceGen.ImportOperationError +import smithy4s.example.error.NotFoundError import smithy4s.example.import_test.OpOutput import smithy4s.syntax._ trait ImportServiceGen[F[_, _, _, _, _]] { self => - def importOperation() : F[Unit, Nothing, OpOutput, Nothing, Nothing] + def importOperation() : F[Unit, ImportOperationError, OpOutput, Nothing, Nothing] def transform[G[_, _, _, _, _]](transformation : smithy4s.Transformation[F, G]) : ImportServiceGen[G] = new Transformed(transformation) class Transformed[G[_, _, _, _, _]](transformation : smithy4s.Transformation[F, G]) extends ImportServiceGen[G] { - def importOperation() = transformation[Unit, Nothing, OpOutput, Nothing, Nothing](self.importOperation()) + def importOperation() = transformation[Unit, ImportOperationError, OpOutput, Nothing, Nothing](self.importOperation()) } } @@ -18,7 +20,7 @@ object ImportServiceGen extends smithy4s.Service[ImportServiceGen, ImportService def apply[F[_]](implicit F: smithy4s.Monadic[ImportServiceGen, F]): F.type = F - val id: smithy4s.ShapeId = smithy4s.ShapeId("smithy4s.example", "ImportService") + val id: smithy4s.ShapeId = smithy4s.ShapeId("smithy4s.example.imp", "ImportService") val hints : smithy4s.Hints = smithy4s.Hints( id, @@ -48,8 +50,8 @@ object ImportServiceGen extends smithy4s.Service[ImportServiceGen, ImportService case ImportOperation() => impl.importOperation() } } - case class ImportOperation() extends ImportServiceOperation[Unit, Nothing, OpOutput, Nothing, Nothing] - object ImportOperation extends smithy4s.Endpoint[ImportServiceOperation, Unit, Nothing, OpOutput, Nothing, Nothing] { + case class ImportOperation() extends ImportServiceOperation[Unit, ImportOperationError, OpOutput, Nothing, Nothing] + object ImportOperation extends smithy4s.Endpoint[ImportServiceOperation, Unit, ImportOperationError, OpOutput, Nothing, Nothing] with smithy4s.Errorable[ImportOperationError] { val id: smithy4s.ShapeId = smithy4s.ShapeId("smithy4s.example.import_test", "ImportOperation") val input: smithy4s.Schema[Unit] = unit.withHints(smithy4s.internals.InputOutput.Input) val output: smithy4s.Schema[OpOutput] = OpOutput.schema.withHints(smithy4s.internals.InputOutput.Output) @@ -60,6 +62,38 @@ object ImportServiceGen extends smithy4s.Service[ImportServiceGen, ImportService smithy.api.Http(smithy.api.NonEmptyString("GET"), smithy.api.NonEmptyString("/test"), Some(200)), ) def wrap(input: Unit) = ImportOperation() + override val errorable: Option[smithy4s.Errorable[ImportOperationError]] = Some(this) + val error: smithy4s.errorUnion.Schema[ImportOperationError] = ImportOperationError.schema + def liftError(throwable: Throwable) : Option[ImportOperationError] = throwable match { + case e: NotFoundError => Some(ImportOperationError.NotFoundErrorCase(e)) + case _ => None + } + def unliftError(e: ImportOperationError) : Throwable = e match { + case ImportOperationError.NotFoundErrorCase(e) => e + } + } + sealed trait ImportOperationError extends scala.Product with scala.Serializable + object ImportOperationError extends smithy4s.ShapeTag.Companion[ImportOperationError] { + val id: smithy4s.ShapeId = smithy4s.ShapeId("smithy4s.example.imp", "ImportOperationError") + + val hints : smithy4s.Hints = smithy4s.Hints( + id, + ) + + case class NotFoundErrorCase(notFoundError: NotFoundError) extends ImportOperationError + + object NotFoundErrorCase { + val hints : smithy4s.Hints = smithy4s.Hints() + val schema: smithy4s.Schema[NotFoundErrorCase] = bijection(NotFoundError.schema, NotFoundErrorCase(_), _.notFoundError) + val alt = schema.oneOf[ImportOperationError]("NotFoundError") + } + + val schema: smithy4s.errorUnion.Schema[ImportOperationError] = errors( + NotFoundErrorCase.alt, + ){ + case c : NotFoundErrorCase => NotFoundErrorCase.alt(c) + } + implicit val staticSchema : schematic.Static[smithy4s.Schema[ImportOperationError]] = schematic.Static(schema) } } diff --git a/modules/example/src/smithy4s/example/imp/package.scala b/modules/example/src/smithy4s/example/imp/package.scala new file mode 100644 index 000000000..9b30d3f5c --- /dev/null +++ b/modules/example/src/smithy4s/example/imp/package.scala @@ -0,0 +1,12 @@ +package smithy4s.example + +package object imp { + type ImportService[F[_]] = smithy4s.Monadic[ImportServiceGen, F] + object ImportService extends smithy4s.Service.Provider[ImportServiceGen, ImportServiceOperation] { + def apply[F[_]](implicit F: ImportService[F]): F.type = F + def service : smithy4s.Service[ImportServiceGen, ImportServiceOperation] = ImportServiceGen + val id: smithy4s.ShapeId = service.id + } + + +} \ No newline at end of file diff --git a/modules/example/src/smithy4s/example/package.scala b/modules/example/src/smithy4s/example/package.scala index ddd1d6003..8b7c08e1b 100644 --- a/modules/example/src/smithy4s/example/package.scala +++ b/modules/example/src/smithy4s/example/package.scala @@ -13,12 +13,6 @@ package object example { def service : smithy4s.Service[FooServiceGen, FooServiceOperation] = FooServiceGen val id: smithy4s.ShapeId = service.id } - type ImportService[F[_]] = smithy4s.Monadic[ImportServiceGen, F] - object ImportService extends smithy4s.Service.Provider[ImportServiceGen, ImportServiceOperation] { - def apply[F[_]](implicit F: ImportService[F]): F.type = F - def service : smithy4s.Service[ImportServiceGen, ImportServiceOperation] = ImportServiceGen - val id: smithy4s.ShapeId = service.id - } type ObjectService[F[_]] = smithy4s.Monadic[ObjectServiceGen, F] object ObjectService extends smithy4s.Service.Provider[ObjectServiceGen, ObjectServiceOperation] { def apply[F[_]](implicit F: ObjectService[F]): F.type = F diff --git a/sampleSpecs/import.smithy b/sampleSpecs/import.smithy index e2de39c46..fdf356ca7 100644 --- a/sampleSpecs/import.smithy +++ b/sampleSpecs/import.smithy @@ -1,11 +1,13 @@ -namespace smithy4s.example +namespace smithy4s.example.imp use smithy4s.api#simpleRestJson use smithy4s.example.import_test#ImportOperation +use smithy4s.example.error#NotFoundError @simpleRestJson service ImportService { version: "1.0.0", - operations: [ImportOperation] + operations: [ImportOperation], + errors: [NotFoundError], } diff --git a/sampleSpecs/importerror.smithy b/sampleSpecs/importerror.smithy new file mode 100644 index 000000000..7dc5a595c --- /dev/null +++ b/sampleSpecs/importerror.smithy @@ -0,0 +1,7 @@ +namespace smithy4s.example.error + +@error("client") +@httpError(404) +structure NotFoundError { + error: String, +}