C'è un modo per restituire uno List
di TypeSymbol
s per ogni classe in un pacchetto utilizzando le macro?Scala macro: ottenere un elenco di TypeSymbols da utilizzare in fase di esecuzione
Quello che sto cercando di realizzare è quello di scrivere una macro che dà fuori qualcosa di equivalente a questo elenco:
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> case class MyClass1()
defined class MyClass1
scala> case class MyClass2()
defined class MyClass2
scala> val typeSymbols = List(typeOf[MyClass1].typeSymbol, typeOf[MyClass2].typeSymbol)
typeSymbols: List[reflect.runtime.universe.Symbol] = List(class MyClass1, class MyClass2)
Qui è la mia messa a punto:
Ho un pacchetto chiamato foo
, in base al quale questi sono definito:
trait FooTrait
case class Bar() extends FooTrait
case class Bar() extends FooTrait
Ecco la mia macro che ottiene tutti i simboli di tipo per le classi sotto foo che si estendono FooTrait
:
def allTypeSymbols_impl[T: c.WeakTypeTag](c: Context)(packageName: c.Expr[String]) = {
import c.universe._
// Get package name from the expression tree
val Literal(Constant(name: String)) = packageName.tree
// Get all classes under given package name
val pkg = c.mirror.staticPackage(name)
// Obtain type symbols for the classes - implementation omitted
val types = getTypeSymbols(c.universe)(List(pkg))
// Apply method for List. For easy readability in later applications
val listApply = Select(reify(List).tree, newTermName("apply"))
val result = types.map {
t =>
val typeName = c.Expr[TypeSymbol](Ident(t))
println(s"Typename: $typeName, $t, ${t.toType}")
reify(typeName.splice).tree
}
println(s"RESULT: ${showRaw(result)}")
c.Expr[List[reflect.runtime.universe.TypeSymbol]](Apply(listApply, result.toList))
}
I primi println
stampa:
Typename: Expr[c.universe.TypeSymbol](Bar), class Bar, foo.Bar
Typename: Expr[c.universe.TypeSymbol](Baz), class Baz, foo.Baz
la seconda stampa:
RESULT: List(Ident(foo.Bar), Ident(foo.Baz))
Ma ottengo questo messaggio di errore:
[error] no type parameters for method any2ArrowAssoc: (x: A)ArrowAssoc[A] exist so that it can be applied to arguments (<notype>)
[error] --- because ---
[error] argument expression's type is not compatible with formal parameter type;
[error] found : <notype>
[error] required: ?A
[error] Note that <none> extends Any, not AnyRef.
[error] Such types can participate in value classes, but instances
[error] cannot appear in singleton types or in reference comparisons.
Cosa devo fare per fare questo lavoro? Sospetto di dover scrivere qualcos'altro invece di Ident
, ma non riuscivo a capire cosa.
Uso di Scala 2.10.2.
Grazie in anticipo!
Grazie ancora Travis! Li ho convertiti in 'TypeSymbol's nella macro. Ho fatto un 'Map' dei simboli ai loro campi' val' dichiarati nelle classi case, ma sto ricevendo questo errore mentre provavo ad accedervi: http://pastebin.com/8dHDRMYy Dovrei rilassare il inserisci i requisiti e vai per "Any" come hai fatto tu? Inoltre, come dovrei farlo per MethodSymbols? C'è un modo? – Emre