From 6ddedb78259a8bd3055f18307ac3c156e6afe16a Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Mon, 1 Dec 2014 13:59:26 +0300 Subject: [PATCH] Better imported/non-imported items sorting in completion --- .../tests/org/jetbrains/jet/jetTestUtils.kt | 16 +++---- .../plugin/completion/CompletionSorting.kt | 47 ++++++++++++++++--- .../weighers/basic/ImportedOrder.Data1.kt | 4 ++ .../weighers/basic/ImportedOrder.Data2.kt | 4 ++ .../weighers/basic/ImportedOrder.Data3.kt | 4 ++ .../weighers/basic/ImportedOrder.kt | 24 ++++++++++ .../weighers/AbstractCompletionWeigherTest.kt | 2 +- .../BasicCompletionWeigherTestGenerated.java | 6 +++ 8 files changed, 89 insertions(+), 18 deletions(-) create mode 100644 idea/testData/completion/weighers/basic/ImportedOrder.Data1.kt create mode 100644 idea/testData/completion/weighers/basic/ImportedOrder.Data2.kt create mode 100644 idea/testData/completion/weighers/basic/ImportedOrder.Data3.kt create mode 100644 idea/testData/completion/weighers/basic/ImportedOrder.kt diff --git a/compiler/tests/org/jetbrains/jet/jetTestUtils.kt b/compiler/tests/org/jetbrains/jet/jetTestUtils.kt index 9eb24b51c16..9579e55884e 100644 --- a/compiler/tests/org/jetbrains/jet/jetTestUtils.kt +++ b/compiler/tests/org/jetbrains/jet/jetTestUtils.kt @@ -25,18 +25,14 @@ public fun String.trimTrailingWhitespacesAndAddNewlineAtEOF(): String = result -> if (result.endsWith("\n")) result else result + "\n" } -public fun CodeInsightTestFixture.configureWithExtraFile(path: String, extraNamePart: String = ".Data") { +public fun CodeInsightTestFixture.configureWithExtraFile(path: String, vararg extraNameParts: String = array(".Data")) { val noExtensionPath = FileUtil.getNameWithoutExtension(path) - val extraPath = array("kt", "java").stream() - .map { ext -> "$noExtensionPath$extraNamePart.$ext" } - .firstOrNull { extraPath -> File(extraPath).exists() } + val extensions = array("kt", "java") + val extraPaths: List = extraNameParts + .flatMap { extensions.map { ext -> "$noExtensionPath$it.$ext" } } + .filter { File(it).exists() } - if (extraPath != null) { - configureByFiles(path, extraPath) - } - else { - configureByFile(path) - } + configureByFiles(*(listOf(path) + extraPaths).copyToArray()) } public fun String.trimIndent(): String { diff --git a/idea/src/org/jetbrains/jet/plugin/completion/CompletionSorting.kt b/idea/src/org/jetbrains/jet/plugin/completion/CompletionSorting.kt index 06c93da3cd2..0c68c20177a 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/CompletionSorting.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/CompletionSorting.kt @@ -38,6 +38,8 @@ import org.jetbrains.jet.plugin.completion.smart.NameSimilarityWeigher import org.jetbrains.jet.plugin.completion.smart.SMART_COMPLETION_ITEM_PRIORITY_KEY import org.jetbrains.jet.plugin.completion.smart.SmartCompletionItemPriority import com.intellij.psi.PsiClass +import java.util.HashSet +import org.jetbrains.jet.lang.resolve.name.FqName public fun CompletionResultSet.addKotlinSorting(parameters: CompletionParameters): CompletionResultSet { var sorter = CompletionSorter.defaultSorter(parameters, getPrefixMatcher())!! @@ -109,11 +111,15 @@ private object PreferMatchingItemWeigher : LookupElementWeigher("kotlin.preferMa } private class JetDeclarationRemotenessWeigher(private val file: JetFile) : LookupElementWeigher("kotlin.declarationRemoteness") { + private val importCache = ImportCache() + private enum class Weight { kotlinDefaultImport thisFile - imported + preciseImport + allUnderImport default + hasImportFromSamePackage notImported } @@ -126,25 +132,52 @@ private class JetDeclarationRemotenessWeigher(private val file: JetFile) : Looku } } - val fqName = fqName(o) + val qualifiedName = qualifiedName(o) // Invalid name can be met for class object descriptor: Test.MyTest.A..testOther - if (fqName != null && isValidJavaFqName(fqName)) { - val importPath = ImportPath(fqName) + if (qualifiedName != null && isValidJavaFqName(qualifiedName)) { + val importPath = ImportPath(qualifiedName) + val fqName = importPath.fqnPart() return when { - ImportInsertHelper.getInstance().needImport(importPath, file) -> Weight.notImported ImportInsertHelper.getInstance().isImportedWithDefault(importPath, file) -> Weight.kotlinDefaultImport - else -> Weight.imported + importCache.isImportedWithPreciseImport(fqName) -> Weight.preciseImport + importCache.isImportedWithAllUnderImport(fqName) -> Weight.allUnderImport + importCache.hasPreciseImportFromPackage(fqName.parent()) -> Weight.hasImportFromSamePackage + else -> Weight.notImported } } return Weight.default } - private fun fqName(lookupObject: Any): String? { + private fun qualifiedName(lookupObject: Any): String? { return when (lookupObject) { is DeclarationDescriptorLookupObject -> DescriptorUtils.getFqName(lookupObject.descriptor).toString() is PsiClass -> lookupObject.getQualifiedName() else -> null } } + + private inner class ImportCache { + private val preciseImports = HashSet() + private val preciseImportPackages = HashSet() + private val allUnderImports = HashSet() + + ;{ + for (import in file.getImportDirectives()) { + val importPath = import.getImportPath() ?: continue + val fqName = importPath.fqnPart() + if (importPath.isAllUnder()) { + allUnderImports.add(fqName) + } + else { + preciseImports.add(fqName) + preciseImportPackages.add(fqName.parent()) + } + } + } + + fun isImportedWithPreciseImport(name: FqName) = name in preciseImports + fun isImportedWithAllUnderImport(name: FqName) = name.parent() in allUnderImports + fun hasPreciseImportFromPackage(packageName: FqName) = packageName in preciseImportPackages + } } diff --git a/idea/testData/completion/weighers/basic/ImportedOrder.Data1.kt b/idea/testData/completion/weighers/basic/ImportedOrder.Data1.kt new file mode 100644 index 00000000000..a5c89e8d385 --- /dev/null +++ b/idea/testData/completion/weighers/basic/ImportedOrder.Data1.kt @@ -0,0 +1,4 @@ +package ppp1 + +class MyClass1 +class MyClass2 diff --git a/idea/testData/completion/weighers/basic/ImportedOrder.Data2.kt b/idea/testData/completion/weighers/basic/ImportedOrder.Data2.kt new file mode 100644 index 00000000000..60086f63d75 --- /dev/null +++ b/idea/testData/completion/weighers/basic/ImportedOrder.Data2.kt @@ -0,0 +1,4 @@ +package ppp2 + +class MyClass3 +class MyClass4 diff --git a/idea/testData/completion/weighers/basic/ImportedOrder.Data3.kt b/idea/testData/completion/weighers/basic/ImportedOrder.Data3.kt new file mode 100644 index 00000000000..b469a91c162 --- /dev/null +++ b/idea/testData/completion/weighers/basic/ImportedOrder.Data3.kt @@ -0,0 +1,4 @@ +package ppp3 + +class MyClass5 +class MyClass6 diff --git a/idea/testData/completion/weighers/basic/ImportedOrder.kt b/idea/testData/completion/weighers/basic/ImportedOrder.kt new file mode 100644 index 00000000000..7edde684ebf --- /dev/null +++ b/idea/testData/completion/weighers/basic/ImportedOrder.kt @@ -0,0 +1,24 @@ +import ppp1.* +import ppp3.MyClass6 + +val v = My + +// INVOCATION_COUNT: 2 + +/* explicitly imported */ +// ORDER: MyClass6 + +/* imported with * */ +// ORDER: MyClass1 + +/* imported with * */ +// ORDER: MyClass2 + +/* another class from the same package imported */ +// ORDER: MyClass5 + +/* not imported */ +// ORDER: MyClass3 + +/* not imported */ +// ORDER: MyClass4 diff --git a/idea/tests/org/jetbrains/jet/completion/weighers/AbstractCompletionWeigherTest.kt b/idea/tests/org/jetbrains/jet/completion/weighers/AbstractCompletionWeigherTest.kt index cea8ce493c9..287a3bda597 100644 --- a/idea/tests/org/jetbrains/jet/completion/weighers/AbstractCompletionWeigherTest.kt +++ b/idea/tests/org/jetbrains/jet/completion/weighers/AbstractCompletionWeigherTest.kt @@ -28,7 +28,7 @@ import org.jetbrains.jet.plugin.JetWithJdkAndRuntimeLightProjectDescriptor public abstract class AbstractCompletionWeigherTest(val completionType: CompletionType, val relativeTestDataPath: String) : JetLightCodeInsightFixtureTestCase() { fun doTest(path: String) { - myFixture.configureWithExtraFile(path) + myFixture.configureWithExtraFile(path, ".Data", ".Data1", ".Data2", ".Data3") val text = myFixture.getEditor().getDocument().getText() diff --git a/idea/tests/org/jetbrains/jet/completion/weighers/BasicCompletionWeigherTestGenerated.java b/idea/tests/org/jetbrains/jet/completion/weighers/BasicCompletionWeigherTestGenerated.java index 64ac9d0f524..a34ea2a535d 100644 --- a/idea/tests/org/jetbrains/jet/completion/weighers/BasicCompletionWeigherTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/completion/weighers/BasicCompletionWeigherTestGenerated.java @@ -59,6 +59,12 @@ public class BasicCompletionWeigherTestGenerated extends AbstractBasicCompletion doTest(fileName); } + @TestMetadata("ImportedOrder.kt") + public void testImportedOrder() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/weighers/basic/ImportedOrder.kt"); + doTest(fileName); + } + @TestMetadata("KeywordsLast.kt") public void testKeywordsLast() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/weighers/basic/KeywordsLast.kt");