Hello,
I created a rule that checks whether each non-primitive field in a class is initialized in the constructor/in declaration. I have created several tests that exhaust most possible code variations, compliant and noncompliant, and these all pass.
However, when I try to run the rule on the actual codebase, I get an error saying:
SonarQube is unable to analyze file : '<my-java-file>': org.sonar.java.model.declaration.MethodTreeImpl cannot be cast to org.sonar.java.model.declaration.MethodTreeImpl -> [Help 1]
The nature of the class in which the analyzer fails is that it has no fields and no constructors. It has one static method that uses generic types. However, my rule only ever traverses past MethodTree
nodes that have Kind "CONSTRUCTOR
" (as you will see below).
When I copy the java class into my file of noncompliant and compliant tests, it analyzes and passes with no problem. It is only when the rule is run directly on the codebase that the analysis fails.
I have extended BaseTreeVisitor
in order to implement this rule (and am therefore using visitXXX()
to express the rule). I have made sure to override all other visit-methods with empty implementations besides the ones I actually need, in order to not get unexpected behaviour due to the base implementation of these methods from BaseTreeVisitor
. All of the relevant code that I wrote and that is actually related to the casting of trees to MethodTree
is shown below (“constructors” is a list of MethodTree
:s):
In visitClass(ClassTree tree)
:
for (Tree t : tree.members()) {
if (t.is(Kind.CONSTRUCTOR)) {
constructors.add((MethodTree) t);
}
}
In visitMethodInvocation(MethodInvocationTree tree)
:
public void visitMethodInvocation(MethodInvocationTree tree) {
if (tree.symbol().declaration().is(Kind.CONSTRUCTOR)) { // if the method invocation is a constructor invocation
...
scan(tree.symbol().declaration()); // declaration() should be a MethodTree representing the invoked constructor
...
}
}
In visitMethod(MethodTree tree)
:
public void visitMethod(MethodTree tree) {
if (tree.is(Kind.CONSTRUCTOR)) {
scan(tree.block());
}
}
As you can see in the code, I only ever work with Kind.CONSTRUCTOR
, and I always check it before casting (which I only do in 1 place). I honestly don’t understand how this error could occur; any help is greatly appreciated.
Best Regards,
Simon Sirak
PS: I use SonarQube version 5.6.6.