Smart completion: this expressions added
This commit is contained in:
@@ -6,6 +6,26 @@
|
||||
<item name='com.intellij.codeInsight.lookup.Lookup com.intellij.openapi.editor.Editor getEditor()'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.codeInsight.lookup.LookupElementBuilder com.intellij.codeInsight.lookup.LookupElementBuilder create(com.intellij.psi.PsiNamedElement)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.codeInsight.lookup.LookupElementBuilder com.intellij.codeInsight.lookup.LookupElementBuilder create(java.lang.Object, java.lang.String)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.codeInsight.lookup.LookupElementBuilder com.intellij.codeInsight.lookup.LookupElementBuilder create(java.lang.String)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.codeInsight.lookup.LookupElementBuilder com.intellij.codeInsight.lookup.LookupElementBuilder createWithIcon(com.intellij.psi.PsiNamedElement)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.codeInsight.lookup.LookupElementBuilder com.intellij.codeInsight.lookup.LookupElementBuilder setTypeText(java.lang.String, boolean)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.codeInsight.lookup.LookupElementBuilder com.intellij.codeInsight.lookup.LookupElementBuilder withInsertHandler(com.intellij.codeInsight.completion.InsertHandler<com.intellij.codeInsight.lookup.LookupElement>)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
@@ -18,6 +38,14 @@
|
||||
name='com.intellij.codeInsight.lookup.LookupElementBuilder com.intellij.codeInsight.lookup.LookupElementBuilder withTailText(java.lang.String)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.codeInsight.lookup.LookupElementBuilder com.intellij.codeInsight.lookup.LookupElementBuilder withTypeText(java.lang.String)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.codeInsight.lookup.LookupElementBuilder com.intellij.codeInsight.lookup.LookupElementBuilder withTypeText(java.lang.String, boolean)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.codeInsight.lookup.MutableLookupElement com.intellij.codeInsight.lookup.MutableLookupElement<T> setInsertHandler(com.intellij.codeInsight.completion.InsertHandler<? extends com.intellij.codeInsight.lookup.LookupElement>)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
|
||||
@@ -15,6 +15,10 @@ import com.google.common.collect.SetMultimap
|
||||
import java.util.*
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.*
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope
|
||||
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration
|
||||
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration
|
||||
import org.jetbrains.jet.lang.resolve.name.Name
|
||||
|
||||
trait SmartCompletionData{
|
||||
fun accepts(descriptor: DeclarationDescriptor): Boolean
|
||||
@@ -44,6 +48,7 @@ fun buildSmartCompletionData(expression: JetSimpleNameExpression, resolveSession
|
||||
|
||||
if (receiver == null) {
|
||||
typeInstantiationItems(expectedType, resolveSession, bindingContext).toCollection(additionalElements)
|
||||
thisItems(expressionWithType, expectedType, bindingContext).toCollection(additionalElements)
|
||||
}
|
||||
|
||||
val dataFlowInfo = bindingContext.get(BindingContext.EXPRESSION_DATA_FLOW_INFO, expressionWithType)
|
||||
@@ -142,6 +147,44 @@ private fun typeInstantiationItems(expectedType: JetType, resolveSession: Cancel
|
||||
return listOf()
|
||||
}
|
||||
|
||||
private fun thisItems(context: JetExpression, expectedType: JetType, bindingContext: BindingContext): Iterable<LookupElement> {
|
||||
val scope = bindingContext.get(BindingContext.RESOLUTION_SCOPE, context)
|
||||
if (scope == null) return listOf()
|
||||
|
||||
val receivers: List<ReceiverParameterDescriptor> = scope.getImplicitReceiversHierarchy()
|
||||
val result = ArrayList<LookupElement>()
|
||||
for (i in 0..receivers.size - 1) {
|
||||
val receiver = receivers[i]
|
||||
val thisType = receiver.getType()
|
||||
if (JetTypeChecker.INSTANCE.isSubtypeOf(thisType, expectedType)) {
|
||||
//TODO: use this code when KT-4258 fixed
|
||||
//val expressionText = if (i == 0) "this" else "this@" + (thisQualifierName(receiver, bindingContext) ?: continue)
|
||||
val qualifier = if (i == 0) null else thisQualifierName(receiver, bindingContext) ?: continue
|
||||
val expressionText = if (qualifier == null) "this" else "this@" + qualifier
|
||||
result.add(LookupElementBuilder.create(expressionText).withTypeText(DescriptorRenderer.TEXT.renderType(thisType)))
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun thisQualifierName(receiver: ReceiverParameterDescriptor, bindingContext: BindingContext): String? {
|
||||
val descriptor: DeclarationDescriptor = receiver.getContainingDeclaration()
|
||||
val name: Name = descriptor.getName()
|
||||
if (!name.isSpecial()) return name.asString()
|
||||
|
||||
val psiElement = BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor)
|
||||
val expression: JetExpression? = when (psiElement) {
|
||||
is JetFunctionLiteral -> psiElement.getParent() as? JetFunctionLiteralExpression
|
||||
is JetObjectDeclaration -> psiElement.getParent() as? JetObjectLiteralExpression
|
||||
else -> null
|
||||
}
|
||||
return ((((expression?.getParent() as? JetValueArgument)
|
||||
?.getParent() as? JetValueArgumentList)
|
||||
?.getParent() as? JetCallExpression)
|
||||
?.getCalleeExpression() as? JetSimpleNameExpression)
|
||||
?.getReferencedName()
|
||||
}
|
||||
|
||||
private data class ProcessDataFlowInfoResult(
|
||||
val variableToTypes: Map<VariableDescriptor, Collection<JetType>> = Collections.emptyMap(),
|
||||
val notNullVariables: Set<VariableDescriptor> = Collections.emptySet()
|
||||
@@ -195,3 +238,14 @@ private fun <T> MutableCollection<T>.addAll(iterator: Iterator<T>) {
|
||||
add(item)
|
||||
}
|
||||
}
|
||||
|
||||
fun<T> accept1(handler: String.(t: T) -> Unit){}
|
||||
fun accept2(handler: Int.() -> Unit){}
|
||||
|
||||
fun foo(){
|
||||
accept1<String>({
|
||||
accept2({
|
||||
val s: String = this@accept1
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
class Foo{
|
||||
fun String.foo(){
|
||||
val foo : Foo = <caret>
|
||||
}
|
||||
}
|
||||
|
||||
// EXIST: { lookupString:"this@Foo", typeText:"Foo" }
|
||||
@@ -0,0 +1,15 @@
|
||||
open class Foo
|
||||
|
||||
fun foo(f: Foo){}
|
||||
|
||||
fun bar() {
|
||||
foo(object: Foo() {
|
||||
inner class Inner {
|
||||
fun f() {
|
||||
val x: Foo = <caret>
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// EXIST: this@foo
|
||||
@@ -0,0 +1,9 @@
|
||||
class Foo{
|
||||
fun String.foo(){
|
||||
fun Foo.bar(){
|
||||
val s: String = <caret>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// EXIST: { lookupString:"this@foo", typeText:"jet.String" }
|
||||
@@ -0,0 +1,12 @@
|
||||
fun accept1(handler: String.() -> Unit){}
|
||||
fun accept2(handler: Int.() -> Unit){}
|
||||
|
||||
fun foo(){
|
||||
accept1({
|
||||
accept2({
|
||||
val s: String = <caret>
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// EXIST: this@accept1
|
||||
@@ -0,0 +1,14 @@
|
||||
object X {
|
||||
fun accept1(handler: String.() -> Unit){}
|
||||
fun accept2(handler: Int.() -> Unit){}
|
||||
}
|
||||
|
||||
fun foo(){
|
||||
X.accept1({
|
||||
X.accept2({
|
||||
val s: String = <caret>
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// EXIST: this@accept1
|
||||
@@ -0,0 +1,12 @@
|
||||
fun<T> accept1(handler: String.(t: T) -> Unit){}
|
||||
fun accept2(handler: Int.() -> Unit){}
|
||||
|
||||
fun foo(){
|
||||
accept1<String>({
|
||||
accept2({
|
||||
val s: String = <caret>
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// EXIST: this@accept1
|
||||
@@ -0,0 +1,5 @@
|
||||
fun String.foo(){
|
||||
val s : String = <caret>
|
||||
}
|
||||
|
||||
// EXIST: { lookupString:"this", typeText:"jet.String" }
|
||||
@@ -1,5 +0,0 @@
|
||||
fun String.foo(){
|
||||
val s : String = <caret>
|
||||
}
|
||||
|
||||
// EXIST: this
|
||||
@@ -126,6 +126,41 @@ public class JetSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT
|
||||
doTest("idea/testData/completion/smart/NotSillyAssignment.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("QualifiedThis.kt")
|
||||
public void testQualifiedThis() throws Exception {
|
||||
doTest("idea/testData/completion/smart/QualifiedThis.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("QualifiedThisOfAnonymousObject.kt")
|
||||
public void testQualifiedThisOfAnonymousObject() throws Exception {
|
||||
doTest("idea/testData/completion/smart/QualifiedThisOfAnonymousObject.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("QualifiedThisOfExtensionFunction.kt")
|
||||
public void testQualifiedThisOfExtensionFunction() throws Exception {
|
||||
doTest("idea/testData/completion/smart/QualifiedThisOfExtensionFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("QualifiedThisOfExtensionLambda1.kt")
|
||||
public void testQualifiedThisOfExtensionLambda1() throws Exception {
|
||||
doTest("idea/testData/completion/smart/QualifiedThisOfExtensionLambda1.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("QualifiedThisOfExtensionLambda2.kt")
|
||||
public void testQualifiedThisOfExtensionLambda2() throws Exception {
|
||||
doTest("idea/testData/completion/smart/QualifiedThisOfExtensionLambda2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("QualifiedThisOfExtensionLambda3.kt")
|
||||
public void testQualifiedThisOfExtensionLambda3() throws Exception {
|
||||
doTest("idea/testData/completion/smart/QualifiedThisOfExtensionLambda3.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("This.kt")
|
||||
public void testThis() throws Exception {
|
||||
doTest("idea/testData/completion/smart/This.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("VariableInitializer.kt")
|
||||
public void testVariableInitializer() throws Exception {
|
||||
doTest("idea/testData/completion/smart/VariableInitializer.kt");
|
||||
|
||||
Reference in New Issue
Block a user