From 0243280668051891dec8a9d54d9d1c25ae438e0e Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Tue, 31 Mar 2015 16:19:42 +0300 Subject: [PATCH] Extension callables index is built correctly when using alias imports --- .../kotlin/idea/stubindex/IndexUtils.kt | 43 ++++++++++++++++--- ...edExtensionFunctionAndAlias.dependency1.kt | 9 ++++ ...edExtensionFunctionAndAlias.dependency2.kt | 3 ++ .../NotImportedExtensionFunctionAndAlias.kt | 9 ++++ ...tiFileJvmBasicCompletionTestGenerated.java | 6 +++ 5 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 idea/testData/completion/basic/multifile/NotImportedExtensionFunctionAndAlias/NotImportedExtensionFunctionAndAlias.dependency1.kt create mode 100644 idea/testData/completion/basic/multifile/NotImportedExtensionFunctionAndAlias/NotImportedExtensionFunctionAndAlias.dependency2.kt create mode 100644 idea/testData/completion/basic/multifile/NotImportedExtensionFunctionAndAlias/NotImportedExtensionFunctionAndAlias.kt diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/IndexUtils.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/IndexUtils.kt index 08f48baf5b7..4bed2903554 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/IndexUtils.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/IndexUtils.kt @@ -16,6 +16,9 @@ package org.jetbrains.kotlin.idea.stubindex +import com.google.common.collect.HashMultimap +import com.google.common.collect.Multimap +import com.intellij.openapi.util.Key import com.intellij.psi.stubs.IndexSink import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.stubs.KotlinCallableStubBase @@ -36,22 +39,25 @@ private fun JetTypeElement.index(declara when (this) { is JetUserType -> { - //TODO: aliases - var typeName = getReferencedName() ?: return + var referenceName = getReferencedName() ?: return if (declaration is JetNamedFunction) { - val typeParameter = declaration.getTypeParameters().firstOrNull { it.getName() == typeName } + val typeParameter = declaration.getTypeParameters().firstOrNull { it.getName() == referenceName } if (typeParameter != null) { val bound = typeParameter.getExtendsBound() if (bound != null) { bound.getTypeElement()?.index(declaration, sink) return } - typeName = "Any" + occurrence("Any") + return } } - occurrence(typeName) + occurrence(referenceName) + + val aliasNames = declaration.getContainingJetFile().aliasImportMap()[referenceName] + aliasNames.forEach { occurrence(it) } } is JetNullableType -> getInnerType()?.index(declaration, sink) @@ -64,3 +70,30 @@ private fun JetTypeElement.index(declara else -> occurrence("Any") } } + +private class CachedAliasImportData(val map: Multimap, val fileModificationStamp: Long) + +private val ALIAS_IMPORT_DATA_KEY = Key("ALIAS_IMPORT_MAP_KEY") + +private fun JetFile.aliasImportMap(): Multimap { + val cached = getUserData(ALIAS_IMPORT_DATA_KEY) + val modificationStamp = getModificationStamp() + if (cached != null && modificationStamp == cached.fileModificationStamp) { + return cached.map + } + + val data = CachedAliasImportData(buildAliasImportMap(), modificationStamp) + putUserData(ALIAS_IMPORT_DATA_KEY, cached) + return data.map +} + +private fun JetFile.buildAliasImportMap(): Multimap { + val map = HashMultimap.create() + val importList = getImportList() ?: return map + for (import in importList.getImports()) { + val aliasName = import.getAliasName() ?: continue + val name = import.getImportPath()?.fqnPart()?.shortName()?.asString() ?: continue + map.put(aliasName, name) + } + return map +} diff --git a/idea/testData/completion/basic/multifile/NotImportedExtensionFunctionAndAlias/NotImportedExtensionFunctionAndAlias.dependency1.kt b/idea/testData/completion/basic/multifile/NotImportedExtensionFunctionAndAlias/NotImportedExtensionFunctionAndAlias.dependency1.kt new file mode 100644 index 00000000000..1aec9b6b8cb --- /dev/null +++ b/idea/testData/completion/basic/multifile/NotImportedExtensionFunctionAndAlias/NotImportedExtensionFunctionAndAlias.dependency1.kt @@ -0,0 +1,9 @@ +package second + +import third.Dependency as MyDependency + +fun MyDependency?.helloFun() { +} + +fun T.helloFunGeneric() { +} diff --git a/idea/testData/completion/basic/multifile/NotImportedExtensionFunctionAndAlias/NotImportedExtensionFunctionAndAlias.dependency2.kt b/idea/testData/completion/basic/multifile/NotImportedExtensionFunctionAndAlias/NotImportedExtensionFunctionAndAlias.dependency2.kt new file mode 100644 index 00000000000..a901cc2604a --- /dev/null +++ b/idea/testData/completion/basic/multifile/NotImportedExtensionFunctionAndAlias/NotImportedExtensionFunctionAndAlias.dependency2.kt @@ -0,0 +1,3 @@ +package third + +class Dependency diff --git a/idea/testData/completion/basic/multifile/NotImportedExtensionFunctionAndAlias/NotImportedExtensionFunctionAndAlias.kt b/idea/testData/completion/basic/multifile/NotImportedExtensionFunctionAndAlias/NotImportedExtensionFunctionAndAlias.kt new file mode 100644 index 00000000000..b5e4788ba19 --- /dev/null +++ b/idea/testData/completion/basic/multifile/NotImportedExtensionFunctionAndAlias/NotImportedExtensionFunctionAndAlias.kt @@ -0,0 +1,9 @@ +package first + +fun firstFun(x: third.Dependency) { + x.hello +} + +// EXIST: helloFun +// EXIST: helloFunGeneric +// NUMBER: 2 \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/completion/MultiFileJvmBasicCompletionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/completion/MultiFileJvmBasicCompletionTestGenerated.java index 96f63264e82..66ada716664 100644 --- a/idea/tests/org/jetbrains/kotlin/completion/MultiFileJvmBasicCompletionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/completion/MultiFileJvmBasicCompletionTestGenerated.java @@ -149,6 +149,12 @@ public class MultiFileJvmBasicCompletionTestGenerated extends AbstractMultiFileJ doTest(fileName); } + @TestMetadata("NotImportedExtensionFunctionAndAlias") + public void testNotImportedExtensionFunctionAndAlias() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/multifile/NotImportedExtensionFunctionAndAlias/"); + doTest(fileName); + } + @TestMetadata("NotImportedExtensionProperty") public void testNotImportedExtensionProperty() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/multifile/NotImportedExtensionProperty/");