From 424c086ba36c9145314dffaf0dbbef060cadf4a4 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Thu, 11 Sep 2014 16:34:32 +0400 Subject: [PATCH] Sort list of declarations suggested for auto-import by proximity #KT-2050 Fixed --- .../plugin/actions/JetAddImportAction.java | 2 +- .../jet/plugin/quickfix/AutoImportFix.kt | 66 +++++++++++++++---- .../sameModuleImportPriority.after.kt | 10 +++ .../sameModuleImportPriority.before.Main.kt | 8 +++ ...ModuleImportPriority.before.data.Sample.kt | 5 ++ .../QuickFixMultiFileTestGenerated.java | 6 ++ 6 files changed, 85 insertions(+), 12 deletions(-) create mode 100644 idea/testData/quickfix/autoImports/sameModuleImportPriority.after.kt create mode 100644 idea/testData/quickfix/autoImports/sameModuleImportPriority.before.Main.kt create mode 100644 idea/testData/quickfix/autoImports/sameModuleImportPriority.before.data.Sample.kt diff --git a/idea/src/org/jetbrains/jet/plugin/actions/JetAddImportAction.java b/idea/src/org/jetbrains/jet/plugin/actions/JetAddImportAction.java index 57bbd85402b..9b852cbde6b 100644 --- a/idea/src/org/jetbrains/jet/plugin/actions/JetAddImportAction.java +++ b/idea/src/org/jetbrains/jet/plugin/actions/JetAddImportAction.java @@ -79,7 +79,7 @@ public class JetAddImportAction implements QuestionAction { // TODO: Validate resolution variants. See AddImportAction.execute() - if (possibleImports.size() == 1){ + if (possibleImports.size() == 1 || ApplicationManager.getApplication().isUnitTestMode()) { addImport(myElement, myProject, possibleImports.get(0)); } else{ diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AutoImportFix.kt b/idea/src/org/jetbrains/jet/plugin/quickfix/AutoImportFix.kt index 096ddf2a3a3..6582297f6eb 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AutoImportFix.kt +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AutoImportFix.kt @@ -22,7 +22,6 @@ import com.intellij.codeInsight.intention.HighPriorityAction import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.command.CommandProcessor import com.intellij.openapi.editor.Editor -import com.intellij.openapi.module.ModuleUtilCore import com.intellij.openapi.project.Project import com.intellij.psi.PsiFile import com.intellij.psi.search.GlobalSearchScope @@ -35,7 +34,6 @@ import org.jetbrains.jet.lang.psi.JetSimpleNameExpression import org.jetbrains.jet.lang.psi.psiUtil.* import org.jetbrains.jet.lang.resolve.DescriptorUtils import org.jetbrains.jet.lang.resolve.ImportPath -import org.jetbrains.jet.lang.resolve.lazy.KotlinCodeAnalyzer import org.jetbrains.jet.lang.resolve.name.FqName import org.jetbrains.jet.plugin.JetBundle import org.jetbrains.jet.plugin.actions.JetAddImportAction @@ -46,12 +44,18 @@ import org.jetbrains.jet.plugin.project.ProjectStructureUtil import org.jetbrains.jet.plugin.project.ResolveSessionForBodies import org.jetbrains.jet.plugin.util.JetPsiHeuristicsUtil import java.util.ArrayList -import org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor +import com.intellij.psi.PsiElement +import org.jetbrains.jet.plugin.codeInsight.DescriptorToDeclarationUtil +import com.intellij.openapi.module.ModuleUtilCore +import org.jetbrains.jet.plugin.ProjectRootsUtil +import org.jetbrains.jet.asJava.unwrapped /** * Check possibility and perform fix for unresolved references. */ public class AutoImportFix(element: JetSimpleNameExpression) : JetHintAction(element), HighPriorityAction { + private val module = ModuleUtilCore.findModuleForPsiElement(element) private val suggestions: Collection = computeSuggestions(element) @@ -108,7 +112,7 @@ public class AutoImportFix(element: JetSimpleNameExpression) : JetHintAction() + val result = ArrayList() if (!element.isImportDirectiveExpression() && !JetPsiUtil.isSelectorInQualified(element)) { result.addAll(getClassNames(referenceName, file, searchScope)) @@ -117,23 +121,38 @@ public class AutoImportFix(element: JetSimpleNameExpression) : JetHintAction + private fun getTopLevelCallables( + name: String, + context: JetExpression, + searchScope: GlobalSearchScope, + resolveSession: ResolveSessionForBodies, + project: Project + ): Collection = KotlinIndicesHelper(project).getTopLevelCallablesByName(name, context, resolveSession, searchScope) - .map { DescriptorUtils.getFqNameSafe(it) } + .map { PrioritizedFqName(it) } .toSet() - private fun getExtensions(name: String, expression: JetSimpleNameExpression, searchScope: GlobalSearchScope, resolveSession: ResolveSessionForBodies, project: Project): Collection + private fun getExtensions( + name: String, + expression: JetSimpleNameExpression, + searchScope: GlobalSearchScope, + resolveSession: ResolveSessionForBodies, + project: Project + ): Collection = KotlinIndicesHelper(project).getCallableExtensions({ it == name }, expression, resolveSession, searchScope) - .map { DescriptorUtils.getFqNameSafe(it) } + .map { PrioritizedFqName(it) } .toSet() - private fun getClassNames(name: String, file: JetFile, searchScope: GlobalSearchScope): Collection + private fun getClassNames(name: String, file: JetFile, searchScope: GlobalSearchScope): Collection = getShortNamesCache(file).getClassesByName(name, searchScope) .filter { JetPsiHeuristicsUtil.isAccessible(it, file) } - .map { FqName(it.getQualifiedName()!!) } + .map { PrioritizedFqName(it.unwrapped, FqName(it.getQualifiedName()!!)) } .toSet() private fun getShortNamesCache(jetFile: JetFile): PsiShortNamesCache { @@ -144,6 +163,31 @@ public class AutoImportFix(element: JetSimpleNameExpression) : JetHintAction Priority.OTHER + ModuleUtilCore.findModuleForPsiElement(declaration) == module -> Priority.MODULE + ProjectRootsUtil.isInSource(declaration, false) -> Priority.PROJECT + else -> Priority.OTHER + } + + return PrioritizedFqName(fqName, priority) + } + + private fun PrioritizedFqName(descriptor: DeclarationDescriptor): PrioritizedFqName { + return PrioritizedFqName( + DescriptorToDeclarationUtil.getDeclaration(element.getContainingJetFile(), descriptor), + DescriptorUtils.getFqNameSafe(descriptor) + ) + } + class object { public fun createFactory(): JetSingleIntentionActionFactory { return object : JetSingleIntentionActionFactory() { diff --git a/idea/testData/quickfix/autoImports/sameModuleImportPriority.after.kt b/idea/testData/quickfix/autoImports/sameModuleImportPriority.after.kt new file mode 100644 index 00000000000..edf1a431468 --- /dev/null +++ b/idea/testData/quickfix/autoImports/sameModuleImportPriority.after.kt @@ -0,0 +1,10 @@ +// "Import" "true" +// ERROR: Unresolved reference: Delegates +// WITH_RUNTIME +package testing + +import some.Delegates + +fun foo() { + val d = Delegates() +} \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/sameModuleImportPriority.before.Main.kt b/idea/testData/quickfix/autoImports/sameModuleImportPriority.before.Main.kt new file mode 100644 index 00000000000..2833bd45c59 --- /dev/null +++ b/idea/testData/quickfix/autoImports/sameModuleImportPriority.before.Main.kt @@ -0,0 +1,8 @@ +// "Import" "true" +// ERROR: Unresolved reference: Delegates +// WITH_RUNTIME +package testing + +fun foo() { + val d = Delegates() +} \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/sameModuleImportPriority.before.data.Sample.kt b/idea/testData/quickfix/autoImports/sameModuleImportPriority.before.data.Sample.kt new file mode 100644 index 00000000000..84f6c1bf26b --- /dev/null +++ b/idea/testData/quickfix/autoImports/sameModuleImportPriority.before.data.Sample.kt @@ -0,0 +1,5 @@ +package some + +public class Delegates { + +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixMultiFileTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixMultiFileTestGenerated.java index 77d606e5da1..de88640dfac 100644 --- a/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixMultiFileTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixMultiFileTestGenerated.java @@ -184,6 +184,12 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes doTestWithExtraFile(fileName); } + @TestMetadata("sameModuleImportPriority.before.Main.kt") + public void testSameModuleImportPriority() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/sameModuleImportPriority.before.Main.kt"); + doTestWithExtraFile(fileName); + } + @TestMetadata("timesAssign.before.Main.kt") public void testTimesAssign() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/timesAssign.before.Main.kt");