How do I get full forwarding of the return type in Xtend Active Annotations?

I have tried Xtend Active Annotations by writing a simple "Recorded" annotation to keep track of when calling methods. Basically I want to write this in Xtend:

@Logged
override onCreate()
{
   sampleFuncCall()
}

      

and get something like this in Java:

@Override void onCreate()
{
   Log.d("TAG", "onCreate started");
   sampleFuncCall();
   Log.d("TAG", "onCreate ended");
}

      

Here's my first try:

@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;                
                }
            ''']
    }
}

      

(Note that I could not find a way to change the .body method and must create a new private method with the "wrapped_" prefix. I think this is bad for performance, so if you know how to change the body method directly, please share) ...

This is where I run into problems with methods that return void

. If the return type of the method was not explicitly declared, I get the following error:

It is not possible to call the 'isVoid' method to reference the intended type until the compile time. Check isInferred () before calling any methods.

Okay, I can add a check for the .returnType.inferred method, but what to do about it - it seems like at this point we still don't know if it will be invalid or not, but knowing that it is important to forward the return value of the method.

Please tell me what is the way to write such an annotation, thanks!

+3


source to share


1 answer


Perhaps you should postpone the computation. to closure



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;                
            }
        ''']

      

+3


source







All Articles