Highlighting duplicated and redandant *-imports as unused

This commit is contained in:
Valentin Kipyatkov
2015-07-21 17:55:13 +03:00
parent feccee2c3e
commit 851057a9ef
4 changed files with 106 additions and 7 deletions
@@ -47,12 +47,12 @@ import org.jetbrains.kotlin.idea.imports.KotlinImportOptimizer
import org.jetbrains.kotlin.idea.imports.importableFqNameSafe
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.psi.JetImportDirective
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
import org.jetbrains.kotlin.resolve.ImportPath
import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets
import java.util.ArrayList
import java.util.HashSet
import java.util.*
class UnusedImportInspection : AbstractKotlinInspection() {
override fun runForWholeFile() = true
@@ -64,23 +64,41 @@ class UnusedImportInspection : AbstractKotlinInspection() {
val descriptorsToImport = KotlinImportOptimizer.collectDescriptorsToImport(file)
val directives = file.importDirectives
val explicitlyImportedFqNames = directives
.asSequence()
.map { it.importPath }
.filterNotNull()
.filter { !it.isAllUnder && !it.hasAlias() }
.map { it.fqnPart() }
.toSet()
val fqNames = HashSet<FqName>()
val parentFqNames = HashSet<FqName>()
for (descriptor in descriptorsToImport) {
val fqName = descriptor.importableFqNameSafe
fqNames.add(fqName)
val parentFqName = fqName.parent()
if (!parentFqName.isRoot) {
parentFqNames.add(parentFqName)
if (fqName !in explicitlyImportedFqNames) { // we don't add parents of explicitly imported fq-names because such imports are not neeeded
val parentFqName = fqName.parent()
if (!parentFqName.isRoot) {
parentFqNames.add(parentFqName)
}
}
}
val problems = ArrayList<ProblemDescriptor>()
val directives = file.importDirectives
val importPaths = HashSet<ImportPath>(directives.size())
for (directive in directives) {
val importPath = directive.importPath ?: continue
if (importPath.alias != null) continue // highlighting of unused alias imports not supported yet
val isUsed = if (importPath.isAllUnder) {
val isUsed = if (!importPaths.add(importPath)) {
false
}
else if (importPath.isAllUnder) {
importPath.fqnPart() in parentFqNames
}
else {
@@ -0,0 +1,14 @@
import java.io.* // used
import java.io.* // duplicated
import java.util.ArrayList // used
import java.util.ArrayList // duplicated
import java.sql.* // unused
import java.sql.* // unused
fun foo(file: File, list: ArrayList<Int>) {
}
// WITH_RUNTIME
// FULL_JDK
@@ -34,4 +34,58 @@
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused import directive</problem_class>
<description>Unused import directive</description>
</problem>
<problem>
<file>unusedStarWhenExplicit.kt</file>
<line>2</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="unusedStarWhenExplicit.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused import directive</problem_class>
<description>Unused import directive</description>
</problem>
<problem>
<file>unusedStarWhenExplicit.kt</file>
<line>4</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="unusedStarWhenExplicit.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused import directive</problem_class>
<description>Unused import directive</description>
</problem>
<problem>
<file>duplicatedImports.kt</file>
<line>2</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="duplicatedImports.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused import directive</problem_class>
<description>Unused import directive</description>
</problem>
<problem>
<file>duplicatedImports.kt</file>
<line>5</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="duplicatedImports.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused import directive</problem_class>
<description>Unused import directive</description>
</problem>
<problem>
<file>duplicatedImports.kt</file>
<line>7</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="duplicatedImports.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused import directive</problem_class>
<description>Unused import directive</description>
</problem>
<problem>
<file>duplicatedImports.kt</file>
<line>8</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="duplicatedImports.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused import directive</problem_class>
<description>Unused import directive</description>
</problem>
</problems>
@@ -0,0 +1,13 @@
import java.io.File // used
import java.io.* // unused because of explicit imports
import java.io.InputStream // used
import java.io.OutputStream // unused
import java.util.ArrayList // used
import java.util.* // used because HashMap is used
fun foo(file: File, input: InputStream, arrayList: ArrayList<Int>, hashMap: HashMap<Int, Char>) {
}
// WITH_RUNTIME
// FULL_JDK