如何在 Xtend 的 Active Annotations 中获得完整的 return 类型转发?
How to get full return type forwarding in Xtend's Active Annotations?
我正在通过编写一个简单的 "Logged" 来试用 Xtend 的活动注释
调用方法时用于跟踪的注解。基本上我想在 Xtend 中写这个:
@Logged
override onCreate()
{
sampleFuncCall()
}
并在 Java 中得到这样的东西:
@Override void onCreate()
{
Log.d("TAG", "onCreate started");
sampleFuncCall();
Log.d("TAG", "onCreate ended");
}
这是我的第一次尝试:
@Active(LoggedAnnotationProcessor)
@Target(ElementType.METHOD)
annotation Logged {
}
class LoggedAnnotationProcessor extends AbstractMethodProcessor
{
override doTransform(MutableMethodDeclaration method, extension TransformationContext context)
{
val prefix = "wrapped_"
method.declaringType.addMethod(prefix + method.simpleName) [ m |
m.static = method.static
m.visibility = Visibility.PRIVATE
m.docComment = method.docComment
m.exceptions = method.exceptions
method.parameters.forEach[ p | m.addParameter(p.simpleName, p.type) ]
m.body = method.body
m.primarySourceElement = method
m.returnType = method.returnType
]
val voidMethod = method.returnType === null || method.returnType.void
method.body = [ '''
try {
android.util.Log.d("TAG", "«method.simpleName» start");
«IF (!voidMethod) method.returnType» ret = «ENDIF»
«prefix + method.simpleName»(«method.parameters.map[simpleName].join(", ")»);
android.util.Log.d("TAG", "«method.simpleName» end");
«IF (!voidMethod)»return ret;«ENDIF»
}
catch(RuntimeException e) {
android.util.Log.d("TAG", "«method.simpleName» ended with exception "
+ e.getClass().getSimpleName() + "\n" + e.getMessage());
throw e;
}
''']
}
}
(请注意,我找不到修改 method.body 的方法,必须创建一个带有 "wrapped_" 前缀的新私有方法。我想这对性能不利,所以如果你知道如何直接修改方法的主体,请分享)。
这里我在使用方法 returning void
时遇到了问题。
如果未明确声明方法的 return 类型,我会收到以下错误:
Cannot call method 'isVoid' on a inferred type reference before the
compilation phase. Check isInferred() before calling any methods.
好的,我可以添加 method.returnType.inferred 的检查,但如何处理它 - 似乎在这个阶段我们仍然不知道它是否会无效,但知道那是对于转发方法的 return 值至关重要。
请告诉我写这样的注释的正确方法是什么,谢谢!
也许你应该推迟计算。到闭幕
method.body = [
val voidMethod = method.returnType === null || method.returnType.void
'''
try {
android.util.Log.d("TAG", "«method.simpleName» start");
«IF (!voidMethod)»«method.returnType» ret = «ENDIF»
«prefix + method.simpleName»(«method.parameters.map[simpleName].join(", ")»);
android.util.Log.d("TAG", "«method.simpleName» end");
«IF (!voidMethod)»return ret;«ENDIF»
}
catch(RuntimeException e) {
android.util.Log.d("TAG", "«method.simpleName» ended with exception "
+ e.getClass().getSimpleName() + "\n" + e.getMessage());
throw e;
}
''']
我正在通过编写一个简单的 "Logged" 来试用 Xtend 的活动注释 调用方法时用于跟踪的注解。基本上我想在 Xtend 中写这个:
@Logged
override onCreate()
{
sampleFuncCall()
}
并在 Java 中得到这样的东西:
@Override void onCreate()
{
Log.d("TAG", "onCreate started");
sampleFuncCall();
Log.d("TAG", "onCreate ended");
}
这是我的第一次尝试:
@Active(LoggedAnnotationProcessor)
@Target(ElementType.METHOD)
annotation Logged {
}
class LoggedAnnotationProcessor extends AbstractMethodProcessor
{
override doTransform(MutableMethodDeclaration method, extension TransformationContext context)
{
val prefix = "wrapped_"
method.declaringType.addMethod(prefix + method.simpleName) [ m |
m.static = method.static
m.visibility = Visibility.PRIVATE
m.docComment = method.docComment
m.exceptions = method.exceptions
method.parameters.forEach[ p | m.addParameter(p.simpleName, p.type) ]
m.body = method.body
m.primarySourceElement = method
m.returnType = method.returnType
]
val voidMethod = method.returnType === null || method.returnType.void
method.body = [ '''
try {
android.util.Log.d("TAG", "«method.simpleName» start");
«IF (!voidMethod) method.returnType» ret = «ENDIF»
«prefix + method.simpleName»(«method.parameters.map[simpleName].join(", ")»);
android.util.Log.d("TAG", "«method.simpleName» end");
«IF (!voidMethod)»return ret;«ENDIF»
}
catch(RuntimeException e) {
android.util.Log.d("TAG", "«method.simpleName» ended with exception "
+ e.getClass().getSimpleName() + "\n" + e.getMessage());
throw e;
}
''']
}
}
(请注意,我找不到修改 method.body 的方法,必须创建一个带有 "wrapped_" 前缀的新私有方法。我想这对性能不利,所以如果你知道如何直接修改方法的主体,请分享)。
这里我在使用方法 returning void
时遇到了问题。
如果未明确声明方法的 return 类型,我会收到以下错误:
Cannot call method 'isVoid' on a inferred type reference before the compilation phase. Check isInferred() before calling any methods.
好的,我可以添加 method.returnType.inferred 的检查,但如何处理它 - 似乎在这个阶段我们仍然不知道它是否会无效,但知道那是对于转发方法的 return 值至关重要。
请告诉我写这样的注释的正确方法是什么,谢谢!
也许你应该推迟计算。到闭幕
method.body = [
val voidMethod = method.returnType === null || method.returnType.void
'''
try {
android.util.Log.d("TAG", "«method.simpleName» start");
«IF (!voidMethod)»«method.returnType» ret = «ENDIF»
«prefix + method.simpleName»(«method.parameters.map[simpleName].join(", ")»);
android.util.Log.d("TAG", "«method.simpleName» end");
«IF (!voidMethod)»return ret;«ENDIF»
}
catch(RuntimeException e) {
android.util.Log.d("TAG", "«method.simpleName» ended with exception "
+ e.getClass().getSimpleName() + "\n" + e.getMessage());
throw e;
}
''']