diff --git a/.gitignore b/.gitignore index 78d8c364..474829f0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .idea **/*.iml **/target/ +.bsp/ release.properties pom.xml.releaseBackup pom.xml.versionsBackup diff --git a/.scalafmt.conf b/.scalafmt.conf index 2cd3edd9..40946f06 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,3 +1,5 @@ version = 2.7.5 -preset=default \ No newline at end of file +preset=default + +runner.dialect = dotty \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index bc4a8007..e1d6d5d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ See also the [CHANGELOG](https://github.com/cucumber/cucumber-jvm/blob/master/CH ### Added +- [Scala] Support Scala 3 RC1 + - Check out the [v7.x upgrade guide](./docs/upgrade_v7.md) + ### Changed - [Build] Use Github Actions instead of Travis CI diff --git a/README.md b/README.md index 57ae4921..b8c9c609 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ The minor version might differ because Cucumber Scala may add Scala-related feat - [Installation](./docs/install.md) - Upgrade notes + - [Version 7.x](docs/upgrade_v7.md) - [Version 6.x](docs/upgrade_v6.md) - [Version 5.x](docs/upgrade_v5.md) - Documentation diff --git a/build.sbt b/build.sbt index 82053069..987760e1 100644 --- a/build.sbt +++ b/build.sbt @@ -33,6 +33,7 @@ ThisBuild / homepage := Some( val scala211 = "2.11.12" val scala212 = "2.12.13" val scala213 = "2.13.5" +val scala3 = "3.0.0-RC1" scalaVersion := scala213 @@ -52,6 +53,7 @@ lazy val commonSettings = Seq( case Some((2, 11)) => ScalacOptions.scalacOptions211 case Some((2, 12)) => ScalacOptions.scalacOptions212 case Some((2, 13)) => ScalacOptions.scalacOptions213 + case Some((3, 0)) => ScalacOptions.scalacOptions3 case _ => Seq() } } @@ -75,23 +77,44 @@ lazy val cucumberScala = (projectMatrix in file("cucumber-scala")) libraryDependencies ++= Seq( "io.cucumber" % "cucumber-core" % cucumberVersion, // Users have to provide it (for JacksonDefaultDataTableTransformer) - "com.fasterxml.jackson.module" %% "jackson-module-scala" % jacksonVersion % Provided, + ("com.fasterxml.jackson.module" %% "jackson-module-scala" % jacksonVersion % Provided) + .withDottyCompat(scalaVersion.value), "junit" % "junit" % junitVersion % Test, "io.cucumber" % "cucumber-junit" % cucumberVersion % Test, - "org.mockito" %% "mockito-scala" % mockitoScalaVersion % Test + ("org.mockito" %% "mockito-scala" % mockitoScalaVersion % Test) + .withDottyCompat(scalaVersion.value) ), libraryDependencies ++= { CrossVersion.partialVersion(scalaVersion.value) match { case Some((2, n)) if n <= 12 => List("org.scala-lang.modules" %% "scala-collection-compat" % "2.4.2") + case Some((3, 0)) => + List("io.github.gaeljw" %% "typetrees" % "0.2.0") case _ => Nil } }, unmanagedSourceDirectories in Compile ++= { val sourceDir = (sourceDirectory in Compile).value CrossVersion.partialVersion(scalaVersion.value) match { - case Some((2, n)) if n <= 11 => Seq(sourceDir / "scala-2.11") - case _ => Seq() + case Some((2, n)) if n <= 11 => + Seq(sourceDir / "scala-2", sourceDir / "scala-2.11") + case Some((2, n)) if n > 11 => + Seq(sourceDir / "scala-2") + case Some((3, 0)) => + Seq(sourceDir / "scala-3") + case _ => + Seq() + } + }, + unmanagedSourceDirectories in Test ++= { + val testSourceDir = (sourceDirectory in Test).value + CrossVersion.partialVersion(scalaVersion.value) match { + case Some((2, _)) => + Seq(testSourceDir / "scala-2") + case Some((3, 0)) => + Seq(testSourceDir / "scala-3") + case _ => + Seq() } }, // Generate I18n traits @@ -102,7 +125,7 @@ lazy val cucumberScala = (projectMatrix in file("cucumber-scala")) Seq(file) }.taskValue ) - .jvmPlatform(scalaVersions = Seq(scala213, scala212, scala211)) + .jvmPlatform(scalaVersions = Seq(scala3, scala213, scala212, scala211)) // Examples project lazy val examples = (projectMatrix in file("examples")) @@ -116,7 +139,7 @@ lazy val examples = (projectMatrix in file("examples")) publishArtifact := false ) .dependsOn(cucumberScala % Test) - .jvmPlatform(scalaVersions = Seq(scala213, scala212)) + .jvmPlatform(scalaVersions = Seq(scala3, scala213, scala212)) // Version policy check diff --git a/cucumber-scala/src/main/codegen/gen.scala b/cucumber-scala/src/main/codegen/gen.scala index 8e95536d..d67d9e3e 100644 --- a/cucumber-scala/src/main/codegen/gen.scala +++ b/cucumber-scala/src/main/codegen/gen.scala @@ -1,6 +1,6 @@ /* - * Generates the evil looking apply methods in ScalaDsl#StepBody for Function1 to Function22 + * Generates the evil looking apply methods in StepDsl#StepBody for Function1 to Function22 */ for (i <- 1 to 22) { val ts = (1 to i).map("T".+).mkString(", ") @@ -15,6 +15,29 @@ for (i <- 1 to 22) { println(p1 + p2 + ": Unit = { " + register + pf + otherwise + closeRegister + "\n") } +/* + * Generates the evil looking apply methods in StepDsl#StepBody for Function1 to Function22 + * Scala 3 + */ +for (i <- 1 to 22) { + val ts = (1 to i).map("T".+).mkString(", ") + val tagsDef = (1 to i).map(n => s"val t$n: TypeTreeTag = typeTreeTag[T$n]").mkString("\n") + val tagsParam = (1 to i).map(n => s"t$n").mkString(", ") + val listParams = (1 to i).map("a" + _ + ":AnyRef").mkString(", ") + val pf = (1 to i).map(n => "a" + n + ".asInstanceOf[T" + n + "]").mkString(",\n ") + + println(s""" + |inline def apply[$ts](f: ($ts) => Any): Unit = { + | $tagsDef + | register($tagsParam) { + | case List($listParams) => + | f($pf) + | case _ => + | throw new IncorrectStepDefinitionException() + | } + |}""".stripMargin) +} + /* * Generates the apply methods in ParameterTypeDsl for Function1 to Function22 */ diff --git a/cucumber-scala/src/main/scala/io/cucumber/scala/ScalaTypeHelper.scala b/cucumber-scala/src/main/scala-2/io/cucumber/scala/ScalaTypeHelper.scala similarity index 100% rename from cucumber-scala/src/main/scala/io/cucumber/scala/ScalaTypeHelper.scala rename to cucumber-scala/src/main/scala-2/io/cucumber/scala/ScalaTypeHelper.scala diff --git a/cucumber-scala/src/main/scala/io/cucumber/scala/StepDsl.scala b/cucumber-scala/src/main/scala-2/io/cucumber/scala/StepDsl.scala similarity index 100% rename from cucumber-scala/src/main/scala/io/cucumber/scala/StepDsl.scala rename to cucumber-scala/src/main/scala-2/io/cucumber/scala/StepDsl.scala diff --git a/cucumber-scala/src/main/scala-3/io/cucumber/scala/ScalaTypeHelper.scala b/cucumber-scala/src/main/scala-3/io/cucumber/scala/ScalaTypeHelper.scala new file mode 100644 index 00000000..71daf762 --- /dev/null +++ b/cucumber-scala/src/main/scala-3/io/cucumber/scala/ScalaTypeHelper.scala @@ -0,0 +1,27 @@ +package io.cucumber.scala + +import io.github.gaeljw.typetrees.TypeTreeTag +import java.lang.reflect.{ParameterizedType, Type} + +object ScalaTypeHelper { + + def asJavaType(tag: TypeTreeTag): Type = { + if (tag.args.isEmpty) { + tag.self.runtimeClass + } else { + new ScalaParameterizedType(tag) + } + } + +} + +class ScalaParameterizedType(tag: TypeTreeTag) extends ParameterizedType { + + override def getActualTypeArguments: Array[Type] = + tag.args.map(ScalaTypeHelper.asJavaType).toArray + + override def getRawType: Type = tag.self.runtimeClass + + override def getOwnerType: Type = null + +} diff --git a/cucumber-scala/src/main/scala-3/io/cucumber/scala/StepDsl.scala b/cucumber-scala/src/main/scala-3/io/cucumber/scala/StepDsl.scala new file mode 100644 index 00000000..3a94189e --- /dev/null +++ b/cucumber-scala/src/main/scala-3/io/cucumber/scala/StepDsl.scala @@ -0,0 +1,1539 @@ +package io.cucumber.scala + +import io.github.gaeljw.typetrees.TypeTreeTag +import io.github.gaeljw.typetrees.TypeTreeTagMacros.typeTreeTag + +import scala.annotation.targetName + +private[scala] trait StepDsl extends BaseScalaDsl { + self => + + final class Step(name: String) { + def apply(regex: String): StepBody = new StepBody(name, regex) + } + + final class StepBody(name: String, regex: String) { + + inline def apply(f: => Any): Unit = { + register() { + case Nil => f + case _ => + throw new IncorrectStepDefinitionException() + } + } + + @targetName("apply_function0") + inline def apply(fun: () => Any): Unit = { + register() { + case Nil => fun.apply() + case _ => + throw new IncorrectStepDefinitionException() + } + } + + /* + * Generated apply1 to apply22 below + */ + inline def apply[T1](f: (T1) => Any): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + register(t1) { + case List(a1: AnyRef) => + f(a1.asInstanceOf[T1]) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + inline def apply[T1, T2](f: (T1, T2) => Any): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + val t2: TypeTreeTag = typeTreeTag[T2] + register(t1, t2) { + case List(a1: AnyRef, a2: AnyRef) => + f(a1.asInstanceOf[T1], a2.asInstanceOf[T2]) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + inline def apply[T1, T2, T3](f: (T1, T2, T3) => Any): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + val t2: TypeTreeTag = typeTreeTag[T2] + val t3: TypeTreeTag = typeTreeTag[T3] + register(t1, t2, t3) { + case List(a1: AnyRef, a2: AnyRef, a3: AnyRef) => + f(a1.asInstanceOf[T1], a2.asInstanceOf[T2], a3.asInstanceOf[T3]) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + inline def apply[T1, T2, T3, T4](f: (T1, T2, T3, T4) => Any): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + val t2: TypeTreeTag = typeTreeTag[T2] + val t3: TypeTreeTag = typeTreeTag[T3] + val t4: TypeTreeTag = typeTreeTag[T4] + register(t1, t2, t3, t4) { + case List(a1: AnyRef, a2: AnyRef, a3: AnyRef, a4: AnyRef) => + f( + a1.asInstanceOf[T1], + a2.asInstanceOf[T2], + a3.asInstanceOf[T3], + a4.asInstanceOf[T4] + ) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + inline def apply[T1, T2, T3, T4, T5]( + f: (T1, T2, T3, T4, T5) => Any + ): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + val t2: TypeTreeTag = typeTreeTag[T2] + val t3: TypeTreeTag = typeTreeTag[T3] + val t4: TypeTreeTag = typeTreeTag[T4] + val t5: TypeTreeTag = typeTreeTag[T5] + register(t1, t2, t3, t4, t5) { + case List(a1: AnyRef, a2: AnyRef, a3: AnyRef, a4: AnyRef, a5: AnyRef) => + f( + a1.asInstanceOf[T1], + a2.asInstanceOf[T2], + a3.asInstanceOf[T3], + a4.asInstanceOf[T4], + a5.asInstanceOf[T5] + ) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + inline def apply[T1, T2, T3, T4, T5, T6]( + f: (T1, T2, T3, T4, T5, T6) => Any + ): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + val t2: TypeTreeTag = typeTreeTag[T2] + val t3: TypeTreeTag = typeTreeTag[T3] + val t4: TypeTreeTag = typeTreeTag[T4] + val t5: TypeTreeTag = typeTreeTag[T5] + val t6: TypeTreeTag = typeTreeTag[T6] + register(t1, t2, t3, t4, t5, t6) { + case List( + a1: AnyRef, + a2: AnyRef, + a3: AnyRef, + a4: AnyRef, + a5: AnyRef, + a6: AnyRef + ) => + f( + a1.asInstanceOf[T1], + a2.asInstanceOf[T2], + a3.asInstanceOf[T3], + a4.asInstanceOf[T4], + a5.asInstanceOf[T5], + a6.asInstanceOf[T6] + ) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + inline def apply[T1, T2, T3, T4, T5, T6, T7]( + f: (T1, T2, T3, T4, T5, T6, T7) => Any + ): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + val t2: TypeTreeTag = typeTreeTag[T2] + val t3: TypeTreeTag = typeTreeTag[T3] + val t4: TypeTreeTag = typeTreeTag[T4] + val t5: TypeTreeTag = typeTreeTag[T5] + val t6: TypeTreeTag = typeTreeTag[T6] + val t7: TypeTreeTag = typeTreeTag[T7] + register(t1, t2, t3, t4, t5, t6, t7) { + case List( + a1: AnyRef, + a2: AnyRef, + a3: AnyRef, + a4: AnyRef, + a5: AnyRef, + a6: AnyRef, + a7: AnyRef + ) => + f( + a1.asInstanceOf[T1], + a2.asInstanceOf[T2], + a3.asInstanceOf[T3], + a4.asInstanceOf[T4], + a5.asInstanceOf[T5], + a6.asInstanceOf[T6], + a7.asInstanceOf[T7] + ) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + inline def apply[T1, T2, T3, T4, T5, T6, T7, T8]( + f: (T1, T2, T3, T4, T5, T6, T7, T8) => Any + ): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + val t2: TypeTreeTag = typeTreeTag[T2] + val t3: TypeTreeTag = typeTreeTag[T3] + val t4: TypeTreeTag = typeTreeTag[T4] + val t5: TypeTreeTag = typeTreeTag[T5] + val t6: TypeTreeTag = typeTreeTag[T6] + val t7: TypeTreeTag = typeTreeTag[T7] + val t8: TypeTreeTag = typeTreeTag[T8] + register(t1, t2, t3, t4, t5, t6, t7, t8) { + case List( + a1: AnyRef, + a2: AnyRef, + a3: AnyRef, + a4: AnyRef, + a5: AnyRef, + a6: AnyRef, + a7: AnyRef, + a8: AnyRef + ) => + f( + a1.asInstanceOf[T1], + a2.asInstanceOf[T2], + a3.asInstanceOf[T3], + a4.asInstanceOf[T4], + a5.asInstanceOf[T5], + a6.asInstanceOf[T6], + a7.asInstanceOf[T7], + a8.asInstanceOf[T8] + ) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + inline def apply[T1, T2, T3, T4, T5, T6, T7, T8, T9]( + f: (T1, T2, T3, T4, T5, T6, T7, T8, T9) => Any + ): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + val t2: TypeTreeTag = typeTreeTag[T2] + val t3: TypeTreeTag = typeTreeTag[T3] + val t4: TypeTreeTag = typeTreeTag[T4] + val t5: TypeTreeTag = typeTreeTag[T5] + val t6: TypeTreeTag = typeTreeTag[T6] + val t7: TypeTreeTag = typeTreeTag[T7] + val t8: TypeTreeTag = typeTreeTag[T8] + val t9: TypeTreeTag = typeTreeTag[T9] + register(t1, t2, t3, t4, t5, t6, t7, t8, t9) { + case List( + a1: AnyRef, + a2: AnyRef, + a3: AnyRef, + a4: AnyRef, + a5: AnyRef, + a6: AnyRef, + a7: AnyRef, + a8: AnyRef, + a9: AnyRef + ) => + f( + a1.asInstanceOf[T1], + a2.asInstanceOf[T2], + a3.asInstanceOf[T3], + a4.asInstanceOf[T4], + a5.asInstanceOf[T5], + a6.asInstanceOf[T6], + a7.asInstanceOf[T7], + a8.asInstanceOf[T8], + a9.asInstanceOf[T9] + ) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + inline def apply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]( + f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) => Any + ): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + val t2: TypeTreeTag = typeTreeTag[T2] + val t3: TypeTreeTag = typeTreeTag[T3] + val t4: TypeTreeTag = typeTreeTag[T4] + val t5: TypeTreeTag = typeTreeTag[T5] + val t6: TypeTreeTag = typeTreeTag[T6] + val t7: TypeTreeTag = typeTreeTag[T7] + val t8: TypeTreeTag = typeTreeTag[T8] + val t9: TypeTreeTag = typeTreeTag[T9] + val t10: TypeTreeTag = typeTreeTag[T10] + register(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) { + case List( + a1: AnyRef, + a2: AnyRef, + a3: AnyRef, + a4: AnyRef, + a5: AnyRef, + a6: AnyRef, + a7: AnyRef, + a8: AnyRef, + a9: AnyRef, + a10: AnyRef + ) => + f( + a1.asInstanceOf[T1], + a2.asInstanceOf[T2], + a3.asInstanceOf[T3], + a4.asInstanceOf[T4], + a5.asInstanceOf[T5], + a6.asInstanceOf[T6], + a7.asInstanceOf[T7], + a8.asInstanceOf[T8], + a9.asInstanceOf[T9], + a10.asInstanceOf[T10] + ) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + inline def apply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]( + f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) => Any + ): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + val t2: TypeTreeTag = typeTreeTag[T2] + val t3: TypeTreeTag = typeTreeTag[T3] + val t4: TypeTreeTag = typeTreeTag[T4] + val t5: TypeTreeTag = typeTreeTag[T5] + val t6: TypeTreeTag = typeTreeTag[T6] + val t7: TypeTreeTag = typeTreeTag[T7] + val t8: TypeTreeTag = typeTreeTag[T8] + val t9: TypeTreeTag = typeTreeTag[T9] + val t10: TypeTreeTag = typeTreeTag[T10] + val t11: TypeTreeTag = typeTreeTag[T11] + register(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11) { + case List( + a1: AnyRef, + a2: AnyRef, + a3: AnyRef, + a4: AnyRef, + a5: AnyRef, + a6: AnyRef, + a7: AnyRef, + a8: AnyRef, + a9: AnyRef, + a10: AnyRef, + a11: AnyRef + ) => + f( + a1.asInstanceOf[T1], + a2.asInstanceOf[T2], + a3.asInstanceOf[T3], + a4.asInstanceOf[T4], + a5.asInstanceOf[T5], + a6.asInstanceOf[T6], + a7.asInstanceOf[T7], + a8.asInstanceOf[T8], + a9.asInstanceOf[T9], + a10.asInstanceOf[T10], + a11.asInstanceOf[T11] + ) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + inline def apply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]( + f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) => Any + ): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + val t2: TypeTreeTag = typeTreeTag[T2] + val t3: TypeTreeTag = typeTreeTag[T3] + val t4: TypeTreeTag = typeTreeTag[T4] + val t5: TypeTreeTag = typeTreeTag[T5] + val t6: TypeTreeTag = typeTreeTag[T6] + val t7: TypeTreeTag = typeTreeTag[T7] + val t8: TypeTreeTag = typeTreeTag[T8] + val t9: TypeTreeTag = typeTreeTag[T9] + val t10: TypeTreeTag = typeTreeTag[T10] + val t11: TypeTreeTag = typeTreeTag[T11] + val t12: TypeTreeTag = typeTreeTag[T12] + register(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12) { + case List( + a1: AnyRef, + a2: AnyRef, + a3: AnyRef, + a4: AnyRef, + a5: AnyRef, + a6: AnyRef, + a7: AnyRef, + a8: AnyRef, + a9: AnyRef, + a10: AnyRef, + a11: AnyRef, + a12: AnyRef + ) => + f( + a1.asInstanceOf[T1], + a2.asInstanceOf[T2], + a3.asInstanceOf[T3], + a4.asInstanceOf[T4], + a5.asInstanceOf[T5], + a6.asInstanceOf[T6], + a7.asInstanceOf[T7], + a8.asInstanceOf[T8], + a9.asInstanceOf[T9], + a10.asInstanceOf[T10], + a11.asInstanceOf[T11], + a12.asInstanceOf[T12] + ) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + inline def apply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]( + f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) => Any + ): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + val t2: TypeTreeTag = typeTreeTag[T2] + val t3: TypeTreeTag = typeTreeTag[T3] + val t4: TypeTreeTag = typeTreeTag[T4] + val t5: TypeTreeTag = typeTreeTag[T5] + val t6: TypeTreeTag = typeTreeTag[T6] + val t7: TypeTreeTag = typeTreeTag[T7] + val t8: TypeTreeTag = typeTreeTag[T8] + val t9: TypeTreeTag = typeTreeTag[T9] + val t10: TypeTreeTag = typeTreeTag[T10] + val t11: TypeTreeTag = typeTreeTag[T11] + val t12: TypeTreeTag = typeTreeTag[T12] + val t13: TypeTreeTag = typeTreeTag[T13] + register(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13) { + case List( + a1: AnyRef, + a2: AnyRef, + a3: AnyRef, + a4: AnyRef, + a5: AnyRef, + a6: AnyRef, + a7: AnyRef, + a8: AnyRef, + a9: AnyRef, + a10: AnyRef, + a11: AnyRef, + a12: AnyRef, + a13: AnyRef + ) => + f( + a1.asInstanceOf[T1], + a2.asInstanceOf[T2], + a3.asInstanceOf[T3], + a4.asInstanceOf[T4], + a5.asInstanceOf[T5], + a6.asInstanceOf[T6], + a7.asInstanceOf[T7], + a8.asInstanceOf[T8], + a9.asInstanceOf[T9], + a10.asInstanceOf[T10], + a11.asInstanceOf[T11], + a12.asInstanceOf[T12], + a13.asInstanceOf[T13] + ) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + inline def apply[ + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14 + ]( + f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) => Any + ): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + val t2: TypeTreeTag = typeTreeTag[T2] + val t3: TypeTreeTag = typeTreeTag[T3] + val t4: TypeTreeTag = typeTreeTag[T4] + val t5: TypeTreeTag = typeTreeTag[T5] + val t6: TypeTreeTag = typeTreeTag[T6] + val t7: TypeTreeTag = typeTreeTag[T7] + val t8: TypeTreeTag = typeTreeTag[T8] + val t9: TypeTreeTag = typeTreeTag[T9] + val t10: TypeTreeTag = typeTreeTag[T10] + val t11: TypeTreeTag = typeTreeTag[T11] + val t12: TypeTreeTag = typeTreeTag[T12] + val t13: TypeTreeTag = typeTreeTag[T13] + val t14: TypeTreeTag = typeTreeTag[T14] + register(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14) { + case List( + a1: AnyRef, + a2: AnyRef, + a3: AnyRef, + a4: AnyRef, + a5: AnyRef, + a6: AnyRef, + a7: AnyRef, + a8: AnyRef, + a9: AnyRef, + a10: AnyRef, + a11: AnyRef, + a12: AnyRef, + a13: AnyRef, + a14: AnyRef + ) => + f( + a1.asInstanceOf[T1], + a2.asInstanceOf[T2], + a3.asInstanceOf[T3], + a4.asInstanceOf[T4], + a5.asInstanceOf[T5], + a6.asInstanceOf[T6], + a7.asInstanceOf[T7], + a8.asInstanceOf[T8], + a9.asInstanceOf[T9], + a10.asInstanceOf[T10], + a11.asInstanceOf[T11], + a12.asInstanceOf[T12], + a13.asInstanceOf[T13], + a14.asInstanceOf[T14] + ) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + inline def apply[ + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15 + ]( + f: ( + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15 + ) => Any + ): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + val t2: TypeTreeTag = typeTreeTag[T2] + val t3: TypeTreeTag = typeTreeTag[T3] + val t4: TypeTreeTag = typeTreeTag[T4] + val t5: TypeTreeTag = typeTreeTag[T5] + val t6: TypeTreeTag = typeTreeTag[T6] + val t7: TypeTreeTag = typeTreeTag[T7] + val t8: TypeTreeTag = typeTreeTag[T8] + val t9: TypeTreeTag = typeTreeTag[T9] + val t10: TypeTreeTag = typeTreeTag[T10] + val t11: TypeTreeTag = typeTreeTag[T11] + val t12: TypeTreeTag = typeTreeTag[T12] + val t13: TypeTreeTag = typeTreeTag[T13] + val t14: TypeTreeTag = typeTreeTag[T14] + val t15: TypeTreeTag = typeTreeTag[T15] + register( + t1, + t2, + t3, + t4, + t5, + t6, + t7, + t8, + t9, + t10, + t11, + t12, + t13, + t14, + t15 + ) { + case List( + a1: AnyRef, + a2: AnyRef, + a3: AnyRef, + a4: AnyRef, + a5: AnyRef, + a6: AnyRef, + a7: AnyRef, + a8: AnyRef, + a9: AnyRef, + a10: AnyRef, + a11: AnyRef, + a12: AnyRef, + a13: AnyRef, + a14: AnyRef, + a15: AnyRef + ) => + f( + a1.asInstanceOf[T1], + a2.asInstanceOf[T2], + a3.asInstanceOf[T3], + a4.asInstanceOf[T4], + a5.asInstanceOf[T5], + a6.asInstanceOf[T6], + a7.asInstanceOf[T7], + a8.asInstanceOf[T8], + a9.asInstanceOf[T9], + a10.asInstanceOf[T10], + a11.asInstanceOf[T11], + a12.asInstanceOf[T12], + a13.asInstanceOf[T13], + a14.asInstanceOf[T14], + a15.asInstanceOf[T15] + ) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + inline def apply[ + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16 + ]( + f: ( + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16 + ) => Any + ): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + val t2: TypeTreeTag = typeTreeTag[T2] + val t3: TypeTreeTag = typeTreeTag[T3] + val t4: TypeTreeTag = typeTreeTag[T4] + val t5: TypeTreeTag = typeTreeTag[T5] + val t6: TypeTreeTag = typeTreeTag[T6] + val t7: TypeTreeTag = typeTreeTag[T7] + val t8: TypeTreeTag = typeTreeTag[T8] + val t9: TypeTreeTag = typeTreeTag[T9] + val t10: TypeTreeTag = typeTreeTag[T10] + val t11: TypeTreeTag = typeTreeTag[T11] + val t12: TypeTreeTag = typeTreeTag[T12] + val t13: TypeTreeTag = typeTreeTag[T13] + val t14: TypeTreeTag = typeTreeTag[T14] + val t15: TypeTreeTag = typeTreeTag[T15] + val t16: TypeTreeTag = typeTreeTag[T16] + register( + t1, + t2, + t3, + t4, + t5, + t6, + t7, + t8, + t9, + t10, + t11, + t12, + t13, + t14, + t15, + t16 + ) { + case List( + a1: AnyRef, + a2: AnyRef, + a3: AnyRef, + a4: AnyRef, + a5: AnyRef, + a6: AnyRef, + a7: AnyRef, + a8: AnyRef, + a9: AnyRef, + a10: AnyRef, + a11: AnyRef, + a12: AnyRef, + a13: AnyRef, + a14: AnyRef, + a15: AnyRef, + a16: AnyRef + ) => + f( + a1.asInstanceOf[T1], + a2.asInstanceOf[T2], + a3.asInstanceOf[T3], + a4.asInstanceOf[T4], + a5.asInstanceOf[T5], + a6.asInstanceOf[T6], + a7.asInstanceOf[T7], + a8.asInstanceOf[T8], + a9.asInstanceOf[T9], + a10.asInstanceOf[T10], + a11.asInstanceOf[T11], + a12.asInstanceOf[T12], + a13.asInstanceOf[T13], + a14.asInstanceOf[T14], + a15.asInstanceOf[T15], + a16.asInstanceOf[T16] + ) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + inline def apply[ + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17 + ]( + f: ( + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17 + ) => Any + ): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + val t2: TypeTreeTag = typeTreeTag[T2] + val t3: TypeTreeTag = typeTreeTag[T3] + val t4: TypeTreeTag = typeTreeTag[T4] + val t5: TypeTreeTag = typeTreeTag[T5] + val t6: TypeTreeTag = typeTreeTag[T6] + val t7: TypeTreeTag = typeTreeTag[T7] + val t8: TypeTreeTag = typeTreeTag[T8] + val t9: TypeTreeTag = typeTreeTag[T9] + val t10: TypeTreeTag = typeTreeTag[T10] + val t11: TypeTreeTag = typeTreeTag[T11] + val t12: TypeTreeTag = typeTreeTag[T12] + val t13: TypeTreeTag = typeTreeTag[T13] + val t14: TypeTreeTag = typeTreeTag[T14] + val t15: TypeTreeTag = typeTreeTag[T15] + val t16: TypeTreeTag = typeTreeTag[T16] + val t17: TypeTreeTag = typeTreeTag[T17] + register( + t1, + t2, + t3, + t4, + t5, + t6, + t7, + t8, + t9, + t10, + t11, + t12, + t13, + t14, + t15, + t16, + t17 + ) { + case List( + a1: AnyRef, + a2: AnyRef, + a3: AnyRef, + a4: AnyRef, + a5: AnyRef, + a6: AnyRef, + a7: AnyRef, + a8: AnyRef, + a9: AnyRef, + a10: AnyRef, + a11: AnyRef, + a12: AnyRef, + a13: AnyRef, + a14: AnyRef, + a15: AnyRef, + a16: AnyRef, + a17: AnyRef + ) => + f( + a1.asInstanceOf[T1], + a2.asInstanceOf[T2], + a3.asInstanceOf[T3], + a4.asInstanceOf[T4], + a5.asInstanceOf[T5], + a6.asInstanceOf[T6], + a7.asInstanceOf[T7], + a8.asInstanceOf[T8], + a9.asInstanceOf[T9], + a10.asInstanceOf[T10], + a11.asInstanceOf[T11], + a12.asInstanceOf[T12], + a13.asInstanceOf[T13], + a14.asInstanceOf[T14], + a15.asInstanceOf[T15], + a16.asInstanceOf[T16], + a17.asInstanceOf[T17] + ) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + inline def apply[ + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18 + ]( + f: ( + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18 + ) => Any + ): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + val t2: TypeTreeTag = typeTreeTag[T2] + val t3: TypeTreeTag = typeTreeTag[T3] + val t4: TypeTreeTag = typeTreeTag[T4] + val t5: TypeTreeTag = typeTreeTag[T5] + val t6: TypeTreeTag = typeTreeTag[T6] + val t7: TypeTreeTag = typeTreeTag[T7] + val t8: TypeTreeTag = typeTreeTag[T8] + val t9: TypeTreeTag = typeTreeTag[T9] + val t10: TypeTreeTag = typeTreeTag[T10] + val t11: TypeTreeTag = typeTreeTag[T11] + val t12: TypeTreeTag = typeTreeTag[T12] + val t13: TypeTreeTag = typeTreeTag[T13] + val t14: TypeTreeTag = typeTreeTag[T14] + val t15: TypeTreeTag = typeTreeTag[T15] + val t16: TypeTreeTag = typeTreeTag[T16] + val t17: TypeTreeTag = typeTreeTag[T17] + val t18: TypeTreeTag = typeTreeTag[T18] + register( + t1, + t2, + t3, + t4, + t5, + t6, + t7, + t8, + t9, + t10, + t11, + t12, + t13, + t14, + t15, + t16, + t17, + t18 + ) { + case List( + a1: AnyRef, + a2: AnyRef, + a3: AnyRef, + a4: AnyRef, + a5: AnyRef, + a6: AnyRef, + a7: AnyRef, + a8: AnyRef, + a9: AnyRef, + a10: AnyRef, + a11: AnyRef, + a12: AnyRef, + a13: AnyRef, + a14: AnyRef, + a15: AnyRef, + a16: AnyRef, + a17: AnyRef, + a18: AnyRef + ) => + f( + a1.asInstanceOf[T1], + a2.asInstanceOf[T2], + a3.asInstanceOf[T3], + a4.asInstanceOf[T4], + a5.asInstanceOf[T5], + a6.asInstanceOf[T6], + a7.asInstanceOf[T7], + a8.asInstanceOf[T8], + a9.asInstanceOf[T9], + a10.asInstanceOf[T10], + a11.asInstanceOf[T11], + a12.asInstanceOf[T12], + a13.asInstanceOf[T13], + a14.asInstanceOf[T14], + a15.asInstanceOf[T15], + a16.asInstanceOf[T16], + a17.asInstanceOf[T17], + a18.asInstanceOf[T18] + ) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + inline def apply[ + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19 + ]( + f: ( + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19 + ) => Any + ): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + val t2: TypeTreeTag = typeTreeTag[T2] + val t3: TypeTreeTag = typeTreeTag[T3] + val t4: TypeTreeTag = typeTreeTag[T4] + val t5: TypeTreeTag = typeTreeTag[T5] + val t6: TypeTreeTag = typeTreeTag[T6] + val t7: TypeTreeTag = typeTreeTag[T7] + val t8: TypeTreeTag = typeTreeTag[T8] + val t9: TypeTreeTag = typeTreeTag[T9] + val t10: TypeTreeTag = typeTreeTag[T10] + val t11: TypeTreeTag = typeTreeTag[T11] + val t12: TypeTreeTag = typeTreeTag[T12] + val t13: TypeTreeTag = typeTreeTag[T13] + val t14: TypeTreeTag = typeTreeTag[T14] + val t15: TypeTreeTag = typeTreeTag[T15] + val t16: TypeTreeTag = typeTreeTag[T16] + val t17: TypeTreeTag = typeTreeTag[T17] + val t18: TypeTreeTag = typeTreeTag[T18] + val t19: TypeTreeTag = typeTreeTag[T19] + register( + t1, + t2, + t3, + t4, + t5, + t6, + t7, + t8, + t9, + t10, + t11, + t12, + t13, + t14, + t15, + t16, + t17, + t18, + t19 + ) { + case List( + a1: AnyRef, + a2: AnyRef, + a3: AnyRef, + a4: AnyRef, + a5: AnyRef, + a6: AnyRef, + a7: AnyRef, + a8: AnyRef, + a9: AnyRef, + a10: AnyRef, + a11: AnyRef, + a12: AnyRef, + a13: AnyRef, + a14: AnyRef, + a15: AnyRef, + a16: AnyRef, + a17: AnyRef, + a18: AnyRef, + a19: AnyRef + ) => + f( + a1.asInstanceOf[T1], + a2.asInstanceOf[T2], + a3.asInstanceOf[T3], + a4.asInstanceOf[T4], + a5.asInstanceOf[T5], + a6.asInstanceOf[T6], + a7.asInstanceOf[T7], + a8.asInstanceOf[T8], + a9.asInstanceOf[T9], + a10.asInstanceOf[T10], + a11.asInstanceOf[T11], + a12.asInstanceOf[T12], + a13.asInstanceOf[T13], + a14.asInstanceOf[T14], + a15.asInstanceOf[T15], + a16.asInstanceOf[T16], + a17.asInstanceOf[T17], + a18.asInstanceOf[T18], + a19.asInstanceOf[T19] + ) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + inline def apply[ + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20 + ]( + f: ( + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20 + ) => Any + ): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + val t2: TypeTreeTag = typeTreeTag[T2] + val t3: TypeTreeTag = typeTreeTag[T3] + val t4: TypeTreeTag = typeTreeTag[T4] + val t5: TypeTreeTag = typeTreeTag[T5] + val t6: TypeTreeTag = typeTreeTag[T6] + val t7: TypeTreeTag = typeTreeTag[T7] + val t8: TypeTreeTag = typeTreeTag[T8] + val t9: TypeTreeTag = typeTreeTag[T9] + val t10: TypeTreeTag = typeTreeTag[T10] + val t11: TypeTreeTag = typeTreeTag[T11] + val t12: TypeTreeTag = typeTreeTag[T12] + val t13: TypeTreeTag = typeTreeTag[T13] + val t14: TypeTreeTag = typeTreeTag[T14] + val t15: TypeTreeTag = typeTreeTag[T15] + val t16: TypeTreeTag = typeTreeTag[T16] + val t17: TypeTreeTag = typeTreeTag[T17] + val t18: TypeTreeTag = typeTreeTag[T18] + val t19: TypeTreeTag = typeTreeTag[T19] + val t20: TypeTreeTag = typeTreeTag[T20] + register( + t1, + t2, + t3, + t4, + t5, + t6, + t7, + t8, + t9, + t10, + t11, + t12, + t13, + t14, + t15, + t16, + t17, + t18, + t19, + t20 + ) { + case List( + a1: AnyRef, + a2: AnyRef, + a3: AnyRef, + a4: AnyRef, + a5: AnyRef, + a6: AnyRef, + a7: AnyRef, + a8: AnyRef, + a9: AnyRef, + a10: AnyRef, + a11: AnyRef, + a12: AnyRef, + a13: AnyRef, + a14: AnyRef, + a15: AnyRef, + a16: AnyRef, + a17: AnyRef, + a18: AnyRef, + a19: AnyRef, + a20: AnyRef + ) => + f( + a1.asInstanceOf[T1], + a2.asInstanceOf[T2], + a3.asInstanceOf[T3], + a4.asInstanceOf[T4], + a5.asInstanceOf[T5], + a6.asInstanceOf[T6], + a7.asInstanceOf[T7], + a8.asInstanceOf[T8], + a9.asInstanceOf[T9], + a10.asInstanceOf[T10], + a11.asInstanceOf[T11], + a12.asInstanceOf[T12], + a13.asInstanceOf[T13], + a14.asInstanceOf[T14], + a15.asInstanceOf[T15], + a16.asInstanceOf[T16], + a17.asInstanceOf[T17], + a18.asInstanceOf[T18], + a19.asInstanceOf[T19], + a20.asInstanceOf[T20] + ) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + inline def apply[ + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21 + ]( + f: ( + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21 + ) => Any + ): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + val t2: TypeTreeTag = typeTreeTag[T2] + val t3: TypeTreeTag = typeTreeTag[T3] + val t4: TypeTreeTag = typeTreeTag[T4] + val t5: TypeTreeTag = typeTreeTag[T5] + val t6: TypeTreeTag = typeTreeTag[T6] + val t7: TypeTreeTag = typeTreeTag[T7] + val t8: TypeTreeTag = typeTreeTag[T8] + val t9: TypeTreeTag = typeTreeTag[T9] + val t10: TypeTreeTag = typeTreeTag[T10] + val t11: TypeTreeTag = typeTreeTag[T11] + val t12: TypeTreeTag = typeTreeTag[T12] + val t13: TypeTreeTag = typeTreeTag[T13] + val t14: TypeTreeTag = typeTreeTag[T14] + val t15: TypeTreeTag = typeTreeTag[T15] + val t16: TypeTreeTag = typeTreeTag[T16] + val t17: TypeTreeTag = typeTreeTag[T17] + val t18: TypeTreeTag = typeTreeTag[T18] + val t19: TypeTreeTag = typeTreeTag[T19] + val t20: TypeTreeTag = typeTreeTag[T20] + val t21: TypeTreeTag = typeTreeTag[T21] + register( + t1, + t2, + t3, + t4, + t5, + t6, + t7, + t8, + t9, + t10, + t11, + t12, + t13, + t14, + t15, + t16, + t17, + t18, + t19, + t20, + t21 + ) { + case List( + a1: AnyRef, + a2: AnyRef, + a3: AnyRef, + a4: AnyRef, + a5: AnyRef, + a6: AnyRef, + a7: AnyRef, + a8: AnyRef, + a9: AnyRef, + a10: AnyRef, + a11: AnyRef, + a12: AnyRef, + a13: AnyRef, + a14: AnyRef, + a15: AnyRef, + a16: AnyRef, + a17: AnyRef, + a18: AnyRef, + a19: AnyRef, + a20: AnyRef, + a21: AnyRef + ) => + f( + a1.asInstanceOf[T1], + a2.asInstanceOf[T2], + a3.asInstanceOf[T3], + a4.asInstanceOf[T4], + a5.asInstanceOf[T5], + a6.asInstanceOf[T6], + a7.asInstanceOf[T7], + a8.asInstanceOf[T8], + a9.asInstanceOf[T9], + a10.asInstanceOf[T10], + a11.asInstanceOf[T11], + a12.asInstanceOf[T12], + a13.asInstanceOf[T13], + a14.asInstanceOf[T14], + a15.asInstanceOf[T15], + a16.asInstanceOf[T16], + a17.asInstanceOf[T17], + a18.asInstanceOf[T18], + a19.asInstanceOf[T19], + a20.asInstanceOf[T20], + a21.asInstanceOf[T21] + ) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + inline def apply[ + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22 + ]( + f: ( + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22 + ) => Any + ): Unit = { + val t1: TypeTreeTag = typeTreeTag[T1] + val t2: TypeTreeTag = typeTreeTag[T2] + val t3: TypeTreeTag = typeTreeTag[T3] + val t4: TypeTreeTag = typeTreeTag[T4] + val t5: TypeTreeTag = typeTreeTag[T5] + val t6: TypeTreeTag = typeTreeTag[T6] + val t7: TypeTreeTag = typeTreeTag[T7] + val t8: TypeTreeTag = typeTreeTag[T8] + val t9: TypeTreeTag = typeTreeTag[T9] + val t10: TypeTreeTag = typeTreeTag[T10] + val t11: TypeTreeTag = typeTreeTag[T11] + val t12: TypeTreeTag = typeTreeTag[T12] + val t13: TypeTreeTag = typeTreeTag[T13] + val t14: TypeTreeTag = typeTreeTag[T14] + val t15: TypeTreeTag = typeTreeTag[T15] + val t16: TypeTreeTag = typeTreeTag[T16] + val t17: TypeTreeTag = typeTreeTag[T17] + val t18: TypeTreeTag = typeTreeTag[T18] + val t19: TypeTreeTag = typeTreeTag[T19] + val t20: TypeTreeTag = typeTreeTag[T20] + val t21: TypeTreeTag = typeTreeTag[T21] + val t22: TypeTreeTag = typeTreeTag[T22] + register( + t1, + t2, + t3, + t4, + t5, + t6, + t7, + t8, + t9, + t10, + t11, + t12, + t13, + t14, + t15, + t16, + t17, + t18, + t19, + t20, + t21, + t22 + ) { + case List( + a1: AnyRef, + a2: AnyRef, + a3: AnyRef, + a4: AnyRef, + a5: AnyRef, + a6: AnyRef, + a7: AnyRef, + a8: AnyRef, + a9: AnyRef, + a10: AnyRef, + a11: AnyRef, + a12: AnyRef, + a13: AnyRef, + a14: AnyRef, + a15: AnyRef, + a16: AnyRef, + a17: AnyRef, + a18: AnyRef, + a19: AnyRef, + a20: AnyRef, + a21: AnyRef, + a22: AnyRef + ) => + f( + a1.asInstanceOf[T1], + a2.asInstanceOf[T2], + a3.asInstanceOf[T3], + a4.asInstanceOf[T4], + a5.asInstanceOf[T5], + a6.asInstanceOf[T6], + a7.asInstanceOf[T7], + a8.asInstanceOf[T8], + a9.asInstanceOf[T9], + a10.asInstanceOf[T10], + a11.asInstanceOf[T11], + a12.asInstanceOf[T12], + a13.asInstanceOf[T13], + a14.asInstanceOf[T14], + a15.asInstanceOf[T15], + a16.asInstanceOf[T16], + a17.asInstanceOf[T17], + a18.asInstanceOf[T18], + a19.asInstanceOf[T19], + a20.asInstanceOf[T20], + a21.asInstanceOf[T21], + a22.asInstanceOf[T22] + ) + case _ => + throw new IncorrectStepDefinitionException() + } + } + + private def register( + tags: TypeTreeTag* + )(pf: PartialFunction[List[Any], Any]): Unit = { + val types = tags.map(ScalaTypeHelper.asJavaType) + registry.registerStep( + ScalaStepDetails(Utils.frame(self), name, regex, types, pf) + ) + } + + } + +} diff --git a/cucumber-scala/src/main/scala/io/cucumber/scala/GlueAdaptor.scala b/cucumber-scala/src/main/scala/io/cucumber/scala/GlueAdaptor.scala index 09fc1819..7fbd3207 100644 --- a/cucumber-scala/src/main/scala/io/cucumber/scala/GlueAdaptor.scala +++ b/cucumber-scala/src/main/scala/io/cucumber/scala/GlueAdaptor.scala @@ -16,7 +16,7 @@ class GlueAdaptor(glue: Glue) { // If the registry is not consistent, this indicates a mistake in the users definition and we want to let him know. registry.checkConsistency().left.foreach { - ex: IncorrectHookDefinitionException => + (ex: IncorrectHookDefinitionException) => throw ex } diff --git a/cucumber-scala/src/test/scala/io/cucumber/scala/ScalaDslStepsTest.scala b/cucumber-scala/src/test/scala-2/io/cucumber/scala/ScalaDslStepsTest.scala similarity index 100% rename from cucumber-scala/src/test/scala/io/cucumber/scala/ScalaDslStepsTest.scala rename to cucumber-scala/src/test/scala-2/io/cucumber/scala/ScalaDslStepsTest.scala diff --git a/cucumber-scala/src/test/scala-3/io/cucumber/scala/ScalaDslStepsTest.scala b/cucumber-scala/src/test/scala-3/io/cucumber/scala/ScalaDslStepsTest.scala new file mode 100644 index 00000000..854b6b56 --- /dev/null +++ b/cucumber-scala/src/test/scala-3/io/cucumber/scala/ScalaDslStepsTest.scala @@ -0,0 +1,348 @@ +package io.cucumber.scala + +import io.cucumber.core.backend._ +import org.junit.Assert.{assertEquals, assertTrue} +import org.junit.Test + +import scala.annotation.nowarn +import scala.util.Try + +@nowarn +class ScalaDslStepsTest { + + @Test + def testDefNoArg(): Unit = { + + var invoked = false + + class Glue extends ScalaDsl with EN { + // On a single line to avoid difference between Scala versions for the location + //@formatter:off + Given("Something") { invoked = true } + //@formatter:on + } + + val glue = new Glue() + + assertClassStepDefinition( + glue.registry.stepDefinitions.head, + "Something", + "ScalaDslStepsTest.scala:21", + Array(), + invoked + ) + } + + @Test + def testDefEmptyArg(): Unit = { + + var invoked = false + + class Glue extends ScalaDsl with EN { + Given("Something") { () => + invoked = true + } + } + + val glue = new Glue() + + assertClassStepDefinition( + glue.registry.stepDefinitions.head, + "Something", + "ScalaDslStepsTest.scala:44", + Array(), + invoked + ) + } + + @Test + def testDefWithArgs(): Unit = { + + var thenumber = 0 + var thecolour = "" + + class Glue extends ScalaDsl with EN { + Given("""Oh boy, (\d+) (\s+) cukes""") { (num: Int, colour: String) => + thenumber = num + thecolour = colour + } + } + + val glue = new Glue() + + assertClassStepDefinition( + glue.registry.stepDefinitions.head, + """Oh boy, (\d+) (\s+) cukes""", + "ScalaDslStepsTest.scala:68", + Array(java.lang.Integer.valueOf(5), "green"), + thenumber == 5 && thecolour == "green" + ) + } + + @Test + def testDefThrowException(): Unit = { + + class GlueWithException extends ScalaDsl with EN { + Given("Something") { () => + val x = 1 + 2 // A not useful line + throw new PendingException() + } + } + + val glue = new GlueWithException() + + assertClassStepDefinitionThrow( + glue.registry.stepDefinitions.head, + classOf[PendingException], + "ScalaDslStepsTest$GlueWithException", + "ScalaDslStepsTest.scala", + 88, + Array() + ) + } + + // Note: this is a corner case that we should prevent to happen in the future + @Test + def testDefNullParameters(): Unit = { + + class Glue extends ScalaDsl with EN { + Given("Something {}") { (str: String) => + // Nothing + println(str) + } + } + + val glue = new Glue() + + assertClassStepDefinitionThrow( + glue.registry.stepDefinitions.head, + classOf[IncorrectStepDefinitionException], + "io.cucumber.scala.ScalaDslStepsTest", + "ScalaDslStepsTest.scala", + 109, + Array(null) + ) + } + + // -------------------- Test on object -------------------- + // Note: for now there is no difference between the two in ScalaDsl but better safe than sorry + + @Test + def testObjectDefNoArg(): Unit = { + + var invoked = false + + object Glue extends ScalaDsl with EN { + // On a single line to avoid difference between Scala versions for the location + //@formatter:off + Given("Something") { invoked = true } + //@formatter:on + } + + assertObjectStepDefinition( + Glue.registry.stepDefinitions.head, + "Something", + "ScalaDslStepsTest.scala:138", + Array(), + invoked + ) + } + + @Test + def testObjectDefEmptyArg(): Unit = { + + var invoked = false + + object Glue extends ScalaDsl with EN { + Given("Something") { () => + invoked = true + } + } + + assertObjectStepDefinition( + Glue.registry.stepDefinitions.head, + "Something", + "ScalaDslStepsTest.scala:159", + Array(), + invoked + ) + } + + @Test + def testObjectDefWithArgs(): Unit = { + + var thenumber = 0 + var thecolour = "" + + object Glue extends ScalaDsl with EN { + Given("""Oh boy, (\d+) (\s+) cukes""") { (num: Int, colour: String) => + thenumber = num + thecolour = colour + } + } + + assertObjectStepDefinition( + Glue.registry.stepDefinitions.head, + """Oh boy, (\d+) (\s+) cukes""", + "ScalaDslStepsTest.scala:181", + Array(java.lang.Integer.valueOf(5), "green"), + thenumber == 5 && thecolour == "green" + ) + } + + @Test + def testObjectDefThrowException(): Unit = { + + object GlueWithException extends ScalaDsl with EN { + Given("Something") { () => + val x = 1 + 2 // A not useful line + throw new PendingException() + } + } + + assertObjectStepDefinitionThrow( + GlueWithException.registry.stepDefinitions.head, + classOf[PendingException], + "ScalaDslStepsTest$GlueWithException", + "ScalaDslStepsTest.scala", + 199, + Array() + ) + } + + // Note: this is a corner case that we should prevent to happen in the future + @Test + def testObjectDefNullParameters(): Unit = { + + object Glue extends ScalaDsl with EN { + Given("Something {}") { (str: String) => + // Nothing + println(str) + } + } + + assertClassStepDefinitionThrow( + Glue.registry.stepDefinitions.head, + classOf[IncorrectStepDefinitionException], + "io.cucumber.scala.ScalaDslStepsTest", + "ScalaDslStepsTest.scala", + 218, + Array(null) + ) + } + + private def assertClassStepDefinition( + stepDetails: ScalaStepDetails, + pattern: String, + location: String, + args: Array[AnyRef], + check: => Boolean + ): Unit = { + assertStepDefinition( + ScalaStepDefinition(stepDetails, true), + pattern, + location, + args, + check + ) + } + + private def assertObjectStepDefinition( + stepDetails: ScalaStepDetails, + pattern: String, + location: String, + args: Array[AnyRef], + check: => Boolean + ): Unit = { + assertStepDefinition( + ScalaStepDefinition(stepDetails, false), + pattern, + location, + args, + check + ) + } + + private def assertStepDefinition( + stepDefinition: StepDefinition, + pattern: String, + location: String, + args: Array[AnyRef], + check: => Boolean + ): Unit = { + assertEquals(pattern, stepDefinition.getPattern) + assertEquals(location, stepDefinition.getLocation) + stepDefinition.execute(args) + assertTrue(check) + } + + private def assertClassStepDefinitionThrow( + stepDetails: ScalaStepDetails, + underlyingExceptionClass: Class[_ <: Exception], + exceptionClassName: String, + exceptionFile: String, + exceptionLine: Int, + args: Array[AnyRef] + ): Unit = { + assertStepDefinitionThrow( + ScalaStepDefinition(stepDetails, true), + underlyingExceptionClass, + exceptionClassName, + exceptionFile, + exceptionLine, + args + ) + } + + private def assertObjectStepDefinitionThrow( + stepDetails: ScalaStepDetails, + underlyingExceptionClass: Class[_ <: Exception], + exceptionClassName: String, + exceptionFile: String, + exceptionLine: Int, + args: Array[AnyRef] + ): Unit = { + assertStepDefinitionThrow( + ScalaStepDefinition(stepDetails, false), + underlyingExceptionClass, + exceptionClassName, + exceptionFile, + exceptionLine, + args + ) + } + + private def assertStepDefinitionThrow( + stepDefinition: StepDefinition, + underlyingExceptionClass: Class[_ <: Exception], + exceptionClassName: String, + exceptionFile: String, + exceptionLine: Int, + args: Array[AnyRef] + ): Unit = { + val tried = Try(stepDefinition.execute(args)) + + assertTrue(tried.isFailure) + + val ex = tried.failed.get + assertTrue(ex.isInstanceOf[CucumberInvocationTargetException]) + + val underlying = ex + .asInstanceOf[CucumberInvocationTargetException] + .getInvocationTargetExceptionCause + assertEquals(underlyingExceptionClass, underlying.getClass) + + val matched = underlying.getStackTrace + .filter(stepDefinition.isDefinedAt) + .head + + // The result is different between Scala versions, that's why we don't check it precisely + assertTrue( + s"$matched did not contain $exceptionClassName", + matched.toString.contains(exceptionClassName) + ) + assertEquals(exceptionFile, matched.getFileName) + assertEquals(exceptionLine, matched.getLineNumber) + } + +} diff --git a/cucumber-scala/src/test/scala/io/cucumber/scala/ScalaDslDataTableTypeTest.scala b/cucumber-scala/src/test/scala/io/cucumber/scala/ScalaDslDataTableTypeTest.scala index 5d02b472..099bf274 100644 --- a/cucumber-scala/src/test/scala/io/cucumber/scala/ScalaDslDataTableTypeTest.scala +++ b/cucumber-scala/src/test/scala/io/cucumber/scala/ScalaDslDataTableTypeTest.scala @@ -35,7 +35,7 @@ class ScalaDslDataTableTypeTest { def testDataTableEntryType(): Unit = { class Glue extends ScalaDsl with EN { - DataTableType { entry: Map[String, String] => + DataTableType { (entry: Map[String, String]) => Author(entry("name"), entry("surname"), entry("famousBook")) } } @@ -81,7 +81,7 @@ class ScalaDslDataTableTypeTest { def testDataTableRowType(): Unit = { class Glue extends ScalaDsl with EN { - DataTableType { row: Seq[String] => + DataTableType { (row: Seq[String]) => Author(row(0), row(1), row(2)) } } @@ -127,7 +127,7 @@ class ScalaDslDataTableTypeTest { def testDataTableCellType(): Unit = { class Glue extends ScalaDsl with EN { - DataTableType { cell: String => + DataTableType { (cell: String) => Cell(cell) } } @@ -173,7 +173,7 @@ class ScalaDslDataTableTypeTest { def testClassDataTableTableType(): Unit = { class Glue extends ScalaDsl with EN { - DataTableType { table: DataTable => + DataTableType { (table: DataTable) => val authors = table .asMaps() .asScala @@ -242,7 +242,7 @@ class ScalaDslDataTableTypeTest { def testObjectDataTableEntryType(): Unit = { object Glue extends ScalaDsl with EN { - DataTableType { entry: Map[String, String] => + DataTableType { (entry: Map[String, String]) => Author(entry("name"), entry("surname"), entry("famousBook")) } } @@ -284,7 +284,7 @@ class ScalaDslDataTableTypeTest { def testObjectDataTableRowType(): Unit = { object Glue extends ScalaDsl with EN { - DataTableType { row: Seq[String] => + DataTableType { (row: Seq[String]) => Author(row(0), row(1), row(2)) } } @@ -326,7 +326,7 @@ class ScalaDslDataTableTypeTest { def testObjectDataTableCellType(): Unit = { object Glue extends ScalaDsl with EN { - DataTableType { cell: String => + DataTableType { (cell: String) => Cell(cell) } } @@ -368,7 +368,7 @@ class ScalaDslDataTableTypeTest { def testObjectDataTableTableType(): Unit = { object Glue extends ScalaDsl with EN { - DataTableType { table: DataTable => + DataTableType { (table: DataTable) => val authors = table .asMaps() .asScala diff --git a/cucumber-scala/src/test/scala/io/cucumber/scala/ScalaDslHooksTest.scala b/cucumber-scala/src/test/scala/io/cucumber/scala/ScalaDslHooksTest.scala index dd2d956d..5e82d790 100644 --- a/cucumber-scala/src/test/scala/io/cucumber/scala/ScalaDslHooksTest.scala +++ b/cucumber-scala/src/test/scala/io/cucumber/scala/ScalaDslHooksTest.scala @@ -30,7 +30,7 @@ class ScalaDslHooksTest { def testBeforeHook(): Unit = { class Glue extends ScalaDsl { - Before { _: Scenario => + Before { (_: Scenario) => invoke() } } @@ -142,7 +142,7 @@ class ScalaDslHooksTest { def testBeforeStepHook(): Unit = { class Glue extends ScalaDsl { - BeforeStep { _: Scenario => + BeforeStep { (_: Scenario) => invoke() } } @@ -254,7 +254,7 @@ class ScalaDslHooksTest { def testAfterHook(): Unit = { class Glue extends ScalaDsl { - After { _: Scenario => + After { (_: Scenario) => invoke() } } @@ -366,7 +366,7 @@ class ScalaDslHooksTest { def testAfterStepHook(): Unit = { class Glue extends ScalaDsl { - AfterStep { _: Scenario => + AfterStep { (_: Scenario) => invoke() } } @@ -481,7 +481,7 @@ class ScalaDslHooksTest { def testObjectBeforeHook(): Unit = { object Glue extends ScalaDsl { - Before { _: Scenario => + Before { (_: Scenario) => invoke() } } @@ -577,7 +577,7 @@ class ScalaDslHooksTest { def testObjectBeforeStepHook(): Unit = { object Glue extends ScalaDsl { - BeforeStep { _: Scenario => + BeforeStep { (_: Scenario) => invoke() } } @@ -673,7 +673,7 @@ class ScalaDslHooksTest { def testObjectAfterHook(): Unit = { object Glue extends ScalaDsl { - After { _: Scenario => + After { (_: Scenario) => invoke() } } @@ -769,7 +769,7 @@ class ScalaDslHooksTest { def testObjectAfterStepHook(): Unit = { object Glue extends ScalaDsl { - AfterStep { _: Scenario => + AfterStep { (_: Scenario) => invoke() } } diff --git a/cucumber-scala/src/test/scala/io/cucumber/scala/steps/classes/MultipleInSameFile.scala b/cucumber-scala/src/test/scala/io/cucumber/scala/steps/classes/MultipleInSameFile.scala index 032e2d51..15e5f7a1 100644 --- a/cucumber-scala/src/test/scala/io/cucumber/scala/steps/classes/MultipleInSameFile.scala +++ b/cucumber-scala/src/test/scala/io/cucumber/scala/steps/classes/MultipleInSameFile.scala @@ -6,18 +6,22 @@ class StepsA extends ScalaDsl with EN { Before { // Nothing + () } BeforeStep { // Nothing + () } After { // Nothing + () } AfterStep { // Nothing + () } Given("""stepA""") { () => diff --git a/cucumber-scala/src/test/scala/io/cucumber/scala/steps/objects/StepsInObject.scala b/cucumber-scala/src/test/scala/io/cucumber/scala/steps/objects/StepsInObject.scala index feb7d8f9..39878770 100644 --- a/cucumber-scala/src/test/scala/io/cucumber/scala/steps/objects/StepsInObject.scala +++ b/cucumber-scala/src/test/scala/io/cucumber/scala/steps/objects/StepsInObject.scala @@ -6,18 +6,22 @@ object StepsInObject extends ScalaDsl with EN { Before { // Nothing + () } BeforeStep { // Nothing + () } After { // Nothing + () } AfterStep { // Nothing + () } Given("""Given step""") { () => diff --git a/cucumber-scala/src/test/scala/io/cucumber/scala/steps/traits/StepsInTrait.scala b/cucumber-scala/src/test/scala/io/cucumber/scala/steps/traits/StepsInTrait.scala index 7c1b5478..453972ae 100644 --- a/cucumber-scala/src/test/scala/io/cucumber/scala/steps/traits/StepsInTrait.scala +++ b/cucumber-scala/src/test/scala/io/cucumber/scala/steps/traits/StepsInTrait.scala @@ -6,18 +6,22 @@ trait TraitWithSteps extends ScalaDsl with EN { Before { // Nothing + () } BeforeStep { // Nothing + () } After { // Nothing + () } AfterStep { // Nothing + () } Given("""Given step""") { () => diff --git a/cucumber-scala/src/test/scala/tests/cukes/StepDefs.scala b/cucumber-scala/src/test/scala/tests/cukes/StepDefs.scala index 36babd95..9df034c2 100644 --- a/cucumber-scala/src/test/scala/tests/cukes/StepDefs.scala +++ b/cucumber-scala/src/test/scala/tests/cukes/StepDefs.scala @@ -161,21 +161,21 @@ class CukesStepDefinitions extends ScalaDsl with EN { person = p } - Then("""^he should say \"(.*)\"""") { s: String => + Then("""^he should say \"(.*)\"""") { (s: String) => assertEquals(person.hello, s) } var cukes: JList[Cukes] = null - Given("^I have eaten the following cukes$") { cs: JList[Cukes] => + Given("^I have eaten the following cukes$") { (cs: JList[Cukes]) => cukes = cs } - Then("""I should have eaten {int} cukes""") { total: Int => + Then("""I should have eaten {int} cukes""") { (total: Int) => assertEquals(total, cukes.asScala.map(_.number).sum) } - And("^they should have been (.*)$") { colors: String => + And("^they should have been (.*)$") { (colors: String) => assertEquals(colors, cukes.asScala.map(_.color).mkString(", ")) } diff --git a/cucumber-scala/src/test/scala/tests/cukes/TypeRegistryConfiguration.scala b/cucumber-scala/src/test/scala/tests/cukes/TypeRegistryConfiguration.scala index 8295f2ea..b5638229 100644 --- a/cucumber-scala/src/test/scala/tests/cukes/TypeRegistryConfiguration.scala +++ b/cucumber-scala/src/test/scala/tests/cukes/TypeRegistryConfiguration.scala @@ -34,7 +34,7 @@ class TypeRegistryConfiguration extends ScalaDsl { s.charAt(0) } - DataTableType { map: Map[String, String] => + DataTableType { (map: Map[String, String]) => Cukes(map("Number").toInt, map("Color")) } diff --git a/cucumber-scala/src/test/scala/tests/datatables/DataTableTypeSteps.scala b/cucumber-scala/src/test/scala/tests/datatables/DataTableTypeSteps.scala index ad1b5a6f..9f9f8452 100644 --- a/cucumber-scala/src/test/scala/tests/datatables/DataTableTypeSteps.scala +++ b/cucumber-scala/src/test/scala/tests/datatables/DataTableTypeSteps.scala @@ -61,7 +61,7 @@ class DataTableTypeSteps extends ScalaDsl with EN { var _authors: Seq[Author] = _ var _names: String = _ - DataTableType { entry: Map[String, String] => + DataTableType { (entry: Map[String, String]) => Author(entry("name"), entry("surname"), entry("famousBook")) } @@ -77,7 +77,7 @@ class DataTableTypeSteps extends ScalaDsl with EN { ) } - DataTableType { row: Seq[String] => + DataTableType { (row: Seq[String]) => AuthorRow(row(0), row(1), row(2)) } @@ -93,7 +93,7 @@ class DataTableTypeSteps extends ScalaDsl with EN { ) } - DataTableType { cell: String => + DataTableType { (cell: String) => AuthorCell(cell) } @@ -105,7 +105,7 @@ class DataTableTypeSteps extends ScalaDsl with EN { AuthorCellWithNone(cell) } - DataTableType { table: DataTable => + DataTableType { (table: DataTable) => val authors = table .asMaps() .asScala @@ -268,7 +268,7 @@ class DataTableTypeSteps extends ScalaDsl with EN { _names = _authors.map(_.name).mkString(",") } - Then("""I get {string}""") { expected: String => + Then("""I get {string}""") { (expected: String) => assert(_names == expected, s"${_names} was not equal to $expected") } diff --git a/cucumber-scala/src/test/scala/tests/datatables/DatatableAsScalaSteps.scala b/cucumber-scala/src/test/scala/tests/datatables/DatatableAsScalaSteps.scala index df7ee495..5fd1dfdd 100644 --- a/cucumber-scala/src/test/scala/tests/datatables/DatatableAsScalaSteps.scala +++ b/cucumber-scala/src/test/scala/tests/datatables/DatatableAsScalaSteps.scala @@ -197,7 +197,7 @@ class DatatableAsScalaSteps extends ScalaDsl with EN { case class CustomType(key1: String, key2: Option[String], key3: String) - DataTableType { map: Map[String, String] => + DataTableType { (map: Map[String, String]) => CustomType(map("key1"), Option(map("key2")), map("key3")) } @@ -214,7 +214,7 @@ class DatatableAsScalaSteps extends ScalaDsl with EN { case class RichCell(content: Option[String]) - DataTableType { cell: String => + DataTableType { (cell: String) => RichCell(Option(cell)) } diff --git a/cucumber-scala/src/test/scala/tests/docstring/DocStringSteps.scala b/cucumber-scala/src/test/scala/tests/docstring/DocStringSteps.scala index 42fd5241..a45efdc7 100644 --- a/cucumber-scala/src/test/scala/tests/docstring/DocStringSteps.scala +++ b/cucumber-scala/src/test/scala/tests/docstring/DocStringSteps.scala @@ -10,19 +10,19 @@ class DocStringSteps extends ScalaDsl with EN { var _text: Any = _ - DocStringType("json") { text => + DocStringType("json") { (text) => JsonText(text) } - DocStringType("xml") { text => + DocStringType("xml") { (text) => XmlText(text) } - Given("the following json text") { json: JsonText => + Given("the following json text") { (json: JsonText) => _text = json } - Given("the following xml text") { xml: XmlText => + Given("the following xml text") { (xml: XmlText) => _text = xml } diff --git a/cucumber-scala/src/test/scala/tests/parametertypes/ParameterTypesSteps.scala b/cucumber-scala/src/test/scala/tests/parametertypes/ParameterTypesSteps.scala index e251a38f..e51eaa9e 100644 --- a/cucumber-scala/src/test/scala/tests/parametertypes/ParameterTypesSteps.scala +++ b/cucumber-scala/src/test/scala/tests/parametertypes/ParameterTypesSteps.scala @@ -11,7 +11,7 @@ case class Point(x: Int, y: Int) class ParameterTypesSteps extends ScalaDsl with EN { - ParameterType("string-builder", "\"(.*)\"") { str => + ParameterType("string-builder", "\"(.*)\"") { (str) => new StringBuilder(str) } @@ -23,11 +23,11 @@ class ParameterTypesSteps extends ScalaDsl with EN { s"-$x-$y-$z-" } - ParameterType("optionalint", """\s?(\d*)\s?""") { str => + ParameterType("optionalint", """\s?(\d*)\s?""") { (str) => Option(str).filter(_.nonEmpty).map(_.toInt) } - ParameterType("optionalstring", "(.*)") { str => + ParameterType("optionalstring", "(.*)") { (str) => Option(str).filter(_.nonEmpty) } @@ -46,7 +46,7 @@ class ParameterTypesSteps extends ScalaDsl with EN { } Given("{string-builder} parameter, defined by lambda") { - builder: StringBuilder => + (builder: StringBuilder) => assert(builder.toString() == "string builder") } @@ -121,22 +121,22 @@ class ParameterTypesSteps extends ScalaDsl with EN { } Given("""an optional string parameter value "{optionalstring}" undefined""") { - value: Option[String] => + (value: Option[String]) => assert(value.isEmpty) } Given("""an optional string parameter value "{optionalstring}" defined""") { - value: Option[String] => + (value: Option[String]) => assert(value.contains("toto")) } Given("""an optional int parameter value{optionalint}undefined""") { - value: Option[Int] => + (value: Option[Int]) => assert(value.isEmpty) } Given("""an optional int parameter value{optionalint}defined""") { - value: Option[Int] => + (value: Option[Int]) => assert(value.contains(5)) } diff --git a/docs/upgrade_v7.md b/docs/upgrade_v7.md new file mode 100644 index 00000000..dc2a082e --- /dev/null +++ b/docs/upgrade_v7.md @@ -0,0 +1,41 @@ +# Upgrading from 6.x to 7.x + +Upgrading from v6 should be straightforward. +Prior to upgrading to v7.0.0 upgrade to latest v6.x and stop using all deprecated features. +Some features will log a deprecation warning. + +See also: +- [Cucumber Scala CHANGELOG](../CHANGELOG.md) + +## Scala 3 support + +This release brings Scala 3 support. + +### Syntactic changes + +If you use Scala 3, you might need to change slightly some of your glue code: +- parenthesis are now necessary even around a single-argument step or hook definition +```scala +// Won't compile anymore +Given("Something {}") { str: String => + // ... +} + +// Instead use: +Given("Something {}") { (str: String) => + // ... +} +``` +- hooks must explicitly return `Unit` (most of the time you already had compile errors with such statements in Scala 2.x as well) +```scala +Before { + // ... // Some code not retuning Unit + () // Explicit Unit +} +``` + +### Other changes + +The line numbers provided in reports might slightly change +from start of a step definition to end of a step definition in some cases. +In case of errors, these line numbers should be more accurate than before. diff --git a/examples/src/main/scala/cucumber/examples/scalacalculator/RpnCalculator.scala b/examples/src/main/scala/cucumber/examples/scalacalculator/RpnCalculator.scala index 09d4b3d9..3e038d48 100644 --- a/examples/src/main/scala/cucumber/examples/scalacalculator/RpnCalculator.scala +++ b/examples/src/main/scala/cucumber/examples/scalacalculator/RpnCalculator.scala @@ -5,8 +5,8 @@ import scala.collection.mutable.Queue sealed trait Arg object Arg { - implicit def op(s: String) = Op(s) - implicit def value(v: Double) = Val(v) + implicit def op(s: String): Op = Op(s) + implicit def value(v: Double): Val = Val(v) } case class Op(value: String) extends Arg diff --git a/examples/src/test/scala/cucumber/examples/scalacalculator/RpnCalculatorStepDefinitions.scala b/examples/src/test/scala/cucumber/examples/scalacalculator/RpnCalculatorStepDefinitions.scala index 97f96254..3812b0fe 100644 --- a/examples/src/test/scala/cucumber/examples/scalacalculator/RpnCalculatorStepDefinitions.scala +++ b/examples/src/test/scala/cucumber/examples/scalacalculator/RpnCalculatorStepDefinitions.scala @@ -13,11 +13,11 @@ class RpnCalculatorStepDefinitions extends ScalaDsl with EN { calc push "+" } - Then("the result is {double}") { expected: Double => + Then("the result is {double}") { (expected: Double) => assertEquals(expected, calc.value, 0.001) } - Before("not @foo") { scenario: Scenario => + Before("not @foo") { (scenario: Scenario) => println(s"Runs before scenarios *not* tagged with @foo (${scenario.getId})") } } diff --git a/project/I18nGenerator.scala b/project/I18nGenerator.scala index bd750759..42ca9852 100644 --- a/project/I18nGenerator.scala +++ b/project/I18nGenerator.scala @@ -16,7 +16,7 @@ object I18nGenerator { private def keywordVal(kw: String): String = { val keyworkValName = java.text.Normalizer .normalize(kw.replaceAll("[\\s',!]", ""), java.text.Normalizer.Form.NFC) - s"""val $keyworkValName = new Step("$keyworkValName")""" + s""" val $keyworkValName = new Step("$keyworkValName")""" } private def traitCode(language: String): String = { diff --git a/project/ScalacOptions.scala b/project/ScalacOptions.scala index 948e0900..872830da 100644 --- a/project/ScalacOptions.scala +++ b/project/ScalacOptions.scala @@ -1,5 +1,19 @@ object ScalacOptions { + val scalacOptions3 = Seq( + "-source:3.0", + "-deprecation", // Emit warning and location for usages of deprecated APIs. + "-explain", // Explain type errors in more detail. +// "-explaintypes", // Explain type errors in more detail. + "-feature", // Emit warning and location for usages of features that should be imported explicitly. + "-language:existentials", // Existential types (besides wildcard types) can be written and inferred + "-language:experimental.macros", // Allow macro definition (besides implementation and application) + "-language:higherKinds", // Allow higher-kinded types + "-language:implicitConversions", // Allow definition of implicit functions called views + "-unchecked", // Enable additional warnings where generated code depends on assumptions. + "-Xfatal-warnings" // Fail the compilation if there are any warnings. + ) + // Source: https://nathankleyn.com/2019/05/13/recommended-scalac-flags-for-2-13/ val scalacOptions213 = Seq( "-deprecation", // Emit warning and location for usages of deprecated APIs. diff --git a/project/plugins.sbt b/project/plugins.sbt index 260cccc6..01191018 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,6 +1,9 @@ // Cross compilation matrix addSbtPlugin("com.eed3si9n" % "sbt-projectmatrix" % "0.7.0") +// Scala 3 (Dotty) +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.5.3") + // Scalafmt (formatter) addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.2")