More correct shadowed declarations filtering in completion

This commit is contained in:
Valentin Kipyatkov
2015-10-30 20:13:13 +03:00
parent 67cf9f9510
commit c11bf32594
7 changed files with 37 additions and 11 deletions
@@ -53,20 +53,22 @@ class ReferenceVariantsHelper(
expression: KtSimpleNameExpression,
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean,
filterOutJavaGettersAndSetters: Boolean = false,
filterOutJavaGettersAndSetters: Boolean = true,
filterOutShadowed: Boolean = true,
excludeNonInitializedVariable: Boolean = true,
useReceiverType: KotlinType? = null
): Collection<DeclarationDescriptor>
= getReferenceVariants(expression, CallTypeAndReceiver.detect(expression),
kindFilter, nameFilter, filterOutJavaGettersAndSetters, filterOutShadowed, useReceiverType)
kindFilter, nameFilter, filterOutJavaGettersAndSetters, filterOutShadowed, excludeNonInitializedVariable, useReceiverType)
fun getReferenceVariants(
contextElement: PsiElement,
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean,
filterOutJavaGettersAndSetters: Boolean = false,
filterOutJavaGettersAndSetters: Boolean = true,
filterOutShadowed: Boolean = true,
excludeNonInitializedVariable: Boolean = true,
useReceiverType: KotlinType? = null
): Collection<DeclarationDescriptor> {
var variants: Collection<DeclarationDescriptor>
@@ -79,12 +81,13 @@ class ReferenceVariantsHelper(
}
}
if (filterOutJavaGettersAndSetters) {
if (filterOutJavaGettersAndSetters && kindFilter.kindMask.and(DescriptorKindFilter.FUNCTIONS_MASK) != 0) {
variants = filterOutJavaGettersAndSetters(variants)
}
variants = variants.excludeNonInitializedVariable(contextElement)
if (excludeNonInitializedVariable && kindFilter.kindMask.and(DescriptorKindFilter.VARIABLES_MASK) != 0) {
variants = excludeNonInitializedVariable(variants, contextElement)
}
return variants
}
@@ -102,16 +105,16 @@ class ReferenceVariantsHelper(
}
// filters out variable inside its initializer
private fun Collection<DeclarationDescriptor>.excludeNonInitializedVariable(contextElement: PsiElement): Collection<DeclarationDescriptor> {
fun excludeNonInitializedVariable(variants: Collection<DeclarationDescriptor>, contextElement: PsiElement): Collection<DeclarationDescriptor> {
for (element in contextElement.parentsWithSelf) {
val parent = element.parent
if (parent is KtVariableDeclaration && element == parent.initializer) {
val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, parent]
return this.filter { it != descriptor }
return variants.filter { it != descriptor }
}
if (element is KtDeclaration) break // we can use variable inside lambda or anonymous object located in its initializer
}
return this
return variants
}
private fun getReferenceVariantsNoVisibilityFilter(
@@ -172,7 +172,7 @@ class BasicCompletionSession(
val contextVariableTypesForSmartCompletion = withCollectRequiredContextVariableTypes(::completeWithSmartCompletion)
fun completeReferenceVariants(lookupElementFactory: LookupElementFactory) {
val (imported, notImported) = referenceVariants!!
val (imported, notImported) = referenceVariantsWithNonInitializedVarExcluded!!
collector.addDescriptorElements(imported, lookupElementFactory)
collector.addDescriptorElements(notImported, lookupElementFactory, notImported = true)
}
@@ -284,6 +284,9 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
if (nameExpression != null && descriptorKindFilter != null) collectReferenceVariants(descriptorKindFilter!!, nameExpression) else null
}
protected val referenceVariantsWithNonInitializedVarExcluded: ReferenceVariants? by lazy {
referenceVariants?.let { ReferenceVariants(referenceVariantsHelper.excludeNonInitializedVariable(it.imported, position), it.notImportedExtensions) }
}
private fun collectReferenceVariants(descriptorKindFilter: DescriptorKindFilter, nameExpression: KtSimpleNameExpression, runtimeReceiver: ExpressionReceiver? = null): ReferenceVariants {
var variants = referenceVariantsHelper.getReferenceVariants(
@@ -292,6 +295,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
descriptorNameFilter,
filterOutJavaGettersAndSetters = false,
filterOutShadowed = false,
excludeNonInitializedVariable = false,
useReceiverType = runtimeReceiver?.type)
val shadowedDeclarationsFilter = if (runtimeReceiver != null)
@@ -78,7 +78,7 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para
val filter = smartCompletion!!.descriptorFilter
var contextVariableTypesForReferenceVariants = filter?.let {
withCollectRequiredContextVariableTypes { lookupElementFactory ->
val (imported, notImported) = referenceVariants ?: return@withCollectRequiredContextVariableTypes
val (imported, notImported) = referenceVariantsWithNonInitializedVarExcluded ?: return@withCollectRequiredContextVariableTypes
imported.forEach { collector.addElements(filter(it, lookupElementFactory)) }
notImported.forEach { collector.addElements(filter(it, lookupElementFactory), notImported = true) }
}
@@ -0,0 +1,7 @@
val xxx: String = ""
class C {
val xxx = x<caret>
}
// ABSENT: xxx
@@ -1929,6 +1929,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
doTest(fileName);
}
@TestMetadata("InInitializer7.kt")
public void testInInitializer7() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/InInitializer7.kt");
doTest(fileName);
}
@TestMetadata("Locals1.kt")
public void testLocals1() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/Locals1.kt");
@@ -1929,6 +1929,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
doTest(fileName);
}
@TestMetadata("InInitializer7.kt")
public void testInInitializer7() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/InInitializer7.kt");
doTest(fileName);
}
@TestMetadata("Locals1.kt")
public void testLocals1() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/Locals1.kt");