From ddd63d69e90863f26f30e30e21f4bd3a64063626 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Thu, 25 Dec 2014 19:13:08 +0300 Subject: [PATCH] KT-6442 Completion of inner class name contains outer name #KT-6442 Fixed --- .../codeInsight/ReferenceVariantsHelper.kt | 35 ++++++++++--------- .../smart/TypeInstantiationItems.kt | 3 ++ .../NoNestedClassesFromImplicitQualifier.kt | 2 +- .../smart/InnerClassInstantiation1.kt | 9 +++++ .../smart/InnerClassInstantiation1.kt.after | 9 +++++ .../smart/InnerClassInstantiation2.kt | 9 +++++ .../smart/InnerClassInstantiation2.kt.after | 9 +++++ .../smart/NoInnerClassInstantiation.kt | 11 ++++++ .../JvmSmartCompletionTestGenerated.java | 6 ++++ .../SmartCompletionHandlerTestGenerated.java | 12 +++++++ 10 files changed, 87 insertions(+), 18 deletions(-) create mode 100644 idea/testData/completion/handlers/smart/InnerClassInstantiation1.kt create mode 100644 idea/testData/completion/handlers/smart/InnerClassInstantiation1.kt.after create mode 100644 idea/testData/completion/handlers/smart/InnerClassInstantiation2.kt create mode 100644 idea/testData/completion/handlers/smart/InnerClassInstantiation2.kt.after create mode 100644 idea/testData/completion/smart/NoInnerClassInstantiation.kt diff --git a/idea/ide-common/src/org/jetbrains/jet/plugin/codeInsight/ReferenceVariantsHelper.kt b/idea/ide-common/src/org/jetbrains/jet/plugin/codeInsight/ReferenceVariantsHelper.kt index 76c3726d00d..de978945bb6 100644 --- a/idea/ide-common/src/org/jetbrains/jet/plugin/codeInsight/ReferenceVariantsHelper.kt +++ b/idea/ide-common/src/org/jetbrains/jet/plugin/codeInsight/ReferenceVariantsHelper.kt @@ -101,7 +101,9 @@ public class ReferenceVariantsHelper( val receiverValue = ExpressionReceiver(receiverExpression, expressionType) val dataFlowInfo = context.getDataFlowInfo(expression) - descriptors.addMembers(receiverValue, callType, dataFlowInfo, kindFilter, nameFilter) + for (variant in SmartCastUtils.getSmartCastVariantsWithLessSpecificExcluded(receiverValue, context, dataFlowInfo)) { + descriptors.addMembersFromReceiver(variant, callType, kindFilter, nameFilter) + } descriptors.addCallableExtensions(resolutionScope, receiverValue, dataFlowInfo, callType, kindFilter, nameFilter) } @@ -113,8 +115,9 @@ public class ReferenceVariantsHelper( // process instance members that can be called via implicit receiver's instances val receivers = resolutionScope.getImplicitReceiversWithInstance() - val fromReceiversFilter = kindFilter.withoutKinds(DescriptorKindFilter.CLASSIFIERS_MASK) exclude DescriptorKindExclude.Extensions - receivers.flatMapTo(descriptorsSet) { it.getType().getMemberScope().getDescriptorsFiltered(fromReceiversFilter, nameFilter) } + for (receiver in receivers) { + descriptorsSet.addMembersFromReceiver(receiver.getType(), CallType.NORMAL, kindFilter, nameFilter) + } val dataFlowInfo = context.getDataFlowInfo(expression) val receiverValues = receivers.map { it.getValue() } @@ -135,25 +138,23 @@ public class ReferenceVariantsHelper( } } - private fun MutableCollection.addMembers( - receiverValue: ExpressionReceiver, + private fun MutableCollection.addMembersFromReceiver( + receiverType: JetType, callType: CallType, - dataFlowInfo: DataFlowInfo, kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean) { + nameFilter: (Name) -> Boolean + ) { var memberFilter = kindFilter exclude DescriptorKindExclude.Extensions - for (variant in SmartCastUtils.getSmartCastVariantsWithLessSpecificExcluded(receiverValue, context, dataFlowInfo)) { - val members = variant.getMemberScope().getDescriptorsFiltered(DescriptorKindFilter.ALL, nameFilter) // filter by kind later because of constructors - for (member in members) { - if (member is ClassDescriptor) { - if (member.isInner()) { - member.getConstructors().filterTo(this) { callType.canCall(it) && memberFilter.accepts(it) } - } - } - else if (callType.canCall(member) && memberFilter.accepts(member)) { - this.add(member) + val members = receiverType.getMemberScope().getDescriptorsFiltered(DescriptorKindFilter.ALL, nameFilter) // filter by kind later because of constructors + for (member in members) { + if (member is ClassDescriptor) { + if (member.isInner()) { + member.getConstructors().filterTo(this) { callType.canCall(it) && memberFilter.accepts(it) } } } + else if (callType.canCall(member) && memberFilter.accepts(member)) { + this.add(member) + } } } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/smart/TypeInstantiationItems.kt b/idea/src/org/jetbrains/jet/plugin/completion/smart/TypeInstantiationItems.kt index aa5f6c3ac28..47f65144dd0 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/smart/TypeInstantiationItems.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/smart/TypeInstantiationItems.kt @@ -141,6 +141,9 @@ class TypeInstantiationItems( return lookupElement.addTail(tail) } + // not all inner classes can be instantiated and we handle them via constructors returned by ReferenceVariantsHelper + if (classifier.isInner()) return null + val isAbstract = classifier.getModality() == Modality.ABSTRACT val allConstructors = classifier.getConstructors() val visibleConstructors = allConstructors.filter { diff --git a/idea/testData/completion/basic/common/NoNestedClassesFromImplicitQualifier.kt b/idea/testData/completion/basic/common/NoNestedClassesFromImplicitQualifier.kt index e7f9a510108..a424f7d4121 100644 --- a/idea/testData/completion/basic/common/NoNestedClassesFromImplicitQualifier.kt +++ b/idea/testData/completion/basic/common/NoNestedClassesFromImplicitQualifier.kt @@ -8,4 +8,4 @@ fun Outer.foo() { } // ABSENT: Nested -// ABSENT: Inner +// EXIST: { itemText: "Inner", tailText: "()", typeText: "Outer.Inner" } diff --git a/idea/testData/completion/handlers/smart/InnerClassInstantiation1.kt b/idea/testData/completion/handlers/smart/InnerClassInstantiation1.kt new file mode 100644 index 00000000000..e479c0a0d0c --- /dev/null +++ b/idea/testData/completion/handlers/smart/InnerClassInstantiation1.kt @@ -0,0 +1,9 @@ +class A { + inner class XYZ + + fun foo() { + val v: XYZ = + } +} + +// ELEMENT: XYZ diff --git a/idea/testData/completion/handlers/smart/InnerClassInstantiation1.kt.after b/idea/testData/completion/handlers/smart/InnerClassInstantiation1.kt.after new file mode 100644 index 00000000000..fbb6fc9dae8 --- /dev/null +++ b/idea/testData/completion/handlers/smart/InnerClassInstantiation1.kt.after @@ -0,0 +1,9 @@ +class A { + inner class XYZ + + fun foo() { + val v: XYZ = XYZ() + } +} + +// ELEMENT: XYZ diff --git a/idea/testData/completion/handlers/smart/InnerClassInstantiation2.kt b/idea/testData/completion/handlers/smart/InnerClassInstantiation2.kt new file mode 100644 index 00000000000..647da0125d2 --- /dev/null +++ b/idea/testData/completion/handlers/smart/InnerClassInstantiation2.kt @@ -0,0 +1,9 @@ +class A { + inner class XYZ +} + +fun A.foo(): A.XYZ { + return +} + +// ELEMENT: XYZ diff --git a/idea/testData/completion/handlers/smart/InnerClassInstantiation2.kt.after b/idea/testData/completion/handlers/smart/InnerClassInstantiation2.kt.after new file mode 100644 index 00000000000..b58d90bf223 --- /dev/null +++ b/idea/testData/completion/handlers/smart/InnerClassInstantiation2.kt.after @@ -0,0 +1,9 @@ +class A { + inner class XYZ +} + +fun A.foo(): A.XYZ { + return XYZ() +} + +// ELEMENT: XYZ diff --git a/idea/testData/completion/smart/NoInnerClassInstantiation.kt b/idea/testData/completion/smart/NoInnerClassInstantiation.kt new file mode 100644 index 00000000000..8516fdbf8f0 --- /dev/null +++ b/idea/testData/completion/smart/NoInnerClassInstantiation.kt @@ -0,0 +1,11 @@ +class C { + inner class Inner +} + +fun foo() : C.Inner { + return +} + +// ABSENT: Inner +// EXIST: foo +// NUMBER: 1 diff --git a/idea/tests/org/jetbrains/jet/completion/JvmSmartCompletionTestGenerated.java b/idea/tests/org/jetbrains/jet/completion/JvmSmartCompletionTestGenerated.java index ac2706e3063..fdf0444667c 100644 --- a/idea/tests/org/jetbrains/jet/completion/JvmSmartCompletionTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/completion/JvmSmartCompletionTestGenerated.java @@ -636,6 +636,12 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT doTest(fileName); } + @TestMetadata("NoInnerClassInstantiation.kt") + public void testNoInnerClassInstantiation() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/smart/NoInnerClassInstantiation.kt"); + doTest(fileName); + } + @TestMetadata("NoNothing.kt") public void testNoNothing() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/smart/NoNothing.kt"); diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/SmartCompletionHandlerTestGenerated.java b/idea/tests/org/jetbrains/jet/completion/handlers/SmartCompletionHandlerTestGenerated.java index 4457accb184..5f021b5aa32 100644 --- a/idea/tests/org/jetbrains/jet/completion/handlers/SmartCompletionHandlerTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/completion/handlers/SmartCompletionHandlerTestGenerated.java @@ -366,6 +366,18 @@ public class SmartCompletionHandlerTestGenerated extends AbstractSmartCompletion doTest(fileName); } + @TestMetadata("InnerClassInstantiation1.kt") + public void testInnerClassInstantiation1() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/smart/InnerClassInstantiation1.kt"); + doTest(fileName); + } + + @TestMetadata("InnerClassInstantiation2.kt") + public void testInnerClassInstantiation2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/smart/InnerClassInstantiation2.kt"); + doTest(fileName); + } + @TestMetadata("JavaEnumMemberInsertsImport.kt") public void testJavaEnumMemberInsertsImport() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/smart/JavaEnumMemberInsertsImport.kt");