Imports from current package are redundant too

This commit is contained in:
Valentin Kipyatkov
2015-07-15 13:29:58 +03:00
parent 68dec99ad7
commit af192698ed
5 changed files with 47 additions and 13 deletions
@@ -80,7 +80,6 @@ public class KotlinImportOptimizer() : ImportOptimizer {
//TODO: keep existing imports? at least aliases (comments) //TODO: keep existing imports? at least aliases (comments)
val importInsertHelper = ImportInsertHelper.getInstance(file.getProject()) val importInsertHelper = ImportInsertHelper.getInstance(file.getProject())
val currentPackageName = file.getPackageFqName()
val descriptorsToImport = detectDescriptorsToImport() val descriptorsToImport = detectDescriptorsToImport()
@@ -90,14 +89,9 @@ public class KotlinImportOptimizer() : ImportOptimizer {
for (descriptor in descriptorsToImport) { for (descriptor in descriptorsToImport) {
val fqName = descriptor.importableFqNameSafe val fqName = descriptor.importableFqNameSafe
val parentFqName = fqName.parent() val parentFqName = fqName.parent()
if (descriptor is PackageViewDescriptor) { if (descriptor is PackageViewDescriptor || parentFqName.isRoot()) {
importsToGenerate.add(ImportPath(fqName, false)) importsToGenerate.add(ImportPath(fqName, false))
} }
else if (parentFqName.isRoot()) {
if (!currentPackageName.isRoot()) {
importsToGenerate.add(ImportPath(fqName, false))
}
}
else { else {
descriptorsByPackages.put(parentFqName, descriptor) descriptorsByPackages.put(parentFqName, descriptor)
} }
@@ -110,7 +104,7 @@ public class KotlinImportOptimizer() : ImportOptimizer {
for (packageName in descriptorsByPackages.keys()) { for (packageName in descriptorsByPackages.keys()) {
val descriptors = descriptorsByPackages[packageName] val descriptors = descriptorsByPackages[packageName]
val fqNames = descriptors.map { it.importableFqNameSafe }.toSet() 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) { if (explicitImports) {
for (fqName in fqNames) { for (fqName in fqNames) {
if (!isImportedByDefault(fqName)) { 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)) 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 // now check that there are no conflicts and all classes are really imported
val fileWithImportsText = StringBuilder { 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") importsToGenerate.filter { it.isAllUnder() }.map { "import " + it.getPathStr() }.joinTo(this, "\n")
}.toString() }.toString()
val fileWithImports = JetPsiFactory(file).createAnalyzableFile("Dummy.kt", fileWithImportsText, file) 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() { public class CollectUsedDescriptorsVisitor(val file: JetFile, val recursive: Boolean) : JetVisitorVoid() {
private val _descriptors = HashSet<DeclarationDescriptor>() private val _descriptors = HashSet<DeclarationDescriptor>()
private val currentPackageName = file.getPackageFqName()
public val descriptors: Set<DeclarationDescriptor> public val descriptors: Set<DeclarationDescriptor>
get() = _descriptors get() = _descriptors
@@ -218,7 +213,10 @@ public class KotlinImportOptimizer() : ImportOptimizer {
?: reference.resolveToDescriptors(bindingContext) ?: reference.resolveToDescriptors(bindingContext)
for (target in targets) { for (target in targets) {
if (!target.canBeReferencedViaImport()) continue 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 (!target.isExtension) { // for non-extension targets, count only non-qualified simple name usages
if (element !is JetNameReferenceExpression) continue if (element !is JetNameReferenceExpression) continue
@@ -226,7 +224,6 @@ public class KotlinImportOptimizer() : ImportOptimizer {
if (element.getReceiverExpression() != null) continue if (element.getReceiverExpression() != null) continue
} }
val importableDescriptor = target.getImportableDescriptor()
if (referencedName != null && importableDescriptor.getName() != referencedName) continue // resolved via alias if (referencedName != null && importableDescriptor.getName() != referencedName) continue // resolved via alias
if (isAccessibleAsMember(importableDescriptor, element)) continue if (isAccessibleAsMember(importableDescriptor, element)) continue
+5 -1
View File
@@ -9,10 +9,14 @@ 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 // highlighting of unused aliases not implemented yet
fun foo(list: ArrayList<String>) { import RootPackageClass // unused because it's in the current package
fun foo(list: ArrayList<String>, p: RootPackageClass) {
list.add("") list.add("")
Date() Date()
} }
class RootPackageClass
// WITH_RUNTIME // WITH_RUNTIME
// FULL_JDK // FULL_JDK
+8
View File
@@ -0,0 +1,8 @@
package pack1
import pack1.ClassInPack1 // unused because it's in the current package
fun foo(p: ClassInPack1) {
}
class ClassInPack1
+8
View File
@@ -0,0 +1,8 @@
package pack2
import pack2.* // unused because it's the current package
fun foo(p: ClassInPack2) {
}
class ClassInPack2
@@ -17,4 +17,21 @@
<description>Unused import directive</description> <description>Unused import directive</description>
</problem> </problem>
<problem>
<file>fileInPack1.kt</file>
<line>3</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="fileInPack1.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused import directive</problem_class>
<description>Unused import directive</description>
</problem>
<problem>
<file>fileInPack2.kt</file>
<line>3</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="fileInPack2.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused import directive</problem_class>
<description>Unused import directive</description>
</problem>
</problems> </problems>