Skip to content

Fix False Positive on UnnecessarySafeCall - #3419

Merged
BraisGabin merged 2 commits into
detekt:masterfrom
cortinico:nc/unnecessary-safe-call-unknown-type
Jan 28, 2021
Merged

Fix False Positive on UnnecessarySafeCall#3419
BraisGabin merged 2 commits into
detekt:masterfrom
cortinico:nc/unnecessary-safe-call-unknown-type

Conversation

@cortinico

Copy link
Copy Markdown
Member

This is a fix for the various false positives on UnnecessarySafeCall.

After some debugging the problems seems to be with misconfigured class-paths (e.g. carp-dk/carp.core-kotlin#223). If the classpath doesn't contain a third-party types, but still has a safe call operator, the Kotlin Compiler raises an Errors.UNNECESSARY_SAFE_CALL detection.

Inside the detection the compiler adds information on the non-nullable type that is the receiver of the safe call (in the .a field). In this patch I'm try to see if the compiler failed to resolve the type => If so, we can skip the report.

Fixes #3409
Fixes #3414

@cortinico cortinico changed the title Fix False Positive on UnnecessarySafeCall Fix False Positive on UnnecessarySafeCall Jan 27, 2021
@cortinico
cortinico force-pushed the nc/unnecessary-safe-call-unknown-type branch from b4cf2ff to 179fe30 Compare January 27, 2021 20:35
@codecov

codecov Bot commented Jan 27, 2021

Copy link
Copy Markdown

Codecov Report

Merging #3419 (8548e5c) into master (95a1220) will increase coverage by 0.00%.
The diff coverage is 66.66%.

Impacted file tree graph

@@            Coverage Diff            @@
##             master    #3419   +/-   ##
=========================================
  Coverage     80.37%   80.37%           
- Complexity     2748     2749    +1     
=========================================
  Files           449      449           
  Lines          8295     8301    +6     
  Branches       1587     1590    +3     
=========================================
+ Hits           6667     6672    +5     
  Misses          774      774           
- Partials        854      855    +1     
Impacted Files Coverage Δ Complexity Δ
...rturbosch/detekt/rules/bugs/UnnecessarySafeCall.kt 75.00% <66.66%> (ø) 5.00 <0.00> (+1.00)
...turbosch/detekt/rules/style/UnusedPrivateMember.kt 90.76% <0.00%> (+0.14%) 5.00% <0.00%> (ø%)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 95a1220...8548e5c. Read the comment docs.

@BraisGabin BraisGabin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any way to create a unit test?

Comment on lines +60 to +66
if (compilerReport != null) {
// For external types, if they're not included in the classpath, we still get an Errors.UNNECESSARY_SAFE_CALL.
// This causes false positives if our users are misconfiguring detekt with Type Resolution.
// Here we try to check if the compiler reports failed to resolve the nullable type.
if (compilerReport is DiagnosticWithParameters1<*, *> && compilerReport.a is ErrorType) {
return
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me this is still strange. Why is this popping up only after updating to the newest compiler version?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be able to find the exact DiagnosticWithParameters1 definition of the errors being reported and add this to the documentation.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me this is still strange. Why is this popping up only after updating to the newest compiler version?

I believe this is related to us enabling the rule by default:
#3419

val compilerReport = bindingContext
.diagnostics
.forElement(safeAccessElement)
.firstOrNull { it.factory == Errors.UNNECESSARY_SAFE_CALL }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we still keep any instead of firstOrNull? I think the code depends on the order for the diagnostics, which seems too fragile.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we still keep any instead of firstOrNull?

I could change it to a forEach as we need to get access to the compilerReport

@cortinico

Copy link
Copy Markdown
Member Author

Is there any way to create a unit test?

Found a test case for it 👌 The only drawback is that we can't compile the test snippet as the import will break the compilation.

@cortinico

Copy link
Copy Markdown
Member Author

Turns out the Kotlin compiler was actually wrong here. I've pushed a fix upstream JetBrains/kotlin#4072 so we can revert our patch as soon as Kotlin 1.5 is out 🥳

@BraisGabin

Copy link
Copy Markdown
Member

How can we be sure that we don't forget? Create the pr with a blocked label and merge it as soon as we move to kotlin 1.5?

@schalkms

schalkms commented Feb 2, 2021

Copy link
Copy Markdown
Member

Turns out the Kotlin compiler was actually wrong here. I've pushed a fix upstream JetBrains/kotlin#4072 so we can revert our patch as soon as Kotlin 1.5 is out 🥳

That's really interesting, so this suspicion was right.
#3409 (comment)

How can we be sure that we don't forget? Create the pr with a blocked label and merge it as soon as we move to kotlin 1.5?

I'd suggest this approach.

@cortinico

Copy link
Copy Markdown
Member Author

How can we be sure that we don't forget? Create the pr with a blocked label and merge it as soon as we move to kotlin 1.5?

Created here #3439

This was referenced Mar 11, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

4 participants