Search code examples
javasonarquberule

Find object's class


Currently I have task to migrate some rules in SonarQube. Older ones are based on PMD and Checkstyle libraries. New ones need to be written with integrated Sonar rules (like most squid rules). Rule I'm currently working on needs to check if any method from class which contains "Dao" in it's name is used in loop.

I'm not quite experienced with rules migration and use of sonar libraries, so I am trying to use some parts from squid rules but I'm not able to find exactly what i need.

@Override
public void visitNode(Tree tree) {
   MethodInvocationTree methodInvocationTree = (MethodInvocationTree) tree;
   IdentifierTree methodName = methodName(methodInvocationTree);

   if ( methodClassContainsDaoInName(tree?) && insideLoop(tree?)) {
      reportIssue(methodName, "DAO methods should not be called inside loop");
   }
}

I'm still stuck on first method (methodClassContainsDaoInName()). Currently I'm trying to get method and object and check if that object's class has "Dao" in it's name. I use this command:

tree.parent().firstToken().text();

this command finds my object but only gives me it's name. I tried to do this:

tree.parent().firstToken().toClass();

but it gives me wrong class (If I recall correctly it returns symbol or token class).

Maybe someone know how could I convert that result to correct object? Maybe someone know better way to make this rule alive and could share some examples?


Solution

  • As a disclaimer, I'm not going to write the rule for you. Everything should be available from the API (syntax or semantic)... Once correctly formulated your requirement in term of rule writing and concepts.

    To reformulate the requirement: You are trying to verify that the class (the object...) owning the called method is a DAO (a.k.a. the owner), and if it's the case, raise an issue (if it's within a loop, but that's another story).

    Now, from the methodInvocationTree itself that you already have, access its associated symbol (there is a symbol() method in the API), then it's owner symbol, which should be the owning class. From the owner symbol, you can then access directly its name, and validate if it contains "Dao".

    Put into code:

    boolean methodFromDao = methodInvocationTree
      .symbol()
      .owner()
      .name()
      .contains("Dao");
    

    Important note: From the syntax API, you used another level of abstraction from the SonarJava API, which gives you access to symbols. In order to complete the semantic, SonarJava requires access to bytecode during analysis. If bytecode is not provided, it is most likely that methods won't be resolved by the semantic engine. Concretely, it means that all the symbols will be unknown, and you won't be able to know their owners.