Fixed filtering of shadowed declarations after changes in extensions treatment

This commit is contained in:
Valentin Kipyatkov
2015-10-28 18:25:03 +03:00
parent be5569d31a
commit 9feed9c3ef
8 changed files with 93 additions and 49 deletions
@@ -58,10 +58,11 @@ class ReferenceVariantsHelper(
kindFilter: DescriptorKindFilter, kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean, nameFilter: (Name) -> Boolean,
filterOutJavaGettersAndSetters: Boolean = false, filterOutJavaGettersAndSetters: Boolean = false,
filterOutShadowed: Boolean = true,
useRuntimeReceiverType: Boolean = false useRuntimeReceiverType: Boolean = false
): Collection<DeclarationDescriptor> ): Collection<DeclarationDescriptor>
= getReferenceVariants(expression, CallTypeAndReceiver.detect(expression), = getReferenceVariants(expression, CallTypeAndReceiver.detect(expression),
kindFilter, nameFilter, filterOutJavaGettersAndSetters, useRuntimeReceiverType) kindFilter, nameFilter, filterOutJavaGettersAndSetters, filterOutShadowed, useRuntimeReceiverType)
fun getReferenceVariants( fun getReferenceVariants(
contextElement: PsiElement, contextElement: PsiElement,
@@ -69,32 +70,39 @@ class ReferenceVariantsHelper(
kindFilter: DescriptorKindFilter, kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean, nameFilter: (Name) -> Boolean,
filterOutJavaGettersAndSetters: Boolean = false, filterOutJavaGettersAndSetters: Boolean = false,
filterOutShadowed: Boolean = true,
useRuntimeReceiverType: Boolean = false useRuntimeReceiverType: Boolean = false
): Collection<DeclarationDescriptor> { ): Collection<DeclarationDescriptor> {
var variants: Collection<DeclarationDescriptor> var variants: Collection<DeclarationDescriptor>
= getReferenceVariantsNoVisibilityFilter(contextElement, kindFilter, nameFilter, callTypeAndReceiver, useRuntimeReceiverType) = getReferenceVariantsNoVisibilityFilter(contextElement, kindFilter, nameFilter, callTypeAndReceiver, useRuntimeReceiverType)
.filter { !it.isAnnotatedAsHidden() && visibilityFilter(it) } .filter { !it.isAnnotatedAsHidden() && visibilityFilter(it) }
ShadowedDeclarationsFilter.create(bindingContext, resolutionFacade, contextElement, callTypeAndReceiver)?.let { if (filterOutShadowed) {
variants = it.filter(variants) ShadowedDeclarationsFilter.create(bindingContext, resolutionFacade, contextElement, callTypeAndReceiver)?.let {
variants = it.filter(variants)
}
} }
if (filterOutJavaGettersAndSetters) { if (filterOutJavaGettersAndSetters) {
val accessorMethodsToRemove = HashSet<FunctionDescriptor>() variants = filterOutJavaGettersAndSetters(variants)
for (variant in variants) {
if (variant is SyntheticJavaPropertyDescriptor) {
accessorMethodsToRemove.add(variant.getMethod.original)
accessorMethodsToRemove.addIfNotNull(variant.setMethod?.original)
}
}
variants = variants.filter { it !is FunctionDescriptor || it.original !in accessorMethodsToRemove }
} }
return variants return variants
} }
fun filterOutJavaGettersAndSetters(variants: Collection<DeclarationDescriptor>): Collection<DeclarationDescriptor> {
val accessorMethodsToRemove = HashSet<FunctionDescriptor>()
for (variant in variants) {
if (variant is SyntheticJavaPropertyDescriptor) {
accessorMethodsToRemove.add(variant.getMethod.original)
accessorMethodsToRemove.addIfNotNull(variant.setMethod?.original)
}
}
return variants.filter { it !is FunctionDescriptor || it.original !in accessorMethodsToRemove }
}
private fun getReferenceVariantsNoVisibilityFilter( private fun getReferenceVariantsNoVisibilityFilter(
contextElement: PsiElement, contextElement: PsiElement,
kindFilter: DescriptorKindFilter, kindFilter: DescriptorKindFilter,
@@ -209,7 +209,11 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
collector.addElements(additionalItems) collector.addElements(additionalItems)
} }
collector.addDescriptorElements(referenceVariants) referenceVariants?.let {
val (imported, notImported) = it
collector.addDescriptorElements(imported)
collector.addDescriptorElements(notImported, notImported = true)
}
completeKeywords() completeKeywords()
@@ -233,13 +237,6 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
flushToResultSet() flushToResultSet()
if (completionKind == CompletionKind.ALL && callTypeAndReceiver.shouldCompleteCallableExtensions()) {
for (extension in getCallableTopLevelExtensions()) {
collector.addDescriptorElements(extension, !isImportableDescriptorImported(extension))
}
flushToResultSet()
}
if (completionKind != CompletionKind.KEYWORDS_ONLY) { if (completionKind != CompletionKind.KEYWORDS_ONLY) {
completeNonImported() completeNonImported()
@@ -411,7 +408,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
} }
if (callTypeAndReceiver.receiver != null) { if (callTypeAndReceiver.receiver != null) {
val referenceVariantsSet = referenceVariants.toSet() val referenceVariantsSet = referenceVariants!!.imported.toSet()
superClasses = superClasses.filter { it in referenceVariantsSet } superClasses = superClasses.filter { it in referenceVariantsSet }
} }
@@ -260,18 +260,41 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
return context return context
} }
protected val referenceVariants: Collection<DeclarationDescriptor> by lazy(LazyThreadSafetyMode.NONE) { /* TODO: not protected because of KT-9809 */
if (descriptorKindFilter != null) { data class ReferenceVariants(val imported: Collection<DeclarationDescriptor>, val notImportedExtensions: Collection<CallableDescriptor>)
referenceVariantsHelper.getReferenceVariants(
nameExpression!!, protected val referenceVariants: ReferenceVariants? by lazy {
descriptorKindFilter!!, if (descriptorKindFilter == null) return@lazy null
descriptorNameFilter,
filterOutJavaGettersAndSetters = configuration.filterOutJavaGettersAndSetters var variants = referenceVariantsHelper.getReferenceVariants(
).excludeNonInitializedVariable(nameExpression) nameExpression!!,
descriptorKindFilter!!,
descriptorNameFilter,
filterOutJavaGettersAndSetters = false,
filterOutShadowed = false)
variants = variants.excludeNonInitializedVariable(nameExpression)
val shadowedDeclarationsFilter = ShadowedDeclarationsFilter.create(bindingContext, resolutionFacade, position, callTypeAndReceiver)
var notImportedExtensions: Collection<CallableDescriptor> = emptyList()
if (callTypeAndReceiver.shouldCompleteCallableExtensions()) {
val extensions = indicesHelper.getCallableTopLevelExtensions({ prefixMatcher.prefixMatches(it) }, callTypeAndReceiver, expression!!, bindingContext)
val pair = extensions.partition { isImportableDescriptorImported(it) }
variants += pair.first
notImportedExtensions = pair.second
} }
else {
emptyList() if (shadowedDeclarationsFilter != null) {
variants = shadowedDeclarationsFilter.filter(variants)
notImportedExtensions = shadowedDeclarationsFilter.filterNonImported(notImportedExtensions, variants)
} }
if (configuration.filterOutJavaGettersAndSetters) {
variants = referenceVariantsHelper.filterOutJavaGettersAndSetters(variants)
}
ReferenceVariants(variants, notImportedExtensions)
} }
// filters out variable inside its initializer // filters out variable inside its initializer
@@ -296,7 +319,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
filterOutJavaGettersAndSetters = configuration.filterOutJavaGettersAndSetters filterOutJavaGettersAndSetters = configuration.filterOutJavaGettersAndSetters
).excludeNonInitializedVariable(nameExpression) ).excludeNonInitializedVariable(nameExpression)
return descriptors.filter { descriptor -> return descriptors.filter { descriptor ->
referenceVariants.none { compareDescriptors(project, it, descriptor) } referenceVariants!!.imported.none { compareDescriptors(project, it, descriptor) }
} }
} }
@@ -317,14 +340,9 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
&& this !is CallTypeAndReceiver.IMPORT_DIRECTIVE && this !is CallTypeAndReceiver.IMPORT_DIRECTIVE
} }
protected fun getCallableTopLevelExtensions(): Collection<CallableDescriptor> {
return indicesHelper.getCallableTopLevelExtensions({ prefixMatcher.prefixMatches(it) }, callTypeAndReceiver, expression!!, bindingContext)
.filterShadowedNonImported() //TODO: not correct!
}
private fun Collection<CallableDescriptor>.filterShadowedNonImported(): Collection<CallableDescriptor> { private fun Collection<CallableDescriptor>.filterShadowedNonImported(): Collection<CallableDescriptor> {
val filter = ShadowedDeclarationsFilter.create(bindingContext, resolutionFacade, nameExpression!!, callTypeAndReceiver) val filter = ShadowedDeclarationsFilter.create(bindingContext, resolutionFacade, nameExpression!!, callTypeAndReceiver)
return if (filter != null) filter.filterNonImported(this, referenceVariants) else this return if (filter != null) filter.filterNonImported(this, referenceVariants!!.imported) else this
} }
protected fun addClassesFromIndex(kindFilter: (ClassKind) -> Boolean) { protected fun addClassesFromIndex(kindFilter: (ClassKind) -> Boolean) {
@@ -73,17 +73,9 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para
if (nameExpression != null) { if (nameExpression != null) {
val filter = smartCompletion!!.descriptorFilter val filter = smartCompletion!!.descriptorFilter
if (filter != null) { if (filter != null) {
referenceVariants.forEach { collector.addElements(filter(it)) } val (imported, notImported) = referenceVariants!!
flushToResultSet() imported.forEach { collector.addElements(filter(it)) }
notImported.forEach { collector.addElements(filter(it), notImported = true) }
if (callTypeAndReceiver.shouldCompleteCallableExtensions()) {
for (extension in getCallableTopLevelExtensions()) {
val elements = filter(extension)
if (elements.isNotEmpty()) {
collector.addElements(elements, !isImportableDescriptorImported(extension))
}
}
}
flushToResultSet() flushToResultSet()
@@ -0,0 +1,3 @@
package dependency1
fun Any.xxx(): Int = 1
@@ -0,0 +1,3 @@
package dependency2
fun ppp.C.xxx(): Int = 1
@@ -0,0 +1,17 @@
package ppp
import dependency1.xxx
import dependency2.xxx
interface I
fun I.xxx() {}
class C : I {
fun foo() {
xx<caret>
}
}
// EXIST: { lookupString: "xxx", itemText: "xxx", tailText: "() for C in dependency2", typeText: "Int" }
// NOTHING_ELSE
@@ -311,6 +311,12 @@ public class MultiFileJvmBasicCompletionTestGenerated extends AbstractMultiFileJ
doTest(fileName); doTest(fileName);
} }
@TestMetadata("PreferMoreSpecificExtension3")
public void testPreferMoreSpecificExtension3() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/multifile/PreferMoreSpecificExtension3/");
doTest(fileName);
}
@TestMetadata("PropertyKeysEmptyString") @TestMetadata("PropertyKeysEmptyString")
public void testPropertyKeysEmptyString() throws Exception { public void testPropertyKeysEmptyString() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/multifile/PropertyKeysEmptyString/"); String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/multifile/PropertyKeysEmptyString/");