Highlighting duplicated and redandant *-imports as unused
This commit is contained in:
@@ -47,12 +47,12 @@ import org.jetbrains.kotlin.idea.imports.KotlinImportOptimizer
|
|||||||
import org.jetbrains.kotlin.idea.imports.importableFqNameSafe
|
import org.jetbrains.kotlin.idea.imports.importableFqNameSafe
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.JetFile
|
import org.jetbrains.kotlin.psi.JetFile
|
||||||
|
import org.jetbrains.kotlin.psi.JetImportDirective
|
||||||
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
|
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
|
||||||
import org.jetbrains.kotlin.resolve.ImportPath
|
import org.jetbrains.kotlin.resolve.ImportPath
|
||||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets
|
||||||
import java.util.ArrayList
|
import java.util.*
|
||||||
import java.util.HashSet
|
|
||||||
|
|
||||||
class UnusedImportInspection : AbstractKotlinInspection() {
|
class UnusedImportInspection : AbstractKotlinInspection() {
|
||||||
override fun runForWholeFile() = true
|
override fun runForWholeFile() = true
|
||||||
@@ -64,23 +64,41 @@ class UnusedImportInspection : AbstractKotlinInspection() {
|
|||||||
|
|
||||||
val descriptorsToImport = KotlinImportOptimizer.collectDescriptorsToImport(file)
|
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 fqNames = HashSet<FqName>()
|
||||||
val parentFqNames = HashSet<FqName>()
|
val parentFqNames = HashSet<FqName>()
|
||||||
for (descriptor in descriptorsToImport) {
|
for (descriptor in descriptorsToImport) {
|
||||||
val fqName = descriptor.importableFqNameSafe
|
val fqName = descriptor.importableFqNameSafe
|
||||||
fqNames.add(fqName)
|
fqNames.add(fqName)
|
||||||
val parentFqName = fqName.parent()
|
|
||||||
if (!parentFqName.isRoot) {
|
if (fqName !in explicitlyImportedFqNames) { // we don't add parents of explicitly imported fq-names because such imports are not neeeded
|
||||||
parentFqNames.add(parentFqName)
|
val parentFqName = fqName.parent()
|
||||||
|
if (!parentFqName.isRoot) {
|
||||||
|
parentFqNames.add(parentFqName)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val problems = ArrayList<ProblemDescriptor>()
|
val problems = ArrayList<ProblemDescriptor>()
|
||||||
val directives = file.importDirectives
|
|
||||||
|
val importPaths = HashSet<ImportPath>(directives.size())
|
||||||
|
|
||||||
for (directive in directives) {
|
for (directive in directives) {
|
||||||
val importPath = directive.importPath ?: continue
|
val importPath = directive.importPath ?: continue
|
||||||
if (importPath.alias != null) continue // highlighting of unused alias imports not supported yet
|
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
|
importPath.fqnPart() in parentFqNames
|
||||||
}
|
}
|
||||||
else {
|
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>
|
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused import directive</problem_class>
|
||||||
<description>Unused import directive</description>
|
<description>Unused import directive</description>
|
||||||
</problem>
|
</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>
|
</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
|
||||||
Reference in New Issue
Block a user