SAM-adapters are sorted as non-extensions in completion and with correct boldness + no parameter names when from compiled
This commit is contained in:
@@ -32,7 +32,7 @@ public class SamCodegenUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (original instanceof SamAdapterExtensionFunctionDescriptor) {
|
if (original instanceof SamAdapterExtensionFunctionDescriptor) {
|
||||||
return ((SamAdapterExtensionFunctionDescriptor) original).getOriginalFunction();
|
return ((SamAdapterExtensionFunctionDescriptor) original).getSourceFunction();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (original.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
|
if (original.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
|
||||||
|
|||||||
+98
-36
@@ -29,15 +29,14 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
|
|||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
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.*
|
||||||
import org.jetbrains.kotlin.types.JetType
|
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitution
|
|
||||||
import org.jetbrains.kotlin.types.Variance
|
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
import java.util.HashMap
|
||||||
import java.util.LinkedHashSet
|
import java.util.LinkedHashSet
|
||||||
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
interface SamAdapterExtensionFunctionDescriptor : FunctionDescriptor {
|
interface SamAdapterExtensionFunctionDescriptor : FunctionDescriptor {
|
||||||
val originalFunction: FunctionDescriptor
|
val sourceFunction: FunctionDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
class SamAdapterFunctionsScope(storageManager: StorageManager) : JetScope by JetScope.Empty {
|
class SamAdapterFunctionsScope(storageManager: StorageManager) : JetScope by JetScope.Empty {
|
||||||
@@ -52,7 +51,7 @@ class SamAdapterFunctionsScope(storageManager: StorageManager) : JetScope by Jet
|
|||||||
if (function.returnType == null) return null
|
if (function.returnType == null) return null
|
||||||
//TODO: it's a temporary hack while original returns a function with platform types
|
//TODO: it's a temporary hack while original returns a function with platform types
|
||||||
val enhancedFunction = function.enhanceSignature()
|
val enhancedFunction = function.enhanceSignature()
|
||||||
return MyFunctionDescriptor(enhancedFunction)
|
return MyFunctionDescriptor.create(enhancedFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<JetType>, name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
|
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<JetType>, name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
|
||||||
@@ -85,38 +84,101 @@ class SamAdapterFunctionsScope(storageManager: StorageManager) : JetScope by Jet
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class MyFunctionDescriptor(
|
private class MyFunctionDescriptor(
|
||||||
override val originalFunction: FunctionDescriptor
|
containingDeclaration: DeclarationDescriptor,
|
||||||
) : SamAdapterExtensionFunctionDescriptor, SimpleFunctionDescriptorImpl(
|
original: SimpleFunctionDescriptor?,
|
||||||
DescriptorUtils.getContainingModule(originalFunction),
|
annotations: Annotations,
|
||||||
null,
|
name: Name,
|
||||||
Annotations.EMPTY, //TODO
|
kind: CallableMemberDescriptor.Kind,
|
||||||
originalFunction.name,
|
source: SourceElement
|
||||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
) : SamAdapterExtensionFunctionDescriptor, SimpleFunctionDescriptorImpl(containingDeclaration, original, annotations, name, kind, source) {
|
||||||
originalFunction.source
|
|
||||||
) {
|
override var sourceFunction: FunctionDescriptor by Delegates.notNull()
|
||||||
init {
|
private set
|
||||||
val typeParamsSum = (originalFunction.typeParameters).toArrayList()
|
|
||||||
val ownerClass = originalFunction.containingDeclaration as ClassDescriptor
|
private var toSourceFunctionTypeParameters: Map<TypeParameterDescriptor, TypeParameterDescriptor>? = null
|
||||||
//TODO: should we go up parents for getters/setters too?
|
|
||||||
for (parent in ownerClass.parentsWithSelf) {
|
companion object {
|
||||||
if (parent !is ClassDescriptor) break
|
fun create(sourceFunction: FunctionDescriptor): MyFunctionDescriptor {
|
||||||
typeParamsSum += parent.typeConstructor.parameters
|
val descriptor = MyFunctionDescriptor(DescriptorUtils.getContainingModule(sourceFunction),
|
||||||
|
null,
|
||||||
|
Annotations.EMPTY, //TODO
|
||||||
|
sourceFunction.name,
|
||||||
|
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||||
|
sourceFunction.source)
|
||||||
|
descriptor.sourceFunction = sourceFunction
|
||||||
|
|
||||||
|
val sourceTypeParams = (sourceFunction.typeParameters).toArrayList()
|
||||||
|
val ownerClass = sourceFunction.containingDeclaration as ClassDescriptor
|
||||||
|
//TODO: should we go up parents for getters/setters too?
|
||||||
|
//TODO: non-inner classes
|
||||||
|
for (parent in ownerClass.parentsWithSelf) {
|
||||||
|
if (parent !is ClassDescriptor) break
|
||||||
|
sourceTypeParams += parent.typeConstructor.parameters
|
||||||
|
}
|
||||||
|
//TODO: duplicated parameter names
|
||||||
|
|
||||||
|
val typeParameters = ArrayList<TypeParameterDescriptor>(sourceTypeParams.size())
|
||||||
|
val typeSubstitutor = DescriptorSubstitutor.substituteTypeParameters(sourceTypeParams, TypeSubstitution.EMPTY, descriptor, typeParameters)
|
||||||
|
|
||||||
|
descriptor.toSourceFunctionTypeParameters = typeParameters.zip(sourceTypeParams).toMap()
|
||||||
|
|
||||||
|
val returnType = typeSubstitutor.safeSubstitute(sourceFunction.returnType!!, Variance.INVARIANT)
|
||||||
|
val receiverType = typeSubstitutor.safeSubstitute(ownerClass.defaultType, Variance.INVARIANT)
|
||||||
|
val valueParameters = SingleAbstractMethodUtils.createValueParametersForSamAdapter(sourceFunction, descriptor, typeSubstitutor)
|
||||||
|
|
||||||
|
val visibility = syntheticExtensionVisibility(sourceFunction)
|
||||||
|
|
||||||
|
descriptor.initialize(receiverType, null, typeParameters, valueParameters, returnType, Modality.FINAL, visibility)
|
||||||
|
|
||||||
|
return descriptor
|
||||||
}
|
}
|
||||||
//TODO: duplicated parameter names
|
|
||||||
|
|
||||||
val typeParameters = ArrayList<TypeParameterDescriptor>(typeParamsSum.size())
|
|
||||||
val typeSubstitutor = DescriptorSubstitutor.substituteTypeParameters(typeParamsSum, TypeSubstitution.EMPTY, this, typeParameters)
|
|
||||||
|
|
||||||
val returnType = typeSubstitutor.safeSubstitute(originalFunction.returnType!!, Variance.INVARIANT)
|
|
||||||
val receiverType = typeSubstitutor.safeSubstitute(ownerClass.defaultType, Variance.INVARIANT)
|
|
||||||
val valueParameters = SingleAbstractMethodUtils.createValueParametersForSamAdapter(originalFunction, this, typeSubstitutor)
|
|
||||||
|
|
||||||
val visibility = syntheticExtensionVisibility(originalFunction)
|
|
||||||
|
|
||||||
initialize(receiverType, null, typeParameters, valueParameters, returnType, Modality.FINAL, visibility)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hasStableParameterNames() = originalFunction.hasStableParameterNames()
|
override fun hasStableParameterNames() = sourceFunction.hasStableParameterNames()
|
||||||
override fun hasSynthesizedParameterNames() = originalFunction.hasSynthesizedParameterNames()
|
override fun hasSynthesizedParameterNames() = sourceFunction.hasSynthesizedParameterNames()
|
||||||
|
|
||||||
|
override fun createSubstitutedCopy(newOwner: DeclarationDescriptor, original: FunctionDescriptor?, kind: CallableMemberDescriptor.Kind): MyFunctionDescriptor {
|
||||||
|
return MyFunctionDescriptor(containingDeclaration, original as SimpleFunctionDescriptor?, annotations, name, kind, source).apply {
|
||||||
|
sourceFunction = this@MyFunctionDescriptor.sourceFunction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doSubstitute(
|
||||||
|
originalSubstitutor: TypeSubstitutor,
|
||||||
|
newOwner: DeclarationDescriptor,
|
||||||
|
newModality: Modality,
|
||||||
|
newVisibility: Visibility,
|
||||||
|
original: FunctionDescriptor?,
|
||||||
|
copyOverrides: Boolean,
|
||||||
|
kind: CallableMemberDescriptor.Kind,
|
||||||
|
newValueParameterDescriptors: MutableList<ValueParameterDescriptor>,
|
||||||
|
newExtensionReceiverParameterType: JetType?,
|
||||||
|
newReturnType: JetType
|
||||||
|
): FunctionDescriptor? {
|
||||||
|
val descriptor = super<SimpleFunctionDescriptorImpl>.doSubstitute(
|
||||||
|
originalSubstitutor, newOwner, newModality, newVisibility, original,
|
||||||
|
copyOverrides, kind, newValueParameterDescriptors, newExtensionReceiverParameterType, newReturnType)
|
||||||
|
as MyFunctionDescriptor? ?: return null
|
||||||
|
|
||||||
|
if (original == null) {
|
||||||
|
throw UnsupportedOperationException("doSubstitute with no original should not be called for synthetic extension")
|
||||||
|
}
|
||||||
|
|
||||||
|
original as MyFunctionDescriptor
|
||||||
|
assert(original.original == original, "original in doSubstitute should have no other original")
|
||||||
|
|
||||||
|
val substitutionMap = HashMap<TypeConstructor, TypeProjection>()
|
||||||
|
for (typeParameter in original.typeParameters) {
|
||||||
|
val typeProjection = originalSubstitutor.substitution[typeParameter.defaultType] ?: continue
|
||||||
|
val sourceTypeParameter = original.toSourceFunctionTypeParameters!![typeParameter]!!
|
||||||
|
substitutionMap[sourceTypeParameter.typeConstructor] = typeProjection
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
val sourceFunctionSubstitutor = TypeSubstitutor.create(substitutionMap)
|
||||||
|
descriptor.sourceFunction = original.sourceFunction.substitute(sourceFunctionSubstitutor)!!
|
||||||
|
|
||||||
|
return descriptor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-3
@@ -255,8 +255,7 @@ public class LookupElementFactory(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor is CallableDescriptor) {
|
if (descriptor is CallableDescriptor) {
|
||||||
val original = descriptor.original
|
val extensionReceiver = descriptor.original.extensionReceiverParameter
|
||||||
val extensionReceiver = original.extensionReceiverParameter
|
|
||||||
when {
|
when {
|
||||||
descriptor is SyntheticJavaPropertyDescriptor -> {
|
descriptor is SyntheticJavaPropertyDescriptor -> {
|
||||||
var from = descriptor.getMethod.getName().asString() + "()"
|
var from = descriptor.getMethod.getName().asString() + "()"
|
||||||
@@ -265,7 +264,7 @@ public class LookupElementFactory(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// no need to show them as extensions
|
// no need to show them as extensions
|
||||||
original is SamAdapterExtensionFunctionDescriptor -> {}
|
descriptor 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)
|
||||||
@@ -336,6 +335,9 @@ public class LookupElementFactory(
|
|||||||
if (descriptor is SyntheticJavaPropertyDescriptor) {
|
if (descriptor is SyntheticJavaPropertyDescriptor) {
|
||||||
return callableWeight(descriptor.getMethod)
|
return callableWeight(descriptor.getMethod)
|
||||||
}
|
}
|
||||||
|
if (descriptor is SamAdapterExtensionFunctionDescriptor) {
|
||||||
|
return callableWeight(descriptor.sourceFunction)
|
||||||
|
}
|
||||||
|
|
||||||
val receiverParameter = descriptor.extensionReceiverParameter ?: descriptor.dispatchReceiverParameter
|
val receiverParameter = descriptor.extensionReceiverParameter ?: descriptor.dispatchReceiverParameter
|
||||||
if (receiverParameter != null) {
|
if (receiverParameter != null) {
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
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" }
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
package lib;
|
|
||||||
|
|
||||||
public class JavaClass {
|
|
||||||
public void execute(Runnable runnable) {}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import lib.JavaClass
|
||||||
|
|
||||||
|
class KotlinClass : JavaClass()
|
||||||
|
|
||||||
|
fun test() = KotlinClass().<caret>
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "execute", itemText: "execute", tailText: "(Runnable!, Int)", typeText: "Unit", attributes: "" }
|
||||||
|
// EXIST: { lookupString: "execute", itemText: "execute", tailText: "((() -> Unit)!, Int)", typeText: "Unit", attributes: "" }
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import lib.*;
|
||||||
|
|
||||||
|
fun foo(j: JavaInterface<String>) {
|
||||||
|
j.<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "execute", itemText: "execute", tailText: "(Task<String!>!, K!)", typeText: "String!", attributes: "bold" }
|
||||||
|
// EXIST: { lookupString: "execute", itemText: "execute", tailText: "(((String!) -> Unit)!, K!)", typeText: "String!", attributes: "bold" }
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
package lib;
|
||||||
|
|
||||||
|
public interface JavaInterface<T> {
|
||||||
|
<K> T execute(Task<T> task, K k);
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package lib;
|
||||||
|
|
||||||
|
public interface Task<T> {
|
||||||
|
void run(T t);
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package lib;
|
||||||
|
|
||||||
|
public class JavaClass {
|
||||||
|
public void execute(Runnable runnable, int x) {}
|
||||||
|
}
|
||||||
+9
-3
@@ -47,9 +47,15 @@ public class JvmWithLibBasicCompletionTestGenerated extends AbstractJvmWithLibBa
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("SAMAdapters.kt")
|
@TestMetadata("SamAdapter.kt")
|
||||||
public void testSAMAdapters() throws Exception {
|
public void testSamAdapter() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/custom/SAMAdapters.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/custom/SamAdapter.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("SamAdapterAndGenerics.kt")
|
||||||
|
public void testSamAdapterAndGenerics() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/custom/SamAdapterAndGenerics.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user