More correct shadowed declarations filtering in completion
This commit is contained in:
+12
-9
@@ -53,20 +53,22 @@ class ReferenceVariantsHelper(
|
|||||||
expression: KtSimpleNameExpression,
|
expression: KtSimpleNameExpression,
|
||||||
kindFilter: DescriptorKindFilter,
|
kindFilter: DescriptorKindFilter,
|
||||||
nameFilter: (Name) -> Boolean,
|
nameFilter: (Name) -> Boolean,
|
||||||
filterOutJavaGettersAndSetters: Boolean = false,
|
filterOutJavaGettersAndSetters: Boolean = true,
|
||||||
filterOutShadowed: Boolean = true,
|
filterOutShadowed: Boolean = true,
|
||||||
|
excludeNonInitializedVariable: Boolean = true,
|
||||||
useReceiverType: KotlinType? = null
|
useReceiverType: KotlinType? = null
|
||||||
): Collection<DeclarationDescriptor>
|
): Collection<DeclarationDescriptor>
|
||||||
= getReferenceVariants(expression, CallTypeAndReceiver.detect(expression),
|
= getReferenceVariants(expression, CallTypeAndReceiver.detect(expression),
|
||||||
kindFilter, nameFilter, filterOutJavaGettersAndSetters, filterOutShadowed, useReceiverType)
|
kindFilter, nameFilter, filterOutJavaGettersAndSetters, filterOutShadowed, excludeNonInitializedVariable, useReceiverType)
|
||||||
|
|
||||||
fun getReferenceVariants(
|
fun getReferenceVariants(
|
||||||
contextElement: PsiElement,
|
contextElement: PsiElement,
|
||||||
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
|
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
|
||||||
kindFilter: DescriptorKindFilter,
|
kindFilter: DescriptorKindFilter,
|
||||||
nameFilter: (Name) -> Boolean,
|
nameFilter: (Name) -> Boolean,
|
||||||
filterOutJavaGettersAndSetters: Boolean = false,
|
filterOutJavaGettersAndSetters: Boolean = true,
|
||||||
filterOutShadowed: Boolean = true,
|
filterOutShadowed: Boolean = true,
|
||||||
|
excludeNonInitializedVariable: Boolean = true,
|
||||||
useReceiverType: KotlinType? = null
|
useReceiverType: KotlinType? = null
|
||||||
): Collection<DeclarationDescriptor> {
|
): Collection<DeclarationDescriptor> {
|
||||||
var variants: Collection<DeclarationDescriptor>
|
var variants: Collection<DeclarationDescriptor>
|
||||||
@@ -79,12 +81,13 @@ class ReferenceVariantsHelper(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filterOutJavaGettersAndSetters && kindFilter.kindMask.and(DescriptorKindFilter.FUNCTIONS_MASK) != 0) {
|
||||||
if (filterOutJavaGettersAndSetters) {
|
|
||||||
variants = filterOutJavaGettersAndSetters(variants)
|
variants = filterOutJavaGettersAndSetters(variants)
|
||||||
}
|
}
|
||||||
|
|
||||||
variants = variants.excludeNonInitializedVariable(contextElement)
|
if (excludeNonInitializedVariable && kindFilter.kindMask.and(DescriptorKindFilter.VARIABLES_MASK) != 0) {
|
||||||
|
variants = excludeNonInitializedVariable(variants, contextElement)
|
||||||
|
}
|
||||||
|
|
||||||
return variants
|
return variants
|
||||||
}
|
}
|
||||||
@@ -102,16 +105,16 @@ class ReferenceVariantsHelper(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// filters out variable inside its initializer
|
// 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) {
|
for (element in contextElement.parentsWithSelf) {
|
||||||
val parent = element.parent
|
val parent = element.parent
|
||||||
if (parent is KtVariableDeclaration && element == parent.initializer) {
|
if (parent is KtVariableDeclaration && element == parent.initializer) {
|
||||||
val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, parent]
|
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
|
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(
|
private fun getReferenceVariantsNoVisibilityFilter(
|
||||||
|
|||||||
+1
-1
@@ -172,7 +172,7 @@ class BasicCompletionSession(
|
|||||||
val contextVariableTypesForSmartCompletion = withCollectRequiredContextVariableTypes(::completeWithSmartCompletion)
|
val contextVariableTypesForSmartCompletion = withCollectRequiredContextVariableTypes(::completeWithSmartCompletion)
|
||||||
|
|
||||||
fun completeReferenceVariants(lookupElementFactory: LookupElementFactory) {
|
fun completeReferenceVariants(lookupElementFactory: LookupElementFactory) {
|
||||||
val (imported, notImported) = referenceVariants!!
|
val (imported, notImported) = referenceVariantsWithNonInitializedVarExcluded!!
|
||||||
collector.addDescriptorElements(imported, lookupElementFactory)
|
collector.addDescriptorElements(imported, lookupElementFactory)
|
||||||
collector.addDescriptorElements(notImported, lookupElementFactory, notImported = true)
|
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
|
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 {
|
private fun collectReferenceVariants(descriptorKindFilter: DescriptorKindFilter, nameExpression: KtSimpleNameExpression, runtimeReceiver: ExpressionReceiver? = null): ReferenceVariants {
|
||||||
var variants = referenceVariantsHelper.getReferenceVariants(
|
var variants = referenceVariantsHelper.getReferenceVariants(
|
||||||
@@ -292,6 +295,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
|||||||
descriptorNameFilter,
|
descriptorNameFilter,
|
||||||
filterOutJavaGettersAndSetters = false,
|
filterOutJavaGettersAndSetters = false,
|
||||||
filterOutShadowed = false,
|
filterOutShadowed = false,
|
||||||
|
excludeNonInitializedVariable = false,
|
||||||
useReceiverType = runtimeReceiver?.type)
|
useReceiverType = runtimeReceiver?.type)
|
||||||
|
|
||||||
val shadowedDeclarationsFilter = if (runtimeReceiver != null)
|
val shadowedDeclarationsFilter = if (runtimeReceiver != null)
|
||||||
|
|||||||
+1
-1
@@ -78,7 +78,7 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para
|
|||||||
val filter = smartCompletion!!.descriptorFilter
|
val filter = smartCompletion!!.descriptorFilter
|
||||||
var contextVariableTypesForReferenceVariants = filter?.let {
|
var contextVariableTypesForReferenceVariants = filter?.let {
|
||||||
withCollectRequiredContextVariableTypes { lookupElementFactory ->
|
withCollectRequiredContextVariableTypes { lookupElementFactory ->
|
||||||
val (imported, notImported) = referenceVariants ?: return@withCollectRequiredContextVariableTypes
|
val (imported, notImported) = referenceVariantsWithNonInitializedVarExcluded ?: return@withCollectRequiredContextVariableTypes
|
||||||
imported.forEach { collector.addElements(filter(it, lookupElementFactory)) }
|
imported.forEach { collector.addElements(filter(it, lookupElementFactory)) }
|
||||||
notImported.forEach { collector.addElements(filter(it, lookupElementFactory), notImported = true) }
|
notImported.forEach { collector.addElements(filter(it, lookupElementFactory), notImported = true) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
val xxx: String = ""
|
||||||
|
|
||||||
|
class C {
|
||||||
|
val xxx = x<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// ABSENT: xxx
|
||||||
+6
@@ -1929,6 +1929,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("Locals1.kt")
|
||||||
public void testLocals1() throws Exception {
|
public void testLocals1() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/Locals1.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/Locals1.kt");
|
||||||
|
|||||||
+6
@@ -1929,6 +1929,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("Locals1.kt")
|
||||||
public void testLocals1() throws Exception {
|
public void testLocals1() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/Locals1.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/Locals1.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user