Two custom rules are blocking each other

Hello,
I am currently re-implementing the two Checkstyle checks NoWhitespaceAfter and NoWhitespaceBefore rules in SonarQube. So I have …

  • NoWhitespaceAfter.java
  • NoWhitespaceBefore.java
  • AbstractNoWhitespace.java (, from which both rules are inheriting, to unite identical logic snippets.)

Unit tests are passing. However, when testing both rules on a local SonarQube server each rule activated on its own is also functioning but as soon as both rules are activated together both rules are detecting compliance and noncompliance cases wrong. For example, the NoWhitespaceBefore only finds whitespaces before < and > tokens but not the other tokens like ++ -- . ... ; when I am checking my test file NoWhitespaceBeforeCheck_AllowLineBreaksFalse_TestFile with SonarLint (as seen on the screenshot).

Please check out my example project to this issue. I’d be really thankful if someone would be looking into that. I also tried the following on a separate branch but the problem persists:

  • Remove the AbstractNoWhitespace to make sure that there is no dependency between both rules anymore.
  • I am using context.getFileLines() (code line) which extracts the Java code to analyze to find neighboring whitespaces. On this branch instead of calling it once I am calling it for every token to visit, to make sure that I am not analyzing outdated code snippets.

I am also wondering if it’s not allowed to override both visitNode(Tree) AND visitToken(SyntaxToken) which I am doing in NoWhitespaceBefore.java.

Kind regards,
Johannes

1 Like

I found the bugs!

  1. It was a NullException I didn’t see because I didn’t turn on “Verbose output” and “Analysis log” in the Eclipse IDE while my rules analyzed different Java files.
  2. And I didn’t know that a rule class instance is only created once for multiple Java files. This caused the value of a class attribute didn’t “reset” for each Java file - which my code was relying on.

QUESTION: This leads me to a follow-up question. Is there an elegant way to call a method only once for each Java file being analyzed? I mean I could probably do something like that:

private HashSet<String> visitedFiles;
	
@Override
public void visitNode(Tree pTree) {
	String visitedFile = context.getInputFile().absolutePath();
	if(visitedFiles.contains(visitedFile)) {
		methodCalledOncePerFile();
		visitedFiles.add(visitedFile);
	}
}

… or I also found the Sensor Inteface. But maybe there is a better way of doing this.

3 Likes

Hey @johannes_ctrl ,

Sorry for getting back so late on this. From what I can see, your abstract NoWhitespaceCheck is an IssuableSubscriptionVisitor, extending itself SubscriptionVisitor. The SubscriptionVisitor class has a method leaveFile(), called only once per file. You can override this one, as it will be call after the complete exploration of the file. We usually use it to clear the state of a rule.

You want to be careful with what you store, as it might lead to memory leaks.

Cheers,
Michael