Completion after "this@" includes immediate this too
#KT-6836 Fixed
This commit is contained in:
@@ -294,7 +294,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
|
|||||||
// if "this" is parsed correctly in the current context - insert it and all this@xxx items
|
// if "this" is parsed correctly in the current context - insert it and all this@xxx items
|
||||||
"this" -> {
|
"this" -> {
|
||||||
if (expression != null) {
|
if (expression != null) {
|
||||||
collector.addElements(thisExpressionItems(bindingContext!!, expression).map { it.factory() })
|
collector.addElements(thisExpressionItems(bindingContext!!, expression, prefix).map { it.factory() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -212,22 +212,27 @@ fun shouldCompleteThisItems(prefixMatcher: PrefixMatcher): Boolean {
|
|||||||
|
|
||||||
data class ThisItemInfo(val factory: () -> LookupElement, val type: FuzzyType)
|
data class ThisItemInfo(val factory: () -> LookupElement, val type: FuzzyType)
|
||||||
|
|
||||||
fun thisExpressionItems(bindingContext: BindingContext, position: JetExpression): Collection<ThisItemInfo> {
|
fun thisExpressionItems(bindingContext: BindingContext, position: JetExpression, prefix: String): Collection<ThisItemInfo> {
|
||||||
val scope = bindingContext[BindingContext.RESOLUTION_SCOPE, position] ?: return listOf()
|
val scope = bindingContext[BindingContext.RESOLUTION_SCOPE, position] ?: return listOf()
|
||||||
|
|
||||||
val result = ArrayList<ThisItemInfo>()
|
val result = ArrayList<ThisItemInfo>()
|
||||||
for ((i, receiver) in scope.getImplicitReceiversWithInstance().withIndex()) {
|
for ((i, receiver) in scope.getImplicitReceiversWithInstance().withIndex()) {
|
||||||
val thisType = receiver.getType()
|
val thisType = receiver.getType()
|
||||||
val fuzzyType = FuzzyType(thisType, listOf())
|
val fuzzyType = FuzzyType(thisType, listOf())
|
||||||
val label = if (i == 0) null else (thisQualifierName(receiver) ?: continue)
|
|
||||||
|
|
||||||
fun createLookupElement(): LookupElement {
|
fun createLookupElement(label: String?): LookupElement {
|
||||||
var element = createKeywordWithLabelElement("this", label)
|
var element = createKeywordWithLabelElement("this", label)
|
||||||
element = element.withTypeText(DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(thisType))
|
element = element.withTypeText(DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(thisType))
|
||||||
return element
|
return element
|
||||||
}
|
}
|
||||||
|
|
||||||
result.add(ThisItemInfo({ createLookupElement() }, fuzzyType))
|
if (i == 0) {
|
||||||
|
result.add(ThisItemInfo({ createLookupElement(null) }, fuzzyType))
|
||||||
|
if (!prefix.startsWith("this@")) continue // if prefix does not start with "this@" do not include immediate this in the form with label
|
||||||
|
}
|
||||||
|
|
||||||
|
val label = thisQualifierName(receiver) ?: continue
|
||||||
|
result.add(ThisItemInfo({ createLookupElement(label) }, fuzzyType))
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ class SmartCompletion(
|
|||||||
|
|
||||||
private fun MutableCollection<LookupElement>.addThisItems(place: JetExpression, expectedInfos: Collection<ExpectedInfo>) {
|
private fun MutableCollection<LookupElement>.addThisItems(place: JetExpression, expectedInfos: Collection<ExpectedInfo>) {
|
||||||
if (shouldCompleteThisItems(prefixMatcher)) {
|
if (shouldCompleteThisItems(prefixMatcher)) {
|
||||||
val items = thisExpressionItems(bindingContext, place)
|
val items = thisExpressionItems(bindingContext, place, prefixMatcher.getPrefix())
|
||||||
for ((factory, type) in items) {
|
for ((factory, type) in items) {
|
||||||
val classifier = { (expectedInfo: ExpectedInfo) -> type.classifyExpectedInfo(expectedInfo) }
|
val classifier = { (expectedInfo: ExpectedInfo) -> type.classifyExpectedInfo(expectedInfo) }
|
||||||
addLookupElements(null, expectedInfos, classifier) {
|
addLookupElements(null, expectedInfos, classifier) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ class Outer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ABSENT: this
|
// ABSENT: this
|
||||||
// ABSENT: "this@foo"
|
// EXIST: { lookupString: "this@foo", itemText: "this", tailText: "@foo", typeText: "String", attributes: "bold" }
|
||||||
// EXIST: { lookupString: "this@Inner", itemText: "this", tailText: "@Inner", typeText: "Outer.Inner", attributes: "bold" }
|
// EXIST: { lookupString: "this@Inner", itemText: "this", tailText: "@Inner", typeText: "Outer.Inner", attributes: "bold" }
|
||||||
// EXIST: { lookupString: "this@Outer", itemText: "this", tailText: "@Outer", typeText: "Outer", attributes: "bold" }
|
// EXIST: { lookupString: "this@Outer", itemText: "this", tailText: "@Outer", typeText: "Outer", attributes: "bold" }
|
||||||
// NUMBER: 2
|
// NUMBER: 3
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
val String.foo: Int
|
||||||
|
get() = this@<caret>.length()
|
||||||
|
|
||||||
|
// EXIST: "this@foo"
|
||||||
|
// NUMBER: 1
|
||||||
@@ -7,7 +7,7 @@ class Outer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ABSENT: this
|
// ABSENT: this
|
||||||
// ABSENT: "this@foo"
|
// EXIST: { lookupString: "this@foo", itemText: "this", tailText: "@foo", typeText: "String", attributes: "bold" }
|
||||||
// EXIST: { lookupString: "this@Inner", itemText: "this", tailText: "@Inner", typeText: "Outer.Inner", attributes: "bold" }
|
// EXIST: { lookupString: "this@Inner", itemText: "this", tailText: "@Inner", typeText: "Outer.Inner", attributes: "bold" }
|
||||||
// EXIST: { lookupString: "this@Outer", itemText: "this", tailText: "@Outer", typeText: "Outer", attributes: "bold" }
|
// EXIST: { lookupString: "this@Outer", itemText: "this", tailText: "@Outer", typeText: "Outer", attributes: "bold" }
|
||||||
// NUMBER: 2
|
// NUMBER: 3
|
||||||
|
|||||||
@@ -330,6 +330,12 @@ public class KeywordCompletionTestGenerated extends AbstractKeywordCompletionTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("QualifiedThisInAccessor.kt")
|
||||||
|
public void testQualifiedThisInAccessor() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/keywords/QualifiedThisInAccessor.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("Return1.kt")
|
@TestMetadata("Return1.kt")
|
||||||
public void testReturn1() throws Exception {
|
public void testReturn1() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/keywords/Return1.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/keywords/Return1.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user