Skip to content

Commit

Permalink
Use Scala 3 in the IDE, for examples & documentation (#3903)
Browse files Browse the repository at this point in the history
  • Loading branch information
adamw authored Jul 5, 2024
1 parent 91a95b7 commit 7f6d421
Show file tree
Hide file tree
Showing 118 changed files with 1,028 additions and 1,314 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ jobs:
- name: Compile
run: sbt $SBT_JAVA_OPTS -v "compileScoped ${{ matrix.scala-version }} ${{ matrix.target-platform }}"
- name: Compile documentation
if: matrix.target-platform == 'JVM' && matrix.java == '11'
if: matrix.target-platform == 'JVM' && matrix.java == '21'
run: sbt $SBT_JAVA_OPTS -v compileDocumentation
- name: Test
if: matrix.target-platform == 'JVM' && matrix.scala-version == '2.12'
Expand Down Expand Up @@ -131,11 +131,11 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0 # checkout tags so that dynver works properly (we need the version for MiMa)
- name: Set up JDK 11
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 11
java-version: 21
cache: 'sbt'
- name: Check MiMa
run: sbt $SBT_JAVA_OPTS -v mimaReportBinaryIssues
Expand Down
158 changes: 48 additions & 110 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,13 @@ val scala2_12 = "2.12.19"
val scala2_13 = "2.13.14"
val scala3 = "3.3.3"

// The `idea.managed` property is set automatically by IntelliJ when it runs sbt for build or import
val ideaManaged = System.getProperty("idea.managed", "false").toBoolean
val ideScalaVersion = if (ideaManaged) scala2_13 else scala3

val scala2Versions = List(scala2_12, scala2_13)
val scala2And3Versions = scala2Versions ++ List(scala3)
val scala2_13And3Versions = List(scala2_13, scala3)
val codegenScalaVersions = List(scala2_12)
val examplesScalaVersions = List(scala3)
val documentationScalaVersion = scala2_13
val examplesScalaVersion = scala3
val documentationScalaVersion = scala3
val ideScalaVersion = scala3

lazy val clientTestServerPort = settingKey[Int]("Port to run the client interpreter test server on")
lazy val startClientTestServer = taskKey[Unit]("Start a http server used by client interpreter tests")
Expand Down Expand Up @@ -78,8 +75,12 @@ val commonSettings = commonSmlBuildSettings ++ ossPublishSettings ++ Seq(
bspEnabled := !ideSkipProject.value,
// slow down for CI
Test / parallelExecution := false,
// remove false alarms about unused implicit definitions in macros
scalacOptions ++= Seq("-Ywarn-macros:after"),
scalacOptions ++= {
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, _)) => Seq("-Ywarn-macros:after") // remove false alarms about unused implicit definitions in macros
case _ => Seq("-Xmax-inlines", "64")
}
},
evictionErrorLevel := Level.Info
)

Expand Down Expand Up @@ -240,7 +241,6 @@ lazy val rawAllAggregates = core.projectRefs ++
play29Client.projectRefs ++
tests.projectRefs ++
perfTests.projectRefs ++
examples2.projectRefs ++
examples.projectRefs ++
documentation.projectRefs ++
openapiCodegenCore.projectRefs ++
Expand All @@ -250,7 +250,7 @@ lazy val rawAllAggregates = core.projectRefs ++
derevo.projectRefs ++
awsCdk.projectRefs

lazy val loomProjects: Seq[String] = Seq(nettyServerSync, nimaServer, examples).flatMap(_.projectRefs).flatMap(projectId)
lazy val loomProjects: Seq[String] = Seq(nettyServerSync, nimaServer, examples, documentation).flatMap(_.projectRefs).flatMap(projectId)

def projectId(projectRef: ProjectReference): Option[String] =
projectRef match {
Expand Down Expand Up @@ -797,7 +797,7 @@ lazy val json4s: ProjectMatrix = (projectMatrix in file("json/json4s"))
scalaTest.value % Test
)
)
.jvmPlatform(scalaVersions = scala2Versions)
.jvmPlatform(scalaVersions = scala2And3Versions)
.dependsOn(core)

lazy val playJson: ProjectMatrix = (projectMatrix in file("json/playjson"))
Expand Down Expand Up @@ -2023,68 +2023,6 @@ lazy val openapiCodegenCli: ProjectMatrix = (projectMatrix in file("openapi-code

// other

lazy val examples2: ProjectMatrix = (projectMatrix in file("examples2"))
.settings(commonJvmSettings)
.settings(
name := "tapir-examples2",
libraryDependencies ++= Seq(
"dev.zio" %% "zio-interop-cats" % Versions.zioInteropCats,
"org.typelevel" %% "cats-effect" % Versions.catsEffect,
"org.http4s" %% "http4s-dsl" % Versions.http4s,
"org.http4s" %% "http4s-circe" % Versions.http4s,
"org.http4s" %% "http4s-blaze-server" % Versions.http4sBlazeServer,
"com.softwaremill.sttp.client3" %% "akka-http-backend" % Versions.sttp,
"com.softwaremill.sttp.client3" %% "pekko-http-backend" % Versions.sttp,
"com.softwaremill.sttp.client3" %% "async-http-client-backend-fs2" % Versions.sttp,
"com.softwaremill.sttp.client3" %% "async-http-client-backend-zio" % Versions.sttp,
"com.softwaremill.sttp.client3" %% "async-http-client-backend-cats" % Versions.sttp,
"com.softwaremill.sttp.apispec" %% "asyncapi-circe-yaml" % Versions.sttpApispec,
"com.github.jwt-scala" %% "jwt-circe" % Versions.jwtScala,
"org.mock-server" % "mockserver-netty" % Versions.mockServer,
"io.circe" %% "circe-generic-extras" % Versions.circeGenericExtras,
"io.opentelemetry" % "opentelemetry-sdk" % Versions.openTelemetry,
"io.opentelemetry" % "opentelemetry-sdk-metrics" % Versions.openTelemetry,
"io.opentelemetry" % "opentelemetry-exporter-otlp" % Versions.openTelemetry,
scalaTest.value,
logback
),
publishArtifact := false,
Compile / run / fork := true
)
.jvmPlatform(scalaVersions = List(scala2_13))
.dependsOn(
akkaHttpServer,
pekkoHttpServer,
armeriaServer,
jdkhttpServer,
http4sServer,
http4sServerZio,
http4sClient,
sttpClient,
openapiDocs,
asyncapiDocs,
circeJson,
swaggerUiBundle,
redocBundle,
zioHttpServer,
nettyServer,
nettyServerCats,
nettyServerZio,
sttpStubServer,
playJson,
prometheusMetrics,
opentelemetryMetrics,
datadogMetrics,
zioMetrics,
sttpMockServer,
zioJson,
vertxServer,
vertxServerCats,
vertxServerZio,
finatraServer,
protobuf
)

lazy val examples: ProjectMatrix = (projectMatrix in file("examples"))
.settings(commonJvmSettings)
.settings(
Expand All @@ -2100,6 +2038,7 @@ lazy val examples: ProjectMatrix = (projectMatrix in file("examples"))
"org.http4s" %% "http4s-dsl" % Versions.http4s,
"org.http4s" %% "http4s-circe" % Versions.http4s,
"org.http4s" %% "http4s-blaze-server" % Versions.http4sBlazeServer,
"org.mock-server" % "mockserver-netty" % Versions.mockServer,
"io.opentelemetry" % "opentelemetry-sdk" % Versions.openTelemetry,
"io.opentelemetry" % "opentelemetry-sdk-metrics" % Versions.openTelemetry,
"io.opentelemetry" % "opentelemetry-exporter-otlp" % Versions.openTelemetry,
Expand All @@ -2109,32 +2048,33 @@ lazy val examples: ProjectMatrix = (projectMatrix in file("examples"))
publishArtifact := false,
Compile / run / fork := true
)
.jvmPlatform(scalaVersions = examplesScalaVersions)
.jvmPlatform(scalaVersions = List(examplesScalaVersion))
.dependsOn(
datadogMetrics,
prometheusMetrics,
opentelemetryMetrics,
zioMetrics,
armeriaServer,
asyncapiDocs,
circeJson,
datadogMetrics,
http4sClient,
http4sServer,
pekkoHttpServer,
armeriaServer,
nettyServer,
http4sServerZio,
iron,
jdkhttpServer,
nettyServer,
nettyServerCats,
http4sClient,
nettyServerSync,
nettyServerZio,
opentelemetryMetrics,
pekkoHttpServer,
picklerJson,
prometheusMetrics,
sttpClient,
sttpMockServer,
sttpStubServer,
swaggerUiBundle,
http4sServerZio,
nettyServerSync,
nettyServerZio,
redocBundle,
zioHttpServer,
zioJson,
redocBundle,
sttpStubServer,
asyncapiDocs,
iron
zioMetrics
)

//TODO this should be invoked by compilation process, see #https://github.com/scalameta/mdoc/issues/355
Expand Down Expand Up @@ -2171,45 +2111,43 @@ lazy val documentation: ProjectMatrix = (projectMatrix in file("generated-doc"))
)
.jvmPlatform(scalaVersions = List(documentationScalaVersion))
.dependsOn(
core % "compile->test",
testing,
akkaHttpServer,
pekkoHttpServer,
armeriaServer,
armeriaServerCats,
armeriaServerZio,
jdkhttpServer,
asyncapiDocs,
circeJson,
core % "compile->test",
datadogMetrics,
enumeratum,
finatraServer,
finatraServerCats,
http4sClient,
http4sServerZio,
jdkhttpServer,
jsoniterScala,
asyncapiDocs,
openapiDocs,
json4s,
nettyServer,
nettyServerCats,
nettyServerSync,
openapiDocs,
opentelemetryMetrics,
pekkoHttpServer,
picklerJson,
playClient,
playJson,
playServer,
prometheusMetrics,
sprayJson,
http4sClient,
http4sServerZio,
nettyServerCats,
sttpClient,
playClient,
sttpMockServer,
sttpStubServer,
swaggerUiBundle,
testing,
tethysJson,
uPickleJson,
vertxServer,
vertxServerCats,
vertxServerZio,
zio,
zioHttpServer,
derevo,
zioJson,
prometheusMetrics,
opentelemetryMetrics,
datadogMetrics,
zioMetrics,
sttpMockServer,
nettyServer,
swaggerUiBundle
zioMetrics
)
7 changes: 1 addition & 6 deletions core/src/main/scala-3/sttp/tapir/macros/CodecMacros.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,8 @@ package sttp.tapir.macros
import sttp.tapir.CodecFormat.TextPlain
import sttp.tapir.{Codec, SchemaAnnotations, Validator}
import sttp.tapir.internal.CodecValueClassMacro
import sttp.tapir.Mapping
import sttp.tapir.DecodeResult
import sttp.tapir.DecodeResult.Value
import sttp.tapir.Schema

trait CodecMacros {
trait CodecMacros:

/** Creates a codec for an enumeration, where the validator is derived using [[sttp.tapir.Validator.derivedEnumeration]]. This requires
* that all subtypes of the sealed hierarchy `T` must be `object`s.
Expand Down Expand Up @@ -64,4 +60,3 @@ trait CodecMacros {

/** Creates a codec for value class based on codecs defined in `Codec` companion */
implicit inline def derivedValueClass[T <: AnyVal]: Codec[String, T, TextPlain] = CodecValueClassMacro.derivedValueClass[T]
}
5 changes: 2 additions & 3 deletions doc/client/play.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ After providing the input parameters, the two following are returned:
Example:

```scala mdoc:compile-only
import sttp.tapir._
import sttp.tapir.*
import sttp.tapir.client.play.PlayClientInterpreter
import sttp.capabilities.pekko.PekkoStreams

Expand All @@ -60,7 +60,7 @@ import scala.concurrent.Future

import play.api.libs.ws.StandaloneWSClient

def example[I, E, O, R >: PekkoStreams](implicit wsClient: StandaloneWSClient) {
def example[I, E, O, R >: PekkoStreams](implicit wsClient: StandaloneWSClient): Unit =
val e: PublicEndpoint[I, E, O, R] = ???
val inputArgs: I = ???

Expand All @@ -71,7 +71,6 @@ def example[I, E, O, R >: PekkoStreams](implicit wsClient: StandaloneWSClient) {
val result: Future[Either[E, O]] = req
.execute()
.map(responseParser)
}
```

## Limitations
Expand Down
12 changes: 6 additions & 6 deletions doc/client/sttp.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ convert sttp's `WebSocket` instance into a pipe. This logic is looked up via the
The required imports are as follows:

```scala
import sttp.tapir.client.sttp.ws.pekkohttp._ // for pekko-streams
import sttp.tapir.client.sttp.ws.akkahttp._ // for akka-streams
import sttp.tapir.client.sttp.ws.fs2._ // for fs2
import sttp.tapir.client.sttp.ws.zio._ // for zio
import sttp.tapir.client.sttp.ws.pekkohttp.* // for pekko-streams
import sttp.tapir.client.sttp.ws.akkahttp.* // for akka-streams
import sttp.tapir.client.sttp.ws.fs2.* // for fs2
import sttp.tapir.client.sttp.ws.zio.* // for zio
```

No additional dependencies are needed, as both of the above implementations are included in the main interpreter,
Expand All @@ -85,9 +85,9 @@ If you'd like to skip that step, e.g. when testing redirects, it's possible to o
description, for example:

```scala :compile-only
import sttp.tapir._
import sttp.tapir.*
import sttp.tapir.client.sttp.SttpClientInterpreter
import sttp.client3._
import sttp.client3.*

SttpClientInterpreter()
.toRequest(endpoint.get.in("hello").in(query[String]("name")), Some(uri"http://localhost:8080"))
Expand Down
18 changes: 9 additions & 9 deletions doc/docs/asyncapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ object:

```scala mdoc:silent
import sttp.apispec.asyncapi.AsyncAPI
import sttp.capabilities.akka.AkkaStreams
import sttp.tapir._
import sttp.capabilities.pekko.PekkoStreams
import sttp.tapir.*
import sttp.tapir.docs.asyncapi.AsyncAPIInterpreter
import sttp.tapir.generic.auto._
import sttp.tapir.json.circe._
import io.circe.generic.auto._
import sttp.tapir.generic.auto.*
import sttp.tapir.json.circe.*
import io.circe.generic.auto.*

case class Response(msg: String, count: Int)
val echoWS = endpoint.out(
webSocketBody[String, CodecFormat.TextPlain, Response, CodecFormat.Json](AkkaStreams))
webSocketBody[String, CodecFormat.TextPlain, Response, CodecFormat.Json](PekkoStreams))

val docs: AsyncAPI = AsyncAPIInterpreter().toAsyncAPI(echoWS, "Echo web socket", "1.0")
```
Expand Down Expand Up @@ -56,7 +56,7 @@ Multiple endpoints can be converted to an `AsyncAPI` instance by calling the met
The asyncapi case classes can then be serialised, either to JSON or YAML using [Circe](https://circe.github.io/circe/):

```scala mdoc:silent
import sttp.apispec.asyncapi.circe.yaml._
import sttp.apispec.asyncapi.circe.yaml.*

println(docs.toYaml)
```
Expand Down Expand Up @@ -84,7 +84,7 @@ Specification extensions can be added by first importing an extension method, an
method which manipulates the appropriate attribute on the schema, endpoint or endpoint input/output:

```scala mdoc:silent
import sttp.tapir.docs.apispec.DocsExtensionAttribute._
import sttp.tapir.docs.apispec.DocsExtensionAttribute.*

endpoint
.post
Expand All @@ -97,4 +97,4 @@ look at **OpenAPI Specification Extensions** section of [documentation](../docs/

## Exposing AsyncAPI documentation

AsyncAPI documentation can be exposed through the [AsyncAPI playground](https://playground.asyncapi.io).
AsyncAPI documentation can be exposed through the [AsyncAPI playground](https://playground.asyncapi.io).
Loading

0 comments on commit 7f6d421

Please sign in to comment.