Skip to content

Commit

Permalink
surface (fix): Fixes #3418 Handle surface of List of generic tuples (#…
Browse files Browse the repository at this point in the history
…3427)

Again starting with the test, passing in Scala 2

Let us see if I will be able to fix it, this time I am not yet sure
where to start.
  • Loading branch information
OndrejSpanel authored Feb 28, 2024
1 parent 08d3fb1 commit a7a8828
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -522,21 +522,29 @@ private[surface] class CompileTimeSurfaceFactory[Q <: Quotes](using quotes: Q):
.collect { case (s: Symbol, i: Int, v: ValDef) =>
// E.g. case class Foo(a: String)(implicit b: Int)
// println(s"=== ${v.show} ${s.flags.show} ${s.flags.is(Flags.Implicit)}")
// Substitue type param to actual types
val resolved: TypeRepr = v.tpt.tpe match
case a: AppliedType =>
val resolvedTypeArgs = a.args.map {
case p if p.typeSymbol.isTypeParam && typeArgTable.contains(p.typeSymbol.name) =>
typeArgTable(p.typeSymbol.name)
case other =>
other
}
// Need to use the base type of the applied type to replace the type parameters
a.tycon.appliedTo(resolvedTypeArgs)
case TypeRef(_, name) if typeArgTable.contains(name) =>
typeArgTable(name)
case other =>
other
// Substitute type param to actual types

def resolveType(t: TypeRepr): TypeRepr =
t match
case a: AppliedType =>
// println(s"=== a.args ${a.args}")
// println(s"=== typeArgTable ${typeArgTable}")
val resolvedTypeArgs = a.args.map {
case p if p.typeSymbol.isTypeParam && typeArgTable.contains(p.typeSymbol.name) =>
typeArgTable(p.typeSymbol.name)
case other =>
resolveType(other)
}
// println(s"=== resolvedTypeArgs ${resolvedTypeArgs}")
// Need to use the base type of the applied type to replace the type parameters
a.tycon.appliedTo(resolvedTypeArgs)
case TypeRef(_, name) if typeArgTable.contains(name) =>
typeArgTable(name)
case other =>
other

val resolved: TypeRepr = resolveType(v.tpt.tpe)

val isSecret = hasSecretAnnotation(s)
val isRequired = hasRequiredAnnotation(s)
val isImplicit = s.flags.is(Flags.Implicit)
Expand Down
47 changes: 47 additions & 0 deletions airframe-surface/src/test/scala/wvlet/airframe/surface/i3418.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* 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 i3418 extends AirSpec {

case class A[P](data: List[(String, P)])
case class AA[T, P](data: List[(T, P)])

case class S(a: A[Int])
case class SS(a: AA[String, Long])

test("Support generic List of tuples") {
val s = Surface.of[S]
debug(s.params)
s.params.size shouldBe 1
val p1 = s.params(0)
p1.name shouldBe "a"
val a1 = p1.surface.params(0)
a1.name shouldBe "data"
a1.surface.name shouldBe "List[Tuple2[String,Int]]"
}

test("Support generic List of tuples with two type parameters") {
val s = Surface.of[SS]
debug(s.params)
s.params.size shouldBe 1
val p1 = s.params(0)
p1.name shouldBe "a"
val a1 = p1.surface.params(0)
a1.name shouldBe "data"
a1.surface.name shouldBe "List[Tuple2[String,Long]]"
}
}

0 comments on commit a7a8828

Please sign in to comment.