Android Studio 3 not highlighting custom lint.

1,337 views
Skip to first unread message

Dani Vila Teissiere

unread,
Nov 14, 2017, 8:46:05 PM11/14/17
to lint-dev
I've been having problems reporting lint errors using a PsiElement, for example:

private void checkClassAnnotations(JavaContext context, PsiClass psiClass, UCallExpression node) {
for (PsiField psiField : psiClass.getAllFields()) {
PsiAnnotation[] allAnnotations = context.getEvaluator().getAllAnnotations(psiField, true);
Set<String> annotations = new HashSet<>();
for (PsiAnnotation allAnnotation : allAnnotations) {
annotations.add(allAnnotation.getQualifiedName());
}
if (!annotations.contains("com.google.gson.annotations.SerializedName")) {
context.report(ISSUE, context.getLocation(psiField),
"The field \"" + psiField.getName() + "\" is not annotated with SerializedName: **Not annotated**");
}
}
}

This method reports fields not annotated with @SerializedName. The problem is that Android Studio doesn't highlight it but if I run lint, the fields are highlighted in the HTML report, but only for Java. I've noticed that when reporting to the UcallExpression Android Studio reports correctly, I tried reporting in the node and it works in Android Studio both for Java and Kotlin:
  context.report(ISSUE, context.getLocation(node),
"The field \"" + psiField.getName() + "\" is not annotated with SerializedName: **Not annotated**");

Reporting to the node works fine for both Kotlin and Java. Is there any way to report to a psiField so the field gets highlighted both in Java and Kotlin?

Thank you!

Daniel.

Tamas Varga

unread,
Nov 15, 2017, 2:39:45 AM11/15/17
to lint-dev

Dani Vila Teissiere

unread,
Nov 15, 2017, 10:15:30 PM11/15/17
to lint-dev
Seems like it could be but in my case it happens in the application module also not just in the library. I'm using https://github.com/googlesamples/android-custom-lint-rules 's android studio 3 example 

Tor Norbye

unread,
Nov 17, 2017, 8:27:06 PM11/17/17
to lint-dev
What is PsiClass here -- where did it come from?  It looks like this check is mostly operating in PSI space; when you do that you run the risk that it only works in Kotlin. Ideally you'd be operating on UElements instead.

-- Tor

Dani Vila Teissiere

unread,
Nov 20, 2017, 9:18:33 PM11/20/17
to lint-dev
The PsiClass comes from javaContext.getEvaluator().findClass(className). I couldn't find any method returning a Uclass from a String:
private PsiClass resolveType(JavaContext javaContext, PsiType type) {
if (type == null) {
return null;
}
if (isGeneric(type)) {
return resolveGeneric(javaContext, type);
} else {
return javaContext.getEvaluator().findClass(type.getCanonicalText());
}
}

This code seems to work since I'm getting the right class. Also, the weird thing is that when I execute ./gradlew lint the HTML report is correct, but only for java. But findClass is also returning Kotlin classes

Tor Norbye

unread,
Nov 29, 2017, 10:44:40 AM11/29/17
to lint-dev
On Monday, November 20, 2017 at 6:18:33 PM UTC-8, Dani Vila Teissiere wrote:
The PsiClass comes from javaContext.getEvaluator().findClass(className). I couldn't find any method returning a Uclass from a String:
private PsiClass resolveType(JavaContext javaContext, PsiType type) {
if (type == null) {
return null;
}
if (isGeneric(type)) {
return resolveGeneric(javaContext, type);
} else {
return javaContext.getEvaluator().findClass(type.getCanonicalText());
}
}

This code seems to work since I'm getting the right class. Also, the weird thing is that when I execute ./gradlew lint the HTML report is correct, but only for java. But findClass is also returning Kotlin classes
 
Yes -- the reason it works in Java is that in Java PSI closely mirrors the Java code, whereas in Kotlin it does not.
If you want to analyze the class resulting from a resolve, you'll need to look up the UClass for it:

    fun handle(reference: UReferenceExpression) {
        val resolved = reference.resolve()
        if (resolved is PsiClass) {
            val uClass = resolved.toUElement() as? UClass
            ...
        }
    }

toUElement is an extension method on PsiElement; if you're not using Kotlin you'd need to access it like this:

            UClass uClass = UastContextKt.toUElement((PsiClass)resolved, UClass.class);

-- Tor

Dani Vila Teissiere

unread,
Dec 12, 2017, 9:21:46 PM12/12/17
to lint-dev
Thanks for your answer Tor. Even if I convert the PsiClass to UElement Android studio doesn't highlight the code. I've noticed that there is a mismatch between the HTML report and the Android Studio report. For example, if I take the example in https://github.com/googlesamples/android-custom-lint-rules and add a couple of classes in Java: TestJava and TestJava2 to the package com.example.lint.library:

package com.example.lint.library;

public class TestJava {
}


package com.example.lint.library;

public class TestJava2 {
String lint = "This is a lint";
}

Then I changed the detector to report to TestJava:

PsiClass found = context.getEvaluator().findClass("com.example.lint.library.TestJava");
if (string.contains("lint") && string.matches(".*\\blint\\b.*")) {
context.report(ISSUE, found, context.getLocation(found),
"This code mentions `lint`: **Congratulations**");
}


TestJava2 is the one having the string literal "This is a lint" but I'm reporting to TestJava, not TestJava2 so I expected to see the TestJava class highlighted in Android Studio but it isn't. But when I check the lint HTML report I see:





I think this is the reason why Android Studio is not highlighting my custom lint.

Dani.

Tor Norbye

unread,
Dec 15, 2017, 3:15:18 PM12/15/17
to lint-dev
On Tuesday, December 12, 2017 at 6:21:46 PM UTC-8, Dani Vila Teissiere wrote:
Thanks for your answer Tor. Even if I convert the PsiClass to UElement Android studio doesn't highlight the code. I've noticed that there is a mismatch between the HTML report and the Android Studio report. For example, if I take the example in https://github.com/googlesamples/android-custom-lint-rules and add a couple of classes in Java: TestJava and TestJava2 to the package com.example.lint.library:

package com.example.lint.library;

public class TestJava {
}


package com.example.lint.library;

public class TestJava2 {
String lint = "This is a lint";
}

Then I changed the detector to report to TestJava:

PsiClass found = context.getEvaluator().findClass("com.example.lint.library.TestJava");
if (string.contains("lint") && string.matches(".*\\blint\\b.*")) {
context.report(ISSUE, found, context.getLocation(found),
"This code mentions `lint`: **Congratulations**");
}

What is "string" in the above code snippet - how are you looking it up? As mentioned above you should be operating on the UClass and then if you're trying to report issues on a field, the corresponding UField members of that UClass.

-- Tor

Jorge Gonzalez

unread,
Aug 1, 2018, 11:12:13 AM8/1/18
to lint-dev
Hi Tor,

Currenty, I'm getting the same issue than Dani, Android Studio does not highlight my custom lint, but it is in HTML report. I am testing the same detector that looking for literal "lint". Do you know if there is some way to say Android studio to highlight it? 

I've been followed your repo https://github.com/googlesamples/android-custom-lint-rules/tree/master/android-studio-3 and I also add into the android module: lintChecks project(':mylint'). I suppose that something I'm doing wrong, could help me?

Regards
Jorge

Anthony Annuzzi

unread,
Aug 2, 2018, 12:47:42 AM8/2/18
to lint-dev
I too am having this issue. I was using Android Studio version 3.0.1 where everything was working as expected. Today I updated to version 3.1.3 and I can no longer see the underline in the IDE.

邢小刚

unread,
Aug 2, 2018, 8:55:31 AM8/2/18
to lint-dev
make sure your Detecotr extends
public class NewThreadDetector extends Detector implements Detector.UastScanner {
}
but not
public class NewThreadDetector extends Detector implements Detector.JavaPsiScanner {

,i use studio 3.1.3,it works.

在 2018年8月1日星期三 UTC+8下午11:12:13,Jorge Gonzalez写道:

Tor Norbye

unread,
Aug 2, 2018, 9:28:52 AM8/2/18
to lint-dev
The first thing to check is whether there's any output in the IDE log (Help > Show Log) which points to a problem. If there are class loading problems or compatibility problems, they would go there. If there's a problem loading custom checks associated with a third party library, we don't want to post red errors in the editor or pop up a warning; since lint's APIs aren't stable yet it's quite possible that the library is an older version using incompatible APIs etc, so the checks are semi-silently ignored (semi- in the sense that it *should* emit warnings into the IDE log, but clients of the library aren't notified loudly that there aren't checks running.)

As of 3.1 there are some new version flags (somewhat similar to minSdkVersion/targetSdkVersion) in the IssueRegistry which tells lint which versions the checks are compatible with; make sure those are set correctly as well.

-- Tor

Will Passidomo

unread,
Dec 11, 2019, 7:37:08 AM12/11/19
to lint-dev
For anyone who stumbled across this issue and still needs an answer, I just spent a while wrangling with the same problem (lint checks showing with `.gradlew lint` but no syntax highlighting in the editor) the issue for me ended up being the Scope value passed into the Issue via the Implementation object. I was experiencing the problem when I used `EnumSet.of(Scope.ALL_JAVA_FILES)` and the problem resolved when I switched it to `Scope.JAVA_FILE_SCOPE`

Hope this helps someone out there :)

Arif Faizin

unread,
Jun 22, 2020, 11:35:02 AM6/22/20
to lint-dev
Thanks Will.. it solve my problem
Reply all
Reply to author
Forward
0 new messages