Can I obtain the specific content of another file that a file depends on when analyzing it?

  • What language are you writing rules for?
    Java

  • What have you tried, and what’s your challenge / stumbling block
    I want to write a rule to identify the code that calls MQ within a transaction. The problem I am facing now is that I don’t know how to handle the following scenario:

public class TestController {

    private TestMq testMq = new TestMq();

    @Transactional
    public void test3() {
        testMq.sendMq();
    }
}

public class TestMq {

    @Autowired
    private PlatformRocketMQProducer mqProducer;

    public void sendMq() {
        mqProducer.syncSend("", "", Collections.emptyList());
    }
}

I know only that test3 calls testMq.sendMq();, but I cannot obtain the specific content of testMq.sendMq(); (as I need to know whether it calls the mqProducer.syncSend method underneath).

Is it possible to implement such a rule?

The version I am using is Community Edition Version 8.9.10 (build 61524).

Hello @Mine,

Thanks for sharing your use case.

Unfortunately, there is no easy way of analyzing source code from other source files within the sonar-java analyzer. The analyzer is fundamentally based on file-by-file analysis and the only information available about other files in the semantics.

One option is to write a custom plugin for SonarQube. Of course, this would require some additional setup, however, it would also give you much more flexibility.

For completeness: There are a couple of rules that do cross-file analysis (e.g. S5693). The APIs used by these rules are not stable, however, and we provide no support for them. Implementing cross-file custom rules for sonar-java is very prone to introducing memory leaks and issues due to improper cleanup. It is barely used by the analyzer itself and we can’t recommend this approach.

Hi, thanks for your reply. I noticed that the DefaultJavaFileScannerContext class is located in the package org.sonar.java.model instead of org.sonar.plugins.java.api. Could you advise me on how to use the class properly?

The DefaultJavaFileScannerContext is the internal implementation of the API JavaFileScannerContext, which is in the API package org.sonar.plugins.java.api. So you can simply use the context as JavaFileScannerContext, your plugin should not need to care about the internal implementation.

but,only DefaultJavaFileScannerContext has createAnalyzerMessage method

Thanks for the clarification. In most cases, JavaFileScannerContext#reportIssue should be enough. If you can’t get around having to save an issue location for later, it is true that it is slightly more complex. Unfortunately, using the createAnalyzerMessage is currently only intended for internal use.

However, if you have a look at what AnalyzerMessage actually does, it is not too complex. The purpose of the class is to remember all the relevant details we need to report an issue later on, without having to keep the AST in memory. The effort to implement a similar data structure should not be extremely high and you can probably keep it a bit simpler compared with the implementation in sonar-java.