Fixed KT-5020 Smart completion should work at the initializer of a val with no explicit type
#KT-5020 Fixed
This commit is contained in:
@@ -144,7 +144,7 @@ class CompletionSession {
|
|||||||
return isVisibleDescriptor(descriptor);
|
return isVisibleDescriptor(descriptor);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
SmartCompletion completion = new SmartCompletion(jetReference.getExpression(), getResolveSession(), visibilityFilter);
|
SmartCompletion completion = new SmartCompletion(jetReference.getExpression(), getResolveSession(), visibilityFilter, (JetFile)parameters.getOriginalFile());
|
||||||
Collection<LookupElement> elements = completion.buildLookupElements(descriptors);
|
Collection<LookupElement> elements = completion.buildLookupElements(descriptors);
|
||||||
if (elements != null) {
|
if (elements != null) {
|
||||||
for (LookupElement element : elements) {
|
for (LookupElement element : elements) {
|
||||||
|
|||||||
@@ -29,10 +29,13 @@ import org.jetbrains.jet.plugin.completion.*
|
|||||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||||
import org.jetbrains.jet.plugin.util.makeNotNullable
|
import org.jetbrains.jet.plugin.util.makeNotNullable
|
||||||
import org.jetbrains.jet.plugin.util.makeNullable
|
import org.jetbrains.jet.plugin.util.makeNullable
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import org.jetbrains.jet.plugin.caches.resolve.getLazyResolveSession
|
||||||
|
|
||||||
class SmartCompletion(val expression: JetSimpleNameExpression,
|
class SmartCompletion(val expression: JetSimpleNameExpression,
|
||||||
val resolveSession: ResolveSessionForBodies,
|
val resolveSession: ResolveSessionForBodies,
|
||||||
val visibilityFilter: (DeclarationDescriptor) -> Boolean) {
|
val visibilityFilter: (DeclarationDescriptor) -> Boolean,
|
||||||
|
val originalFile: JetFile) {
|
||||||
|
|
||||||
private val bindingContext = resolveSession.resolveToElement(expression)
|
private val bindingContext = resolveSession.resolveToElement(expression)
|
||||||
private val moduleDescriptor = resolveSession.getModuleDescriptor()
|
private val moduleDescriptor = resolveSession.getModuleDescriptor()
|
||||||
@@ -73,7 +76,7 @@ class SmartCompletion(val expression: JetSimpleNameExpression,
|
|||||||
receiver = null
|
receiver = null
|
||||||
}
|
}
|
||||||
|
|
||||||
val allExpectedInfos = ExpectedInfos(bindingContext, moduleDescriptor).calculate(expressionWithType) ?: return null
|
val allExpectedInfos = calcExpectedInfos(expressionWithType) ?: return null
|
||||||
val filteredExpectedInfos = allExpectedInfos.filter { !it.`type`.isError() }
|
val filteredExpectedInfos = allExpectedInfos.filter { !it.`type`.isError() }
|
||||||
if (filteredExpectedInfos.isEmpty()) return null
|
if (filteredExpectedInfos.isEmpty()) return null
|
||||||
|
|
||||||
@@ -125,6 +128,23 @@ class SmartCompletion(val expression: JetSimpleNameExpression,
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun calcExpectedInfos(expression: JetExpression): Collection<ExpectedInfo>? {
|
||||||
|
// if our expression is initializer of implicitly typed variable - take type of variable from original file
|
||||||
|
val varDeclaration = expression.getParent() as? JetVariableDeclaration
|
||||||
|
if (varDeclaration != null && expression == varDeclaration.getInitializer() && varDeclaration.getTypeRef() == null) {
|
||||||
|
val offset = varDeclaration.getTextRange()!!.getStartOffset()
|
||||||
|
val originalDeclaration = PsiTreeUtil.findElementOfClassAtOffset(originalFile, offset, javaClass<JetVariableDeclaration>(), true)
|
||||||
|
if (originalDeclaration != null) {
|
||||||
|
val variableDescriptor = originalDeclaration.getLazyResolveSession().resolveToDescriptor(originalDeclaration) as? VariableDescriptor
|
||||||
|
if (variableDescriptor != null) {
|
||||||
|
return listOf(ExpectedInfo(variableDescriptor.getType(), null))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ExpectedInfos(bindingContext, moduleDescriptor).calculate(expression)
|
||||||
|
}
|
||||||
|
|
||||||
private fun calcItemsToSkip(expression: JetExpression): Set<DeclarationDescriptor> {
|
private fun calcItemsToSkip(expression: JetExpression): Set<DeclarationDescriptor> {
|
||||||
val parent = expression.getParent()
|
val parent = expression.getParent()
|
||||||
when(parent) {
|
when(parent) {
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
fun foo(p1: String, p2: Int) {
|
||||||
|
val v = <caret>"a"
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: p1
|
||||||
|
// ABSENT: p2
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
class A(s: String) {
|
||||||
|
val v = s.<caret>length()
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: size
|
||||||
|
// ABSENT: substring
|
||||||
@@ -231,6 +231,16 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT
|
|||||||
doTest("idea/testData/completion/smart/IfValueInBlock2.kt");
|
doTest("idea/testData/completion/smart/IfValueInBlock2.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ImplicitlyTypedValInitializer1.kt")
|
||||||
|
public void testImplicitlyTypedValInitializer1() throws Exception {
|
||||||
|
doTest("idea/testData/completion/smart/ImplicitlyTypedValInitializer1.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ImplicitlyTypedValInitializer2.kt")
|
||||||
|
public void testImplicitlyTypedValInitializer2() throws Exception {
|
||||||
|
doTest("idea/testData/completion/smart/ImplicitlyTypedValInitializer2.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("InElvisOperator1.kt")
|
@TestMetadata("InElvisOperator1.kt")
|
||||||
public void testInElvisOperator1() throws Exception {
|
public void testInElvisOperator1() throws Exception {
|
||||||
doTest("idea/testData/completion/smart/InElvisOperator1.kt");
|
doTest("idea/testData/completion/smart/InElvisOperator1.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user