From ffb859591df2613dfe5012352100bef5ae230f53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Koz=C5=82owski?= Date: Thu, 5 Oct 2023 23:53:59 +0200 Subject: [PATCH 1/3] Support open enums --- .../scala/playground/CompilationError.scala | 7 +++++++ .../scala/playground/NodeEncoderVisitor.scala | 8 +++++++- .../scala/playground/QueryCompilerVisitor.scala | 17 ++++++++++++++++- modules/core/src/test/smithy/demo.smithy | 9 ++++++--- .../playground/language/CompletionVisitor.scala | 8 +++++--- project/plugins.sbt | 4 +--- 6 files changed, 42 insertions(+), 11 deletions(-) diff --git a/modules/core/src/main/scala/playground/CompilationError.scala b/modules/core/src/main/scala/playground/CompilationError.scala index 1aeded31a..3b3b620ae 100644 --- a/modules/core/src/main/scala/playground/CompilationError.scala +++ b/modules/core/src/main/scala/playground/CompilationError.scala @@ -137,6 +137,9 @@ sealed trait CompilationErrorDetails extends Product with Serializable { case EmptyStruct(possibleValues) => s"found empty struct, expected one of: ${possibleValues.mkString_(", ")}." + case InvalidIntEnumValue(value) => + s"Invalid value for open int enum: $value - must be an integer." + case UnknownEnumValue(name, possibleValues) => s"Unknown enum value: $name. Available values: ${possibleValues.mkString(", ")}" @@ -227,6 +230,10 @@ object CompilationErrorDetails { possibleValues: NonEmptyList[String] ) extends CompilationErrorDetails + final case class InvalidIntEnumValue( + value: String + ) extends CompilationErrorDetails + final case class UnknownEnumValue( value: String, possibleValues: List[String], diff --git a/modules/core/src/main/scala/playground/NodeEncoderVisitor.scala b/modules/core/src/main/scala/playground/NodeEncoderVisitor.scala index 37a346cec..5039de12c 100644 --- a/modules/core/src/main/scala/playground/NodeEncoderVisitor.scala +++ b/modules/core/src/main/scala/playground/NodeEncoderVisitor.scala @@ -32,6 +32,7 @@ import smithy4s.schema.CollectionTag.ListTag import smithy4s.schema.CollectionTag.SetTag import smithy4s.schema.CollectionTag.VectorTag import smithy4s.schema.EnumTag +import smithy4s.schema.EnumTag._ import smithy4s.schema.EnumValue import smithy4s.schema.Field import smithy4s.schema.Primitive @@ -172,7 +173,12 @@ object NodeEncoderVisitor extends SchemaVisitor[NodeEncoder] { self => tag: EnumTag[E], values: List[EnumValue[E]], total: E => EnumValue[E], - ): NodeEncoder[E] = string.contramap(total(_).name) + ): NodeEncoder[E] = + tag match { + case ClosedIntEnum | ClosedStringEnum => string.contramap(total(_).name) + // todo: test + case OpenIntEnum(_) | OpenStringEnum(_) => string.contramap(total(_).stringValue) + } def struct[S]( shapeId: ShapeId, diff --git a/modules/core/src/main/scala/playground/QueryCompilerVisitor.scala b/modules/core/src/main/scala/playground/QueryCompilerVisitor.scala index e8f90cc68..fe35dac18 100644 --- a/modules/core/src/main/scala/playground/QueryCompilerVisitor.scala +++ b/modules/core/src/main/scala/playground/QueryCompilerVisitor.scala @@ -25,6 +25,8 @@ import smithy4s.schema.CollectionTag.ListTag import smithy4s.schema.CollectionTag.SetTag import smithy4s.schema.CollectionTag.VectorTag import smithy4s.schema.EnumTag +import smithy4s.schema.EnumTag.OpenIntEnum +import smithy4s.schema.EnumTag.OpenStringEnum import smithy4s.schema.EnumValue import smithy4s.schema.Field import smithy4s.schema.Primitive @@ -490,7 +492,20 @@ object QueryCompilerVisitorInternal extends SchemaVisitor[QueryCompiler] { Ior.bothNec(CompilationError.warning(EnumFallback(v.name), range).deprecated, v.value) case (None, None) => - Ior.leftNec(CompilationError.error(UnknownEnumValue(name, values.map(_.name)), range)) + tag match { + // todo: test + case OpenIntEnum(unknown) => + name + .toIntOption + .toRightIor(CompilationError.error(InvalidIntEnumValue(name), range)) + .toIorNec + .map(unknown) + + // todo: test + case OpenStringEnum(unknown) => unknown(name).pure[QueryCompiler.Result] + case _ => + Ior.leftNec(CompilationError.error(UnknownEnumValue(name, values.map(_.name)), range)) + } } } diff --git a/modules/core/src/test/smithy/demo.smithy b/modules/core/src/test/smithy/demo.smithy index af8c7695f..736d8e57f 100644 --- a/modules/core/src/test/smithy/demo.smithy +++ b/modules/core/src/test/smithy/demo.smithy @@ -3,6 +3,7 @@ $version: "2" namespace demo.smithy use alloy#UUID +use alloy#openEnum use alloy#simpleRestJson use smithy4s.meta#indexedSeq use smithy4s.meta#refinement @@ -67,9 +68,10 @@ structure CreateHeroInput { friendSet: FriendSet hasNewtypes: HasNewtypes hasDeprecations: HasDeprecations - doc: Document, - sparse: SampleSparseList, + doc: Document + sparse: SampleSparseList sparseMap: SampleSparseMap + tier: PrivacyTier } @uniqueItems @@ -141,6 +143,7 @@ map PowerMap { value: Hero } +@openEnum enum Power { ICE = "Ice" FIRE = "Fire" @@ -148,6 +151,7 @@ enum Power { WIND = "Wind" } +@openEnum intEnum PrivacyTier { PUBLIC = 0 PRIVATE = 1 @@ -265,7 +269,6 @@ structure HasMixin with [SampleMixin] { name: String } - @sparse list SampleSparseList { member: Integer diff --git a/modules/language-support/src/main/scala/playground/language/CompletionVisitor.scala b/modules/language-support/src/main/scala/playground/language/CompletionVisitor.scala index b8262c32e..66aa83685 100644 --- a/modules/language-support/src/main/scala/playground/language/CompletionVisitor.scala +++ b/modules/language-support/src/main/scala/playground/language/CompletionVisitor.scala @@ -33,7 +33,7 @@ import smithy4s.dynamic.DynamicSchemaIndex import smithy4s.schema.Alt import smithy4s.schema.CollectionTag import smithy4s.schema.EnumTag -import smithy4s.schema.EnumTag.IntEnum +import smithy4s.schema.EnumTag._ import smithy4s.schema.EnumValue import smithy4s.schema.Field import smithy4s.schema.Primitive @@ -261,8 +261,10 @@ object CompletionItem { case e @ EnumerationSchema(_, _, _, _, _) => e.tag match { - case IntEnum() => now(s"intEnum ${e.shapeId.name}") - case _ => now(s"enum ${e.shapeId.name}") + case ClosedIntEnum => now(s"intEnum ${e.shapeId.name}") + case OpenIntEnum(_) => now(s"intEnum(open) ${e.shapeId.name}") + case OpenStringEnum(_) => now(s"enum(open) ${e.shapeId.name}") + case ClosedStringEnum => now(s"enum ${e.shapeId.name}") } case MapSchema(shapeId, _, key, value) => diff --git a/project/plugins.sbt b/project/plugins.sbt index 43876a260..275e99b49 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,10 +1,8 @@ -ThisBuild / libraryDependencySchemes += "org.scala-lang.modules" %% "scala-xml" % VersionScheme.Always - addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.5.11") addSbtPlugin("io.github.davidgregory084" % "sbt-tpolecat" % "0.4.3") // try to keep in sync with smithy-build.json -addSbtPlugin("com.disneystreaming.smithy4s" % "smithy4s-sbt-codegen" % "0.18.0") +addSbtPlugin("com.disneystreaming.smithy4s" % "smithy4s-sbt-codegen" % "dev-SNAPSHOT") addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.11.0") addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "1.1.1") From 3cf445932e2d8e2372bffd51a2849628585b79c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Koz=C5=82owski?= Date: Tue, 10 Oct 2023 20:12:38 +0200 Subject: [PATCH 2/3] bump to 0.18.1 --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 275e99b49..d88e85f3d 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -2,7 +2,7 @@ addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.5.11") addSbtPlugin("io.github.davidgregory084" % "sbt-tpolecat" % "0.4.3") // try to keep in sync with smithy-build.json -addSbtPlugin("com.disneystreaming.smithy4s" % "smithy4s-sbt-codegen" % "dev-SNAPSHOT") +addSbtPlugin("com.disneystreaming.smithy4s" % "smithy4s-sbt-codegen" % "0.18.1") addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.11.0") addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "1.1.1") From c309fed110b35e51727b4dec1f99b589ac543cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Koz=C5=82owski?= Date: Tue, 10 Oct 2023 22:26:04 +0200 Subject: [PATCH 3/3] Update open enum type rendering --- modules/core/src/test/smithy/demo.smithy | 14 ++++++++++++-- .../playground/language/CompletionVisitor.scala | 4 ++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/modules/core/src/test/smithy/demo.smithy b/modules/core/src/test/smithy/demo.smithy index 736d8e57f..8eefde074 100644 --- a/modules/core/src/test/smithy/demo.smithy +++ b/modules/core/src/test/smithy/demo.smithy @@ -143,7 +143,6 @@ map PowerMap { value: Hero } -@openEnum enum Power { ICE = "Ice" FIRE = "Fire" @@ -151,7 +150,6 @@ enum Power { WIND = "Wind" } -@openEnum intEnum PrivacyTier { PUBLIC = 0 PRIVATE = 1 @@ -279,3 +277,15 @@ map SampleSparseMap { key: String value: Integer } + +@openEnum +enum OpenStringEnum { + ICE + FIRE +} + +@openEnum +intEnum OpenIntEnum { + ICE = 1 + FIRE = 2 +} diff --git a/modules/language-support/src/main/scala/playground/language/CompletionVisitor.scala b/modules/language-support/src/main/scala/playground/language/CompletionVisitor.scala index 66aa83685..da58e78db 100644 --- a/modules/language-support/src/main/scala/playground/language/CompletionVisitor.scala +++ b/modules/language-support/src/main/scala/playground/language/CompletionVisitor.scala @@ -262,8 +262,8 @@ object CompletionItem { case e @ EnumerationSchema(_, _, _, _, _) => e.tag match { case ClosedIntEnum => now(s"intEnum ${e.shapeId.name}") - case OpenIntEnum(_) => now(s"intEnum(open) ${e.shapeId.name}") - case OpenStringEnum(_) => now(s"enum(open) ${e.shapeId.name}") + case OpenIntEnum(_) => now(s"@openEnum intEnum ${e.shapeId.name}") + case OpenStringEnum(_) => now(s"@openEnum enum ${e.shapeId.name}") case ClosedStringEnum => now(s"enum ${e.shapeId.name}") }