Using org.sonar.java.matcher.MethodMatcher package in a custom rule

SONARQUBE version 7.7
Hi, i need to write a rule that check if exist a class that extends “myclass”.
If exist it is mandatory that this class overrides “mymethod”.
I’m used for write this rule, the sonar standard class for the rule S2160 that use org.sonar.java.matcher.MethodMatcher package.
below my code:

package org.sonar.samples.java.checks;
import org.sonar.check.Rule;
import org.sonar.java.matcher.MethodMatcher;
import org.sonar.java.matcher.TypeCriteria;
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.semantic.Symbol;
import org.sonar.plugins.java.api.semantic.Type;
import org.sonar.plugins.java.api.tree.ClassTree;
import org.sonar.plugins.java.api.tree.NewClassTree;
import org.sonar.plugins.java.api.tree.Tree;
import java.util.Collections;
import java.util.List;
import org.sonar.check.Priority;
 
@Rule(
		  key = "MySecondCustomCheck",
		  name = "MyClass class needs override MyMethod",
		  description = "MyClass class needs override MyMethod",
		  priority = Priority.CRITICAL,
		  tags = {"bug"})

public class MySecondCustomCheck extends IssuableSubscriptionVisitor {
	  private static final String MY_CLASS = "MyClass";
	  private static final MethodMatcher MyMethod = MethodMatcher.create().typeDefinition(TypeCriteria.subtypeOf(MY_CLASS)).name("MyMethod");
  @Override
  public List<Tree.Kind> nodesToVisit() {
	    return Collections.singletonList(Tree.Kind.CLASS);
	  }	 
  
	  @Override
	  public void visitNode(Tree tree) {
	    ClassTree classTree = (ClassTree) tree;
	    Symbol.TypeSymbol classSymbol = classTree.symbol();
	    if (classSymbol != null
	      && isDirectSubtypeOfThread(classSymbol)
	      && !overridesMyMethodMethod(classSymbol)){
	      Tree report = classTree.simpleName();
	      Tree parent = classTree.parent();
	      if(parent.is(Tree.Kind.NEW_CLASS)) {
	        NewClassTree newClassTree = (NewClassTree) parent;
	        report = newClassTree.identifier();
	      }
	      reportIssue(report, "Don't extend \"MY_CLASS\", since the \"MyMethod\" method is not overridden.");
	    }
	  }

	  private static boolean isDirectSubtypeOfThread(Symbol.TypeSymbol classSymbol) {
		    Type superClass = classSymbol.superClass();
		    return superClass != null && superClass.is(MY_CLASS);
		  }

		  private static boolean overridesMyMethodMethod(Symbol.TypeSymbol classSymbol) {
		    return classSymbol.lookupSymbols("MyMethod").stream().anyMatch(MyMethod::matches);
		  }
}

I have this error when i try to restart SonarQube:

2019.06.04 12:06:25 ERROR web[][o.s.s.p.Platform] Background initialization failed. Stopping SonarQube
java.lang.NoClassDefFoundError: Lorg/sonar/java/matcher/MethodMatcher;
	at java.lang.Class.getDeclaredFields0(Native Method)
	at java.lang.Class.privateGetDeclaredFields(Unknown Source)
	at java.lang.Class.getDeclaredFields(Unknown Source)
	at org.sonar.api.utils.FieldUtils2.getFields(FieldUtils2.java:51)
	at org.sonar.api.server.rule.RulesDefinitionAnnotationLoader.loadRule(RulesDefinitionAnnotationLoader.java:89)
	at org.sonar.api.server.rule.RulesDefinitionAnnotationLoader.loadRule(RulesDefinitionAnnotationLoader.java:70)
	at org.sonar.api.server.rule.RulesDefinitionAnnotationLoader.load(RulesDefinitionAnnotationLoader.java:62)
	at org.sonar.samples.java.MyJavaRulesDefinition.define(MyJavaRulesDefinition.java:59)
	at org.sonar.server.rule.RuleDefinitionsLoader.load(RuleDefinitionsLoad

Any Help?

The class org.sonar.java.matcher.MethodMatcher is not from api package. It is in java-frontend module which is marked as provided during compile time. But only classes under api packages are provided during analyze time or during rules loading at the server side. So you have to include and shadow the java-frontend package or copy the class to your plugin.

2 Likes

Thank you! it work!

Hey @bruna and @Josef_Prochazka (thanks for your answer!)

As a complementary note, I would like to add that we are currently planning to add the MethodMatchers to the SonarJava API. I would consequently strongly encourage you to vote for the following ticket in our backlog: SONARJAVA-2357

Cheers,
Michael