vendredi 14 janvier 2022

Can an `ElementVisitor` be used to traverse the statements in the body of a method?

I'm trying to make a custom annotation that checks to see if a certain method is called in a method's body annotated with it. Something like:

@TypeQualifierDefault(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
@interface MutatingMethod {
}

interface Mutable {
  void preMutate();
  void postMutate();
  // other methods
}

And then within a certain Mutable class we would have:

class Structure<T> implements Mutable {
  @MutatingMethod
  void add(T data) {
    preMutate();
    // actual mutation code
    postMutate();
  }
}

I want to be able to get warnings of some sort if the body of a method like add that is annotated with @MutatingMethod does not include calls to preMutate and postMutate. Can an ElementVisitor (javax.lang.model.element.ElementVisitor) be used to traverse the (possibly obfuscated) statements and method calls in the body of a method? If so what would that look like? If not what else can I use?

Just to clarify, I know this is impossible (or more difficult) to accomplish in runtime via bytecode decompilation, so this annotation is meant to only work during compilation via reflection (java.lang.reflect.* and javax.lang.model.*) and is not retained in class files.

You are free to modify the code however you want to get it to work, for example by introducing a new annotation called @MutableType that Structure and any other Mutable types must be annotated with it for this to work.

A cherry on top would be to assert that preMutate is called before postMutate and not after.

It shouldn't matter but I'm using Gradle and the IntelliJ IDEA IDE.

Any help is greatly appreciated; material on this is strangely scarce and/or inadequate on the web. I have been using publicly available sources to learn about this!





Aucun commentaire:

Enregistrer un commentaire