I am in the process of writing a few custom rules and have a few questions that I believe are not documented.
Which order of traversal does IssuableSubscriptionVisitor or BaseTreeVisitor use?
Does it follow the normal call by value java evaluation strategy?
Is parsing raw Java code into an AST done per file base? More generally,
if I have a visitor implementation based on IssuableSubscriptionVisitor or BaseTreeVisitor, will a new visitor instance be used for each file SonarQube checks?
Welcome in this forum and the world of (java) custom rule writing.
As you might have seen, Java Custom rules are going to be relying on the SonarJava plugin, which is open source. There is then a good chance that you will find most of your answers directly in the source code. Have a look at its github repository: SonarSource/sonar-java. It will also give you the opportunity to look how to write a rule, if it’s behavior should be close from one already existing.
Now, to answer your question:
The BaseTreeVisitor is going to rely on the accept() method that each Java Tree implements. Its usual entry point is the CompilationUnitTree, which will then lead to exploration of all the children, recursively, as defined by the strategy implemented by each visit...() method. You can control the order of the visit by overriding some methods, which will then allows you to skip some part of the code for instance.
The IssuableSubscriptionVisitor, as being a SubscriptionVisitor, is relying directly on the AST structure, and will visit everything, from the CompilationUnitTree, as root, to the tokens, as leaves. You can not easily decide to bypass some part of the AS, but you can target some elements very precisely.
The analysis, and parsing is done on a per-file basis. However, it’s usually the same instance of the rule which is going to be reused from file to file during the whole analysis. You should then be careful on what you may store in your rules. Knowing that from each tree you have a link to the children and parents, storing trees during analysis and not releasing the resources between files may lead to memory leaks.