Skip to content
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

UnusedImports: Lots of false positives #3074

Closed
3flex opened this issue Sep 14, 2020 · 4 comments · Fixed by #3079
Closed

UnusedImports: Lots of false positives #3074

3flex opened this issue Sep 14, 2020 · 4 comments · Fixed by #3079

Comments

@3flex
Copy link
Member

3flex commented Sep 14, 2020

Expected Behavior

java.util.HashMap is not reported as unused, since the type is used in the function value parameter:

import java.util.HashMap

fun doesNothing(thing: HashMap<String, String>) {
    // nothing
}

Observed Behavior

java.util.HashMap is reported as unused by UnusedImports rule.

Steps to Reproduce

Run detekt with type resolution enabled on the code provided above.

Context

Lots of false positives in detekt 1.13.x.

Your Environment

  • Version of detekt used: 1.13.1
  • Version of Gradle used (if applicable): 6.6.1
  • Operating System and version: Windows 10
  • Link to your project (if it's a public repository): N/A
@3flex 3flex changed the title UnusedImports: Lots of false negatives UnusedImports: Lots of false positives Sep 14, 2020
@cortinico
Copy link
Member

I've just done a quick run and I was able to reproduce but only with type resolution enabled. UnusedImports is one of those mixed rule #2994 that should probably be avoided.

@BraisGabin
Copy link
Member

Well, actually you don't need to import HashMap to make your code work. Extracted from Kotlin:

package kotlin.collections

@SinceKotlin("1.1") public actual typealias HashMap<K, V> = java.util.HashMap<K, V>

I don't know if there's a good reason to keep that import.

@3flex 3flex closed this as completed Sep 14, 2020
@3flex 3flex reopened this Sep 14, 2020
@3flex
Copy link
Member Author

3flex commented Sep 15, 2020

Thanks @BraisGabin it was just one very simple example. Here's another:

import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent

@Module
@InstallIn(SingletonComponent::class)
object DbModule {
    // other code exists here
}

In this example all three imports are being reported, but they're being used. Actually every single import in the real file is being flagged by this rule now.

@cortinico
Copy link
Member

I've done further investigations on this front. The offending commit is #3033

Currently the UnusedImports is substantially broken for users with Type Resolution enabled. The problem is that the UnusedImports rule was modified to run differently when Type Resolution is enabled in #3033. Tests were not updated instead (see #3077 has 6 failing tests on that rule).

The problem is actually here:

return if (bindingContext == BindingContext.EMPTY) {
identifier !in namedReferencesAsString
} else {
val fqNames = namedReferences.mapNotNull {
it.getResolvedCall(bindingContext)?.resultingDescriptor?.fqNameOrNull()
}
importPath?.fqName?.let { it !in fqNames } == true
}

The assumption in this code is that all the KtReferenceExpression will succeed the getResolvedCall() resolution. This is not the case for the two posted snippets as there KtReferenceExpression is actually referring a KtUserType (an annotation and a parameter type).
We would have to adapt the code to treat all the possible variants of KtReferenceExpression (I'm not aware of how many are there and how error prone this could be, might be eventually easy).

I advice we revert #3033 (to close this issue) and eventually reopen #3020.

Ideally we should consider having UnusedImports working only with TR enabled or have a separate rule (see #2994 for more context on this topic).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants