Custom Rule Plugin - CompilationUnitTreeImpl ClassCastException

I have developed a custom rule recently housed in its own plugin .jar file which I’ve added to the /extensions/plugins of our SonarQube instance.

Recently I had to roll it back. The rule was not activated to run for one of our projects but Sonar Analysis still failed because of our plugin.

The reason:

Unable to run check class org.sonar.java.DefaultJavaResourceLocator - on file ‘src/main/java/com/edwardjones/iaa/oauth/DummyController.java’, To help improve SonarJava, please report this problem to SonarSource : see Join the Community | SonarQube

java.lang.ClassCastException: org.sonar.java.model.JavaTree$CompilationUnitTreeImpl cannot be cast to org.sonar.java.model.JavaTree$CompilationUnitTreeImpl

I do not see the CompilationUnitTreeImpl anywhere in the code-base and am stuck. I’m unsure how to get past this and could use a hand.

Would someone guide me past this? Thank you for your time all.

Hello Jeremy,

This class is not part of the sonar-java-plugin API, and so even it might work while running your unit tests, this won’t work in production. The classes are not available, and you can not cast your JavaTree classes to any implementation classes.

In order to fix this, you should check your custom-rules and remove cast to implementation classes. Now, I would be curious to know the reasons if you really need the cast in your rule. Maybe we can improve our API.

This issue looks like an incompatibility of bytecode. Can you check that the version of the SonarSource Java Analyzer installed on your SonarQube instance corresponds to the version of the sonar-java-plugin dependency of your custom-rules plugin?

Cheers,
Michael

Hi @Michael ,

Thank you for responding to me sir.

I’ve reviewed what you had suggested I take a look at and the only time I see any reference to an ‘Impl’ class is in the following snippet where I highlighted.

I also see a couple casts like the following sir.

Would I need to do something different?

**Lastly @Michael, regarding the dependencies, is this what you are referencing specifically sir? **
No version is provided. Do you think this could be the cause?

image

Also, does the following need to be in-sync with what is the sonar-java jar in the distribution? Could this also cause an issue like this?

image

Hello,

Yes, they have to. If your SQ instance is running version 6.14.0.254603 of the java analyzer (that’s an example), then you need to have the same version in your pom.xml.

You are necessarily providing a version, it is just probably defined in the properties part of your pom (it uses a propoerty ${java.plugin.version}).
However, note that the dependency over the java-checks module is extremely suspicious… and can also cause the issues you are getting. You are not supposed to use classes from this module in your custom rules. At worst, duplicate the classes from the checks module should be the way to go.

The first screenshot is implemented completely wrongly. The other 2 are fine.
For the first one, and without questionning the logic (I feel it would fail in many cases), here is how some part of your code should look like ideally:

// stop calling 'context.getTree()' on every lines
PackageDeclarationTree packageDecl = context.getTree().packageDeclaration();
if (packageDecl != null) {
  // this can not be null
  ExpressionTree packageName = packageDecl.packageName();
  // no need to check the class, the API helps
  if (packageName.is(Tree.Kind.MEMBER_SELECT)) {
    MemberSelectExpressionTree mset = (MemberSelectExpressionTree) packageName;
    // ...
  } else if (packageName.is(Tree.Kind.IDENTIFIER)) {
    IdentifierTree id = (IdentifierTree) packageName;
    // ...
}

Looking at the screenshot, I have the feeling that the person who implemented it might not have spent enought time on our tutorial, or didn’t explored enough the sonar-java-plugni API and already implemented rues. Their is a lot of wrong patterns in there. It would help to have another look.

Hope this helps,
Michael

@Michael

Thanks for your response.

Based on your response, will definitely need to upgrade the java.plugin.version property in the pom.xml. The version I’m in need to syncing it with is 6.1.0.20866.

Immediately out of the gate, the “JavaSymbol” class is no longer recognized (shown below). Do you have any API recommendations for doing the same thing with something that is supported with 6.1?

Would this do the trick in your opinion (or is best approach using your API)? Will be testing soon; however from your perspective, would this have an adverse impact?

image

Secondly, do we need to have this dependency in our custom plugin? Currently it isn’t there and other than the issue we had, things worked fine.

image

Lastly sir, I took a direct Docker image initially for 7.9.5 and it came with the sonar-java version of 5.13.*. 7.9.6 came with 6.1. Out of curiosity, what are the ramifications (if any) by using sonar-java 5.13 in the 7.9.6 distribution?

Thank you so much for your guidance. Very much appreciated.

Yep, JavaSymbol was again an implementation class which has been dropped. Use Symbol.MethodSymbol instead (the same way you are using Symbol.TypeSymbol a few lines below).

That would do the trick, and that should not have any adverse impact. If you can not use anymore some method, it was anyway wrong, because these methods should have never been used at first.

Like I said earlier, you should have this ${java.plugin.version} property defined somewhere, or it would simply not work.

  • SQ 7.9.5 embed sonarjava 5.13.*, but you should update it through the SonarQube marketplace to sonarjava 6.3.2.*.
  • You should then use API of java 6.3.2 as well. APIs from version 5.13 and 6.3 are absolutely not compatible.
  • The ramifications are that if you make your plugin rely on API of 5.13, it simply won’t work with the future versions of SonarQube. Note that new LTS 8.9 just got released, and it embeds SonarJava 6.15.1.*. This last version is much closer to 6.3 in terms of API, and a world apart from 5.13.

Good luck with your changes,
Michael

@Michael

Hi again sir, so I upgraded the version and it is now in-sync with the sonar-java.jar version in the SQ distribution.

I’m still seeing the same issue however. It partially helped. This problem was impacting 3 projects. 2 of them are now not impacted. The last one is and it makes no sense to me. Same ‘exact’ issue.

CompilationUnitTreeImpl does not exist anywhere in code-base and am not casting to any impl classes.

Based on your advice sir:
1.) I have confirmed that I am not casting to any impl classes (notes earlier in thread).
2.) Brought version in-sync.

One new thing I noticed:

Do you think this relates to the java-front end dependency? Where I need to set the scope to “provided”?

Is there anything else you can recommend?

Thank you for your time.