Skip to content

Commit 7b0d96c

Browse files
authored
airframe-surface: Scala 3: Pass all tests on JVM (#2052)
* Handle case fields as method arguments wvlet.airframe.surface.MultipleConstructorArgsTest wvlet.airframe.surface.ClassSurfaceTest * Fix confusion of List[String] wand String Fix wvlet.airframe.surface.RecursiveSurfaceTest * Treat type parameter such as T Fix wvlet.airframe.surface.RecursiveHigherKindTypeTest * Different key for type params to avoid cache collision fix wvlet.airframe.surface.RecursiveHigherKindTypeTest * Different key for type bounds fix wvlet.airframe.surface.reflect.RuntimeSurfaceTest fix wvlet.airframe.surface.SurfaceTest
1 parent 9363558 commit 7b0d96c

File tree

2 files changed

+28
-6
lines changed

2 files changed

+28
-6
lines changed

airframe-surface/src/main/scala-3/wvlet/airframe/surface/CompileTimeSurfaceFactory.scala

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package wvlet.airframe.surface
22
import scala.quoted._
3+
import dotty.tools.dotc.core.{Types as DottyTypes}
34

45
private[surface] object CompileTimeSurfaceFactory {
56

@@ -47,17 +48,19 @@ private[surface] class CompileTimeSurfaceFactory[Q <: Quotes](using quotes: Q) {
4748

4849
private def fullTypeNameOf(t: TypeRepr): String = {
4950
def sanitize(symbol: Symbol): String = {
50-
val name = symbol.fullName.split("\\.").toList match {
51+
val nameParts: List[String] = symbol.fullName.split("\\.").toList match {
5152
case "scala" :: "Predef$" :: tail =>
52-
tail.mkString(".")
53+
tail
5354
case "scala" :: "collection" :: "immutable" :: tail =>
54-
tail.mkString(".")
55+
tail
5556
case "scala" :: nme :: Nil =>
56-
nme
57+
List(nme)
5758
case other =>
5859
other
5960
}
60-
name.toString.stripSuffix("$").replaceAll("\\.package\\$", ".").replaceAll("\\$+", ".")
61+
nameParts
62+
.mkString(".").stripSuffix("$").replaceAll("\\.package\\$", ".").replaceAll("\\$+", ".")
63+
.replaceAll("\\.\\.", ".")
6164
}
6265
t match {
6366
case a: AppliedType if a.args.nonEmpty =>
@@ -89,7 +92,18 @@ private[surface] class CompileTimeSurfaceFactory[Q <: Quotes](using quotes: Q) {
8992
// For debugging
9093
// println(s"[${typeNameOf(t)}]\n ${t}")
9194
val generator = factory.andThen { expr =>
92-
'{ wvlet.airframe.surface.surfaceCache.getOrElseUpdate(${ Expr(fullTypeNameOf(t)) }, ${ expr }) }
95+
val cacheKey =
96+
if (typeNameOf(t) == "scala.Any" && classOf[DottyTypes.TypeBounds].isAssignableFrom(t.getClass)) {
97+
// Distinguish scala.Any and type bounds (such as _)
98+
s"${fullTypeNameOf(t)} for ${t}"
99+
} else if (typeNameOf(t) == "scala.Any" && classOf[DottyTypes.TypeParamRef].isAssignableFrom(t.getClass)) {
100+
// This ensure different cache key for each Type Parameter (such as T and U).
101+
// This is required because fullTypeNameOf of every Type Parameters is `scala.Any`.
102+
s"${fullTypeNameOf(t)} for ${t}"
103+
} else {
104+
fullTypeNameOf(t)
105+
}
106+
'{ wvlet.airframe.surface.surfaceCache.getOrElseUpdate(${ Expr(cacheKey) }, ${ expr }) }
93107
}
94108
val surface = generator(t)
95109
// println(s"--- ${surface.show}")
@@ -110,6 +124,7 @@ private[surface] class CompileTimeSurfaceFactory[Q <: Quotes](using quotes: Q) {
110124
javaEnumFactory orElse
111125
exisitentialTypeFactory orElse
112126
genericTypeWithConstructorFactory orElse
127+
typeParameterFactory orElse
113128
genericTypeFactory
114129
}
115130

@@ -260,6 +275,12 @@ private[surface] class CompileTimeSurfaceFactory[Q <: Quotes](using quotes: Q) {
260275
}
261276
}
262277

278+
private def typeParameterFactory: Factory = {
279+
case p: DottyTypes.ParamRef if (fullTypeNameOf(p) == "Any") =>
280+
val paramName = Expr(p.paramName.toString)
281+
'{ HigherKindedTypeSurface(${ paramName }, ${ paramName }, AnyRefSurface, Nil) }
282+
}
283+
263284
private def genericTypeFactory: Factory = {
264285
case a: AppliedType =>
265286
val typeArgs = a.args.map(surfaceOf(_))

airframe-surface/src/test/scala/wvlet/airframe/surface/SurfaceTest.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ class SurfaceTest extends SurfaceSpec {
184184
}
185185

186186
test("resolve generic abstract type") {
187+
assertEquals(Surface.of[D[_]].typeArgs, Seq(ExistentialType))
187188
val d = check(Surface.of[D[_]], "D[_]")
188189
assertEquals(d.typeArgs.length, 1)
189190
check(Surface.of[Map[_, _]], "Map[_,_]")

0 commit comments

Comments
 (0)