diff --git a/idea/src/org/jetbrains/kotlin/idea/imports/KotlinImportOptimizer.kt b/idea/src/org/jetbrains/kotlin/idea/imports/KotlinImportOptimizer.kt index 0811bebb276..34185deec00 100644 --- a/idea/src/org/jetbrains/kotlin/idea/imports/KotlinImportOptimizer.kt +++ b/idea/src/org/jetbrains/kotlin/idea/imports/KotlinImportOptimizer.kt @@ -46,16 +46,30 @@ import org.jetbrains.kotlin.resolve.scopes.utils.* class KotlinImportOptimizer : ImportOptimizer { override fun supports(file: PsiFile?) = file is KtFile - override fun processFile(file: PsiFile?): Runnable { - val ktFile = (file as? KtFile) ?: return Runnable { /* empty runnable */ } - val preparedImports = prepareImports(ktFile) ?: return Runnable { /* empty runnable */ } + override fun processFile(file: PsiFile?): ImportOptimizer.CollectingInfoRunnable { + val ktFile = (file as? KtFile) ?: return DO_NOTHING + val (add, remove, imports) = prepareImports(ktFile) ?: return DO_NOTHING - return Runnable { - replaceImports(ktFile, preparedImports) + return object : ImportOptimizer.CollectingInfoRunnable { + override fun getUserNotificationInfo(): String = if (remove == 0) "Rearranged imports" + else buildString { + append("Removed ") + append(remove) + append(" import") + if (remove > 1) append("s") + if (add > 0) { + append(", added ") + append(add) + append(" import") + if (add > 1) append("s") + } + } + + override fun run() = replaceImports(ktFile, imports) } } - private fun prepareImports(file: KtFile): List? { + private fun prepareImports(file: KtFile): OptimizeInformation? { ApplicationManager.getApplication().assertReadAccessAllowed() val moduleInfo = file.getNullableModuleInfo() @@ -68,9 +82,17 @@ class KotlinImportOptimizer : ImportOptimizer { val descriptorsToImport = collectDescriptorsToImport(file) - return prepareOptimizedImports(file, descriptorsToImport) + val imports = prepareOptimizedImports(file, descriptorsToImport) ?: return null + val intersect = imports.intersect(oldImports.map { it.importPath }) + return OptimizeInformation( + add = imports.size - intersect.size, + remove = oldImports.size - intersect.size, + imports = imports + ) } + private data class OptimizeInformation(val add: Int, val remove: Int, val imports: List) + private class CollectUsedDescriptorsVisitor(file: KtFile) : KtVisitorVoid() { private val currentPackageName = file.packageFqName private val aliases: Map> = file.importDirectives @@ -220,5 +242,11 @@ class KotlinImportOptimizer : ImportOptimizer { return bindingContext[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, element as? KtReferenceExpression]?.let { listOf(it) } ?: resolveToDescriptors(bindingContext) } + + private val DO_NOTHING = object : ImportOptimizer.CollectingInfoRunnable { + override fun run() = Unit + + override fun getUserNotificationInfo() = "Unused imports not found" + } } } diff --git a/idea/testData/editor/optimizeImports/common/ArrayAccessExpression.kt b/idea/testData/editor/optimizeImports/common/ArrayAccessExpression.kt index 1c80e559a11..cd0b376e20d 100644 --- a/idea/testData/editor/optimizeImports/common/ArrayAccessExpression.kt +++ b/idea/testData/editor/optimizeImports/common/ArrayAccessExpression.kt @@ -1,3 +1,4 @@ +// WITH_MESSAGE: "Unused imports not found" import test1.MyClass import test1.get diff --git a/idea/testData/editor/optimizeImports/common/ArrayAccessExpression.kt.after b/idea/testData/editor/optimizeImports/common/ArrayAccessExpression.kt.after index 1c80e559a11..cd0b376e20d 100644 --- a/idea/testData/editor/optimizeImports/common/ArrayAccessExpression.kt.after +++ b/idea/testData/editor/optimizeImports/common/ArrayAccessExpression.kt.after @@ -1,3 +1,4 @@ +// WITH_MESSAGE: "Unused imports not found" import test1.MyClass import test1.get diff --git a/idea/testData/editor/optimizeImports/common/ClassMemberImported.kt b/idea/testData/editor/optimizeImports/common/ClassMemberImported.kt index 5e1b3773e6b..bfb45764cf5 100644 --- a/idea/testData/editor/optimizeImports/common/ClassMemberImported.kt +++ b/idea/testData/editor/optimizeImports/common/ClassMemberImported.kt @@ -1,3 +1,4 @@ +// WITH_MESSAGE: "Removed 5 imports, added 2 imports" package test import dependency.* diff --git a/idea/testData/editor/optimizeImports/common/ClassMemberImported.kt.after b/idea/testData/editor/optimizeImports/common/ClassMemberImported.kt.after index f3220afd1b3..388880635aa 100644 --- a/idea/testData/editor/optimizeImports/common/ClassMemberImported.kt.after +++ b/idea/testData/editor/optimizeImports/common/ClassMemberImported.kt.after @@ -1,3 +1,4 @@ +// WITH_MESSAGE: "Removed 5 imports, added 2 imports" package test import dependency.A diff --git a/idea/testData/editor/optimizeImports/common/ConflictWithAlias2.kt b/idea/testData/editor/optimizeImports/common/ConflictWithAlias2.kt index c0203313241..ae83d25b463 100644 --- a/idea/testData/editor/optimizeImports/common/ConflictWithAlias2.kt +++ b/idea/testData/editor/optimizeImports/common/ConflictWithAlias2.kt @@ -1,3 +1,4 @@ +// WITH_MESSAGE: "Removed 4 imports, added 1 import" import duration.* import duration.hours as hour import duration.minutes as minute diff --git a/idea/testData/editor/optimizeImports/common/ConflictWithAlias2.kt.after b/idea/testData/editor/optimizeImports/common/ConflictWithAlias2.kt.after index 874e6806e6d..a1072ec394d 100644 --- a/idea/testData/editor/optimizeImports/common/ConflictWithAlias2.kt.after +++ b/idea/testData/editor/optimizeImports/common/ConflictWithAlias2.kt.after @@ -1,3 +1,4 @@ +// WITH_MESSAGE: "Removed 4 imports, added 1 import" import duration.minutes import duration.hours as hour import duration.seconds as second diff --git a/idea/testData/editor/optimizeImports/common/CurrentPackage.kt b/idea/testData/editor/optimizeImports/common/CurrentPackage.kt index 6182b0149e7..9ecf165919b 100644 --- a/idea/testData/editor/optimizeImports/common/CurrentPackage.kt +++ b/idea/testData/editor/optimizeImports/common/CurrentPackage.kt @@ -1,3 +1,4 @@ +// WITH_MESSAGE: "Removed 1 import" package ppp import ppp.* diff --git a/idea/testData/editor/optimizeImports/common/CurrentPackage.kt.after b/idea/testData/editor/optimizeImports/common/CurrentPackage.kt.after index 43d070d7a36..90d65522c12 100644 --- a/idea/testData/editor/optimizeImports/common/CurrentPackage.kt.after +++ b/idea/testData/editor/optimizeImports/common/CurrentPackage.kt.after @@ -1,3 +1,4 @@ +// WITH_MESSAGE: "Removed 1 import" package ppp open class C diff --git a/idea/testData/editor/optimizeImports/common/DefaultImportAndAlias.kt b/idea/testData/editor/optimizeImports/common/DefaultImportAndAlias.kt index 628ff0c021f..385e662f606 100644 --- a/idea/testData/editor/optimizeImports/common/DefaultImportAndAlias.kt +++ b/idea/testData/editor/optimizeImports/common/DefaultImportAndAlias.kt @@ -1,3 +1,4 @@ +// WITH_MESSAGE: "Rearranged imports" import pack1.a import pack1.a as a1 import kotlin.collections.List diff --git a/idea/testData/editor/optimizeImports/common/DefaultImportAndAlias.kt.after b/idea/testData/editor/optimizeImports/common/DefaultImportAndAlias.kt.after index 7d2af8c3a01..b7c18d2f591 100644 --- a/idea/testData/editor/optimizeImports/common/DefaultImportAndAlias.kt.after +++ b/idea/testData/editor/optimizeImports/common/DefaultImportAndAlias.kt.after @@ -1,3 +1,4 @@ +// WITH_MESSAGE: "Rearranged imports" import pack1.a import kotlin.collections.List import kotlin.run diff --git a/idea/testData/editor/optimizeImports/common/DefaultImportAndAlias2.kt b/idea/testData/editor/optimizeImports/common/DefaultImportAndAlias2.kt index 7f643ba7119..cf1e73f52fb 100644 --- a/idea/testData/editor/optimizeImports/common/DefaultImportAndAlias2.kt +++ b/idea/testData/editor/optimizeImports/common/DefaultImportAndAlias2.kt @@ -1,3 +1,4 @@ +// WITH_MESSAGE: "Removed 1 import" import pack1.a import pack1.a as a1 import kotlin.run as run1 diff --git a/idea/testData/editor/optimizeImports/common/DefaultImportAndAlias2.kt.after b/idea/testData/editor/optimizeImports/common/DefaultImportAndAlias2.kt.after index a8c85438605..ba365008fc1 100644 --- a/idea/testData/editor/optimizeImports/common/DefaultImportAndAlias2.kt.after +++ b/idea/testData/editor/optimizeImports/common/DefaultImportAndAlias2.kt.after @@ -1,3 +1,4 @@ +// WITH_MESSAGE: "Removed 1 import" import pack1.a import pack1.a as a1 import kotlin.run as run1 diff --git a/idea/tests/org/jetbrains/kotlin/idea/imports/AbstractOptimizeImportsTest.kt b/idea/tests/org/jetbrains/kotlin/idea/imports/AbstractOptimizeImportsTest.kt index 7e3c2b82cac..23ceebd7b6e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/imports/AbstractOptimizeImportsTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/imports/AbstractOptimizeImportsTest.kt @@ -6,16 +6,23 @@ package org.jetbrains.kotlin.idea.imports import com.intellij.testFramework.LightProjectDescriptor +import junit.framework.TestCase import org.jetbrains.kotlin.AbstractImportsTest import org.jetbrains.kotlin.idea.test.KotlinStdJSProjectDescriptor import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.test.InTextDirectivesUtils abstract class AbstractOptimizeImportsTest : AbstractImportsTest() { override fun doTest(file: KtFile): String { OptimizedImportsBuilder.testLog = StringBuilder() try { - KotlinImportOptimizer().processFile(file).run() + val optimizer = KotlinImportOptimizer().processFile(file) + optimizer.run() + val message = InTextDirectivesUtils.findStringWithPrefixes(file.text, "// WITH_MESSAGE: ") + if (message != null) { + TestCase.assertEquals(message, optimizer.userNotificationInfo) + } return OptimizedImportsBuilder.testLog.toString() } finally { OptimizedImportsBuilder.testLog = null