Correct completion of nested/inner classes after dot
#KT-1889 Fixed
This commit is contained in:
@@ -110,6 +110,9 @@ public class DescriptorKindFilter(
|
|||||||
public fun withoutKinds(kinds: Int): DescriptorKindFilter
|
public fun withoutKinds(kinds: Int): DescriptorKindFilter
|
||||||
= DescriptorKindFilter(kindMask and kinds.inv(), excludes)
|
= DescriptorKindFilter(kindMask and kinds.inv(), excludes)
|
||||||
|
|
||||||
|
public fun withKinds(kinds: Int): DescriptorKindFilter
|
||||||
|
= DescriptorKindFilter(kindMask or kinds, excludes)
|
||||||
|
|
||||||
public fun restrictedToKinds(kinds: Int): DescriptorKindFilter? {
|
public fun restrictedToKinds(kinds: Int): DescriptorKindFilter? {
|
||||||
val mask = kindMask and kinds
|
val mask = kindMask and kinds
|
||||||
if (mask == 0) return null
|
if (mask == 0) return null
|
||||||
|
|||||||
+12
-2
@@ -102,9 +102,19 @@ public class ReferenceVariantsHelper(
|
|||||||
val receiverValue = ExpressionReceiver(receiverExpression, expressionType)
|
val receiverValue = ExpressionReceiver(receiverExpression, expressionType)
|
||||||
val dataFlowInfo = context.getDataFlowInfo(expression)
|
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)) {
|
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)
|
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))
|
.withIcon(JetDescriptorIconProvider.getIcon(descriptor, declaration, Iconable.ICON_FLAG_VISIBILITY))
|
||||||
|
|
||||||
when (descriptor) {
|
when (descriptor) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
class C {
|
class C {
|
||||||
class Nested
|
class Nested
|
||||||
inner class Inner
|
inner class Inner1
|
||||||
|
inner class Inner2(s: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun foo(c: C) {
|
fun foo(c: C) {
|
||||||
@@ -8,4 +9,5 @@ fun foo(c: C) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ABSENT: Nested
|
// 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);
|
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")
|
@TestMetadata("InsideIdentifier.kt")
|
||||||
public void testInsideIdentifier() throws Exception {
|
public void testInsideIdentifier() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/smart/InsideIdentifier.kt");
|
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 testInfixCallOnSpace() = doTest(1, "to", null, null, ' ')
|
||||||
|
|
||||||
fun testImportedEnumMember() { doTest(1, "AAA", null, null, '\n') }
|
fun testImportedEnumMember() { doTest(1, "AAA", null, null, '\n') }
|
||||||
|
|
||||||
|
fun testInnerClass() { doTest(1, "Inner", null, null, '\n') }
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user