SonarJava custom rule. package declaration

java

(Nate) #1

Must-share information (formatted with Markdown):

  • which versions are you using (SonarQube, Scanner, Plugin, and any relevant extension)
  • what are you trying to achieve
  • what have you tried so far to achieve this

My company is currently using SonarQube 6.7.4. and SonarJava version 5.5.0

I am trying to write a custom rule that needs to read which package a given java file is in.

e.g.

package com.foo.bar.mypackage;
     // ^ I need to read this line.

Currently I explored the PackageDeclarationTree interface but there doesn’t seem a way to extract the

string out of the packageName() ExpressionTree. I initially thought that

something like
packageDeclaration.packageName().symbolType().fullyQualifiedName() would give me the package name but it instead returns !unknownSymbol!, which seems strange.

I also tried casting packageName() to a MemberSelectionExpressionTree, which exposes identifier() and expression() methods. The identifier() gives me the very last part of my package mypackage but again the expression part is an ExpressionTree.


(Tibor Blenessy) #2

hello @nnnkkk,

unfortunately, this is currently not possible, because we don’t associate entry in symbol table for package declarations. I created the ticket to improve the API https://jira.sonarsource.com/browse/SONARJAVA-3085

However there are two quite straightforward workarounds, depending on what you want to achieve

  1. On syntax level, you can recursively loop through package declaration (which will be of type MemberSelectExpressionTree) to construct the name of the package. Example of doing this can be found in the utility method here https://github.com/SonarSource/sonar-java/blob/d881dd0c37c3893f3614bcb64c11887d0722a5b1/java-frontend/src/main/java/org/sonar/java/model/PackageUtils.java#L37

  2. If you are starting from any type declared in the compilation unit, you will be able to get the owner of this type, which will be the package symbol. For example this will work context.getTree().types().get(0).symbol().owner().name (this expression is accessing the first type declared in the compilation unit, getting the symbol and its owner is necessarily the package of the compilation unit).


(Nate) #3

Hi Tibor,

Thanks for your reply. I noticed that we are actually using SonarQube 7.6 and SonarJava 5.10.1 instead. Am I in luck with the newer version or is the API still limited?

Best


(Nate) #4

@saberduck

I ended up going with your first suggestion. The utility method seems exposed publicly So we reused it directly.


(Tibor Blenessy) #5

@nnnkkk , the method is exposed publicly, however it is not part of the api package org.sonar.plugins.java.api, so it will not be available during runtime to your plugin. Plugins are loaded by different classloaders for isolation, and they can only use classes in the API package.