Skip to content

Commit

Permalink
Generate enum values as uppercase types for better Scala 3 compat
Browse files Browse the repository at this point in the history
- Update dependencies

Co-authored-by: Andreas Drobisch <[email protected]>
Co-authored-by: Saskia Gennrich <[email protected]>
  • Loading branch information
3 people committed Nov 22, 2024
1 parent a624771 commit 22800bd
Show file tree
Hide file tree
Showing 33 changed files with 185 additions and 128 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
scala: [2.12.19]
scala: [2.12.20]
java: [[email protected]+7]
runs-on: ${{ matrix.os }}
steps:
Expand Down Expand Up @@ -63,7 +63,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
scala: [2.12.19]
scala: [2.12.20]
java: [[email protected]+7]
runs-on: ${{ matrix.os }}
steps:
Expand All @@ -80,12 +80,12 @@ jobs:
java-version: 15.0.2+7
cache: sbt

- name: Download target directories (2.12.19)
- name: Download target directories (2.12.20)
uses: actions/download-artifact@v4
with:
name: target-${{ matrix.os }}-2.12.19-${{ matrix.java }}
name: target-${{ matrix.os }}-2.12.20-${{ matrix.java }}

- name: Inflate target directories (2.12.19)
- name: Inflate target directories (2.12.20)
run: |
tar xf targets.tar
rm targets.tar
Expand Down
12 changes: 6 additions & 6 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,17 @@ inThisBuild(
)
)

val circeVersion = "0.14.6"
val circeVersion = "0.14.10"

lazy val root = (project in file("."))
.enablePlugins(SbtPlugin, ParadoxSitePlugin, GhpagesPlugin)
.settings(
name := "sbt-scraml",
libraryDependencies += "com.commercetools.rmf" % "raml-model" % "0.2.0-20240119124459",
libraryDependencies += "org.scalameta" %% "scalameta" % "4.4.35",
libraryDependencies += "org.scalameta" %% "scalafmt-dynamic" % "3.7.17",
libraryDependencies += "org.typelevel" %% "cats-effect" % "3.5.3",
libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.17" % Test,
libraryDependencies += "com.commercetools.rmf" % "raml-model" % "0.2.0-20240722205528",
libraryDependencies += "org.scalameta" %% "scalameta" % "4.8.15",
libraryDependencies += "org.scalameta" %% "scalafmt-dynamic" % "3.8.3",
libraryDependencies += "org.typelevel" %% "cats-effect" % "3.5.6",
libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test,
libraryDependencies ++= Seq(
"io.circe" %% "circe-core",
"io.circe" %% "circe-generic",
Expand Down
11 changes: 6 additions & 5 deletions examples/build.sbt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
scalaVersion := "2.13.14"
scalaVersion := "3.3.4"

val circeVersion = "0.14.7"
val tapirVersion = "1.10.7"
val tapirVersion = "1.11.9"

lazy val examples = (project in file("."))
.settings(
Expand All @@ -16,14 +16,15 @@ lazy val examples = (project in file("."))
libraryDependencies += "com.softwaremill.sttp.tapir" %% "tapir-core" % tapirVersion,
libraryDependencies += "com.softwaremill.sttp.tapir" %% "tapir-json-circe" % tapirVersion,
libraryDependencies += "com.softwaremill.sttp.tapir" %% "tapir-sttp-client" % tapirVersion,
libraryDependencies += "com.softwaremill.sttp.tapir" %% "tapir-akka-http-server" % tapirVersion,
libraryDependencies += "com.softwaremill.sttp.tapir" %% "tapir-pekko-http-server" % tapirVersion,
libraryDependencies += "com.softwaremill.sttp.client3" %% "async-http-client-backend-cats" % "3.9.6",

libraryDependencies += "org.typelevel" %% "cats-effect" % "3.5.4",

ramlFile := Some(file("../src/sbt-test/sbt-scraml/simple/api/simple.raml")),
ramlFile := Some(file("/Users/sbrunk/repos/commercetools/commercetools-api-reference-scala/reference/api-specs/api/api.raml")),
ramlFieldMatchPolicy := scraml.FieldMatchPolicy.Exact(),
basePackageName := "scraml.examples",
librarySupport := Set(scraml.libs.CirceJsonSupport(), scraml.libs.TapirSupport("Endpoints")),
Compile / sourceGenerators += runScraml
Compile / sourceGenerators += runScraml,
Compile / scalacOptions ++= Seq("-Xmax-inlines", "128")
)
2 changes: 1 addition & 1 deletion examples/project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=1.6.2
sbt.version=1.10.5
168 changes: 84 additions & 84 deletions examples/src/main/scala/examples/GreetingExample.scala
Original file line number Diff line number Diff line change
@@ -1,84 +1,84 @@
package examples

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import cats.effect.{ExitCode, IO, IOApp}
import scraml.examples.{DataType, Endpoints, SomeEnum}
import scraml.examples.Endpoints.Greeting.GetGreetingParams
import sttp.client3.SttpBackend
import sttp.client3.asynchttpclient.cats.AsyncHttpClientCatsBackend
import sttp.model.{Header, StatusCode}
import sttp.tapir.DecodeResult.{Failure, Value}
import sttp.tapir.client.sttp.WebSocketToPipe

import scala.concurrent.Future

class GreetingClient(apiUrl: String)(backend: SttpBackend[IO, Any])(implicit wsToPipe: WebSocketToPipe[Any]) {
import sttp.client3._
import sttp.tapir._
import sttp.tapir.client.sttp.SttpClientInterpreter

private lazy val client = SttpClientInterpreter()
private def authenticate: IO[String] = IO.pure("sometoken")

def getGreeting(params: GetGreetingParams): IO[DataType] = for {
accessToken <- authenticate
// adding an input and output to the endpoint to access headers and to provide an access token (checking not implemented)
response <- client.toClient(Endpoints.Greeting.getGreeting.in(auth.bearer[String]()).out(headers), Some(uri"$apiUrl"), backend)(wsToPipe)(params, accessToken)
result <- response match {
case Value(value) => IO.fromEither(value.left.map(error => new RuntimeException(s"error in $response: $error")))
case error: Failure => IO.raiseError(new RuntimeException(s"error while getting greeting: $error"))
}
(data, headers) = result
_ <- IO(println(s"got headers: $headers"))
} yield data
}

object GreetingClient {
def apply(apiUrl: String): IO[(GreetingClient, SttpBackend[IO, Any])] =
AsyncHttpClientCatsBackend[IO]().flatMap(backend => IO((new GreetingClient(apiUrl)(backend), backend)))
}

object GreetingServer {
import sttp.tapir._
import sttp.tapir.server.akkahttp.AkkaHttpServerInterpreter
import scala.concurrent.Future
import akka.http.scaladsl.server.Route

def getGreeting(params: GetGreetingParams): Future[Either[Unit, (DataType, StatusCode, List[Header])]] =
Future.successful(Right((DataType(params.name.getOrElse("no input"), customTypeProp = BigDecimal(42)), StatusCode.Ok, List(Header("custom-header", "value")))))

implicit val httpSystem: ActorSystem = ActorSystem("http")

import httpSystem.dispatcher

// adding outputs to provide statusCode and headers in the implementation
val greetingWithStatusAndHeaders = Endpoints.Greeting.getGreeting.out(statusCode and sttp.tapir.headers)

val greetingRoute: Route =
AkkaHttpServerInterpreter().toRoute(greetingWithStatusAndHeaders.serverLogic(getGreeting))

def startServer: IO[Http.ServerBinding] =
IO.fromFuture(IO(Http().newServerAt("localhost", 8080).bind(greetingRoute)))
}

object GreetingApp extends IOApp {
implicit class FutureOps[T](future: => Future[T]) {
def toIO: IO[T] = IO.fromFuture(IO(future))
}

override def run(args: List[String]): IO[ExitCode] = for {
binding <- GreetingServer.startServer
(clientWithBackend) <- GreetingClient(
apiUrl = s"http://${binding.localAddress.getHostName}:${binding.localAddress.getPort}"
)
(client, clientBackend) = clientWithBackend
result <- client.getGreeting(GetGreetingParams(enum_type = SomeEnum.A, name = Some("world"))).attempt
_ <- IO(println(result))
_ <-
clientBackend
.close()
.guarantee(binding.unbind().toIO.void)
.guarantee(GreetingServer.httpSystem.terminate().toIO.void)
} yield ExitCode.Success
}
//package examples
//
//import org.apache.pekko.actor.ActorSystem
//import org.apache.pekko.http.scaladsl.Http
//import cats.effect.{ExitCode, IO, IOApp}
//import scraml.examples.{DataType, Endpoints, SomeEnum}
//import scraml.examples.Endpoints.Greeting.GetGreetingParams
//import sttp.client3.SttpBackend
//import sttp.client3.asynchttpclient.cats.AsyncHttpClientCatsBackend
//import sttp.model.{Header, StatusCode}
//import sttp.tapir.DecodeResult.{Failure, Value}
//import sttp.tapir.client.sttp.WebSocketToPipe
//
//import scala.concurrent.Future
//
//class GreetingClient(apiUrl: String)(backend: SttpBackend[IO, Any])(implicit wsToPipe: WebSocketToPipe[Any]) {
// import sttp.client3._
// import sttp.tapir._
// import sttp.tapir.client.sttp.SttpClientInterpreter
//
// private lazy val client = SttpClientInterpreter()
// private def authenticate: IO[String] = IO.pure("sometoken")
//
// def getGreeting(params: GetGreetingParams): IO[DataType] = for {
// accessToken <- authenticate
// // adding an input and output to the endpoint to access headers and to provide an access token (checking not implemented)
// response <- client.toClient(Endpoints.Greeting.getGreeting.in(auth.bearer[String]()).out(headers), Some(uri"$apiUrl"), backend)(wsToPipe)(params, accessToken)
// result <- response match {
// case Value(value) => IO.fromEither(value.left.map(error => new RuntimeException(s"error in $response: $error")))
// case error: Failure => IO.raiseError(new RuntimeException(s"error while getting greeting: $error"))
// }
// (data, headers) = result
// _ <- IO(println(s"got headers: $headers"))
// } yield data
//}
//
//object GreetingClient {
// def apply(apiUrl: String): IO[(GreetingClient, SttpBackend[IO, Any])] =
// AsyncHttpClientCatsBackend[IO]().flatMap(backend => IO((new GreetingClient(apiUrl)(backend), backend)))
//}
//
//object GreetingServer {
// import sttp.tapir._
// import sttp.tapir.server.pekkohttp.PekkoHttpServerInterpreter
// import scala.concurrent.Future
// import org.apache.pekko.http.scaladsl.server.Route
//
// def getGreeting(params: GetGreetingParams): Future[Either[Unit, (DataType, StatusCode, List[Header])]] =
// Future.successful(Right((DataType(params.name.getOrElse("no input"), customTypeProp = BigDecimal(42)), StatusCode.Ok, List(Header("custom-header", "value")))))
//
// implicit val httpSystem: ActorSystem = ActorSystem("http")
//
// import httpSystem.dispatcher
//
// // adding outputs to provide statusCode and headers in the implementation
// val greetingWithStatusAndHeaders = Endpoints.Greeting.getGreeting.out(statusCode and sttp.tapir.headers)
//
// val greetingRoute: Route =
// PekkoHttpServerInterpreter().toRoute(greetingWithStatusAndHeaders.serverLogic(getGreeting))
//
// def startServer: IO[Http.ServerBinding] =
// IO.fromFuture(IO(Http().newServerAt("localhost", 8080).bind(greetingRoute)))
//}
//
//object GreetingApp extends IOApp {
// implicit class FutureOps[T](future: => Future[T]) {
// def toIO: IO[T] = IO.fromFuture(IO(future))
// }
//
// override def run(args: List[String]): IO[ExitCode] = for {
// binding <- GreetingServer.startServer
// (clientWithBackend) <- GreetingClient(
// apiUrl = s"http://${binding.localAddress.getHostName}:${binding.localAddress.getPort}"
// )
// (client, clientBackend) = clientWithBackend
// result <- client.getGreeting(GetGreetingParams(enum_type = SomeEnum.A, name = Some("world"))).attempt
// _ <- IO(println(result))
// _ <-
// clientBackend
// .close()
// .guarantee(binding.unbind().toIO.void)
// .guarantee(GreetingServer.httpSystem.terminate().toIO.void)
// } yield ExitCode.Success
//}
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version = 1.10.0
sbt.version = 1.10.5
2 changes: 1 addition & 1 deletion src/main/scala/scraml/DefaultModelGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ object DefaultModelGen extends ModelGen {
extendedType = Init(Type.Name(stringType.getName), Name(""), Nil)
enumInstances: List[Stat] = enumInstanceNames.map { instanceName =>
q"""
case object ${Term.Name(instanceName)} extends $extendedType
case object ${Term.Name(instanceName.toUpperCase())} extends $extendedType
"""
}.toList

Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/scraml/ModelGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ object ModelGen {
def addDefaultEnum(property: StringType): TypeRefDetails = {
Option(property.getDefault).fold(this) { instance =>
val enumType = Term.Name(property.getName)
val enumInstance = Term.Name(instance.getValue.toString)
val enumInstance = Term.Name(instance.getValue.toString.toUpperCase)

copy(defaultValue = Option(q"$enumType.$enumInstance"))
}
Expand Down
6 changes: 3 additions & 3 deletions src/main/scala/scraml/libs/CirceJsonSupport.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class CirceJsonSupport(formats: Map[String, String]) extends LibrarySupport with
object HasRefinements extends HasFacets {
def apply(context: ModelGenContext, classDef: Defn.Class): Boolean =
context.isLibraryEnabled[RefinedSupport.type]() &&
classDef.ctor.paramss.flatten
classDef.ctor.paramClauses.flatten
.map(p => propertyNameFrom(p.name.value))
.flatMap(name => RMFUtil.findAllDeclarations(context.objectType, name).map(_._2))
.exists { prop =>
Expand Down Expand Up @@ -1016,7 +1016,7 @@ class CirceJsonSupport(formats: Map[String, String]) extends LibrarySupport with
Case(
Lit.String(instance.getValue.toString),
None,
Term.Apply(Term.Name("Right"), List(Term.Name(instance.getValue.toString)))
Term.Apply(Term.Name("Right"), List(Term.Name(instance.getValue.toString.toUpperCase)))
)
)
.toList ++ (params.generateDefaultEnumVariant match {
Expand Down Expand Up @@ -1068,7 +1068,7 @@ class CirceJsonSupport(formats: Map[String, String]) extends LibrarySupport with
enumType.getEnum.asScala
.map(instance =>
Case(
Term.Name(instance.getValue.toString),
Term.Name(instance.getValue.toString.toUpperCase),
None,
Lit.String(instance.getValue.toString)
)
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/scraml/libs/SphereJsonSupport.scala
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ object SphereJsonSupport extends LibrarySupport with JsonSupport {
Case(
Lit.String(instance.getValue().toString()),
None,
Term.Select(Term.Name(instance.getValue().toString()), Term.Name("valid"))
Term.Select(Term.Name(instance.getValue().toString().toUpperCase()), Term.Name("valid"))
)
)
.toList ++ List(other)
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/scraml/libs/TapirSupport.scala
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ final class TapirSupport(endpointsObjectName: String) extends LibrarySupport {
Case(
Lit.String(enum.getValue.toString),
None,
q"sttp.tapir.DecodeResult.Value(${Term.Name(enum.getValue.toString)})"
q"sttp.tapir.DecodeResult.Value(${Term.Name(enum.getValue.toString.toUpperCase())})"
)
}
++
Expand Down Expand Up @@ -425,7 +425,7 @@ final class TapirSupport(endpointsObjectName: String) extends LibrarySupport {
${Term.PartialFunction(
enumNames.map { enum =>
Case(
Term.Name(enum),
Term.Name(enum.toUpperCase),
None,
Lit.String(enum)
)
Expand Down
2 changes: 1 addition & 1 deletion src/sbt-test/sbt-scraml/cats/build.sbt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
lazy val root = (project in file("."))
.settings(
scalaVersion := "2.13.8",
scalaVersion := "2.13.15",
name := "scraml-cats-test",
version := "0.1",
ramlFile := Some(file("api/simple.raml")),
Expand Down
2 changes: 1 addition & 1 deletion src/sbt-test/sbt-scraml/cats/project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version = 1.6.1
sbt.version = 1.10.5
2 changes: 1 addition & 1 deletion src/sbt-test/sbt-scraml/ct-api-sphere/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ val circeVersion = "0.14.1"

lazy val root = (project in file("."))
.settings(
scalaVersion := "2.12.16",
scalaVersion := "2.13.15",
name := "scraml-ct-api-sphere-test",
version := "0.1",
ramlFile := Some(file("reference/api-specs/api/api.raml")),
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version = 1.6.1
sbt.version = 1.10.5
2 changes: 1 addition & 1 deletion src/sbt-test/sbt-scraml/ct-api/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ val tapirVersion = "1.1.0"

lazy val root = (project in file("."))
.settings(
scalaVersion := "2.13.8",
scalaVersion := "2.13.15",
name := "scraml-ct-api-circe-test",
version := "0.1",
ramlFile := Some(file("reference/api-specs/api/api.raml")),
Expand Down
2 changes: 1 addition & 1 deletion src/sbt-test/sbt-scraml/ct-api/project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version = 1.6.1
sbt.version = 1.10.5
2 changes: 2 additions & 0 deletions src/sbt-test/sbt-scraml/json/api/enum.raml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ type: string
enum:
- A
- B
- enum
- type
2 changes: 1 addition & 1 deletion src/sbt-test/sbt-scraml/json/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ val circeVersion = "0.14.2"
lazy val root = (project in file("."))
.settings(
name := "scraml-json-test",
scalaVersion := "2.12.16",
scalaVersion := "2.13.15",
version := "0.1",
ramlFile := Some(file("api/json.raml")),
basePackageName := "scraml",
Expand Down
2 changes: 1 addition & 1 deletion src/sbt-test/sbt-scraml/json/project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version = 1.6.1
sbt.version = 1.10.5
4 changes: 2 additions & 2 deletions src/sbt-test/sbt-scraml/json/test
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
> compile
$ exists target/scala-2.12/src_managed/main/scraml/datatypes.scala
$ exists target/scala-2.12/src_managed/main/scraml/package.scala
$ exists target/scala-2.13/src_managed/main/scraml/datatypes.scala
$ exists target/scala-2.13/src_managed/main/scraml/package.scala
> run
Loading

0 comments on commit 22800bd

Please sign in to comment.