Unused import: support also imports as alias
#KT-12392 Fixed
This commit is contained in:
@@ -61,7 +61,7 @@ class OptimizedImportsBuilder(
|
||||
}
|
||||
|
||||
data class InputData(
|
||||
val descriptorsToImport: Set<DeclarationDescriptor>,
|
||||
val descriptorsToImport: Map<DeclarationDescriptor, Set<Name>>,
|
||||
val references: Collection<AbstractReference>
|
||||
)
|
||||
|
||||
@@ -124,7 +124,7 @@ class OptimizedImportsBuilder(
|
||||
.mapTo(importsToGenerate) { it.importPath }
|
||||
|
||||
val descriptorsByParentFqName = HashMap<FqName, MutableSet<DeclarationDescriptor>>()
|
||||
for (descriptor in data.descriptorsToImport) {
|
||||
for (descriptor in data.descriptorsToImport.keys) {
|
||||
val fqName = descriptor.importableFqName!!
|
||||
|
||||
val explicitImportPath = ImportPath(fqName, false)
|
||||
|
||||
@@ -79,7 +79,7 @@ class KotlinImportOptimizer : ImportOptimizer {
|
||||
.mapNotNull(KtImportDirective::importedFqName)
|
||||
.toSet()
|
||||
|
||||
private val descriptorsToImport = HashSet<DeclarationDescriptor>()
|
||||
private val descriptorsToImport = LinkedHashMap<DeclarationDescriptor, Set<Name>>()
|
||||
private val abstractRefs = ArrayList<OptimizedImportsBuilder.AbstractReference>()
|
||||
|
||||
val data: OptimizedImportsBuilder.InputData
|
||||
@@ -107,7 +107,6 @@ class KotlinImportOptimizer : ImportOptimizer {
|
||||
val targets = reference.targets(bindingContext)
|
||||
for (target in targets) {
|
||||
val importableDescriptor = target.getImportableDescriptor()
|
||||
if (importableDescriptor.name !in names) continue // resolved via alias
|
||||
|
||||
val importableFqName = target.importableFqName ?: continue
|
||||
val parentFqName = importableFqName.parent()
|
||||
@@ -118,7 +117,7 @@ class KotlinImportOptimizer : ImportOptimizer {
|
||||
|
||||
if (isAccessibleAsMember(importableDescriptor, element, bindingContext)) continue
|
||||
|
||||
descriptorsToImport.add(importableDescriptor)
|
||||
descriptorsToImport.compute(importableDescriptor) { _, u -> u?.plus(names) ?: names.toHashSet() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,12 +49,12 @@ import org.jetbrains.kotlin.idea.imports.OptimizedImportsBuilder
|
||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtCodeFragment
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtImportDirective
|
||||
import org.jetbrains.kotlin.psi.psiUtil.siblings
|
||||
import org.jetbrains.kotlin.resolve.ImportPath
|
||||
import java.util.*
|
||||
|
||||
class KotlinUnusedImportInspection : AbstractKotlinInspection() {
|
||||
data class ImportData(val unusedImports: List<KtImportDirective>, val optimizerData: OptimizedImportsBuilder.InputData)
|
||||
@@ -75,11 +75,11 @@ class KotlinUnusedImportInspection : AbstractKotlinInspection() {
|
||||
.map { it.fqName }
|
||||
.toSet()
|
||||
|
||||
val fqNames = HashSet<FqName>()
|
||||
val fqNames = HashMap<FqName, Set<Name>>()
|
||||
val parentFqNames = HashSet<FqName>()
|
||||
for (descriptor in optimizerData.descriptorsToImport) {
|
||||
for ((descriptor, names) in optimizerData.descriptorsToImport) {
|
||||
val fqName = descriptor.importableFqName!!
|
||||
fqNames.add(fqName)
|
||||
fqNames.compute(fqName) { _, u -> u?.plus(names) ?: names }
|
||||
|
||||
if (fqName !in explicitlyImportedFqNames) { // we don't add parents of explicitly imported fq-names because such imports are not needed
|
||||
val parentFqName = fqName.parent()
|
||||
@@ -95,12 +95,11 @@ class KotlinUnusedImportInspection : AbstractKotlinInspection() {
|
||||
val resolutionFacade = file.getResolutionFacade()
|
||||
for (directive in directives) {
|
||||
val importPath = directive.importPath ?: continue
|
||||
if (importPath.alias != null) continue // highlighting of unused alias imports not supported yet
|
||||
|
||||
val isUsed = when {
|
||||
!importPaths.add(importPath) -> false
|
||||
importPath.isAllUnder -> importPath.fqName in parentFqNames
|
||||
importPath.fqName in fqNames -> true
|
||||
importPath.fqName in fqNames -> importPath.importedName?.let { it in fqNames.getValue(importPath.fqName) } ?: false
|
||||
// case for type alias
|
||||
else -> directive.targetDescriptors(resolutionFacade).firstOrNull()?.let { it.importableFqName in fqNames } ?: false
|
||||
}
|
||||
|
||||
+3
-2
@@ -7,11 +7,12 @@ import java.util.ArrayList // used
|
||||
import java.unresolved.* // unused but unresolved
|
||||
import java.net.Unresolved // unused but unresolved
|
||||
|
||||
import java.net.ConnectException as CE // highlighting of unused aliases not implemented yet
|
||||
import java.net.ConnectException as CE // unused
|
||||
import java.net.ConnectException as ConExc // used
|
||||
|
||||
import RootPackageClass // unused because it's in the current package
|
||||
|
||||
fun foo(list: ArrayList<String>, p: RootPackageClass) {
|
||||
fun foo(list: ArrayList<String>, p: RootPackageClass, e: ConExc) {
|
||||
list.add("")
|
||||
Date()
|
||||
}
|
||||
|
||||
@@ -17,6 +17,15 @@
|
||||
<description>Unused import directive</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>file.kt</file>
|
||||
<line>10</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<entry_point TYPE="file" FQNAME="simple.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused import directive</problem_class>
|
||||
<description>Unused import directive</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>fileInPack1.kt</file>
|
||||
<line>3</line>
|
||||
|
||||
Reference in New Issue
Block a user