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

Support open enums #350

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
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
7 changes: 7 additions & 0 deletions modules/core/src/main/scala/playground/CompilationError.scala
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,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(", ")}"

Expand Down Expand Up @@ -228,6 +231,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],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import smithy4s.capability.EncoderK
import smithy4s.schema.Alt
import smithy4s.schema.CollectionTag
import smithy4s.schema.EnumTag
import smithy4s.schema.EnumTag._
import smithy4s.schema.EnumValue
import smithy4s.schema.Field
import smithy4s.schema.Primitive
Expand Down Expand Up @@ -164,7 +165,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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import smithy4s.Timestamp
import smithy4s.schema.Alt
import smithy4s.schema.CollectionTag
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
Expand Down Expand Up @@ -483,7 +485,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))
}
}

}
Expand Down
19 changes: 16 additions & 3 deletions modules/core/src/test/smithy/demo.smithy
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -290,7 +292,6 @@ structure HasMixin with [SampleMixin] {
name: String
}


@sparse
list SampleSparseList {
member: Integer
Expand All @@ -301,3 +302,15 @@ map SampleSparseMap {
key: String
value: Integer
}

@openEnum
enum OpenStringEnum {
ICE
FIRE
}

@openEnum
intEnum OpenIntEnum {
ICE = 1
FIRE = 2
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -251,8 +251,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"@openEnum intEnum ${e.shapeId.name}")
case OpenStringEnum(_) => now(s"@openEnum enum ${e.shapeId.name}")
case ClosedStringEnum => now(s"enum ${e.shapeId.name}")
}

case MapSchema(shapeId, _, key, value) =>
Expand Down
2 changes: 0 additions & 2 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
ThisBuild / libraryDependencySchemes += "org.scala-lang.modules" %% "scala-xml" % VersionScheme.Always

addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.5.11")
addSbtPlugin("org.typelevel" % "sbt-tpolecat" % "0.5.2")

Expand Down
Loading