Correct completion of nested/inner classes after dot

#KT-1889 Fixed
This commit is contained in:
Valentin Kipyatkov
2014-12-05 08:44:29 +03:00
parent 8f32a6c1f9
commit 6ec10b9b6b
9 changed files with 64 additions and 5 deletions
@@ -110,6 +110,9 @@ public class DescriptorKindFilter(
public fun withoutKinds(kinds: Int): DescriptorKindFilter
= DescriptorKindFilter(kindMask and kinds.inv(), excludes)
public fun withKinds(kinds: Int): DescriptorKindFilter
= DescriptorKindFilter(kindMask or kinds, excludes)
public fun restrictedToKinds(kinds: Int): DescriptorKindFilter? {
val mask = kindMask and kinds
if (mask == 0) return null
@@ -102,9 +102,19 @@ public class ReferenceVariantsHelper(
val receiverValue = ExpressionReceiver(receiverExpression, expressionType)
val dataFlowInfo = context.getDataFlowInfo(expression)
val mask = kindFilter.withoutKinds(DescriptorKindFilter.NON_SINGLETON_CLASSIFIERS_MASK).exclude(DescriptorKindExclude.Extensions)
var memberFilter = kindFilter exclude DescriptorKindExclude.Extensions
for (variant in SmartCastUtils.getSmartCastVariantsWithLessSpecificExcluded(receiverValue, context, dataFlowInfo)) {
variant.getMemberScope().getDescriptorsFiltered(mask, nameFilter).filterTo(descriptors) { callType.canCall(it) }
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(descriptors) { callType.canCall(it) && memberFilter.accepts(it) }
}
}
else if (callType.canCall(member) && memberFilter.accepts(member)) {
descriptors.add(member)
}
}
}
descriptors.addCallableExtensions(resolutionScope, receiverValue, dataFlowInfo, callType, kindFilter, nameFilter)
@@ -144,7 +144,11 @@ public class LookupElementFactory(
}
var element = LookupElementBuilder.create(DeclarationDescriptorLookupObject(descriptor, resolutionFacade, declaration), descriptor.getName().asString())
val name = if (descriptor is ConstructorDescriptor)
descriptor.getContainingDeclaration().getName().asString()
else
descriptor.getName().asString()
var element = LookupElementBuilder.create(DeclarationDescriptorLookupObject(descriptor, resolutionFacade, declaration), name)
.withIcon(JetDescriptorIconProvider.getIcon(descriptor, declaration, Iconable.ICON_FLAG_VISIBILITY))
when (descriptor) {
@@ -1,6 +1,7 @@
class C {
class Nested
inner class Inner
inner class Inner1
inner class Inner2(s: String)
}
fun foo(c: C) {
@@ -8,4 +9,5 @@ fun foo(c: C) {
}
// ABSENT: Nested
// ABSENT: Inner
// EXIST: { lookupString: "Inner1", itemText: "Inner1", tailText: "()", typeText: "C.Inner1" }
// EXIST: { lookupString: "Inner2", itemText: "Inner2", tailText: "(s: String)", typeText: "C.Inner2" }
@@ -0,0 +1,7 @@
class C {
inner class Inner(s: String)
}
fun foo(c: C) {
c.<caret>
}
@@ -0,0 +1,7 @@
class C {
inner class Inner(s: String)
}
fun foo(c: C) {
c.Inner(<caret>)
}
@@ -0,0 +1,18 @@
trait T
class C {
inner class Inner1(s: String) : T
inner class Inner2 : T
inner class Inner3
class Nested: T
}
fun foo(c: C): T {
return c.<caret>
}
// EXIST: { lookupString: "Inner1", itemText: "Inner1", tailText: "(s: String)", typeText: "C.Inner1" }
// EXIST: { lookupString: "Inner2", itemText: "Inner2", tailText: "()", typeText: "C.Inner2" }
// ABSENT: Inner3
// ABSENT: Nested
// NUMBER: 2
@@ -444,6 +444,12 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT
doTest(fileName);
}
@TestMetadata("InnerClass.kt")
public void testInnerClass() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/smart/InnerClass.kt");
doTest(fileName);
}
@TestMetadata("InsideIdentifier.kt")
public void testInsideIdentifier() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/smart/InsideIdentifier.kt");
@@ -168,4 +168,6 @@ public class BasicCompletionHandlerTest : CompletionHandlerTestBase(){
fun testInfixCallOnSpace() = doTest(1, "to", null, null, ' ')
fun testImportedEnumMember() { doTest(1, "AAA", null, null, '\n') }
fun testInnerClass() { doTest(1, "Inner", null, null, '\n') }
}