File tree Expand file tree Collapse file tree 6 files changed +76
-10
lines changed
js/src/main/scala/wvlet/surface
jvm/src/main/scala/wvlet/surface/reflect
airframe/src/test/scala/wvlet/airframe Expand file tree Collapse file tree 6 files changed +76
-10
lines changed Original file line number Diff line number Diff line change @@ -115,7 +115,15 @@ private[surface] object SurfaceMacros {
115
115
if symbol.isType &&
116
116
symbol.asType.isAliasType &&
117
117
! belongsToScalaDefault(alias) =>
118
- val inner = surfaceOf(alias.dealias)
118
+ val dealiased = alias.dealias
119
+ val inner = if (alias != dealiased) {
120
+ surfaceOf(dealiased)
121
+ } else {
122
+ // When higher kind types are aliased (e.g., type M[A] = Future[A]),
123
+ // alias.dealias will not return the aliased type (Future[A]),
124
+ // So we need to find the resulting type by applying type erasure.
125
+ surfaceOf(alias.erasure)
126
+ }
119
127
val name = symbol.asType.name.decodedName.toString
120
128
val fullName = s " ${prefix.typeSymbol.fullName}. ${name}"
121
129
q " wvlet.surface.Alias( ${name}, ${fullName}, $inner) "
@@ -399,7 +407,15 @@ private[surface] object SurfaceMacros {
399
407
case t @ TypeRef (NoPrefix , symbol, args) if ! t.typeSymbol.isClass =>
400
408
q " wvlet.surface.ExistentialType "
401
409
case t =>
402
- val expr = q " new wvlet.surface.GenericSurface(classOf[ $t]) "
410
+ val finalType =
411
+ if (t.typeSymbol.asType.isAbstract && ! (t =:= typeOf[AnyRef ])) {
412
+ // Use M[_] for type M
413
+ t.erasure
414
+ } else {
415
+ t
416
+ }
417
+
418
+ val expr = q " new wvlet.surface.GenericSurface(classOf[ ${finalType}]) "
403
419
expr
404
420
}
405
421
Original file line number Diff line number Diff line change @@ -260,10 +260,20 @@ object SurfaceFactory extends LogSupport {
260
260
if symbol.isType &&
261
261
symbol.asType.isAliasType &&
262
262
! belongsToScalaDefault(alias) =>
263
- val inner = surfaceOf(alias.dealias)
263
+ val dealiased = alias.dealias
264
+ val inner = if (alias != dealiased) {
265
+ surfaceOf(dealiased)
266
+ } else {
267
+ // When higher kind types are aliased (e.g., type M[A] = Future[A]),
268
+ // alias.dealias will not return the aliased type (Future[A]),
269
+ // So we need to find the resulting type by applying type erasure.
270
+ surfaceOf(alias.erasure)
271
+ }
272
+
264
273
val name = symbol.asType.name.decodedName.toString
265
274
val fullName = s " ${prefix.typeSymbol.fullName}. ${name}"
266
- Alias (name, fullName, inner)
275
+ val a = Alias (name, fullName, inner)
276
+ a
267
277
}
268
278
269
279
private def arrayFactory : SurfaceMatcher = {
Original file line number Diff line number Diff line change 13
13
*/
14
14
package wvlet .surface
15
15
import scala .language .existentials
16
- import scala .reflect .runtime .{universe => ru }
17
16
18
17
/**
19
18
* Parameters of a Surface
Original file line number Diff line number Diff line change
1
+ /*
2
+ * Licensed under the Apache License, Version 2.0 (the "License");
3
+ * you may not use this file except in compliance with the License.
4
+ * You may obtain a copy of the License at
5
+ *
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Unless required by applicable law or agreed to in writing, software
9
+ * distributed under the License is distributed on an "AS IS" BASIS,
10
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ * See the License for the specific language governing permissions and
12
+ * limitations under the License.
13
+ */
14
+ package wvlet .surface
15
+ import wvlet .surface
16
+ import scala .language .higherKinds
17
+
18
+ object RecursiveHigherKindTypeTest {
19
+ trait Holder [M [_]]
20
+
21
+ class MyTask [A ]
22
+
23
+ object Holder {
24
+ type BySkinny [A ] = MyTask [A ]
25
+ def bySkinny : Holder [BySkinny ] = new InterpretedHolder
26
+ }
27
+
28
+ import Holder ._
29
+ class InterpretedHolder extends Holder [BySkinny ] {}
30
+ }
31
+
32
+ /**
33
+ *
34
+ */
35
+ class RecursiveHigherKindTypeTest extends SurfaceSpec {
36
+ import RecursiveHigherKindTypeTest ._
37
+ import Holder .BySkinny
38
+
39
+ " Surface" should {
40
+ " support recursive higher kind types" in {
41
+ val s = surface.of[Holder [BySkinny ]]
42
+ s.name shouldBe " Holder[BySkinny]"
43
+ s.typeArgs(0 ).dealias.name shouldBe " MyTask[_]"
44
+ }
45
+ }
46
+ }
Original file line number Diff line number Diff line change @@ -19,7 +19,6 @@ object RecursiveSurfaceTest {
19
19
20
20
case class Leaf (name : String )
21
21
case class Cons (head : String , tail : Cons )
22
-
23
22
case class TypedCons [A ](head : String , tail : TypedCons [A ])
24
23
25
24
}
@@ -71,5 +70,4 @@ class RecursiveSurfaceTest extends SurfaceSpec {
71
70
lazyC.isOption shouldBe false
72
71
}
73
72
}
74
-
75
73
}
Original file line number Diff line number Diff line change @@ -15,14 +15,12 @@ package wvlet.airframe
15
15
import scala .language .higherKinds
16
16
17
17
object HigherKindTypeTest {
18
-
19
18
trait Holder [M [_]] {
20
19
def hello = " hello"
21
20
}
22
21
23
22
trait Task [A ]
24
23
trait MyFuture [A ]
25
-
26
24
trait HolderInterpreted extends Holder [Task ]
27
25
28
26
val interpreted = new HolderInterpreted {
@@ -47,7 +45,6 @@ class HigherKindTypeTest extends AirframeSpec {
47
45
.noLifeCycleLogging
48
46
49
47
" Airframe" should {
50
-
51
48
" support higher kind types" in {
52
49
design.build[HolderInterpreted ] { repo =>
53
50
repo.hello shouldBe " new interpretation"
You can’t perform that action at this time.
0 commit comments