KT-3553 Problem with propagation for extension functions
#KT-3553 fixed
This commit is contained in:
+61
-27
@@ -20,7 +20,10 @@ import com.google.common.collect.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -154,47 +157,52 @@ public class SignaturesPropagationData {
|
||||
private JavaDescriptorResolver.ValueParameterDescriptors modifyValueParametersAccordingToSuperMethods(
|
||||
@NotNull JavaDescriptorResolver.ValueParameterDescriptors parameters // descriptors built by parameters resolver
|
||||
) {
|
||||
// we are not processing receiver type specifically:
|
||||
// if this function comes from Kotlin, then we don't need to do it, if it doesn't, then it can't have receiver
|
||||
assert parameters.getReceiverType() == null : "Parameters before propagation have receiver type," +
|
||||
" but propagation should be disabled for functions compiled from Kotlin in class: " +
|
||||
DescriptorUtils.getFQName(containingClass);
|
||||
|
||||
JetType receiverType = null;
|
||||
List<ValueParameterDescriptor> resultParameters = Lists.newArrayList();
|
||||
|
||||
boolean shouldBeExtension = checkIfShouldBeExtension();
|
||||
|
||||
for (ValueParameterDescriptor originalParam : parameters.getDescriptors()) {
|
||||
final int index = originalParam.getIndex();
|
||||
final int originalIndex = originalParam.getIndex();
|
||||
List<TypeAndVariance> typesFromSuperMethods = ContainerUtil.map(superFunctions,
|
||||
new Function<FunctionDescriptor, TypeAndVariance>() {
|
||||
@Override
|
||||
public TypeAndVariance fun(FunctionDescriptor superFunction) {
|
||||
ReceiverParameterDescriptor receiver = superFunction.getReceiverParameter();
|
||||
int index = receiver != null ? originalIndex - 1 : originalIndex;
|
||||
if (index == -1) {
|
||||
assert receiver != null : "can't happen: index is -1, while function is not extension";
|
||||
return new TypeAndVariance(receiver.getType(), INVARIANT);
|
||||
}
|
||||
return new TypeAndVariance(superFunction.getValueParameters().get(index).getType(), INVARIANT);
|
||||
}
|
||||
});
|
||||
|
||||
VarargCheckResult varargCheckResult =
|
||||
checkVarargInSuperFunctions(originalParam);
|
||||
VarargCheckResult varargCheckResult = checkVarargInSuperFunctions(originalParam);
|
||||
|
||||
JetType altType = modifyTypeAccordingToSuperMethods(varargCheckResult.parameterType, typesFromSuperMethods, MEMBER_SIGNATURE_CONTRAVARIANT);
|
||||
|
||||
resultParameters.add(new ValueParameterDescriptorImpl(
|
||||
originalParam.getContainingDeclaration(),
|
||||
index,
|
||||
originalParam.getAnnotations(),
|
||||
originalParam.getName(),
|
||||
altType,
|
||||
originalParam.declaresDefaultValue(),
|
||||
varargCheckResult.isVararg ? KotlinBuiltIns.getInstance().getArrayElementType(altType) : null
|
||||
));
|
||||
if (shouldBeExtension && originalIndex == 0) {
|
||||
receiverType = altType;
|
||||
}
|
||||
else {
|
||||
resultParameters.add(new ValueParameterDescriptorImpl(
|
||||
originalParam.getContainingDeclaration(),
|
||||
shouldBeExtension ? originalIndex - 1 : originalIndex,
|
||||
originalParam.getAnnotations(),
|
||||
originalParam.getName(),
|
||||
altType,
|
||||
originalParam.declaresDefaultValue(),
|
||||
varargCheckResult.isVararg ? KotlinBuiltIns.getInstance().getArrayElementType(altType) : null
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
JetType originalReceiverType = parameters.getReceiverType();
|
||||
if (originalReceiverType != null) {
|
||||
JetType substituted = SignaturesUtil.createSubstitutorForTypeParameters(autoTypeParameterToModified)
|
||||
.substitute(originalReceiverType, INVARIANT);
|
||||
assert substituted != null;
|
||||
return new JavaDescriptorResolver.ValueParameterDescriptors(substituted, resultParameters);
|
||||
}
|
||||
else {
|
||||
return new JavaDescriptorResolver.ValueParameterDescriptors(null, resultParameters);
|
||||
}
|
||||
return new JavaDescriptorResolver.ValueParameterDescriptors(receiverType, resultParameters);
|
||||
}
|
||||
|
||||
private static List<FunctionDescriptor> getSuperFunctionsForMethod(
|
||||
@@ -270,7 +278,7 @@ public class SignaturesPropagationData {
|
||||
for (FunctionDescriptor fun : klass.getDefaultType().getMemberScope().getFunctions(functionName)) {
|
||||
CallableMemberDescriptor.Kind kind = fun.getKind();
|
||||
if ((kind == CallableMemberDescriptor.Kind.DECLARATION || kind == CallableMemberDescriptor.Kind.DELEGATION) &&
|
||||
fun.getValueParameters().size() == parameterCount) {
|
||||
fun.getValueParameters().size() + (fun.getReceiverParameter() != null ? 1 : 0) == parameterCount) {
|
||||
PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bindingContext, fun);
|
||||
if (declaration instanceof PsiMethod) {
|
||||
result.put(fqName, Pair.create(fun, (PsiMethod) declaration));
|
||||
@@ -295,12 +303,38 @@ public class SignaturesPropagationData {
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean checkIfShouldBeExtension() {
|
||||
boolean someSupersExtension = false;
|
||||
boolean someSupersNotExtension = false;
|
||||
|
||||
for (FunctionDescriptor superFunction : superFunctions) {
|
||||
if (superFunction.getReceiverParameter() != null) {
|
||||
someSupersExtension = true;
|
||||
}
|
||||
else {
|
||||
someSupersNotExtension = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (someSupersExtension) {
|
||||
if (someSupersNotExtension) {
|
||||
reportError("Incompatible super methods: some are extension functions, some are not");
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private VarargCheckResult checkVarargInSuperFunctions(@NotNull ValueParameterDescriptor originalParam) {
|
||||
boolean someSupersVararg = false;
|
||||
boolean someSupersNotVararg = false;
|
||||
for (FunctionDescriptor superFunction : superFunctions) {
|
||||
if (superFunction.getValueParameters().get(originalParam.getIndex()).getVarargElementType() != null) {
|
||||
int originalIndex = originalParam.getIndex();
|
||||
int index = superFunction.getReceiverParameter() != null ? originalIndex - 1 : originalIndex;
|
||||
if (index != -1 && superFunction.getValueParameters().get(index).getVarargElementType() != null) {
|
||||
someSupersVararg = true;
|
||||
}
|
||||
else {
|
||||
|
||||
+1
-1
@@ -151,7 +151,7 @@ public final class JavaFunctionResolver {
|
||||
List<String> signatureErrors = Lists.newArrayList();
|
||||
|
||||
List<FunctionDescriptor> superFunctions;
|
||||
if (ownerDescriptor instanceof ClassDescriptor) {
|
||||
if (ownerDescriptor instanceof ClassDescriptor && !method.getJetMethodAnnotation().isDefined()) { // don't propagate for Kotlin functions
|
||||
SignaturesPropagationData signaturesPropagationData = new SignaturesPropagationData(
|
||||
(ClassDescriptor) ownerDescriptor, returnType, valueParameterDescriptors, methodTypeParameters, method, trace);
|
||||
superFunctions = signaturesPropagationData.getSuperFunctions();
|
||||
|
||||
Reference in New Issue
Block a user