Ausgabe
Meine Aufgabe ist es, Typinformationen in Java-ähnlicher Notation auszugeben (unter Verwendung von <
, >
für die Notation von Typargumenten). In Scala 2 habe ich diese kleine Methode scala.reflect.Manifest
als Quelle für das Typsymbol und seine Parameter:
def typeOf[T](implicit manifest: Manifest[T]): String = {
def loop[T0](m: Manifest[T0]): String =
if (m.typeArguments.isEmpty) m.runtimeClass.getSimpleName
else {
val typeArguments = m.typeArguments.map(loop(_)).mkString(",")
raw"""${m.runtimeClass.getSimpleName}<$typeArguments>"""
}
loop(manifest)
}
Leider sind in Scala 3 Manifeste nicht verfügbar. Gibt es eine Scala 3-native Möglichkeit, dies umzuschreiben? Ich bin offen für einige Inline-Makros. Was ich bisher probiert habe ist
inline def typeOf[T]: String = ${typeOfImpl}
private def typeOfImpl[T: Type](using Quotes): Expr[String] =
import quotes.reflect.*
val tree = TypeTree.of[T]
tree.show
// ^^ call is parameterized with Printer but AFAIK there's no way
// to provide your own implementation for it. You can to chose
// from predefined ones. So how do I proceed from here?
Ich weiß, dass Scala-Typen nicht alle als Java-Typen dargestellt werden können. Ich beabsichtige, nur einfache abzudecken, die die ursprüngliche Methode abdecken konnte. Keine Wildcards oder Existentials, nur vollständig aufgelöste Typen wie:
List[String]
Auflösung:List<String>
List[Option[String]]
Auflösung:List<Option<String>>
Map[String,Option[Int]]
Auflösung:Map<String,Option<Int>>
Lösung
Die letzte funktionierende Lösung, die ich mir ausgedacht habe, war:
def typeOfImpl[T: Type](using Quotes): Expr[String] = {
import quotes.reflect.*
TypeRepr.of[T] match {
case AppliedType(tpr, args) =>
val typeName = Expr(tpr.show)
val typeArguments = Expr.ofList(args.map {
_.asType match {
case '[t] => typeOfImpl[t]
}
})
'{
val tpeName = ${ typeName }
val typeArgs = ${ typeArguments }
typeArgs.mkString(tpeName + "<", ", ", ">")
}
case tpr: TypeRef => Expr(tpr.show)
case other =>
report.errorAndAbort(s"unsupported type: ${other.show}", Position.ofMacroExpansion)
}
}
Beantwortet von – SimY4
Antwort geprüft von – Clifford M. (FixError Volunteer)