Extension SAM-adapters shown in completion
This commit is contained in:
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.load.java.typeEnhacement.enhanceSignature
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
|
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||||
import org.jetbrains.kotlin.storage.StorageManager
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
import org.jetbrains.kotlin.types.DescriptorSubstitutor
|
import org.jetbrains.kotlin.types.DescriptorSubstitutor
|
||||||
@@ -32,6 +33,7 @@ import org.jetbrains.kotlin.types.JetType
|
|||||||
import org.jetbrains.kotlin.types.TypeSubstitution
|
import org.jetbrains.kotlin.types.TypeSubstitution
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
import java.util.LinkedHashSet
|
||||||
|
|
||||||
interface SamAdapterExtensionFunctionDescriptor : FunctionDescriptor {
|
interface SamAdapterExtensionFunctionDescriptor : FunctionDescriptor {
|
||||||
val originalFunction: FunctionDescriptor
|
val originalFunction: FunctionDescriptor
|
||||||
@@ -73,6 +75,15 @@ class SamAdapterFunctionsScope(storageManager: StorageManager) : JetScope by Jet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<JetType>): Collection<FunctionDescriptor> {
|
||||||
|
return receiverTypes.flatMapTo(LinkedHashSet<FunctionDescriptor>()) { type ->
|
||||||
|
type.memberScope.getDescriptors(DescriptorKindFilter.FUNCTIONS)
|
||||||
|
.filterIsInstance<FunctionDescriptor>()
|
||||||
|
.map { extensionForFunction(it.original) }
|
||||||
|
.filterNotNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class MyFunctionDescriptor(
|
private class MyFunctionDescriptor(
|
||||||
override val originalFunction: FunctionDescriptor
|
override val originalFunction: FunctionDescriptor
|
||||||
) : SamAdapterExtensionFunctionDescriptor, SimpleFunctionDescriptorImpl(
|
) : SamAdapterExtensionFunctionDescriptor, SimpleFunctionDescriptorImpl(
|
||||||
|
|||||||
@@ -66,6 +66,10 @@ class AllUnderImportsScope : JetScope {
|
|||||||
return scopes.flatMap { it.getSyntheticExtensionProperties(receiverTypes) }
|
return scopes.flatMap { it.getSyntheticExtensionProperties(receiverTypes) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<JetType>): Collection<FunctionDescriptor> {
|
||||||
|
return scopes.flatMap { it.getSyntheticExtensionFunctions(receiverTypes) }
|
||||||
|
}
|
||||||
|
|
||||||
override fun getPackage(name: Name): PackageViewDescriptor? = null // packages are not imported by all under imports
|
override fun getPackage(name: Name): PackageViewDescriptor? = null // packages are not imported by all under imports
|
||||||
|
|
||||||
override fun getLocalVariable(name: Name): VariableDescriptor? = null
|
override fun getLocalVariable(name: Name): VariableDescriptor? = null
|
||||||
|
|||||||
@@ -279,6 +279,17 @@ class LazyImportScope(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<JetType>): Collection<FunctionDescriptor> {
|
||||||
|
// we do not perform any filtering by visibility here because all descriptors from both visible/invisible filter scopes are to be added anyway
|
||||||
|
if (filteringKind == FilteringKind.INVISIBLE_CLASSES) return listOf()
|
||||||
|
|
||||||
|
return importResolver.storageManager.compute {
|
||||||
|
importResolver.indexedImports.imports.flatMapTo(LinkedHashSet<FunctionDescriptor>()) { import ->
|
||||||
|
importResolver.getImportScope(import, LookupMode.EVERYTHING).getSyntheticExtensionFunctions(receiverTypes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun getDeclarationsByLabel(labelName: Name): Collection<DeclarationDescriptor> = listOf()
|
override fun getDeclarationsByLabel(labelName: Name): Collection<DeclarationDescriptor> = listOf()
|
||||||
|
|
||||||
override fun getDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> {
|
override fun getDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> {
|
||||||
|
|||||||
@@ -59,6 +59,10 @@ public abstract class AbstractScopeAdapter : JetScope {
|
|||||||
return workerScope.getSyntheticExtensionProperties(receiverTypes)
|
return workerScope.getSyntheticExtensionProperties(receiverTypes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<JetType>): Collection<FunctionDescriptor> {
|
||||||
|
return workerScope.getSyntheticExtensionFunctions(receiverTypes)
|
||||||
|
}
|
||||||
|
|
||||||
override fun getLocalVariable(name: Name): VariableDescriptor? {
|
override fun getLocalVariable(name: Name): VariableDescriptor? {
|
||||||
return workerScope.getLocalVariable(name)
|
return workerScope.getLocalVariable(name)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,9 @@ public open class ChainedScope(
|
|||||||
override fun getSyntheticExtensionProperties(receiverTypes: Collection<JetType>): Collection<PropertyDescriptor>
|
override fun getSyntheticExtensionProperties(receiverTypes: Collection<JetType>): Collection<PropertyDescriptor>
|
||||||
= getFromAllScopes { it.getSyntheticExtensionProperties(receiverTypes) }
|
= getFromAllScopes { it.getSyntheticExtensionProperties(receiverTypes) }
|
||||||
|
|
||||||
|
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<JetType>): Collection<FunctionDescriptor>
|
||||||
|
= getFromAllScopes { it.getSyntheticExtensionFunctions(receiverTypes) }
|
||||||
|
|
||||||
override fun getImplicitReceiversHierarchy(): List<ReceiverParameterDescriptor> {
|
override fun getImplicitReceiversHierarchy(): List<ReceiverParameterDescriptor> {
|
||||||
if (implicitReceiverHierarchy == null) {
|
if (implicitReceiverHierarchy == null) {
|
||||||
val result = ArrayList<ReceiverParameterDescriptor>()
|
val result = ArrayList<ReceiverParameterDescriptor>()
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ public class FilteringScope(private val workerScope: JetScope, private val predi
|
|||||||
|
|
||||||
override fun getSyntheticExtensionProperties(receiverTypes: Collection<JetType>): Collection<PropertyDescriptor> = workerScope.getSyntheticExtensionProperties(receiverTypes).filter(predicate)
|
override fun getSyntheticExtensionProperties(receiverTypes: Collection<JetType>): Collection<PropertyDescriptor> = workerScope.getSyntheticExtensionProperties(receiverTypes).filter(predicate)
|
||||||
|
|
||||||
|
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<JetType>): Collection<FunctionDescriptor> = workerScope.getSyntheticExtensionFunctions(receiverTypes).filter(predicate)
|
||||||
|
|
||||||
override fun getLocalVariable(name: Name) = filterDescriptor(workerScope.getLocalVariable(name))
|
override fun getLocalVariable(name: Name) = filterDescriptor(workerScope.getLocalVariable(name))
|
||||||
|
|
||||||
override fun getDescriptors(kindFilter: DescriptorKindFilter,
|
override fun getDescriptors(kindFilter: DescriptorKindFilter,
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ public interface JetScope {
|
|||||||
public fun getSyntheticExtensionFunctions(receiverTypes: Collection<JetType>, name: Name): Collection<FunctionDescriptor>
|
public fun getSyntheticExtensionFunctions(receiverTypes: Collection<JetType>, name: Name): Collection<FunctionDescriptor>
|
||||||
|
|
||||||
public fun getSyntheticExtensionProperties(receiverTypes: Collection<JetType>): Collection<PropertyDescriptor>
|
public fun getSyntheticExtensionProperties(receiverTypes: Collection<JetType>): Collection<PropertyDescriptor>
|
||||||
|
public fun getSyntheticExtensionFunctions(receiverTypes: Collection<JetType>): Collection<FunctionDescriptor>
|
||||||
|
|
||||||
public fun getContainingDeclaration(): DeclarationDescriptor
|
public fun getContainingDeclaration(): DeclarationDescriptor
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ public abstract class JetScopeImpl : JetScope {
|
|||||||
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<JetType>, name: Name): Collection<FunctionDescriptor> = emptyList()
|
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<JetType>, name: Name): Collection<FunctionDescriptor> = emptyList()
|
||||||
|
|
||||||
override fun getSyntheticExtensionProperties(receiverTypes: Collection<JetType>): Collection<PropertyDescriptor> = emptyList()
|
override fun getSyntheticExtensionProperties(receiverTypes: Collection<JetType>): Collection<PropertyDescriptor> = emptyList()
|
||||||
|
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<JetType>): Collection<FunctionDescriptor> = emptyList()
|
||||||
|
|
||||||
override fun getDeclarationsByLabel(labelName: Name): Collection<DeclarationDescriptor> = emptyList()
|
override fun getDeclarationsByLabel(labelName: Name): Collection<DeclarationDescriptor> = emptyList()
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,11 @@ public class SubstitutingScope(private val workerScope: JetScope, private val su
|
|||||||
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<JetType>, name: Name): Collection<FunctionDescriptor>
|
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<JetType>, name: Name): Collection<FunctionDescriptor>
|
||||||
= substitute(workerScope.getSyntheticExtensionFunctions(receiverTypes, name))
|
= substitute(workerScope.getSyntheticExtensionFunctions(receiverTypes, name))
|
||||||
|
|
||||||
override fun getSyntheticExtensionProperties(receiverTypes: Collection<JetType>): Collection<PropertyDescriptor> = substitute(workerScope.getSyntheticExtensionProperties(receiverTypes))
|
override fun getSyntheticExtensionProperties(receiverTypes: Collection<JetType>): Collection<PropertyDescriptor>
|
||||||
|
= substitute(workerScope.getSyntheticExtensionProperties(receiverTypes))
|
||||||
|
|
||||||
|
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<JetType>): Collection<FunctionDescriptor>
|
||||||
|
= substitute(workerScope.getSyntheticExtensionFunctions(receiverTypes))
|
||||||
|
|
||||||
override fun getPackage(name: Name) = workerScope.getPackage(name)
|
override fun getPackage(name: Name) = workerScope.getPackage(name)
|
||||||
|
|
||||||
|
|||||||
@@ -115,6 +115,14 @@ public class ErrorUtils {
|
|||||||
return ERROR_PROPERTY_GROUP;
|
return ERROR_PROPERTY_GROUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Collection<FunctionDescriptor> getSyntheticExtensionFunctions(
|
||||||
|
@NotNull Collection<? extends JetType> receiverTypes
|
||||||
|
) {
|
||||||
|
return Collections.<FunctionDescriptor>singleton(createErrorFunction(this));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VariableDescriptor getLocalVariable(@NotNull Name name) {
|
public VariableDescriptor getLocalVariable(@NotNull Name name) {
|
||||||
return ERROR_PROPERTY;
|
return ERROR_PROPERTY;
|
||||||
@@ -239,6 +247,14 @@ public class ErrorUtils {
|
|||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Collection<FunctionDescriptor> getSyntheticExtensionFunctions(
|
||||||
|
@NotNull Collection<? extends JetType> receiverTypes
|
||||||
|
) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public DeclarationDescriptor getContainingDeclaration() {
|
public DeclarationDescriptor getContainingDeclaration() {
|
||||||
|
|||||||
+16
-3
@@ -42,7 +42,8 @@ import org.jetbrains.kotlin.types.JetType
|
|||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import java.util.*
|
import java.util.HashSet
|
||||||
|
import java.util.LinkedHashSet
|
||||||
|
|
||||||
public class ReferenceVariantsHelper(
|
public class ReferenceVariantsHelper(
|
||||||
private val context: BindingContext,
|
private val context: BindingContext,
|
||||||
@@ -185,11 +186,23 @@ public class ReferenceVariantsHelper(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!kindFilter.excludes.contains(DescriptorKindExclude.Extensions)) {
|
if (!kindFilter.excludes.contains(DescriptorKindExclude.Extensions)) {
|
||||||
for (extension in resolutionScope.getSyntheticExtensionProperties(receiverTypes)) {
|
fun processExtension(extension: CallableDescriptor) {
|
||||||
if (nameFilter(extension.getName()) && kindFilter.accepts(extension)) {
|
if (nameFilter(extension.name) && kindFilter.accepts(extension)) {
|
||||||
addAll(extension.substituteExtensionIfCallable(receiverValue, callType, context, dataFlowInfo, containingDeclaration))
|
addAll(extension.substituteExtensionIfCallable(receiverValue, callType, context, dataFlowInfo, containingDeclaration))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (kindFilter.acceptsKinds(DescriptorKindFilter.VARIABLES_MASK)) {
|
||||||
|
for (extension in resolutionScope.getSyntheticExtensionProperties(receiverTypes)) {
|
||||||
|
processExtension(extension)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kindFilter.acceptsKinds(DescriptorKindFilter.FUNCTIONS_MASK)) {
|
||||||
|
for (extension in resolutionScope.getSyntheticExtensionFunctions(receiverTypes)) {
|
||||||
|
processExtension(extension)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.psi.psiUtil.parents
|
|||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor
|
||||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
||||||
import org.jetbrains.kotlin.types.JetType
|
import org.jetbrains.kotlin.types.JetType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
@@ -263,6 +264,9 @@ public class LookupElementFactory(
|
|||||||
element = element.appendTailText(" (from $from)", true)
|
element = element.appendTailText(" (from $from)", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// no need to show them as extensions
|
||||||
|
original is SamAdapterExtensionFunctionDescriptor -> {}
|
||||||
|
|
||||||
extensionReceiver != null -> {
|
extensionReceiver != null -> {
|
||||||
val receiverPresentation = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(extensionReceiver.type)
|
val receiverPresentation = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(extensionReceiver.type)
|
||||||
element = element.appendTailText(" for $receiverPresentation", true)
|
element = element.appendTailText(" for $receiverPresentation", true)
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
fun foo() {
|
||||||
|
javax.swing.SwingUtilities.invoke<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST_JAVA_ONLY: { lookupString: "invokeLater", itemText: "invokeLater", tailText: "(Runnable!)", typeText: "Unit" }
|
||||||
|
// EXIST_JAVA_ONLY: { lookupString: "invokeLater", itemText: "invokeLater", tailText: " {...} ((() -> Unit)!)", typeText: "Unit" }
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import lib.JavaClass
|
||||||
|
|
||||||
|
fun test() = JavaClass().<caret>
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "execute", itemText: "execute", tailText: "(Runnable!)", typeText: "Unit" }
|
||||||
|
// EXIST: { lookupString: "execute", itemText: "execute", tailText: " {...} ((() -> Unit)!)", typeText: "Unit" }
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package lib;
|
||||||
|
|
||||||
|
public class JavaClass {
|
||||||
|
public void execute(Runnable runnable) {}
|
||||||
|
}
|
||||||
+6
@@ -769,6 +769,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("SAMAdaptersStatic.kt")
|
||||||
|
public void testSAMAdaptersStatic() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/SAMAdaptersStatic.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("SafeCallAfterNullable.kt")
|
@TestMetadata("SafeCallAfterNullable.kt")
|
||||||
public void testSafeCallAfterNullable() throws Exception {
|
public void testSafeCallAfterNullable() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/SafeCallAfterNullable.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/SafeCallAfterNullable.kt");
|
||||||
|
|||||||
+6
@@ -769,6 +769,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("SAMAdaptersStatic.kt")
|
||||||
|
public void testSAMAdaptersStatic() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/SAMAdaptersStatic.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("SafeCallAfterNullable.kt")
|
@TestMetadata("SafeCallAfterNullable.kt")
|
||||||
public void testSafeCallAfterNullable() throws Exception {
|
public void testSafeCallAfterNullable() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/SafeCallAfterNullable.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/SafeCallAfterNullable.kt");
|
||||||
|
|||||||
+6
@@ -47,6 +47,12 @@ public class JvmWithLibBasicCompletionTestGenerated extends AbstractJvmWithLibBa
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("SAMAdapters.kt")
|
||||||
|
public void testSAMAdapters() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/custom/SAMAdapters.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("TopLevelNonImportedExtFun.kt")
|
@TestMetadata("TopLevelNonImportedExtFun.kt")
|
||||||
public void testTopLevelNonImportedExtFun() throws Exception {
|
public void testTopLevelNonImportedExtFun() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/custom/TopLevelNonImportedExtFun.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/custom/TopLevelNonImportedExtFun.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user