diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 8c08200b6c..a8411358a3 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -37,7 +37,7 @@ jobs: name: airframe-coverage file: ./projectJVM/target/scoverage-report/scoverage.xml - name: Archive code coverage results - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: code-coverage-report path: ./projectJVM/target/scoverage-report diff --git a/airframe-di/src/main/scala/wvlet/airframe/AirframeSession.scala b/airframe-di/src/main/scala/wvlet/airframe/AirframeSession.scala index a825c82dd1..5c48bad49d 100644 --- a/airframe-di/src/main/scala/wvlet/airframe/AirframeSession.scala +++ b/airframe-di/src/main/scala/wvlet/airframe/AirframeSession.scala @@ -280,7 +280,7 @@ private[airframe] class AirframeSession( trace(s"[${name}] Search bindings for ${tpe}, dependencies:[${seen.mkString(" <- ")}]") if (seen.contains(tpe)) { - error(s"Found cyclic dependencies: ${seen} at ${sourceCode}") + error(s"Found cyclic dependencies within types [${seen.mkString(", ")}] at ${sourceCode}") throw new CYCLIC_DEPENDENCY(seen, sourceCode) } diff --git a/airframe-di/src/test/scala-3/wvlet/airframe/di/Scala3TypeDITest.scala b/airframe-di/src/test/scala-3/wvlet/airframe/di/Scala3TypeDITest.scala new file mode 100644 index 0000000000..19bd5c5e02 --- /dev/null +++ b/airframe-di/src/test/scala-3/wvlet/airframe/di/Scala3TypeDITest.scala @@ -0,0 +1,86 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package wvlet.airframe.di +import wvlet.airframe.surface.Surface +import wvlet.airframe.{AirframeException, Design} +import wvlet.airspec.AirSpec + +object Scala3TypeDITest extends AirSpec: + + opaque type Env = String + + test("opaque type factory binding"): + val d = Design.newSilentDesign + .bind[Env].toInstance("hello") + .bind[Int].toProvider { (env: Env) => 0 } + .bind[Long].toProvider[Env] { (env: Env) => 0 } + d.build[Env]: x => + x shouldBe "hello" + intercept[AirframeException] { + d.build[String]: x => + fail("should not reach here") + } + + test("resolve explicit provider arg types"): + d.build[Long] { x => + x shouldBe 0 + } + + test("resolve implicit provider arg types"): + pending(s"Scala 3 eagerly resolves provide function arg types") + d.build[Int] { x => + x shouldBe 0 + } + + case class ThreadManager(numThreads: Int = 1) + trait Service1 + trait Service2 + + test("Use intersection type for factory binding"): + val t1 = ThreadManager(10) + val t2 = ThreadManager(20) + + val d = Design.newSilentDesign + .bind[ThreadManager & Service1].toInstance(t1.asInstanceOf[ThreadManager & Service1]) + .bind[ThreadManager & Service2].toInstance(t2.asInstanceOf[ThreadManager & Service2]) + .bind[Int].toProvider[ThreadManager & Service1] { _.numThreads } + .bind[Long].toProvider[ThreadManager & Service2] { _.numThreads.toLong } + + d.build[ThreadManager & Service1] { x => x shouldBe t1 } + d.build[ThreadManager & Service2] { x => x shouldBe t2 } + d.build[ThreadManager & Service1] { x => x shouldBe t1 } + d.build[Int] { x => x shouldBe t1.numThreads } + d.build[Long] { x => x shouldBe t2.numThreads } + + test("Use tagged type for factory binding"): + import wvlet.airframe.surface.tag.* + val t1 = ThreadManager(10) + val t2 = ThreadManager(20) + + val s = Surface.of[ThreadManager @@ Service1] + debug(s) + val f = Surface.of[(ThreadManager @@ Service1) => Int] + debug(f) + + val d = Design.newSilentDesign + .bind[ThreadManager @@ Service1].toInstance(t1) + .bind[ThreadManager @@ Service2].toInstance(t2) + .bind[Int].toProvider[ThreadManager @@ Service1] { _.numThreads } + .bind[Long].toProvider[ThreadManager @@ Service2] { _.numThreads.toLong } + + d.build[ThreadManager @@ Service1] { x => x shouldBe t1 } + d.build[ThreadManager @@ Service2] { x => x shouldBe t2 } + d.build[ThreadManager @@ Service1] { x => x shouldBe t1 } + d.build[Int] { x => x shouldBe t1.numThreads } + d.build[Long] { x => x shouldBe t2.numThreads } diff --git a/airframe-surface/src/main/scala-3/wvlet/airframe/surface/CompileTimeSurfaceFactory.scala b/airframe-surface/src/main/scala-3/wvlet/airframe/surface/CompileTimeSurfaceFactory.scala index e814fa6672..c98613128e 100644 --- a/airframe-surface/src/main/scala-3/wvlet/airframe/surface/CompileTimeSurfaceFactory.scala +++ b/airframe-surface/src/main/scala-3/wvlet/airframe/surface/CompileTimeSurfaceFactory.scala @@ -143,6 +143,7 @@ private[surface] class CompileTimeSurfaceFactory[Q <: Quotes](using quotes: Q) { private def factory: Factory = { taggedTypeFactory orElse + andOrTypeFactory orElse aliasFactory orElse higherKindedTypeFactory orElse primitiveTypeFactory orElse @@ -190,7 +191,21 @@ private[surface] class CompileTimeSurfaceFactory[Q <: Quotes](using quotes: Q) { scalaDefaultPackages.exists(p => nme.startsWith(p)) } + private def andOrTypeFactory: Factory = { + case t: AndType => + '{ IntersectionSurface(${ surfaceOf(t.left) }, ${ surfaceOf(t.right) }) } + case t: OrType => + '{ UnionSurface(${ surfaceOf(t.left) }, ${ surfaceOf(t.right) }) } + } + private def aliasFactory: Factory = { + case t if t.typeSymbol.typeRef.isOpaqueAlias => + // Treat opaque types in Scala 3 as alias types + val alias = t.typeSymbol + val inner = surfaceOf(t.dealias) + val name = Expr(alias.name) + val fullName = Expr(fullTypeNameOf(t)) + '{ Alias(${ name }, ${ fullName }, ${ inner }) } case t if t.typeSymbol.isType && t.typeSymbol.isAliasType && !belongsToScalaDefault(t) => val dealiased = t.dealias // println(s"=== alias factory: ${t}, ${dealiased}, ${t.simplified}") diff --git a/airframe-surface/src/main/scala/wvlet/airframe/surface/Surfaces.scala b/airframe-surface/src/main/scala/wvlet/airframe/surface/Surfaces.scala index d950cedf6d..10ec000917 100644 --- a/airframe-surface/src/main/scala/wvlet/airframe/surface/Surfaces.scala +++ b/airframe-surface/src/main/scala/wvlet/airframe/surface/Surfaces.scala @@ -282,6 +282,46 @@ case class TaggedSurface(base: Surface, tag: Surface) extends Surface { override def objectFactory: Option[ObjectFactory] = base.objectFactory } +/** + * Represents Scala 3 intersection types, in which the left type is the primary type. This is because applying + * intersection is difficult without knowing the application context. + * @param left + * @param right + */ +case class IntersectionSurface(left: Surface, right: Surface) extends Surface { + override def toString: String = name + override def rawType: Class[_] = left.rawType + override def typeArgs: Seq[Surface] = left.typeArgs + override def params: Seq[Parameter] = left.params + override def name: String = s"${left.name}&${right.name}" + override def fullName: String = s"${left.fullName}&${right.fullName}" + override def isOption: Boolean = left.isOption + override def isAlias: Boolean = left.isAlias + override def isPrimitive: Boolean = left.isPrimitive + override def dealias: Surface = left.dealias + override def objectFactory: Option[ObjectFactory] = left.objectFactory +} + +/** + * Represents Scala 3 union types, in which the left type is the primary type. This is because deciding which side of + * types in the union is difficult without knowing the application context. + * @param left + * @param right + */ +case class UnionSurface(left: Surface, right: Surface) extends Surface { + override def toString: String = name + override def rawType: Class[_] = left.rawType + override def typeArgs: Seq[Surface] = left.typeArgs + override def params: Seq[Parameter] = left.params + override def name: String = s"${left.name}|${right.name}" + override def fullName: String = s"${left.fullName}|${right.fullName}" + override def isOption: Boolean = left.isOption + override def isAlias: Boolean = left.isAlias + override def isPrimitive: Boolean = left.isPrimitive + override def dealias: Surface = UnionSurface(left.dealias, right.dealias) + override def objectFactory: Option[ObjectFactory] = left.objectFactory.orElse(right.objectFactory) +} + case object AnyRefSurface extends GenericSurface(classOf[AnyRef]) { override def name: String = "AnyRef" } diff --git a/airframe-surface/src/test/scala-3/wvlet/airframe/surface/IntersectionTypeTest.scala b/airframe-surface/src/test/scala-3/wvlet/airframe/surface/IntersectionTypeTest.scala new file mode 100644 index 0000000000..650c95d860 --- /dev/null +++ b/airframe-surface/src/test/scala-3/wvlet/airframe/surface/IntersectionTypeTest.scala @@ -0,0 +1,30 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package wvlet.airframe.surface +import wvlet.airspec.AirSpec + +object IntersectionTypeTest extends AirSpec: + trait Label1 + + test("support intersection type") { + // ... + val s = Surface.of[String & Label1] + s.name shouldBe "String&Label1" + s.fullName shouldBe "java.lang.String&wvlet.airframe.surface.IntersectionTypeTest.Label1" + s shouldMatch { case i: IntersectionSurface => + i.left shouldBe Surface.of[String] + i.right shouldBe Surface.of[Label1] + } + s shouldNotBe Surface.of[String] + } diff --git a/airframe-surface/src/test/scala-3/wvlet/airframe/surface/Scala3NewTypeTest.scala b/airframe-surface/src/test/scala-3/wvlet/airframe/surface/Scala3NewTypeTest.scala new file mode 100644 index 0000000000..a69baf0240 --- /dev/null +++ b/airframe-surface/src/test/scala-3/wvlet/airframe/surface/Scala3NewTypeTest.scala @@ -0,0 +1,73 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package wvlet.airframe.surface +import wvlet.airspec.AirSpec + +object Scala3NewTypeTest extends AirSpec: + trait Label1 + + test("support intersection type") { + val s = Surface.of[String & Label1] + s.name shouldBe "String&Label1" + s.fullName shouldBe "java.lang.String&wvlet.airframe.surface.Scala3NewTypeTest.Label1" + s shouldMatch { case i: IntersectionSurface => + i.left shouldBe Surface.of[String] + i.right shouldBe Surface.of[Label1] + } + s shouldNotBe Surface.of[String] + } + + test("support union type") { + val s = Surface.of[String | Label1] + s.name shouldBe "String|Label1" + s.fullName shouldBe "java.lang.String|wvlet.airframe.surface.Scala3NewTypeTest.Label1" + s shouldMatch { case i: UnionSurface => + i.left shouldBe Surface.of[String] + i.right shouldBe Surface.of[Label1] + } + s shouldNotBe Surface.of[String] + } + + opaque type MyEnv = String + + test("opaque types") { + val s = Surface.of[MyEnv] + s.name shouldBe "MyEnv" + s.fullName shouldBe "wvlet.airframe.surface.Scala3NewTypeTest.MyEnv" + s shouldNotBe Surface.of[String] + s.dealias shouldBe Surface.of[String] + } + + test("opaque type in function types") { + val s = Surface.of[MyEnv => String] + s.name shouldBe "Function1[MyEnv,String]" + } + + case class MyString(env: MyEnv) + + test("opaque type in constructor args") { + val s = Surface.of[MyString] + s.name shouldBe "MyString" + s.params(0).surface.name shouldBe "MyEnv" + } + + class A { + def hello(env: MyEnv): String = env + } + + test("opaque type in method args") { + val m = Surface.methodsOf[A].find(_.name == "hello") + m shouldBe defined + m.get.args(0).surface.name shouldBe "MyEnv" + } diff --git a/airspec/build.sbt b/airspec/build.sbt index b9fafe216e..393144d7b3 100644 --- a/airspec/build.sbt +++ b/airspec/build.sbt @@ -15,8 +15,8 @@ Global / onChangedBuildSource := ReloadOnSourceChanges val SCALA_2_12 = "2.12.18" val SCALA_2_13 = "2.13.12" -val SCALA_3_0 = "3.3.1" -val targetScalaVersions = SCALA_3_0 :: SCALA_2_13 :: SCALA_2_12 :: Nil +val SCALA_3 = "3.3.1" +val targetScalaVersions = SCALA_3 :: SCALA_2_13 :: SCALA_2_12 :: Nil val SCALACHECK_VERSION = "1.17.0" val JS_JAVA_LOGGING_VERSION = "1.0.0" diff --git a/airspec/project/plugin.sbt b/airspec/project/plugin.sbt index a79866ea2c..e9edb269e3 100755 --- a/airspec/project/plugin.sbt +++ b/airspec/project/plugin.sbt @@ -10,7 +10,7 @@ addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.11.0") addDependencyTreePlugin // For Scala.js -val SCALAJS_VERSION = sys.env.getOrElse("SCALAJS_VERSION", "1.14.0") +val SCALAJS_VERSION = sys.env.getOrElse("SCALAJS_VERSION", "1.15.0") addSbtPlugin("org.scala-js" % "sbt-scalajs" % SCALAJS_VERSION) addSbtPlugin("ch.epfl.scala" % "sbt-scalajs-bundler" % "0.21.1") libraryDependencies ++= ( diff --git a/build.sbt b/build.sbt index 2ccb4f11c1..b99158c407 100644 --- a/build.sbt +++ b/build.sbt @@ -14,7 +14,7 @@ val SCALACHECK_VERSION = "1.17.0" val MSGPACK_VERSION = "0.9.6" val SCALA_PARSER_COMBINATOR_VERSION = "2.3.0" val SQLITE_JDBC_VERSION = "3.44.1.0" -val SLF4J_VERSION = "2.0.9" +val SLF4J_VERSION = "2.0.11" val JS_JAVA_LOGGING_VERSION = "1.0.0" val JS_JAVA_TIME_VERSION = "1.0.0" val SCALAJS_DOM_VERSION = "2.8.0" diff --git a/docs/airframe-surface.md b/docs/airframe-surface.md index b9c95dbd2f..37a9e5b866 100644 --- a/docs/airframe-surface.md +++ b/docs/airframe-surface.md @@ -76,14 +76,54 @@ h.args(0).surface // Surface.of[String] ### Type alias ```scala - type UserName = String Surface.of[UserName] // Returns UserName:=String +``` + +In Scala 3, [opaque type aliases](https://docs.scala-lang.org/scala3/reference/other-new-features/opaques.html) are also supported: + +```scala +opaque type UserName = String +Surface.of[UserName] // Returns UserName:=String +``` + +Warning: In Scala 3, due to the eager type alias expansion https://github.com/wvlet/airframe/issues/2200, the surface of a type alias can be the same surface of the referenced type. If you need to differentiate the same type with different names, use intersection types. + +```scala +type UserName = String + +// In Scala 3, this function can be resolved as String => Int: +val f1 = { (x: UserName) => x.toString.length } + +// To resolve this as UserName => Int, explicitly specify the function type: +val f2: Funciton1[UserName, Int] = { (x: UserName) => x.toString.length } +``` + +### Intersection Types + +In Scala3, you can use [intersection types](https://docs.scala-lang.org/scala3/reference/new-types/intersection-types.html) for labeling types. + +For example, you can use `String & Environment` and `String & Stage` for differentiating the same type for different purposes: + +```scala +import wvlet.airframe.surface.Surface + +trait Environment +trait Stage + +Surface.of[String & Environment] +Surface.of[String & Stage] +``` + +Union type `A | B` is also supported: +```scala +import wvlet.airframe.surface.Surface +Surface.of[String | Int] ``` -### Tagged Type +### Tagged Types To have different surfaces for the same type, you can use tagged type (@@): diff --git a/examples/rpc-examples/hello-rpc/build.sbt b/examples/rpc-examples/hello-rpc/build.sbt index d97021b2c4..80aebfa73e 100644 --- a/examples/rpc-examples/hello-rpc/build.sbt +++ b/examples/rpc-examples/hello-rpc/build.sbt @@ -1,4 +1,4 @@ -val AIRFRAME_VERSION = "23.12.0" +val AIRFRAME_VERSION = "23.12.1" ThisBuild / scalaVersion := "3.2.2" // RPC API definition. This project should contain only RPC interfaces diff --git a/examples/rpc-examples/hello-rpc/project/plugins.sbt b/examples/rpc-examples/hello-rpc/project/plugins.sbt index 03e56af583..680bc8a175 100644 --- a/examples/rpc-examples/hello-rpc/project/plugins.sbt +++ b/examples/rpc-examples/hello-rpc/project/plugins.sbt @@ -1,5 +1,5 @@ ThisBuild / libraryDependencySchemes += "org.scala-lang.modules" %% "scala-xml" % "always" addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.18") -addSbtPlugin("org.wvlet.airframe" % "sbt-airframe" % "23.12.0") +addSbtPlugin("org.wvlet.airframe" % "sbt-airframe" % "23.12.1") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2") diff --git a/examples/rpc-examples/rpc-scalajs/build.sbt b/examples/rpc-examples/rpc-scalajs/build.sbt index 624e1a1f3c..0bc518407e 100644 --- a/examples/rpc-examples/rpc-scalajs/build.sbt +++ b/examples/rpc-examples/rpc-scalajs/build.sbt @@ -1,6 +1,6 @@ Global / onChangedBuildSource := ReloadOnSourceChanges -val AIRFRAME_VERSION = "23.12.0" +val AIRFRAME_VERSION = "23.12.1" ThisBuild / scalaVersion := "3.2.2" lazy val rpcExample = diff --git a/examples/rpc-examples/rpc-scalajs/project/plugins.sbt b/examples/rpc-examples/rpc-scalajs/project/plugins.sbt index e140d9af29..9e92e11d00 100644 --- a/examples/rpc-examples/rpc-scalajs/project/plugins.sbt +++ b/examples/rpc-examples/rpc-scalajs/project/plugins.sbt @@ -1,6 +1,6 @@ ThisBuild / libraryDependencySchemes += "org.scala-lang.modules" %% "scala-xml" % "always" -addSbtPlugin("org.wvlet.airframe" % "sbt-airframe" % "23.12.0") -addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.14.0") +addSbtPlugin("org.wvlet.airframe" % "sbt-airframe" % "23.12.1") +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.15.0") addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.3.2") addSbtPlugin("io.spray" % "sbt-revolver" % "0.10.0") diff --git a/examples/rx-demo/gallery/build.sbt b/examples/rx-demo/gallery/build.sbt index bbc118d875..6d30e06941 100644 --- a/examples/rx-demo/gallery/build.sbt +++ b/examples/rx-demo/gallery/build.sbt @@ -1,6 +1,6 @@ Global / onChangedBuildSource := ReloadOnSourceChanges -val AIRFRAME_VERSION = "23.12.0" +val AIRFRAME_VERSION = "23.12.1" ThisBuild / scalaVersion := "2.13.12" lazy val gallery = diff --git a/examples/rx-demo/gallery/project/plugins.sbt b/examples/rx-demo/gallery/project/plugins.sbt index 13b6c58dc5..6f4661b8a0 100644 --- a/examples/rx-demo/gallery/project/plugins.sbt +++ b/examples/rx-demo/gallery/project/plugins.sbt @@ -1,3 +1,3 @@ ThisBuild / libraryDependencySchemes += "org.scala-lang.modules" %% "scala-xml" % "always" -addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.14.0") +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.15.0") diff --git a/project/plugin.sbt b/project/plugin.sbt index e929fa72ac..8669299db5 100755 --- a/project/plugin.sbt +++ b/project/plugin.sbt @@ -17,7 +17,7 @@ addSbtPlugin("org.wvlet.airframe" % "sbt-airframe" % SBT_AIRFRAME_VERSION) addDependencyTreePlugin // For Scala.js -val SCALAJS_VERSION = sys.env.getOrElse("SCALAJS_VERSION", "1.14.0") +val SCALAJS_VERSION = sys.env.getOrElse("SCALAJS_VERSION", "1.15.0") addSbtPlugin("org.scala-js" % "sbt-scalajs" % SCALAJS_VERSION) addSbtPlugin("ch.epfl.scala" % "sbt-scalajs-bundler" % "0.21.1") libraryDependencies ++= ( @@ -28,7 +28,7 @@ libraryDependencies ++= ( addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.0.1") // Documentation -addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.5.1") +addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.5.2") // For generating Lexer/Parser from ANTLR4 grammar (.g4) addSbtPlugin("com.simplytyped" % "sbt-antlr4" % "0.8.3") diff --git a/sbt-airframe/src/sbt-test/sbt-airframe/generate-client/build.sbt b/sbt-airframe/src/sbt-test/sbt-airframe/generate-client/build.sbt index 4ed06d4e27..ad04ebfe87 100644 --- a/sbt-airframe/src/sbt-test/sbt-airframe/generate-client/build.sbt +++ b/sbt-airframe/src/sbt-test/sbt-airframe/generate-client/build.sbt @@ -5,7 +5,7 @@ ThisBuild / libraryDependencySchemes += "org.scala-lang.modules" %% "scala-parse ThisBuild / resolvers ++= Resolver.sonatypeOssRepos("snapshots") -ThisBuild / scalaVersion := "3.3.0" +ThisBuild / scalaVersion := "3.3.1" lazy val root = project.aggregate(spi, server) diff --git a/sbt-airframe/src/sbt-test/sbt-airframe/grpc/build.sbt b/sbt-airframe/src/sbt-test/sbt-airframe/grpc/build.sbt index 38b2955eb1..291a8eb6bf 100644 --- a/sbt-airframe/src/sbt-test/sbt-airframe/grpc/build.sbt +++ b/sbt-airframe/src/sbt-test/sbt-airframe/grpc/build.sbt @@ -7,9 +7,7 @@ val buildSettings: Seq[Def.Setting[_]] = Seq( libraryDependencies += "org.wvlet.airframe" %% "airspec" % AIRSPEC_VERSION % Test ) ThisBuild / resolvers ++= Resolver.sonatypeOssRepos("snapshots") -// TODO: To use Scala 3, https://github.com/wvlet/airframe/issues/2883 needs to be fixed -ThisBuild / scalaVersion := "3.3.0" -// ThisBuild / crossScalaVersions := Seq("2.13.12", "3.2.2") +ThisBuild / scalaVersion := "3.3.1" lazy val root = project diff --git a/sbt-airframe/src/sbt-test/sbt-airframe/js-client/build.sbt b/sbt-airframe/src/sbt-test/sbt-airframe/js-client/build.sbt index 478d92c4b5..91fa9df229 100644 --- a/sbt-airframe/src/sbt-test/sbt-airframe/js-client/build.sbt +++ b/sbt-airframe/src/sbt-test/sbt-airframe/js-client/build.sbt @@ -1,6 +1,6 @@ ThisBuild / resolvers ++= Resolver.sonatypeOssRepos("snapshots") -ThisBuild / scalaVersion := "3.3.0" +ThisBuild / scalaVersion := "3.3.1" lazy val root = project.aggregate(spi.js, client.js) @@ -24,7 +24,7 @@ lazy val client = ) .jsSettings( libraryDependencies ++= Seq( - "org.scala-js" %%% "scalajs-dom" % "2.1.0" + "org.scala-js" %%% "scalajs-dom" % "2.8.0" ) ) .dependsOn(spi) diff --git a/sbt-airframe/src/sbt-test/sbt-airframe/js-client/project/plugins.sbt b/sbt-airframe/src/sbt-test/sbt-airframe/js-client/project/plugins.sbt index ec5bf61b75..5a67726399 100644 --- a/sbt-airframe/src/sbt-test/sbt-airframe/js-client/project/plugins.sbt +++ b/sbt-airframe/src/sbt-test/sbt-airframe/js-client/project/plugins.sbt @@ -7,5 +7,5 @@ sys.props.get("plugin.version") match { // For Scala.js addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.3.2") -val SCALAJS_VERSION = sys.env.getOrElse("SCALAJS_VERSION", "1.14.0") +val SCALAJS_VERSION = sys.env.getOrElse("SCALAJS_VERSION", "1.15.0") addSbtPlugin("org.scala-js" % "sbt-scalajs" % SCALAJS_VERSION) diff --git a/sbt-airframe/src/sbt-test/sbt-airframe/openapi/build.sbt b/sbt-airframe/src/sbt-test/sbt-airframe/openapi/build.sbt index e0f69945e9..0d8655eff4 100644 --- a/sbt-airframe/src/sbt-test/sbt-airframe/openapi/build.sbt +++ b/sbt-airframe/src/sbt-test/sbt-airframe/openapi/build.sbt @@ -5,7 +5,7 @@ enablePlugins(AirframeHttpPlugin) name := "Open API Test" version := "1.0.0" -ThisBuild / scalaVersion := "3.3.0" +ThisBuild / scalaVersion := "3.3.1" airframeHttpOpenAPIPackages := Seq("example.api") airframeHttpOpts := "-l debug" diff --git a/sbt-airframe/src/sbt-test/sbt-airframe/rpc-netty/build.sbt b/sbt-airframe/src/sbt-test/sbt-airframe/rpc-netty/build.sbt index 46c2db47a1..97a3bdbc83 100644 --- a/sbt-airframe/src/sbt-test/sbt-airframe/rpc-netty/build.sbt +++ b/sbt-airframe/src/sbt-test/sbt-airframe/rpc-netty/build.sbt @@ -12,7 +12,7 @@ val buildSettings: Seq[Def.Setting[_]] = Seq( libraryDependencies += "org.wvlet.airframe" %% "airspec" % AIRSPEC_VERSION % Test ) -ThisBuild / scalaVersion := "3.3.0" +ThisBuild / scalaVersion := "3.3.1" lazy val root = project.aggregate(api, server)