Fixed filtering of shadowed declarations after changes in extensions treatment
This commit is contained in:
+20
-12
@@ -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,
|
||||||
|
|||||||
+6
-9
@@ -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 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+35
-17
@@ -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) {
|
||||||
|
|||||||
+3
-11
@@ -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()
|
||||||
|
|
||||||
|
|||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package dependency1
|
||||||
|
|
||||||
|
fun Any.xxx(): Int = 1
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package dependency2
|
||||||
|
|
||||||
|
fun ppp.C.xxx(): Int = 1
|
||||||
+17
@@ -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
|
||||||
+6
@@ -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/");
|
||||||
|
|||||||
Reference in New Issue
Block a user