Sonar-java-plugin 6.2.0.21135 - MissingTypeBinding in Test Classes

Hi,

I have a problem with migration my java custom rules from sonar-java-plugin version 6.1.0.20866 to 6.2.0.21135. I have some rules which check if a certain annotation exists on the class definition. I used to check the fully qualified name of the annotation like so:

    annotationTree.symbolType().fullyQualifiedName().equals("javax.inject.Named")

This worked until I tried to migrate my custom java rule plugin to version 6.2.0.21135. With this version, the check fails, as annotationTree.symbolType() holds a “org.eclipse.jdt.internal.compiler.lookup.MissingTypeBinding”. So the result of annotationTree.symbolType().fullyQualifiedName() is just the simple Name. “Named” in the case above.

I’ve tested this with the following TestRule:

    package de.empic.sonar.rule;

    import com.google.common.collect.ImmutableList;
    import org.sonar.api.utils.log.Logger;
    import org.sonar.api.utils.log.Loggers;
    import org.sonar.check.Priority;
    import org.sonar.check.Rule;
    import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
    import org.sonar.plugins.java.api.JavaFileScanner;
    import org.sonar.plugins.java.api.tree.AnnotationTree;
    import org.sonar.plugins.java.api.tree.Tree;

    import java.util.List;

    @Rule(
            key = JavaTestRule.KEY,
            priority = Priority.MINOR,
            name = "Java Test Rule",
            tags = {"testrule"},
            description = "TestRule!")
    public class JavaTestRule extends IssuableSubscriptionVisitor implements JavaFileScanner {

        private final Logger LOGGER = Loggers.get(getKey());

        public static final String KEY = "de.empic.sonar.rule.JavaTestRule";

        @Override
        public List<Tree.Kind> nodesToVisit() {
            return ImmutableList.of(Tree.Kind.ANNOTATION);
        }

        @Override
        public void visitNode(Tree tree) {
            if (tree.kind() == Tree.Kind.ANNOTATION) {
                LOGGER.warn(((AnnotationTree)tree).symbolType().fullyQualifiedName());
            }
        }

        public String getKey() {
            return KEY;
        }

    }

My test class is:

    package de.empic.sonar.testFiles;

    import org.apache.log4j.Logger;

    import javax.annotation.PostConstruct;
    import javax.faces.view.ViewScoped;
    import javax.inject.Inject;
    import javax.inject.Named;
    import java.io.Serializable;

    @ViewScoped
    @Named
    public class TestClass implements Serializable
    {
       private static final long serialVersionUID = 1L;

       Logger logger = Logger.getLogger(this.getClass());

       @Inject
       private RemoteManagement slWebManagement;

       @PostConstruct
       public void init()
       {
          if (logger.isInfoEnabled())
          {
             logger.info("initializing corrective action handling for OAS");
          }
       }
    }

Running the rule in a JUnit test against the test class with sonar java plugin verions 6.1.0.20866.gives the following Result:

    [WARN] javax.faces.view.ViewScoped
    [WARN] javax.inject.Named
    [WARN] javax.inject.Inject
    [WARN] javax.annotation.PostConstruct

Running it with sonar java plugin version 6.2.0.21135 gives the following result:

    [WARN] ViewScoped
    [WARN] Named
    [WARN] Inject
    [WARN] PostConstruct

I suppose my problem is related to SONARJAVA-3297 which states:

Test files which are used to test rules are not always correct java code. This led to numerous issues in the past (wrong resolution, more difficult debug sessions, useless investigation, bugs, introduction of false positives or false negatives).

In order to to improve the quality of the rules, let’s move the test sources in a dedicated module, compiled and written in valid Java.

But there is no hint on how to move my own test sources to a dedicated module.

Can somebody help me?

Hey @tschindler,

To me, it looks like the bytecode of the dependencies which would provide the annotations you are targeting is not provided anymore to the rules Verifier. It might indeed be a consequence of the change we made. However, if it’s the case, you might simply need to provide a jar that contains these annotations, and there should be a way to do it using the verifier.

You should not have to do that, it should work as before. But indeed, you might have to change the way you were providing bytecode of the dependencies used by your test classes. Have a look at the changes we did on our custom rules example when bumping support to our Java Analyzer 6.2, it will certainly help you:

If you wonder what is "target/test-jars", it comes from this line, which places jar used by test classes into a particular folder:

https://github.com/SonarSource/sonar-custom-rules-examples/blob/master/java-custom-rules/pom.xml#L205


Finally, and as a side note, just a small hint regarding your example code. Instead of writing this:

annotationTree.symbolType().fullyQualifiedName().equals("javax.inject.Named")

I would write this:

annotationTree.symbolType().is("javax.inject.Named")

Which makes your rule easier to read.

Also, we just released java Analyzer 6.3, could you give it a try?

We reworked some of custom-rules related API and provided some new useful methods and classes:

  • A new RulesVerifier interface,
  • A useful MethodMatchers to simplify targeting of methods
  • Parameterized type information notably

Hope this helps,
Michael

1 Like

Hi @Michael,

thank you very much for your help. I changed now to the new plugin version 6.3.0.21585 and changed all my tests using now the new RulesVerifier interface and it worked perfectly. Without your help I would have been lost.

Best Regards
Thomas

Glad it helped! Happy rules coding!