From 3948c1e0079db38d95a93fce63515a1f5050173f Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 19 Jan 2017 18:49:22 +0300 Subject: [PATCH] KT-15153 Support typeAlias extensions in completion and add import #KT-15153 fixed --- .../kotlin/generators/tests/GenerateTests.kt | 5 ++ .../idea/stubindex/IdeStubIndexService.java | 2 + .../kotlin/idea/stubindex/IndexUtils.kt | 32 ++++++--- ...otlinTypeAliasByExpansionShortNameIndex.kt | 38 ++++++++++ .../ExtensionOnTypeAliasFromOtherTypeAlias.kt | 13 ++++ .../test/JSBasicCompletionTestGenerated.java | 6 ++ .../test/JvmBasicCompletionTestGenerated.java | 6 ++ .../kotlin/idea/core/KotlinIndicesHelper.kt | 25 ++++++- idea/src/META-INF/plugin.xml | 1 + ...nPropertyOnTypeAliasFromExpansion.after.kt | 10 +++ ...ypeAliasFromExpansion.before.Dependency.kt | 7 ++ ...rtyOnTypeAliasFromExpansion.before.Main.kt | 9 +++ ...ertyOnTypeAliasFromOtherTypeAlias.after.kt | 10 +++ ...iasFromOtherTypeAlias.before.Dependency.kt | 8 +++ ...TypeAliasFromOtherTypeAlias.before.Main.kt | 9 +++ .../typeAliasExtensionFunction.after.kt | 10 +++ ...liasExtensionFunction.before.Dependency.kt | 9 +++ .../typeAliasExtensionFunction.before.Main.kt | 9 +++ ...ExtensionFunctionInTypeAliasChain.after.kt | 9 +++ ...ctionInTypeAliasChain.before.Dependency.kt | 10 +++ ...ionFunctionInTypeAliasChain.before.Main.kt | 8 +++ .../typeAliasExtensionProperty.after.kt | 10 +++ ...liasExtensionProperty.before.Dependency.kt | 7 ++ .../typeAliasExtensionProperty.before.Main.kt | 9 +++ .../functionalTypes.kt | 17 +++++ .../typealiasExpansionIndex/generics.kt | 7 ++ .../typealiasExpansionIndex/simpleType.kt | 3 + ...nTypeAliasByExpansionShortNameIndexTest.kt | 70 +++++++++++++++++++ ...yExpansionShortNameIndexTestGenerated.java | 56 +++++++++++++++ .../QuickFixMultiFileTestGenerated.java | 30 ++++++++ 30 files changed, 432 insertions(+), 13 deletions(-) create mode 100644 idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/KotlinTypeAliasByExpansionShortNameIndex.kt create mode 100644 idea/idea-completion/testData/basic/common/ExtensionOnTypeAliasFromOtherTypeAlias.kt create mode 100644 idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromExpansion.after.kt create mode 100644 idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromExpansion.before.Dependency.kt create mode 100644 idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromExpansion.before.Main.kt create mode 100644 idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromOtherTypeAlias.after.kt create mode 100644 idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromOtherTypeAlias.before.Dependency.kt create mode 100644 idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromOtherTypeAlias.before.Main.kt create mode 100644 idea/testData/quickfix/autoImports/typeAliasExtensionFunction.after.kt create mode 100644 idea/testData/quickfix/autoImports/typeAliasExtensionFunction.before.Dependency.kt create mode 100644 idea/testData/quickfix/autoImports/typeAliasExtensionFunction.before.Main.kt create mode 100644 idea/testData/quickfix/autoImports/typeAliasExtensionFunctionInTypeAliasChain.after.kt create mode 100644 idea/testData/quickfix/autoImports/typeAliasExtensionFunctionInTypeAliasChain.before.Dependency.kt create mode 100644 idea/testData/quickfix/autoImports/typeAliasExtensionFunctionInTypeAliasChain.before.Main.kt create mode 100644 idea/testData/quickfix/autoImports/typeAliasExtensionProperty.after.kt create mode 100644 idea/testData/quickfix/autoImports/typeAliasExtensionProperty.before.Dependency.kt create mode 100644 idea/testData/quickfix/autoImports/typeAliasExtensionProperty.before.Main.kt create mode 100644 idea/testData/typealiasExpansionIndex/functionalTypes.kt create mode 100644 idea/testData/typealiasExpansionIndex/generics.kt create mode 100644 idea/testData/typealiasExpansionIndex/simpleType.kt create mode 100644 idea/tests/org/jetbrains/kotlin/idea/AbstractKotlinTypeAliasByExpansionShortNameIndexTest.kt create mode 100644 idea/tests/org/jetbrains/kotlin/idea/KotlinTypeAliasByExpansionShortNameIndexTestGenerated.java diff --git a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index 9b04eb743ae..f287961a109 100755 --- a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -47,6 +47,7 @@ import org.jetbrains.kotlin.formatter.AbstractFormatterTest import org.jetbrains.kotlin.formatter.AbstractTypingIndentationTestBase import org.jetbrains.kotlin.generators.tests.generator.* import org.jetbrains.kotlin.idea.AbstractExpressionSelectionTest +import org.jetbrains.kotlin.idea.AbstractKotlinTypeAliasByExpansionShortNameIndexTest import org.jetbrains.kotlin.idea.AbstractSmartSelectionTest import org.jetbrains.kotlin.idea.actions.AbstractGotoTestOrCodeActionTest import org.jetbrains.kotlin.idea.caches.resolve.AbstractIdeCompiledLightClassTest @@ -529,6 +530,10 @@ fun main(args: Array) { model("quickfix", pattern = """^(\w+)\.((before\.Main\.\w+)|(test))$""", testMethod = "doTestWithExtraFile") } + testClass { + model("typealiasExpansionIndex") + } + testClass { model("highlighter") } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/IdeStubIndexService.java b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/IdeStubIndexService.java index 2c4975d0ab1..31244ebe50e 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/IdeStubIndexService.java +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/IdeStubIndexService.java @@ -177,6 +177,8 @@ public class IdeStubIndexService extends StubIndexService { sink.occurrence(KotlinTypeAliasShortNameIndex.getInstance().getKey(), name); } + IndexUtilsKt.indexTypeAliasExpansion(stub, sink); + if (stub.isTopLevel()) { FqName fqName = stub.getFqName(); if (fqName != null) { 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 e8bbcbe4e89..a97cb6cda4c 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 @@ -20,34 +20,44 @@ import com.intellij.psi.stubs.IndexSink import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.stubs.KotlinCallableStubBase +import org.jetbrains.kotlin.psi.stubs.KotlinTypeAliasStub import org.jetbrains.kotlin.util.aliasImportMap fun indexTopLevelExtension(stub: KotlinCallableStubBase, sink: IndexSink) { if (stub.isExtension()) { val declaration = stub.psi val containingTypeReference = declaration.receiverTypeReference!! - containingTypeReference.typeElement?.index(declaration, sink, containingTypeReference) + containingTypeReference.typeElement?.index(declaration, containingTypeReference) { typeName -> + val name = declaration.name ?: return@index + sink.occurrence(KotlinTopLevelExtensionsByReceiverTypeIndex.INSTANCE.key, + KotlinTopLevelExtensionsByReceiverTypeIndex.buildKey(typeName, name)) + } } } -private fun KtTypeElement.index( - declaration: TDeclaration, sink: IndexSink, containingTypeReference: KtTypeReference -) { - fun occurrence(typeName: String) { - val name = declaration.name ?: return - sink.occurrence(KotlinTopLevelExtensionsByReceiverTypeIndex.INSTANCE.key, - KotlinTopLevelExtensionsByReceiverTypeIndex.buildKey(typeName, name)) +fun indexTypeAliasExpansion(stub: KotlinTypeAliasStub, sink: IndexSink) { + val declaration = stub.psi + val typeReference = declaration.getTypeReference() ?: return + val typeElement = typeReference.typeElement ?: return + typeElement.index(declaration, typeReference) { typeName -> + sink.occurrence(KotlinTypeAliasByExpansionShortNameIndex.KEY, typeName) } +} +private fun KtTypeElement.index( + declaration: KtTypeParameterListOwner, + containingTypeReference: KtTypeReference, + occurrence: (String) -> Unit +) { when (this) { is KtUserType -> { - var referenceName = referencedName ?: return + val referenceName = referencedName ?: return val typeParameter = declaration.typeParameters.firstOrNull { it.name == referenceName } if (typeParameter != null) { val bound = typeParameter.extendsBound if (bound != null) { - bound.typeElement?.index(declaration, sink, containingTypeReference) + bound.typeElement?.index(declaration, containingTypeReference, occurrence) } else { occurrence("Any") @@ -60,7 +70,7 @@ private fun KtTypeElement.index( aliasImportMap()[referenceName].forEach { occurrence(it) } } - is KtNullableType -> innerType?.index(declaration, sink, containingTypeReference) + is KtNullableType -> innerType?.index(declaration, containingTypeReference, occurrence) is KtFunctionType -> { val arity = parameters.size + (if (receiverTypeReference != null) 1 else 0) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/KotlinTypeAliasByExpansionShortNameIndex.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/KotlinTypeAliasByExpansionShortNameIndex.kt new file mode 100644 index 00000000000..7f8dd419f08 --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/KotlinTypeAliasByExpansionShortNameIndex.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.stubindex + +import com.intellij.openapi.project.Project +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.stubs.StringStubIndexExtension +import com.intellij.psi.stubs.StubIndex +import com.intellij.psi.stubs.StubIndexKey +import org.jetbrains.kotlin.psi.KtTypeAlias + +class KotlinTypeAliasByExpansionShortNameIndex : StringStubIndexExtension() { + override fun getKey(): StubIndexKey = KEY + + override fun get(key: String, project: Project, scope: GlobalSearchScope) = + StubIndex.getElements(KEY, key, project, scope, KtTypeAlias::class.java)!! + + companion object { + val KEY = KotlinIndexUtil.createIndexKey(KotlinTypeAliasByExpansionShortNameIndex::class.java) + val INSTANCE = KotlinTypeAliasByExpansionShortNameIndex() + + @JvmStatic fun getInstance() = INSTANCE + } +} \ No newline at end of file diff --git a/idea/idea-completion/testData/basic/common/ExtensionOnTypeAliasFromOtherTypeAlias.kt b/idea/idea-completion/testData/basic/common/ExtensionOnTypeAliasFromOtherTypeAlias.kt new file mode 100644 index 00000000000..7514047d6c3 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/ExtensionOnTypeAliasFromOtherTypeAlias.kt @@ -0,0 +1,13 @@ +class A + +typealias TA = A +typealias TA1 = A + +fun TA.ext() {} + +fun usage() { + val ta = TA1() + ta. +} + +// EXIST: ext \ No newline at end of file diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java index 6b12b600704..a6adaabdb07 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java @@ -158,6 +158,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes doTest(fileName); } + @TestMetadata("ExtensionOnTypeAliasFromOtherTypeAlias.kt") + public void testExtensionOnTypeAliasFromOtherTypeAlias() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/ExtensionOnTypeAliasFromOtherTypeAlias.kt"); + doTest(fileName); + } + @TestMetadata("ExtensionToIntInFloatStyle.kt") public void testExtensionToIntInFloatStyle() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/ExtensionToIntInFloatStyle.kt"); diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java index 0659225530f..e81342ca190 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java @@ -158,6 +158,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT doTest(fileName); } + @TestMetadata("ExtensionOnTypeAliasFromOtherTypeAlias.kt") + public void testExtensionOnTypeAliasFromOtherTypeAlias() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/ExtensionOnTypeAliasFromOtherTypeAlias.kt"); + doTest(fileName); + } + @TestMetadata("ExtensionToIntInFloatStyle.kt") public void testExtensionToIntInFloatStyle() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/ExtensionToIntInFloatStyle.kt"); diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt index f3bf4b25adf..2564f5ca473 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt @@ -49,7 +49,6 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.isHiddenInResolution import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList import java.lang.reflect.Field import java.lang.reflect.Modifier @@ -175,9 +174,31 @@ class KotlinIndicesHelper( suitableExtensions } + + private fun resolveTypeAliasesUsingIndex(type: KotlinType, originalTypeName: String, out: MutableCollection) { + val index = KotlinTypeAliasByExpansionShortNameIndex.INSTANCE + + fun searchRecursively(typeName: String) { + ProgressManager.checkCanceled() + index[typeName, project, scope].asSequence() + .map { it.resolveToDescriptorIfAny() as? TypeAliasDescriptor } + .filterNotNull() + .filter { it.expandedType == type } + .map { it.name.asString() } + .filter { it !in out } + .onEach(::searchRecursively) + .toCollection(out) + } + + searchRecursively(originalTypeName) + } + private fun MutableCollection.addTypeNames(type: KotlinType) { val constructor = type.constructor - addIfNotNull(constructor.declarationDescriptor?.name?.asString()) + constructor.declarationDescriptor?.name?.asString()?.let { typeName -> + add(typeName) + resolveTypeAliasesUsingIndex(type, typeName, this) + } constructor.supertypes.forEach { addTypeNames(it) } } diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 217c072da93..72efd37ee8b 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -662,6 +662,7 @@ + diff --git a/idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromExpansion.after.kt b/idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromExpansion.after.kt new file mode 100644 index 00000000000..242e4693566 --- /dev/null +++ b/idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromExpansion.after.kt @@ -0,0 +1,10 @@ +// "Import" "true" +// ERROR: Unresolved reference: ext + +import dep.A +import dep.ext + +fun use() { + val ta = A() + ta.ext +} \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromExpansion.before.Dependency.kt b/idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromExpansion.before.Dependency.kt new file mode 100644 index 00000000000..8cb4c67dbe1 --- /dev/null +++ b/idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromExpansion.before.Dependency.kt @@ -0,0 +1,7 @@ +package dep + +class A + +typealias TA = A + +val TA.ext: String get() = "ext" \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromExpansion.before.Main.kt b/idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromExpansion.before.Main.kt new file mode 100644 index 00000000000..b45dd5bfb70 --- /dev/null +++ b/idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromExpansion.before.Main.kt @@ -0,0 +1,9 @@ +// "Import" "true" +// ERROR: Unresolved reference: ext + +import dep.A + +fun use() { + val ta = A() + ta.ext +} \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromOtherTypeAlias.after.kt b/idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromOtherTypeAlias.after.kt new file mode 100644 index 00000000000..b96a78e29fc --- /dev/null +++ b/idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromOtherTypeAlias.after.kt @@ -0,0 +1,10 @@ +// "Import" "true" +// ERROR: Unresolved reference: ext + +import dep.TA1 +import dep.ext + +fun use() { + val ta = TA1() + ta.ext +} \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromOtherTypeAlias.before.Dependency.kt b/idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromOtherTypeAlias.before.Dependency.kt new file mode 100644 index 00000000000..f5caa8c5061 --- /dev/null +++ b/idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromOtherTypeAlias.before.Dependency.kt @@ -0,0 +1,8 @@ +package dep + +class A + +typealias TA = A +typealias TA1 = A + +val TA.ext: String get() = "ext" \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromOtherTypeAlias.before.Main.kt b/idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromOtherTypeAlias.before.Main.kt new file mode 100644 index 00000000000..1b24c4796dc --- /dev/null +++ b/idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromOtherTypeAlias.before.Main.kt @@ -0,0 +1,9 @@ +// "Import" "true" +// ERROR: Unresolved reference: ext + +import dep.TA1 + +fun use() { + val ta = TA1() + ta.ext +} \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/typeAliasExtensionFunction.after.kt b/idea/testData/quickfix/autoImports/typeAliasExtensionFunction.after.kt new file mode 100644 index 00000000000..64ff8c76acc --- /dev/null +++ b/idea/testData/quickfix/autoImports/typeAliasExtensionFunction.after.kt @@ -0,0 +1,10 @@ +// "Import" "true" +// ERROR: Unresolved reference: ext + +import dep.TA +import dep.ext + +fun use() { + val ta = TA() + ta.ext() +} \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/typeAliasExtensionFunction.before.Dependency.kt b/idea/testData/quickfix/autoImports/typeAliasExtensionFunction.before.Dependency.kt new file mode 100644 index 00000000000..76011d66d6f --- /dev/null +++ b/idea/testData/quickfix/autoImports/typeAliasExtensionFunction.before.Dependency.kt @@ -0,0 +1,9 @@ +package dep + +class A + +typealias TA = A + +fun TA.ext() { + +} \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/typeAliasExtensionFunction.before.Main.kt b/idea/testData/quickfix/autoImports/typeAliasExtensionFunction.before.Main.kt new file mode 100644 index 00000000000..b38b035e203 --- /dev/null +++ b/idea/testData/quickfix/autoImports/typeAliasExtensionFunction.before.Main.kt @@ -0,0 +1,9 @@ +// "Import" "true" +// ERROR: Unresolved reference: ext + +import dep.TA + +fun use() { + val ta = TA() + ta.ext() +} \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/typeAliasExtensionFunctionInTypeAliasChain.after.kt b/idea/testData/quickfix/autoImports/typeAliasExtensionFunctionInTypeAliasChain.after.kt new file mode 100644 index 00000000000..1789f406f30 --- /dev/null +++ b/idea/testData/quickfix/autoImports/typeAliasExtensionFunctionInTypeAliasChain.after.kt @@ -0,0 +1,9 @@ +// "Import" "true" +// ERROR: Unresolved reference: ext + +import dep.TTA +import dep.ext + +fun use(taa: TTA) { + taa.ext() +} \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/typeAliasExtensionFunctionInTypeAliasChain.before.Dependency.kt b/idea/testData/quickfix/autoImports/typeAliasExtensionFunctionInTypeAliasChain.before.Dependency.kt new file mode 100644 index 00000000000..63804f46e8e --- /dev/null +++ b/idea/testData/quickfix/autoImports/typeAliasExtensionFunctionInTypeAliasChain.before.Dependency.kt @@ -0,0 +1,10 @@ +package dep + +class A + +typealias TA = A +typealias TTA = TA + +fun TA.ext() { + +} \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/typeAliasExtensionFunctionInTypeAliasChain.before.Main.kt b/idea/testData/quickfix/autoImports/typeAliasExtensionFunctionInTypeAliasChain.before.Main.kt new file mode 100644 index 00000000000..df30f8a379a --- /dev/null +++ b/idea/testData/quickfix/autoImports/typeAliasExtensionFunctionInTypeAliasChain.before.Main.kt @@ -0,0 +1,8 @@ +// "Import" "true" +// ERROR: Unresolved reference: ext + +import dep.TTA + +fun use(taa: TTA) { + taa.ext() +} \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/typeAliasExtensionProperty.after.kt b/idea/testData/quickfix/autoImports/typeAliasExtensionProperty.after.kt new file mode 100644 index 00000000000..996db3e88b3 --- /dev/null +++ b/idea/testData/quickfix/autoImports/typeAliasExtensionProperty.after.kt @@ -0,0 +1,10 @@ +// "Import" "true" +// ERROR: Unresolved reference: ext + +import dep.TA +import dep.ext + +fun use() { + val ta = TA() + ta.ext +} \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/typeAliasExtensionProperty.before.Dependency.kt b/idea/testData/quickfix/autoImports/typeAliasExtensionProperty.before.Dependency.kt new file mode 100644 index 00000000000..8cb4c67dbe1 --- /dev/null +++ b/idea/testData/quickfix/autoImports/typeAliasExtensionProperty.before.Dependency.kt @@ -0,0 +1,7 @@ +package dep + +class A + +typealias TA = A + +val TA.ext: String get() = "ext" \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/typeAliasExtensionProperty.before.Main.kt b/idea/testData/quickfix/autoImports/typeAliasExtensionProperty.before.Main.kt new file mode 100644 index 00000000000..511eb439066 --- /dev/null +++ b/idea/testData/quickfix/autoImports/typeAliasExtensionProperty.before.Main.kt @@ -0,0 +1,9 @@ +// "Import" "true" +// ERROR: Unresolved reference: ext + +import dep.TA + +fun use() { + val ta = TA() + ta.ext +} \ No newline at end of file diff --git a/idea/testData/typealiasExpansionIndex/functionalTypes.kt b/idea/testData/typealiasExpansionIndex/functionalTypes.kt new file mode 100644 index 00000000000..8eae25486ab --- /dev/null +++ b/idea/testData/typealiasExpansionIndex/functionalTypes.kt @@ -0,0 +1,17 @@ +typealias TA = () -> Unit +// CONTAINS (key="Function0", value="TA") + +typealias TB = () -> String +// CONTAINS (key="Function0", value="TB") + +typealias TC = (String) -> Unit +// CONTAINS (key="Function1", value="TC") + +typealias TD = String.() -> Unit +// CONTAINS (key="Function1", value="TD") + +typealias TE = (String, String) -> Unit +// CONTAINS (key="Function2", value="TE") + +typealias TF = String.(String) -> Unit +// CONTAINS (key="Function2", value="TF") \ No newline at end of file diff --git a/idea/testData/typealiasExpansionIndex/generics.kt b/idea/testData/typealiasExpansionIndex/generics.kt new file mode 100644 index 00000000000..24589d63ebf --- /dev/null +++ b/idea/testData/typealiasExpansionIndex/generics.kt @@ -0,0 +1,7 @@ +class A + +typealias TA = A +// CONTAINS (key="A", value="TA") + +typealias TB = A +// CONTAINS (key="A", value="TB") \ No newline at end of file diff --git a/idea/testData/typealiasExpansionIndex/simpleType.kt b/idea/testData/typealiasExpansionIndex/simpleType.kt new file mode 100644 index 00000000000..5740e4befd1 --- /dev/null +++ b/idea/testData/typealiasExpansionIndex/simpleType.kt @@ -0,0 +1,3 @@ +class A +typealias TA = A +// CONTAINS (key="A", value="TA") \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/AbstractKotlinTypeAliasByExpansionShortNameIndexTest.kt b/idea/tests/org/jetbrains/kotlin/idea/AbstractKotlinTypeAliasByExpansionShortNameIndexTest.kt new file mode 100644 index 00000000000..9cad04dca47 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/AbstractKotlinTypeAliasByExpansionShortNameIndexTest.kt @@ -0,0 +1,70 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea + +import com.intellij.psi.search.GlobalSearchScope +import org.jetbrains.kotlin.idea.stubindex.KotlinTypeAliasByExpansionShortNameIndex +import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase +import org.jetbrains.kotlin.test.InTextDirectivesUtils +import org.jetbrains.kotlin.test.KotlinTestUtils +import org.junit.Assert + +abstract class AbstractKotlinTypeAliasByExpansionShortNameIndexTest : KotlinLightCodeInsightFixtureTestCase() { + + + override fun getTestDataPath(): String { + return KotlinTestUtils.getHomeDirectory() + "/" + } + + lateinit var scope: GlobalSearchScope + + override fun setUp() { + super.setUp() + scope = GlobalSearchScope.allScope(project) + } + + override fun getProjectDescriptor() = super.getProjectDescriptorFromTestName() + + fun doTest(file: String) { + myFixture.configureByFile(file) + val fileText = myFixture.file.text + InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileText, "CONTAINS").forEach { + assertIndexContains(it) + } + } + + private val regex = "\\(key=\"(.*?)\"[, ]*value=\"(.*?)\"\\)".toRegex() + + fun assertIndexContains(record: String) { + val index = KotlinTypeAliasByExpansionShortNameIndex.INSTANCE + val (_, key, value) = regex.find(record)!!.groupValues + val result = index.get(key, project, scope) + if (value !in result.map { it.name }) { + Assert.fail(buildString { + appendln("Record $record not found in index") + appendln("Index contents:") + index.getAllKeys(project).asSequence().forEach { + appendln("KEY: $it") + index.get(it, project, scope).forEach { + appendln(" ${it.name}") + } + } + }) + } + } + +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/KotlinTypeAliasByExpansionShortNameIndexTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/KotlinTypeAliasByExpansionShortNameIndexTestGenerated.java new file mode 100644 index 00000000000..f9c39799184 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/KotlinTypeAliasByExpansionShortNameIndexTestGenerated.java @@ -0,0 +1,56 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TargetBackend; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("idea/testData/typealiasExpansionIndex") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class KotlinTypeAliasByExpansionShortNameIndexTestGenerated extends AbstractKotlinTypeAliasByExpansionShortNameIndexTest { + public void testAllFilesPresentInTypealiasExpansionIndex() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/typealiasExpansionIndex"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("functionalTypes.kt") + public void testFunctionalTypes() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/typealiasExpansionIndex/functionalTypes.kt"); + doTest(fileName); + } + + @TestMetadata("generics.kt") + public void testGenerics() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/typealiasExpansionIndex/generics.kt"); + doTest(fileName); + } + + @TestMetadata("simpleType.kt") + public void testSimpleType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/typealiasExpansionIndex/simpleType.kt"); + doTest(fileName); + } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java index fd022c65231..cf8966fe9b2 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java @@ -150,6 +150,18 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes doTestWithExtraFile(fileName); } + @TestMetadata("extensionPropertyOnTypeAliasFromExpansion.before.Main.kt") + public void testExtensionPropertyOnTypeAliasFromExpansion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromExpansion.before.Main.kt"); + doTestWithExtraFile(fileName); + } + + @TestMetadata("extensionPropertyOnTypeAliasFromOtherTypeAlias.before.Main.kt") + public void testExtensionPropertyOnTypeAliasFromOtherTypeAlias() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/extensionPropertyOnTypeAliasFromOtherTypeAlias.before.Main.kt"); + doTestWithExtraFile(fileName); + } + @TestMetadata("factoryFunctionFromLambda.before.Main.kt") public void testFactoryFunctionFromLambda() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/factoryFunctionFromLambda.before.Main.kt"); @@ -582,6 +594,24 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes doTestWithExtraFile(fileName); } + @TestMetadata("typeAliasExtensionFunction.before.Main.kt") + public void testTypeAliasExtensionFunction() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/typeAliasExtensionFunction.before.Main.kt"); + doTestWithExtraFile(fileName); + } + + @TestMetadata("typeAliasExtensionFunctionInTypeAliasChain.before.Main.kt") + public void testTypeAliasExtensionFunctionInTypeAliasChain() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/typeAliasExtensionFunctionInTypeAliasChain.before.Main.kt"); + doTestWithExtraFile(fileName); + } + + @TestMetadata("typeAliasExtensionProperty.before.Main.kt") + public void testTypeAliasExtensionProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/typeAliasExtensionProperty.before.Main.kt"); + doTestWithExtraFile(fileName); + } + @TestMetadata("typeAliasImport.before.Main.kt") public void testTypeAliasImport() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/typeAliasImport.before.Main.kt");