-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add missing null annotation detector #11
Conversation
This adds a lint rule to inform when we are missing null annotations in Java code. It currently only informs for fields, and requires Android null annotations (`@NonNull`, and `@Nullable`).
This implements missing null annotation detection for method parameters and method return types. Injected parameters are ignored for this rule.
WordPressLint/src/main/java/org/wordpress/android/lint/MissingNullAnnotationDetector.kt
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👋 @mkevins !
I have reviewed and tested this PR as per the instructions, everything (almost
) works as expected, great job! 🌟 🌟 🌟
I have left a question (❓), a couple of suggestions (💡) and some minor (🔍) comments for you to consider. I am NOT going to approve this PR as I think it is better for us to at least discuss those before merging. I think it will be beneficial for us get this custom Android Lint rule to the best state possible before starting utilizing it.
EXTRAS
(hence the almost
above)
- Warning (
⚠️ ): There are 3 Lint failures when having this custom Android Lint rule on. Those are related to the ReaderCommentListActivity.java, ReaderPostActions.java and ReaderVideoViewerActivity.java classes. I am not sure what's the actual issue with those classes, but we might need to figure it out before proceeding with adding and enabling this custom Android Lint rule. Otherwise we might not be able to utilize it. Also, suppressing this custom Android Lint rule on those classes doesn't work, those indeed need to be disabled. In more details, there are unexpected failures during lint analysis on those classes and it is reported that this is a bug in lint or one of the libraries it depends on. The message reports thatcom.intellij.openapi.editor.Document.getImmutableCharSequence()
cannot be invoked becausedocument
is null (🤷). This Android Lint crash definitely involves theorg.wordpress.android.lint.MissingNullAnnotationDetector
detector. - Warning (
⚠️ ): To avoid having each client adding extra Android Lint configuration to ignore the**/generated/**
build related path, let's bake that into this custom Android Lint rule itself so that any generated files are ignored.
WordPressLint/src/main/java/org/wordpress/android/lint/WordPressIssueRegistry.kt
Show resolved
Hide resolved
WordPressLint/src/main/java/org/wordpress/android/lint/MissingNullAnnotationDetector.kt
Outdated
Show resolved
Hide resolved
WordPressLint/src/main/java/org/wordpress/android/lint/MissingNullAnnotationDetector.kt
Show resolved
Hide resolved
WordPressLint/src/test/java/org/wordpress/android/lint/MissingNullAnnotationDetectorTest.kt
Outdated
Show resolved
Hide resolved
WordPressLint/src/test/java/org/wordpress/android/lint/MissingNullAnnotationDetectorTest.kt
Show resolved
Hide resolved
WordPressLint/src/test/java/org/wordpress/android/lint/MissingNullAnnotationDetectorTest.kt
Outdated
Show resolved
Hide resolved
I was unable to reproduce this in my current local state, but I'll attempt again after the other changes are committed. I also tried added each of the files you mentioned as tests (locally, and not committed), and the tests did not crash. Instead, the output was what we'd expect: all the violations present in those files were reported. Maybe you can try again after the other changes are pushed, and see if you can still reproduce it?
Where do you envision this configuration being added? I don't think it should be within the scanner itself, since that would mean we'd still be traversing into those directories and possibly even parsing / building the UAST before ignoring rule at time of visiting. I imagine you have something else in mind, though, and if so, would you mind elaborating with a specific suggestion? |
This should be opened as an issue in the repo instead.
Thanks for your feedback Petros! I've implemented most of your suggestions, and noted any exceptions. Also, I've answered most of the questions, but there are still a few unresolved (the error you encountered being the most significant). This is ready for another pass, and perhaps more debugging if you encounter the error again. It would be good to see what is different about our environments as well which would make it reproducible for you but not me. 🤔 |
👋 @mkevins !
I just tried again on my side and was able to reproduce it once more. 😢 FYI: I am using this I am attaching a screenshot below for your convenience. See the 3 One of those 3 Let me know if you get the same by following these exact steps as I am not sure if your are using AS instead of CLI, or which variant you are using on your side (I usually try things first on |
👋 @mkevins !
I actually do believe (if possible) that this be included within the scanner itself. Otherwise, every client of this library would need to be adding this extra
What I am envisioning is that a custom Android Lint rule having a way to ignore by default anything |
I have an update on this @mkevins !
As I was trying to reply to you here, and updating the As such, I think our first problem is gone, it is just that one needs to be careful about how to configure the Thus, I think if we take this away and manage to exclude the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Many thanks for applying my suggestions @mkevins and adding all the enhancements, approved, you rock! 🙇 ❤️ 🚀
I reviewed and tested this update, then resolved almost all comment. I just left 2 of them open, just for us to discuss on them. We can merge this PR anyway:
WordPressLint/src/main/java/org/wordpress/android/lint/MissingNullAnnotationDetector.kt
Outdated
Show resolved
Hide resolved
WordPressLint/src/main/java/org/wordpress/android/lint/MissingNullAnnotationDetector.kt
Show resolved
Hide resolved
Btw @mkevins , now that the |
Another update on this @mkevins ! I tried that again today as I was trying to gather some updated metrics for the project thread and those 3 x
Plus, see screenshot below on such 1 x
FYI: This 1 x |
I was finally able to reproduce this issue, by using the same command That said, I've had some time to dig further into this, and I looked at the error report that was generated for these Java files. It seems there is a
So, based on that clue, I wrote some temporary code to aid in debugging: Debugging patchdiff --git a/WordPressLint/src/main/java/org/wordpress/android/lint/MissingNullAnnotationDetector.kt b/WordPressLint/src/main/java/org/wordpress/android/lint/MissingNullAnnotationDetector.kt
index 14699f4..6a840b4 100644
--- a/WordPressLint/src/main/java/org/wordpress/android/lint/MissingNullAnnotationDetector.kt
+++ b/WordPressLint/src/main/java/org/wordpress/android/lint/MissingNullAnnotationDetector.kt
@@ -48,10 +48,23 @@ class MissingNullAnnotationDetector : Detector(), SourceCodeScanner {
private fun visitParameter(node: UMethod, parameter: UParameter) {
if (parameter.requiresNullAnnotation && !parameter.isNullAnnotated) {
- if (node.isConstructor)
- report(parameter, MISSING_CONSTRUCTOR_PARAMETER_ANNOTATION)
- else
+ if (node.isConstructor) {
+// report(parameter, MISSING_CONSTRUCTOR_PARAMETER_ANNOTATION)
+ var source: String? = null
+
+ runCatching {
+ source = parameter.asSourceString()
+ }
+ source?.also {
+ report(parameter, MISSING_CONSTRUCTOR_PARAMETER_ANNOTATION)
+ } ?: fakeReport(
+ parameter,
+ MISSING_CONSTRUCTOR_PARAMETER_ANNOTATION,
+ "snaplog:\n node = $node\n parameter = $parameter",
+ )
+ } else {
report(parameter, MISSING_METHOD_PARAMETER_ANNOTATION)
+ }
}
}
}
@@ -140,6 +153,12 @@ private fun Issue.Companion.create(
)
/* JavaContext Extensions */
+private fun JavaContext.fakeReport(node: UElement, issue: Issue, message: String) = report(
+ issue,
+ node,
+ getLocation(node),
+ message,
+)
private fun JavaContext.report(node: UElement, issue: Issue) = report(
issue,
node,
diff --git a/WordPressLint/src/test/java/org/wordpress/android/lint/MissingNullAnnotationDetectorTest.kt b/WordPressLint/src/test/java/org/wordpress/android/lint/MissingNullAnnotationDetectorTest.kt
index 1bfab47..fd1b790 100644
--- a/WordPressLint/src/test/java/org/wordpress/android/lint/MissingNullAnnotationDetectorTest.kt
+++ b/WordPressLint/src/test/java/org/wordpress/android/lint/MissingNullAnnotationDetectorTest.kt
@@ -2,11 +2,13 @@ package org.wordpress.android.lint
import com.android.tools.lint.checks.infrastructure.LintDetectorTest
import com.android.tools.lint.checks.infrastructure.TestLintTask.lint
+import org.junit.Ignore
import org.junit.Test
import org.wordpress.android.lint.Utils.nonNullClass
import org.wordpress.android.lint.Utils.nullableClass
+@Ignore
class MissingNullAnnotationDetectorTest {
@Test
fun `it should inform when null annotation is missing on field`() { tl;dr is that this catches the NPE and reports a "fake" issue to provide more diagnostics about the bug directly in the lint report. In particular, information about the
and two others that look nearly identical, except for So, it seems that lint is choking on the anonymous implementation when it tries to find the "source string" of the constructor parameter (since it doesn't really exist 😅). Good news is, we can just ignore this scenario, since there is nothing to annotate anyway. 😃 I have pushed an update for this: dfaedd1, and this is ready for another look. |
👋 @mkevins !
👍 + 🤷
🥇
How fitting indeed... 😅
🥇
🎉
🤔
Very interesting, great investigation skills Matt! 💯 x 💯 ^ 💯
Stop choking YOU! 😅
I agree! 💯
Did take another look, plus tested this update and everything is now working as expected, I think we are ready to start using this rule in production Matt, starting with WP/JPAndroid (🎉), that is, give-or-take this and this, which are still pending, wdyt? 🤔 |
WordPressLint/src/main/java/org/wordpress/android/lint/MissingNullAnnotationDetector.kt
Show resolved
Hide resolved
I think this is a good idea, but I also think that removing this code is quite large, and thus could be handled in a separate PR (especially given the title and description of this current PR). I'll open an issue for it 👍 Update: I've opened an issue for this: #12 |
Now that we've resolved the main blocking issue (the crash resulting from lint analysis of the unusual anonymous subclass implementations), I don't think altering the scanner is necessary for this PR. Also, in my testing, adding those lines even in the Also, our configuration within WordPress-Android already has many such exclusions, but this is likely because we are explicitly including generated sources in our From the documentation on the
So, considering all of this, I don't think it is in the purview of this detector to override configurations declared explicitly at the usage site. Wdyt? |
I agree, thanks for creating this issue @mkevins ! 💯 |
👋 @mkevins !
👍
Yea, this is not related to the Lint crashes, but actually a separate issue, apologies for the confusion. 🫂
Hmmm... I didn't think of that, which is the fact that having
I am convinced Matt, let's keep things as is for now and maybe revisit this later on (if needed), thanks so much for taking a closer look at it. 🥇 🚀 🚀 🚀 I THINK WE ARE READY TO MERGE THIS & START USING THIS CUSTOM ANDROID LINT RULE! 🚀 🚀 🚀 |
Thanks for all your help getting this into shape Petros!
I have merged it, but I think we still need to add some GitHub action, or other CI pipeline to publish to s3 before we can use it without using |
Thank YOU @mkevins ! 🥇 💯 🙇
Right, true, I meant start using this custom Android Lint rule after we short out the publishing part, another PR perhaps, after we are done with #12 , wdyt? 🤔 |
Description
This PR adds rules to inform about missing null annotations in Java code.
To test:
Unit tests
Run the unit tests in the project.
Testing with WordPress-Android
Following the same steps from this PR: #10, the out-dated rules should be removed, and no errors should be present.
Since the severity is informational, after running this, look around within Android Studio. Missing null annotations should be underlined in gray, and should not be present on fields / parameters with the
@Inject
annotation.