SonarLint intergrating with SonarQube (with custom rules) inconsistencies - Java

I’m trying to make a custom QualityProfiles (in java) in SonarQube work for SonarLint using Android Studio. However, I found some inconsistencies between SonarQube vs SonarLint.

For example, in SonarQube, it would be able to detect all instances of this method:

SharedPreferences mPrefs = context.getSharedPreferences(...)

with

public void visitMethodInvocation(MethodInvocationTree tree) {
    if (tree != null && tree.symbol() != null && tree.symbol().name() != null) {
        if (tree.symbol().name().equals("getSharedPreferences")) {
            context.reportIssue(this, tree, "getSharedPreferences  was used");}}}

However, in SonarLint, no instance of the method was detected. Also, I had to put in the check

if (tree != null && tree.symbol() != null && tree.symbol().name() != null)

because SonarLint could potentially crash after scanning couple lines even though it did not crash in SonarQube. I have a method to trace variables’ declaration and it works just fine in SonarQube (flag all the issues) but it is strange that SonarLint is having problem right at the first step.

I am using the latest version of SonarQube 7.6 and the latest version of SonarLint 4.0.2.3009

Potential related problem:

Hi @ToanKst

To my knowledge, this might come from a difference when processing the project classpath. When processing a file, SonarJava relies on:

  • the project dependencies (usually JAR files)
  • the compiled .class of other files of the project

The second point might be an issue in IntelliJ based IDEs like Android Studio, because the project is not compiled “on the fly” like in Eclipse. I’m not saying this is a long run solution, but maybe you should try to manually trigger a full build of the project in Android Studio, then see if your check works better.

Also, look at SonarLint logs (enable verbose + analysis output) and look for messages like “Unable to resolve type ‘xxxx’” that would indicate a classpath configuration issue.

Thanks for the reply, the problem is indeed with the project dependencies. After reading the link Emmanuel Comba mentioned in Sonar Rule: Symbol and SymbolType always unknown, I learn that the project being scanned provide the environments, therefore, it was able to detect all the methods that I was looking for. However, in test environment (and the results/failures kinda similar to SonarLint x SonarQube integration), I have to provide the the dependencies myself. Otherwise, it wouldn’t recognize SharedPreference, Context, or even String:

12:10:35.416 [main] DEBUG o.s.j.b.loader.SquidClassLoader - .class not found for javax
12:10:35.416 [main] DEBUG o.s.j.b.loader.SquidClassLoader - .class not found for javax.crypto
12:10:35.523 [main] DEBUG o.s.j.b.loader.SquidClassLoader - .class not found for StringBuilder
12:10:35.523 [main] DEBUG o.s.j.b.loader.SquidClassLoader - .class not found for java.lang.package-info
12:10:35.523 [main] DEBUG o.s.j.b.loader.SquidClassLoader - .class not found for java.lang.Synthetic$StringBuilder
12:10:35.523 [main] DEBUG o.s.j.b.loader.SquidClassLoader - .class not found for String
12:10:35.523 [main] DEBUG o.s.j.b.loader.SquidClassLoader - .class not found for java.lang.Synthetic$String
12:10:35.523 [main] DEBUG o.s.j.b.loader.SquidClassLoader - .class not found for String
12:10:35.523 [main] DEBUG o.s.j.b.loader.SquidClassLoader - .class not found for java.lang.Synthetic$String
12:10:35.538 [main] DEBUG o.s.j.b.loader.SquidClassLoader - .class not found for SharedPreferences
12:10:35.538 [main] DEBUG o.s.j.b.loader.SquidClassLoader - .class not found for java.lang.SharedPreferences
12:10:35.538 [main] DEBUG o.s.j.b.loader.SquidClassLoader - .class not found for java.lang.Synthetic$SharedPreferences
12:10:35.538 [main] DEBUG o.s.j.b.loader.SquidClassLoader - .class not found for StringBuilder
12:10:35.538 [main] DEBUG o.s.j.b.loader.SquidClassLoader - .class not found for java.lang.Synthetic$StringBuilder
12:10:35.538 [main] DEBUG o.s.j.b.loader.SquidClassLoader - .class not found for Context
12:10:35.538 [main] DEBUG o.s.j.b.loader.SquidClassLoader - .class not found for java.lang.Context
12:10:35.538 [main] DEBUG o.s.j.b.loader.SquidClassLoader - .class not found for java.lang.Synthetic$Context
12:10:35.538 [main] DEBUG o.s.j.b.loader.SquidClassLoader - .class not found for Context
12:10:35.538 [main] DEBUG o.s.j.b.loader.SquidClassLoader - .class not found for java.lang.Context
12:10:35.538 [main] DEBUG o.s.j.b.loader.SquidClassLoader - .class not found for java.lang.Synthetic$Context

I’m planning to find a way to build all those artifacts and put them under

<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-dependency-plugin</artifactId>
				<version>2.10</version>
				<executions>
					<execution>
						<id>copy</id>
						<phase>test-compile</phase>
						<goals>
							<goal>copy</goal>
						</goals>
						<configuration>
							<artifactItems>
all the dependencies go here

If you have any cleaner or alternative solutions for this, please advise. I really appreciate any help about this issue as my solution is kinda a brute-force attempt and require more artifacts to be added as I go.

Another summary of the issue:

Could you please tell me how to enable the log in Android Studio or IntelliJ? I don’t see the option anywhere under Setting/Other Settings/SonarLint General Settings or SonarLint Project Settings

Thanks, I never thought about checking there as I am quite a beginner with plugins. I found that it indeed query the issues from the portal but never reported or flagged it.

Log:

Java Main Files AST scan
1 source files to be analyzed
Initializing metadata of file file://C:/Users/toanle/Documents/Developer/WASH/mHealth/app/src/main/java/com/WASH/Activity/MainActivity.java
Classes not found during the analysis : [android.app.Activity, android.app.Fragment, android.content.BroadcastReceiver, android.content.Context, android.content.Intent, android.content.IntentSender, android.content.IntentSender$SendIntentException, android.content.res.ColorStateList, android.content.res.Configuration, android.content.res.Resources, android.graphics.Canvas, android.graphics.Paint, android.graphics.Rect, android.graphics.drawable.Drawable, android.net.Uri, android.os.Bundle, android.os.Handler, android.os.Parcelable, android.preference.PreferenceFragment, android.util.AttributeSet, android.util.TypedValue, android.view.KeyEvent, android.view.LayoutInflater, android.view.Menu, android.view.MenuInflater, android.view.MenuItem, android.view.MotionEvent, android.view.View, android.view.View$OnClickListener, android.view.ViewGroup, android.view.ViewGroup$LayoutParams, android.widget.ArrayAdapter, android.widget.EditText, android.widget.FrameLayout, android.widget.Spinner, org.json.JSONArray, org.json.JSONException, org.json.JSONObject]
1/1 source files have been analyzed
Java Main Files AST scan (done) | time=526ms
Java Test Files AST scan
0 source files to be analyzed
0/0 source files have been analyzed
Java Test Files AST scan (done) | time=2ms
'Scala Sensor' skipped because there is no related file in current project
'Python Squid Sensor' skipped because there is no related file in current project
Execute Sensor: JavaXmlSensor
'Kotlin Sensor' skipped because there is no related file in current project
'PHP sensor' skipped because there is no related file in current project
'Analyzer for "php.ini" files' skipped because there is no related file in current project
'SonarJS' skipped because there is no related file in current project
'Ruby Sensor' skipped because there is no related file in current project
Done in 731ms

Processed 1 issue in 1 ms
Found 1 issue (the decoy issue with "MyCompany" mehod similar to the sample
Fetching server issues in 1 file
GET 200 http://localhost:9000/batch/issues?key=test%3Asrc%2Fmain%2Fjava%2Fcom%2FWASH%2FActivity%2FMainActivity.java | time=406ms

The contains of issue file does have what I am looking for:

AWklULr5xbvouzVVqCqb  test 1src/main/java/com/WASH/Activity/MainActivity.java"
mycompany-java* UseSecureRandomOrKeyGenerator0Y: Avoid using Brand in method name@ H Z OPENb 9083dc7854139f9755c12b184c616391p8EA* -z VULNERABILITY
 
AWklaaUrrsZhqQGBI4OK  test 1src/main/java/com/WASH/Activity/MainActivity.java"
mycompany-java*¬AvoidGlobalReadableWritableFile0d:FgetSharedPreferences using MODE_WORLD_READABLE or MODE_WORLD_WRITEABLE@ H Z OPENb 5a87ec7f82d997f8c3ef81ebba6cd09fp`Y%+ -z VULNERABILITY

Do you have any insights about SonarLint not flagging the 2nd issue queried from SonarQube server?

SonarQube
Imgur

SonarLint (not showing the issue)
Imgur

To me the issue is likely to come from:

Since your method parameter is Context.MODE_WORLD_READABLE and the type Context is not found, SonarJava will probably fail to resolve the override. I’m not sure how classpath of Android projects is computed, would need to do some tests to see if the issue is in SonarLint. Can you share the part of the logs having the value of sonar.java.libraries?

It seemed like SonarLint did “Java Test Files AST scan” (1) and could not find the issue due to the missing .class files, then, it queried of the issues (2) from SonarQube portal (which show the issue) but (2) did not override (1) or failed to show

Don’t be confused by the call to /batch/issues. This is used for issue tracking, ie muting issues that have been flagged as false positive/won’t fix on the server. If an issue is not found by SonarLint in the first place, it will never be reported, even if returned by /batch/issues (it could have been fixed locally for instance).