From af192698edca119128262f7b51d2e1ac7d354d95 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Wed, 15 Jul 2015 13:29:58 +0300 Subject: [PATCH] Imports from current package are redundant too --- .../idea/imports/KotlinImportOptimizer.kt | 21 ++++++++----------- .../testData/inspections/unusedImport/file.kt | 6 +++++- .../inspections/unusedImport/fileInPack1.kt | 8 +++++++ .../inspections/unusedImport/fileInPack2.kt | 8 +++++++ .../unusedImport/inspectionData/expected.xml | 17 +++++++++++++++ 5 files changed, 47 insertions(+), 13 deletions(-) create mode 100644 idea/testData/inspections/unusedImport/fileInPack1.kt create mode 100644 idea/testData/inspections/unusedImport/fileInPack2.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/imports/KotlinImportOptimizer.kt b/idea/src/org/jetbrains/kotlin/idea/imports/KotlinImportOptimizer.kt index c3b161502f8..73d3eeae8d5 100644 --- a/idea/src/org/jetbrains/kotlin/idea/imports/KotlinImportOptimizer.kt +++ b/idea/src/org/jetbrains/kotlin/idea/imports/KotlinImportOptimizer.kt @@ -80,7 +80,6 @@ public class KotlinImportOptimizer() : ImportOptimizer { //TODO: keep existing imports? at least aliases (comments) val importInsertHelper = ImportInsertHelper.getInstance(file.getProject()) - val currentPackageName = file.getPackageFqName() val descriptorsToImport = detectDescriptorsToImport() @@ -90,14 +89,9 @@ public class KotlinImportOptimizer() : ImportOptimizer { for (descriptor in descriptorsToImport) { val fqName = descriptor.importableFqNameSafe val parentFqName = fqName.parent() - if (descriptor is PackageViewDescriptor) { + if (descriptor is PackageViewDescriptor || parentFqName.isRoot()) { importsToGenerate.add(ImportPath(fqName, false)) } - else if (parentFqName.isRoot()) { - if (!currentPackageName.isRoot()) { - importsToGenerate.add(ImportPath(fqName, false)) - } - } else { descriptorsByPackages.put(parentFqName, descriptor) } @@ -110,7 +104,7 @@ public class KotlinImportOptimizer() : ImportOptimizer { for (packageName in descriptorsByPackages.keys()) { val descriptors = descriptorsByPackages[packageName] val fqNames = descriptors.map { it.importableFqNameSafe }.toSet() - val explicitImports = packageName != currentPackageName && fqNames.size() < codeStyleSettings.NAME_COUNT_TO_USE_STAR_IMPORT + val explicitImports = fqNames.size() < codeStyleSettings.NAME_COUNT_TO_USE_STAR_IMPORT if (explicitImports) { for (fqName in fqNames) { if (!isImportedByDefault(fqName)) { @@ -125,7 +119,7 @@ public class KotlinImportOptimizer() : ImportOptimizer { } } - if (packageName != currentPackageName && !fqNames.all(::isImportedByDefault)) { + if (!fqNames.all(::isImportedByDefault)) { importsToGenerate.add(ImportPath(packageName, true)) } } @@ -133,7 +127,7 @@ public class KotlinImportOptimizer() : ImportOptimizer { // now check that there are no conflicts and all classes are really imported val fileWithImportsText = StringBuilder { - append("package ").append(currentPackageName.render()).append("\n") + append("package ").append(file.getPackageFqName().render()).append("\n") importsToGenerate.filter { it.isAllUnder() }.map { "import " + it.getPathStr() }.joinTo(this, "\n") }.toString() val fileWithImports = JetPsiFactory(file).createAnalyzableFile("Dummy.kt", fileWithImportsText, file) @@ -187,6 +181,7 @@ public class KotlinImportOptimizer() : ImportOptimizer { public class CollectUsedDescriptorsVisitor(val file: JetFile, val recursive: Boolean) : JetVisitorVoid() { private val _descriptors = HashSet() + private val currentPackageName = file.getPackageFqName() public val descriptors: Set get() = _descriptors @@ -218,7 +213,10 @@ public class KotlinImportOptimizer() : ImportOptimizer { ?: reference.resolveToDescriptors(bindingContext) for (target in targets) { if (!target.canBeReferencedViaImport()) continue - if (target is PackageViewDescriptor && target.fqName.parent() == FqName.ROOT) continue // no need to import top-level packages + val importableDescriptor = target.getImportableDescriptor() + val parentFqName = DescriptorUtils.getFqNameSafe(importableDescriptor).parent() + if (target is PackageViewDescriptor && parentFqName == FqName.ROOT) continue // no need to import top-level packages + if (target !is PackageViewDescriptor && parentFqName == currentPackageName) continue if (!target.isExtension) { // for non-extension targets, count only non-qualified simple name usages if (element !is JetNameReferenceExpression) continue @@ -226,7 +224,6 @@ public class KotlinImportOptimizer() : ImportOptimizer { if (element.getReceiverExpression() != null) continue } - val importableDescriptor = target.getImportableDescriptor() if (referencedName != null && importableDescriptor.getName() != referencedName) continue // resolved via alias if (isAccessibleAsMember(importableDescriptor, element)) continue diff --git a/idea/testData/inspections/unusedImport/file.kt b/idea/testData/inspections/unusedImport/file.kt index 7bdc213e62a..404e1b6d06c 100644 --- a/idea/testData/inspections/unusedImport/file.kt +++ b/idea/testData/inspections/unusedImport/file.kt @@ -9,10 +9,14 @@ import java.net.Unresolved // unused but unresolved import java.net.ConnectException as CE // highlighting of unused aliases not implemented yet -fun foo(list: ArrayList) { +import RootPackageClass // unused because it's in the current package + +fun foo(list: ArrayList, p: RootPackageClass) { list.add("") Date() } +class RootPackageClass + // WITH_RUNTIME // FULL_JDK diff --git a/idea/testData/inspections/unusedImport/fileInPack1.kt b/idea/testData/inspections/unusedImport/fileInPack1.kt new file mode 100644 index 00000000000..7bd1f2ee394 --- /dev/null +++ b/idea/testData/inspections/unusedImport/fileInPack1.kt @@ -0,0 +1,8 @@ +package pack1 + +import pack1.ClassInPack1 // unused because it's in the current package + +fun foo(p: ClassInPack1) { +} + +class ClassInPack1 diff --git a/idea/testData/inspections/unusedImport/fileInPack2.kt b/idea/testData/inspections/unusedImport/fileInPack2.kt new file mode 100644 index 00000000000..aee750ad3ce --- /dev/null +++ b/idea/testData/inspections/unusedImport/fileInPack2.kt @@ -0,0 +1,8 @@ +package pack2 + +import pack2.* // unused because it's the current package + +fun foo(p: ClassInPack2) { +} + +class ClassInPack2 diff --git a/idea/testData/inspections/unusedImport/inspectionData/expected.xml b/idea/testData/inspections/unusedImport/inspectionData/expected.xml index d2568c984bf..6783a5a1094 100644 --- a/idea/testData/inspections/unusedImport/inspectionData/expected.xml +++ b/idea/testData/inspections/unusedImport/inspectionData/expected.xml @@ -17,4 +17,21 @@ Unused import directive + + fileInPack1.kt + 3 + light_idea_test_case + + Unused import directive + Unused import directive + + + + fileInPack2.kt + 3 + light_idea_test_case + + Unused import directive + Unused import directive +