I try to write a custom Sonar-rule (Java) and struggle with the proper way for getting annotation of invoked Java methods.
This rule should detect illegal access to methods and fields marked as @VisibleForTesting
. Accesing such elements from production code is illegal, but access from the same class is legal.
My first approach is to implement BaseTreeVisitor.visitMethodInvocation(MethodInvocationTree)
and use the metadata of the belonging symbol:
- get annotations:
methodInvocationSymbol.metadata().annotations()
- analyse the names of the symbols of each
AnnotationInstance
(annotations class) and its owner (annotations package)
This works great as long other classes invoke the method. When the call is made inside the same class - the annotations name and package are set to !unknownSymbol!
.
I also tried an alternative approach: to analyse the IdentifierTree
of the AnnotationTree
(inside of BaseTreeVisitor.visitMethodInvocation(MethodInvocationTree))
, but I could not find the way how to get the package name of the annotation.
I use sonar-java-plugin 3.7.1 and sonar-plugin-api 5.1.
The code is commited in this mvn / Eclipse project.
The UnexpectedAccessCheckTest
contains 2 use-cases. The "InvokedFromOtherClass" works well. The InvokedFromSameClass
passes the test, but it happens only by accident - the annotation is not correctly detected.
It produces this output:
[main] DEBUG d.t.s.p.vft.checks.IsAnAnnotation - Checking Annotation.
Expected [com.google.common.annotations.VisibleForTesting]
got [.!unknownSymbol!]
The correct running use-case produces this:
[main] DEBUG d.t.s.p.vft.checks.IsAnAnnotation - Checking Annotation.
Expected [com.google.common.annotations.VisibleForTesting]
got [com.google.common.annotations.VisibleForTesting]
Do you have any hint for me?