Hi,
I want prevent empty lines at the beginning of methods, but methods where the first line is a comment are ok. I try to read all trivia during setContext of my rule. Following code works fine during JUnit debug in eclipse.
@Rule(key = "UnnecessaryEmptyLineRule", name = "At least one unnecessary empty line exists.",
description = "A method shall not have an unnecessary empty line at the beginning or end.", priority = Priority.MAJOR, tags = {"brain-overload"})
public class UnnecessaryEmptyLineRule extends IssuableSubscriptionVisitor {
private Map<Integer, SyntaxTrivia> trivias = new HashMap<>();
@Override
public List<Tree.Kind> nodesToVisit() {
// Register to the kind of nodes you want to be called upon visit.
return Arrays.asList(Tree.Kind.CONSTRUCTOR, Tree.Kind.METHOD);
}
@Override
public void setContext(JavaFileScannerContext context) {
findTrivia(context.getTree());
super.setContext(context);
}
private void findTrivia(Tree tree) {
JavaTree javaTree = (JavaTree) tree;
if (javaTree.kind() == Tree.Kind.TOKEN) {
trivias.putAll(((SyntaxToken) tree).trivias().stream().collect(Collectors.toMap(SyntaxTrivia::startLine, t -> t)));
}
if (!javaTree.isLeaf()) {
javaTree.getChildren().forEach(this::findTrivia);
}
}
@Override
public void visitNode(Tree tree) {
MethodTree methodTree = (MethodTree) tree;
SyntaxToken firstLine = methodTree.closeParenToken();
if (methodTree.throwsToken() != null) {
firstLine = methodTree.throwsToken();
}
SyntaxToken lastLine = methodTree.lastToken();
int lastCodeLine = 0;
int firstCodeLine = 0;
List<StatementTree> statements = methodTree.block().body();
for (StatementTree statement : statements) {
if (firstCodeLine > statement.firstToken().line() || firstCodeLine == 0) {
firstCodeLine = statement.firstToken().line();
}
if (lastCodeLine < statement.lastToken().line()) {
lastCodeLine = statement.lastToken().line();
}
}
if (firstCodeLine - firstLine.line() > 1 && !trivias.containsKey(firstLine.line() + 1)) {
reportIssue(firstLine, "unecessary empty line");
}
if (lastLine.line() - lastCodeLine > 1) {
reportIssue(lastLine, "unecessary empty line");
}
}
}
When it’s executed via ‘mvn sonar:sonar’ on my project against a sonar server I get following error:
[INFO] Load project repositories (done) | time=44ms
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 12.046 s
[INFO] Finished at: 2020-12-18T14:10:57+01:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.sonarsource.scanner.maven:sonar-maven-plugin:3.7.0.1746:sonar (default-cli) on project custom-rules: Execution default-cli of goal org.sonarsource.scanner.maven:sonar-maven-plugin:3.7.0.1746:sonar failed: A required class was missing while executing
org.sonarsource.scanner.maven:sonar-maven-plugin:3.7.0.1746:sonar: org/sonar/java/model/JavaTree
[ERROR] -----------------------------------------------------
[ERROR] realm = plugin>org.codehaus.mojo:sonar-maven-plugin:3.7.0.1746
[ERROR] strategy = org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy
[ERROR] urls[0] = file:/C:/Users/tre/.m2/repository/org/sonarsource/scanner/maven/sonar-maven-plugin/3.7.0.1746/sonar-maven-plugin-3.7.0.1746.jar
[ERROR] urls[1] = file:/C:/Users/tre/.m2/repository/org/sonatype/plexus/plexus-sec-dispatcher/1.4/plexus-sec-dispatcher-1.4.jar
[ERROR] urls[2] = file:/C:/Users/tre/.m2/repository/org/sonatype/plexus/plexus-cipher/1.4/plexus-cipher-1.4.jar
[ERROR] urls[3] = file:/C:/Users/tre/.m2/repository/org/codehaus/plexus/plexus-utils/3.2.1/plexus-utils-3.2.1.jar
[ERROR] urls[4] = file:/C:/Users/tre/.m2/repository/org/sonarsource/scanner/api/sonar-scanner-api/2.14.0.2002/sonar-scanner-api-2.14.0.2002.jar
[ERROR] urls[5] = file:/C:/Users/tre/.m2/repository/commons-lang/commons-lang/2.6/commons-lang-2.6.jar
[ERROR] Number of foreign imports: 1
[ERROR] import: Entry[import from realm ClassRealm[project>com.tre.plugins:custom-rules:1.0.3, parent: ClassRealm[maven.api, parent: null]]]
[ERROR]
[ERROR] -----------------------------------------------------
[ERROR] : org.sonar.java.model.JavaTree
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/PluginContainerException
TestFile
class FooBar {
int foo() { // Noncompliant
return 1;
} // Noncompliant
void bar() {
// some comment
return 2;
}
}
All other code is pretty much the same as from https://github.com/SonarSource/sonar-java.
Any advice is appreciated.