İsteğe bağlı olarak adlandırılan argümanlara sahip bir statik ek açıklama kullanmak isterseniz, Federico'nın tekniğinde bir varyasyon gösteren bir yanıttır. Bu durumda, vaka eşleme ifadesindeki olası çağrı ifadelerini dikkate almanız gerekir. İsteğe bağlı bir argüman açıkça adlandırılmış olabilir, bir isim olmadan verilebilir veya mevcut olmayabilir. Bunların her biri, aşağıda gösterildiği gibi, c.prefix.tree
'da ayrı bir model olarak derleme zamanında ortaya çıkar. İşte
@compileTimeOnly("Must enable the Scala macro paradise compiler plugin to expand static annotations")
class noop(arg1: Int, arg2: Int = 0) extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro AnnotationMacros.noop
}
class AnnotationMacros(val c: whitebox.Context) {
import c.universe._
// an annotation that doesn't do anything:
def noop(annottees: c.Expr[Any]*): c.Expr[Any] = {
// cases for handling optional arguments
val (arg1q, arg2q) = c.prefix.tree match {
case q"new noop($arg1, arg2 = $arg2)" => (arg1, arg2) // user gave named arg2
case q"new noop($arg1, $arg2)" => (arg1, arg2) // arg2 without name
case q"new noop($arg1)" => (arg1, q"0") // arg2 defaulted
case _ => c.abort(c.enclosingPosition, "unexpected annotation pattern!")
}
// print out the values
println(s"arg1= ${evalTree[Int](arg1q)} arg2= ${evalTree[Int](arg2q)}")
// just return the original annotee:
annottees.length match {
case 1 => c.Expr(q"{ ${annottees(0)} }")
case _ => c.abort(c.enclosingPosition, "Only one annottee!")
}
}
def evalTree[T](tree: Tree) = c.eval(c.Expr[T(c.untypecheck(tree.duplicate)))
}
o isimler
arg2
bir örnek çağırma olduğunu ve bu yüzden ilk desen maç olacak -
case q"new noop($arg1, arg2 = $arg2)"
- Yukarıda:
object demo {
// I will match this pattern: case q"new noop($arg1, arg2 = $arg2)"
@noop(1, arg2 = 2)
trait someDeclarationToAnnotate
}
Not Ayrıca, çünkü bu desenler çalışma biçimi nedeniyle, etmelisin Makro kodu içinde varsayılan argüman değerini açıkça belirtin, ki bu maalesef biraz hacky, ama nihai değerlendirme sınıfı sizin için mevcut değil.
Bir deneme olarak, aslında evalTree[scope.of.class.noop](c.prefix.tree)
numaralı telefonu arayarak sınıfı oluşturmayı denedim, ancak Scala derleyici bir hata atar, çünkü ek açıklama makro kodunun içerisindeki ek açıklamalara yapılan bir başvuru geçersiz sayılır.
Bu çözüm ilginç ancak bazı nedenlerden dolayı bana “hacky” gibi görünüyor. Ayrıca, "B" türünde herhangi bir türden değil, Boolean türünde olmak istiyorum. Birisi ''Foo (“ AAA ”)' 'diyebilir ve kodlarının kurucunun imzasına bakarak derleneceğini düşünebilir. Ayrıca, daha fazla argüman eklemeye karar verirsem daha kafa karıştırıcı olur. Ama bu çözüm işe yarıyor, teşekkürler! –
Kaygılarınızı yansıtmak için yanıt düzenlendi. –
Bu kod şimdi derlenmiyor. Parametre türünü Boole'den Any'a değiştirdiğinizde, her şey yolunda. Hata iletisi şöyledir: '' Null türündeki bir ifade, örtük dönüştürme için uygun değil'' –