Optimize Imports: improve tooltip information
#KT-21374 Fixed
This commit is contained in:
@@ -46,16 +46,30 @@ import org.jetbrains.kotlin.resolve.scopes.utils.*
|
|||||||
class KotlinImportOptimizer : ImportOptimizer {
|
class KotlinImportOptimizer : ImportOptimizer {
|
||||||
override fun supports(file: PsiFile?) = file is KtFile
|
override fun supports(file: PsiFile?) = file is KtFile
|
||||||
|
|
||||||
override fun processFile(file: PsiFile?): Runnable {
|
override fun processFile(file: PsiFile?): ImportOptimizer.CollectingInfoRunnable {
|
||||||
val ktFile = (file as? KtFile) ?: return Runnable { /* empty runnable */ }
|
val ktFile = (file as? KtFile) ?: return DO_NOTHING
|
||||||
val preparedImports = prepareImports(ktFile) ?: return Runnable { /* empty runnable */ }
|
val (add, remove, imports) = prepareImports(ktFile) ?: return DO_NOTHING
|
||||||
|
|
||||||
return Runnable {
|
return object : ImportOptimizer.CollectingInfoRunnable {
|
||||||
replaceImports(ktFile, preparedImports)
|
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<ImportPath>? {
|
private fun prepareImports(file: KtFile): OptimizeInformation? {
|
||||||
ApplicationManager.getApplication().assertReadAccessAllowed()
|
ApplicationManager.getApplication().assertReadAccessAllowed()
|
||||||
|
|
||||||
val moduleInfo = file.getNullableModuleInfo()
|
val moduleInfo = file.getNullableModuleInfo()
|
||||||
@@ -68,9 +82,17 @@ class KotlinImportOptimizer : ImportOptimizer {
|
|||||||
|
|
||||||
val descriptorsToImport = collectDescriptorsToImport(file)
|
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<ImportPath>)
|
||||||
|
|
||||||
private class CollectUsedDescriptorsVisitor(file: KtFile) : KtVisitorVoid() {
|
private class CollectUsedDescriptorsVisitor(file: KtFile) : KtVisitorVoid() {
|
||||||
private val currentPackageName = file.packageFqName
|
private val currentPackageName = file.packageFqName
|
||||||
private val aliases: Map<FqName, List<Name>> = file.importDirectives
|
private val aliases: Map<FqName, List<Name>> = file.importDirectives
|
||||||
@@ -220,5 +242,11 @@ class KotlinImportOptimizer : ImportOptimizer {
|
|||||||
return bindingContext[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, element as? KtReferenceExpression]?.let { listOf(it) }
|
return bindingContext[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, element as? KtReferenceExpression]?.let { listOf(it) }
|
||||||
?: resolveToDescriptors(bindingContext)
|
?: resolveToDescriptors(bindingContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val DO_NOTHING = object : ImportOptimizer.CollectingInfoRunnable {
|
||||||
|
override fun run() = Unit
|
||||||
|
|
||||||
|
override fun getUserNotificationInfo() = "Unused imports not found"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// WITH_MESSAGE: "Unused imports not found"
|
||||||
import test1.MyClass
|
import test1.MyClass
|
||||||
import test1.get
|
import test1.get
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// WITH_MESSAGE: "Unused imports not found"
|
||||||
import test1.MyClass
|
import test1.MyClass
|
||||||
import test1.get
|
import test1.get
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// WITH_MESSAGE: "Removed 5 imports, added 2 imports"
|
||||||
package test
|
package test
|
||||||
|
|
||||||
import dependency.*
|
import dependency.*
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// WITH_MESSAGE: "Removed 5 imports, added 2 imports"
|
||||||
package test
|
package test
|
||||||
|
|
||||||
import dependency.A
|
import dependency.A
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// WITH_MESSAGE: "Removed 4 imports, added 1 import"
|
||||||
import duration.*
|
import duration.*
|
||||||
import duration.hours as hour
|
import duration.hours as hour
|
||||||
import duration.minutes as minute
|
import duration.minutes as minute
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// WITH_MESSAGE: "Removed 4 imports, added 1 import"
|
||||||
import duration.minutes
|
import duration.minutes
|
||||||
import duration.hours as hour
|
import duration.hours as hour
|
||||||
import duration.seconds as second
|
import duration.seconds as second
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// WITH_MESSAGE: "Removed 1 import"
|
||||||
package ppp
|
package ppp
|
||||||
|
|
||||||
import ppp.*
|
import ppp.*
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// WITH_MESSAGE: "Removed 1 import"
|
||||||
package ppp
|
package ppp
|
||||||
|
|
||||||
open class C
|
open class C
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// WITH_MESSAGE: "Rearranged imports"
|
||||||
import pack1.a
|
import pack1.a
|
||||||
import pack1.a as a1
|
import pack1.a as a1
|
||||||
import kotlin.collections.List
|
import kotlin.collections.List
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// WITH_MESSAGE: "Rearranged imports"
|
||||||
import pack1.a
|
import pack1.a
|
||||||
import kotlin.collections.List
|
import kotlin.collections.List
|
||||||
import kotlin.run
|
import kotlin.run
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// WITH_MESSAGE: "Removed 1 import"
|
||||||
import pack1.a
|
import pack1.a
|
||||||
import pack1.a as a1
|
import pack1.a as a1
|
||||||
import kotlin.run as run1
|
import kotlin.run as run1
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// WITH_MESSAGE: "Removed 1 import"
|
||||||
import pack1.a
|
import pack1.a
|
||||||
import pack1.a as a1
|
import pack1.a as a1
|
||||||
import kotlin.run as run1
|
import kotlin.run as run1
|
||||||
|
|||||||
@@ -6,16 +6,23 @@
|
|||||||
package org.jetbrains.kotlin.idea.imports
|
package org.jetbrains.kotlin.idea.imports
|
||||||
|
|
||||||
import com.intellij.testFramework.LightProjectDescriptor
|
import com.intellij.testFramework.LightProjectDescriptor
|
||||||
|
import junit.framework.TestCase
|
||||||
import org.jetbrains.kotlin.AbstractImportsTest
|
import org.jetbrains.kotlin.AbstractImportsTest
|
||||||
import org.jetbrains.kotlin.idea.test.KotlinStdJSProjectDescriptor
|
import org.jetbrains.kotlin.idea.test.KotlinStdJSProjectDescriptor
|
||||||
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||||
|
|
||||||
abstract class AbstractOptimizeImportsTest : AbstractImportsTest() {
|
abstract class AbstractOptimizeImportsTest : AbstractImportsTest() {
|
||||||
override fun doTest(file: KtFile): String {
|
override fun doTest(file: KtFile): String {
|
||||||
OptimizedImportsBuilder.testLog = StringBuilder()
|
OptimizedImportsBuilder.testLog = StringBuilder()
|
||||||
try {
|
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()
|
return OptimizedImportsBuilder.testLog.toString()
|
||||||
} finally {
|
} finally {
|
||||||
OptimizedImportsBuilder.testLog = null
|
OptimizedImportsBuilder.testLog = null
|
||||||
|
|||||||
Reference in New Issue
Block a user