2013-07-15 8 views
7

पर टाइप करने के लिए TypeSymbols की एक सूची प्राप्त करना क्या मैक्रोज़ का उपयोग कर पैकेज के तहत प्रत्येक वर्ग के लिए TypeSymbol एस List वापस करने का कोई तरीका है?स्कैला मैक्रोज़: रनटाइम

क्या मैं प्राप्त करने के लिए कोशिश कर रहा हूँ उस मैक्रो बाहर कुछ बराबर देता है इस सूची में लिखने के लिए है:

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) 

यहाँ मेरी सेटअप है:

मैं foo नाम के एक पैकेज, जिसके तहत इन हैं परिभाषित:

trait FooTrait 

case class Bar() extends FooTrait 

case class Bar() extends FooTrait 

यहाँ मेरी मैक्रो foo कि विस्तार 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)) 
} 

पहले println प्रिंट:

Typename: Expr[c.universe.TypeSymbol](Bar), class Bar, foo.Bar 
Typename: Expr[c.universe.TypeSymbol](Baz), class Baz, foo.Baz 

दूसरा एक प्रिंट:

RESULT: List(Ident(foo.Bar), Ident(foo.Baz)) 

लेकिन मैं इस त्रुटि संदेश मिलता है:

[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. 

क्या मैं करने के लिए क्या करना चाहिए यह काम करो? मुझे संदेह है कि मुझे Ident के बजाय कुछ और लिखना है, लेकिन मुझे पता नहीं लगा सका।

स्कैला 2.10.2 का उपयोग करना।

अग्रिम धन्यवाद!

उत्तर

7

आप reifyType का उपयोग करने के क्रम ब्रह्मांड में प्रतिबिंब कलाकृतियों को बनाने के लिए है:

import scala.language.experimental.macros 
import scala.reflect.macros.Context 

object PackageMacros { 
    def allTypeSymbols[T](packageName: String) = macro allTypeSymbols_impl[T] 

    def allTypeSymbols_impl[T: c.WeakTypeTag](c: Context)(
    packageName: c.Expr[String] 
) = { 
    import c.universe._ 

    val pkg = packageName.tree match { 
     case Literal(Constant(name: String)) => c.mirror.staticPackage(name) 
    } 

    val types = pkg.typeSignature.members.collect { 
     case sym: ClassSymbol => 
     c.reifyType(treeBuild.mkRuntimeUniverseRef, EmptyTree, sym.toType) 
    }.toList 

    val listApply = Select(reify(List).tree, newTermName("apply")) 

    c.Expr[List[Any]](Apply(listApply, types)) 
    } 
} 

यह आपको प्रकार टैग, नहीं प्रतीकों की एक सूची दे देंगे, लेकिन आप बहुत आसानी से प्रतीकों प्राप्त कर सकते हैं, या तो इस तरह :

scala> PackageMacros.allTypeSymbols("foo").map(_.tpe.typeSymbol) foreach println 
class Baz$ 
class Bar 
class Baz 
trait FooTrait 
class Bar$ 

या मैक्रो में ही।

+0

धन्यवाद फिर से ट्रेविस! मैंने उन्हें मैक्रो में टाइप टाइपबोल में बदल दिया। मैंने केस क्लास में घोषित अपने 'वैल' फ़ील्ड में प्रतीकों से 'मैप' बनाया है, लेकिन मुझे इसे एक्सेस करने का प्रयास करते समय यह त्रुटि मिल रही है: http://pastebin.com/8dHDRMYy क्या मुझे आराम करना चाहिए टाइप आवश्यकता है और आपके जैसा 'कोई भी' के लिए जाना है? इसके अलावा, मैं MethodSymbols के लिए यह कैसे करूँगा? क्या उधर रास्ता है? – Emre

संबंधित मुद्दे