diff --git a/build.sbt b/build.sbt index c368af20..0ce73bfc 100644 --- a/build.sbt +++ b/build.sbt @@ -10,8 +10,8 @@ def previousVersion = "0.7.0" def scala213 = "2.13.2" def scala212 = "2.12.11" def scala211 = "2.11.12" -def scala3Stable = "3.0.0-M1" -def scala3Previous = "0.27.0-RC1" +def scala3Stable = "3.0.0-M2" +def scala3Previous = List("3.0.0-M1", "0.27.0-RC1") def junitVersion = "4.13" def gcp = "com.google.cloud" % "google-cloud-storage" % "1.113.4" inThisBuild( @@ -61,7 +61,7 @@ addCommandAlias( ) val isPreScala213 = Set[Option[(Long, Long)]](Some((2, 11)), Some((2, 12))) val scala2Versions = List(scala213, scala212, scala211) -val scala3Versions = List(scala3Previous, scala3Stable) +val scala3Versions = scala3Stable :: scala3Previous val allScalaVersions = scala2Versions ++ scala3Versions def isNotScala211(v: Option[(Long, Long)]): Boolean = !v.contains((2, 11)) def isScala2(v: Option[(Long, Long)]): Boolean = v.exists(_._1 == 2) @@ -316,7 +316,7 @@ lazy val docs = project mdocVariables := Map( "VERSION" -> version.value.replaceFirst("\\+.*", ""), "SCALA3_PREVIOUS_VERSION" -> scala3Stable, - "SCALA3_STABLE_VERSION" -> scala3Stable, + "SCALA3_STABLE_VERSION" -> scala3Previous.head, "SUPPORTED_SCALA_VERSIONS" -> allScalaVersions.mkString(", ") ), fork := false diff --git a/munit/shared/src/main/scala-3/munit/internal/Compat.scala b/munit/shared/src/main/scala-3.0.0-M1/munit/internal/Compat.scala similarity index 100% rename from munit/shared/src/main/scala-3/munit/internal/Compat.scala rename to munit/shared/src/main/scala-3.0.0-M1/munit/internal/Compat.scala diff --git a/munit/shared/src/main/scala-3/munit/internal/MacroCompat.scala b/munit/shared/src/main/scala-3.0.0-M1/munit/internal/MacroCompat.scala similarity index 95% rename from munit/shared/src/main/scala-3/munit/internal/MacroCompat.scala rename to munit/shared/src/main/scala-3.0.0-M1/munit/internal/MacroCompat.scala index 9f108422..83d49a45 100644 --- a/munit/shared/src/main/scala-3/munit/internal/MacroCompat.scala +++ b/munit/shared/src/main/scala-3.0.0-M1/munit/internal/MacroCompat.scala @@ -11,7 +11,7 @@ object MacroCompat { } def locationImpl()(using qctx: QuoteContext): Expr[Location] = { - import qctx.tasty.{_, given _} + import qctx.reflect.{_, given} val path = rootPosition.sourceFile.jpath.toString val startLine = rootPosition.startLine + 1 '{ new Location(${Expr(path)}, ${Expr(startLine)}) } @@ -22,7 +22,7 @@ object MacroCompat { } def clueImpl[T:Type](value: Expr[T])(using qctx: QuoteContext): Expr[Clue[T]] = { - import qctx.tasty.{_, given _} + import qctx.reflect.{_, given} val source = value.unseal.pos.sourceCode val valueType = implicitly[scala.quoted.Type[T]].show '{ new Clue(${Expr(source)}, $value, ${Expr(valueType)}) } diff --git a/munit/shared/src/main/scala-3.0.0-M2/munit/internal/Compat.scala b/munit/shared/src/main/scala-3.0.0-M2/munit/internal/Compat.scala new file mode 100644 index 00000000..7e489e23 --- /dev/null +++ b/munit/shared/src/main/scala-3.0.0-M2/munit/internal/Compat.scala @@ -0,0 +1,13 @@ +package munit.internal + +import scala.reflect.Selectable.reflectiveSelectable + +object Compat { + type LazyList[+T] = scala.LazyList[T] + val LazyList = scala.LazyList + def productElementNames(p: Product): Iterator[String] = + p.productElementNames + def collectionClassName(i: Iterable[_]): String = { + i.asInstanceOf[{ def collectionClassName: String }].collectionClassName + } +} diff --git a/munit/shared/src/main/scala-3.0.0-M2/munit/internal/MacroCompat.scala b/munit/shared/src/main/scala-3.0.0-M2/munit/internal/MacroCompat.scala new file mode 100644 index 00000000..e9049620 --- /dev/null +++ b/munit/shared/src/main/scala-3.0.0-M2/munit/internal/MacroCompat.scala @@ -0,0 +1,47 @@ +package munit.internal + +import munit.Clue +import munit.Location +import scala.quoted._ + +object MacroCompat { + + trait LocationMacro { + inline implicit def generate: Location = ${ locationImpl() } + } + + def locationImpl()(using Quotes): Expr[Location] = { + import quotes.reflect._ + val pos = Position.ofMacroExpansion + val path = pos.sourceFile.jpath.toString + val startLine = pos.startLine + 1 + '{ new Location(${Expr(path)}, ${Expr(startLine)}) } + } + + trait ClueMacro { + inline implicit def generate[T](value: T): Clue[T] = ${ clueImpl('value) } + } + + def clueImpl[T: Type](value: Expr[T])(using Quotes): Expr[Clue[T]] = { + import quotes.reflect._ + val source = Term.of(value).pos.sourceCode + val valueType = Type.show[T] + '{ new Clue(${Expr(source)}, $value, ${Expr(valueType)}) } + } + + trait CompileErrorMacro { + inline def compileErrors(inline code: String): String = { + val errors = scala.compiletime.testing.typeCheckErrors(code) + errors.map { error => + val indent = " " * (error.column - 1) + val trimMessage = error.message.linesIterator.map { line => + if (line.matches(" +")) "" + else line + }.mkString("\n") + val separator = if (error.message.contains('\n')) "\n" else " " + s"error:${separator}${trimMessage}\n${error.lineContent}\n${indent}^" + }.mkString("\n") + } + } + +}