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

Use Scala 3 in the IDE, for examples & documentation #3903

Merged
merged 8 commits into from
Jul 5, 2024
Merged
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
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
Loading