Preliminary support for extension functions: they participate in overload resolution only if no such name is found in the receiver type itself.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.jet.lang.descriptors;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -26,12 +27,13 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public FunctionDescriptor initialize(@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters, @NotNull JetType unsubstitutedReturnType) {
|
||||
return super.initialize(typeParameters, unsubstitutedValueParameters, unsubstitutedReturnType);
|
||||
public FunctionDescriptor initialize(@Nullable JetType receiverType, @NotNull List<TypeParameterDescriptor> typeParameters, @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters, @NotNull JetType unsubstitutedReturnType) {
|
||||
assert receiverType == null;
|
||||
return super.initialize(null, typeParameters, unsubstitutedValueParameters, unsubstitutedReturnType);
|
||||
}
|
||||
|
||||
public ConstructorDescriptor initialize(@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters) {
|
||||
super.initialize(Collections.<TypeParameterDescriptor>emptyList(), unsubstitutedValueParameters, getContainingDeclaration().getDefaultType());
|
||||
super.initialize(null, Collections.<TypeParameterDescriptor>emptyList(), unsubstitutedValueParameters, getContainingDeclaration().getDefaultType());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@ public interface FunctionDescriptor extends DeclarationDescriptor {
|
||||
@NotNull
|
||||
DeclarationDescriptor getContainingDeclaration();
|
||||
|
||||
// @Nullable
|
||||
// JetType getReceiverType();
|
||||
@Nullable
|
||||
JetType getReceiverType();
|
||||
|
||||
@NotNull
|
||||
List<TypeParameterDescriptor> getTypeParameters();
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
||||
import org.jetbrains.jet.lang.types.Variance;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -18,9 +19,9 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
|
||||
private List<TypeParameterDescriptor> typeParameters;
|
||||
private List<ValueParameterDescriptor> unsubstitutedValueParameters;
|
||||
private JetType unsubstitutedReturnType;
|
||||
private JetType receiverType;
|
||||
|
||||
private final Set<FunctionDescriptor> overriddenFunctions = Sets.newHashSet();
|
||||
|
||||
private final FunctionDescriptor original;
|
||||
|
||||
public FunctionDescriptorImpl(
|
||||
@@ -40,15 +41,22 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
|
||||
}
|
||||
|
||||
public FunctionDescriptor initialize(
|
||||
@Nullable JetType receiverType,
|
||||
@NotNull List<TypeParameterDescriptor> typeParameters,
|
||||
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
|
||||
@Nullable JetType unsubstitutedReturnType) {
|
||||
this.receiverType = receiverType;
|
||||
this.typeParameters = typeParameters;
|
||||
this.unsubstitutedValueParameters = unsubstitutedValueParameters;
|
||||
this.unsubstitutedReturnType = unsubstitutedReturnType;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType getReceiverType() {
|
||||
return receiverType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<? extends FunctionDescriptor> getOverriddenFunctions() {
|
||||
@@ -91,6 +99,15 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
|
||||
FunctionDescriptorImpl substitutedDescriptor;
|
||||
substitutedDescriptor = createSubstitutedCopy();
|
||||
|
||||
JetType receiverType = getReceiverType();
|
||||
JetType substitutedReceiverType = null;
|
||||
if (receiverType != null) {
|
||||
substitutedReceiverType = substitutor.substitute(receiverType, Variance.IN_VARIANCE);
|
||||
if (substitutedReceiverType == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
List<ValueParameterDescriptor> substitutedValueParameters = FunctionDescriptorUtil.getSubstitutedValueParameters(substitutedDescriptor, this, substitutor);
|
||||
if (substitutedValueParameters == null) {
|
||||
return null;
|
||||
@@ -102,6 +119,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
|
||||
}
|
||||
|
||||
substitutedDescriptor.initialize(
|
||||
substitutedReceiverType,
|
||||
Collections.<TypeParameterDescriptor>emptyList(), // TODO : questionable
|
||||
substitutedValueParameters,
|
||||
substitutedReturnType
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
package org.jetbrains.jet.lang.descriptors;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.WritableScope;
|
||||
import org.jetbrains.jet.lang.resolve.WritableScopeImpl;
|
||||
import org.jetbrains.jet.lang.resolve.*;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
|
||||
import java.util.*;
|
||||
@@ -99,6 +98,10 @@ public class FunctionDescriptorUtil {
|
||||
@NotNull
|
||||
public static JetScope getFunctionInnerScope(@NotNull JetScope outerScope, @NotNull FunctionDescriptor descriptor, @NotNull BindingTrace trace) {
|
||||
WritableScope parameterScope = new WritableScopeImpl(outerScope, descriptor, trace.getErrorHandler());
|
||||
JetType receiverType = descriptor.getReceiverType();
|
||||
if (receiverType != null) {
|
||||
parameterScope.setThisType(receiverType);
|
||||
}
|
||||
for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) {
|
||||
parameterScope.addTypeParameterDescriptor(typeParameter);
|
||||
}
|
||||
@@ -229,4 +232,54 @@ public class FunctionDescriptorUtil {
|
||||
|
||||
return OverrideCompatibilityInfo.success();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static FunctionGroup filteredFunctionGroup(@NotNull final FunctionGroup functionGroup, @NotNull final Function<FunctionDescriptor, Boolean> criterion) {
|
||||
return new FunctionGroup() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return functionGroup.getName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public OverloadResolutionResult getPossiblyApplicableFunctions(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
|
||||
OverloadResolutionResult possiblyApplicableFunctions = functionGroup.getPossiblyApplicableFunctions(typeArguments, positionedValueArgumentTypes);
|
||||
List<FunctionDescriptor> functionDescriptors = Lists.newArrayList(possiblyApplicableFunctions.getFunctionDescriptors());
|
||||
for (Iterator<FunctionDescriptor> iterator = functionDescriptors.iterator(); iterator.hasNext(); ) {
|
||||
FunctionDescriptor functionDescriptor = iterator.next();
|
||||
if (!criterion.apply(functionDescriptor)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
if (functionDescriptors.isEmpty()) {
|
||||
return OverloadResolutionResult.nameNotFound();
|
||||
}
|
||||
if (possiblyApplicableFunctions.isSuccess() || possiblyApplicableFunctions.isAmbiguity()) {
|
||||
if (functionDescriptors.size() == 1) {
|
||||
return OverloadResolutionResult.success(functionDescriptors.get(0));
|
||||
}
|
||||
return OverloadResolutionResult.ambiguity(functionDescriptors);
|
||||
}
|
||||
if (functionDescriptors.size() == 1) {
|
||||
return OverloadResolutionResult.singleFunctionArgumentMismatch(functionDescriptors.get(0));
|
||||
}
|
||||
return OverloadResolutionResult.ambiguity(functionDescriptors);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
// TODO: not implemented
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<FunctionDescriptor> getFunctionDescriptors() {
|
||||
// TODO: not implemented
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,11 @@ public class PropertyGetterDescriptor extends PropertyAccessorDescriptor {
|
||||
overriddenGetters.add(overriddenGetter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType getReceiverType() {
|
||||
return null; // TODO
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<ValueParameterDescriptor> getUnsubstitutedValueParameters() {
|
||||
|
||||
@@ -40,6 +40,11 @@ public class PropertySetterDescriptor extends PropertyAccessorDescriptor {
|
||||
overriddenSetters.add(overriddenSetter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType getReceiverType() {
|
||||
return null; // TODO
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<ValueParameterDescriptor> getUnsubstitutedValueParameters() {
|
||||
|
||||
@@ -24,6 +24,18 @@ public class JetFunction extends JetTypeParameterListOwner implements JetDeclara
|
||||
visitor.visitFunction(this);
|
||||
}
|
||||
|
||||
public boolean hasTypeParameterListBeforeFunctionName() {
|
||||
JetTypeParameterList typeParameterList = getTypeParameterList();
|
||||
if (typeParameterList == null) {
|
||||
return false;
|
||||
}
|
||||
PsiElement nameIdentifier = getNameIdentifier();
|
||||
if (nameIdentifier == null) {
|
||||
return false;
|
||||
}
|
||||
return nameIdentifier.getTextOffset() > typeParameterList.getTextOffset();
|
||||
}
|
||||
|
||||
@Nullable @IfNotParsed
|
||||
public JetParameterList getValueParameterList() {
|
||||
return (JetParameterList) findChildByType(JetNodeTypes.VALUE_PARAMETER_LIST);
|
||||
|
||||
@@ -174,8 +174,19 @@ public class ClassDescriptorResolver {
|
||||
WritableScope innerScope = new WritableScopeImpl(scope, functionDescriptor, trace.getErrorHandler());
|
||||
innerScope.addLabeledDeclaration(functionDescriptor);
|
||||
|
||||
// The two calls below have side-effects on parameterScope
|
||||
|
||||
List<TypeParameterDescriptor> typeParameterDescriptors = resolveTypeParameters(functionDescriptor, innerScope, function.getTypeParameters());
|
||||
|
||||
JetType receiverType = null;
|
||||
JetTypeReference receiverTypeRef = function.getReceiverTypeRef();
|
||||
if (receiverTypeRef != null) {
|
||||
JetScope scopeForReceiver =
|
||||
function.hasTypeParameterListBeforeFunctionName()
|
||||
? innerScope
|
||||
: scope;
|
||||
receiverType = typeResolver.resolveType(scopeForReceiver, receiverTypeRef);
|
||||
}
|
||||
|
||||
List<ValueParameterDescriptor> valueParameterDescriptors = resolveValueParameters(functionDescriptor, innerScope, function.getValueParameters());
|
||||
|
||||
JetTypeReference returnTypeRef = function.getReturnTypeRef();
|
||||
@@ -201,6 +212,7 @@ public class ClassDescriptorResolver {
|
||||
}
|
||||
|
||||
functionDescriptor.initialize(
|
||||
receiverType,
|
||||
typeParameterDescriptors,
|
||||
valueParameterDescriptors,
|
||||
returnType);
|
||||
|
||||
@@ -23,7 +23,7 @@ public class OverloadResolver {
|
||||
@NotNull
|
||||
public OverloadDomain getOverloadDomain(JetType receiverType, @NotNull JetScope outerScope, @NotNull String name) {
|
||||
// TODO : extension lookup
|
||||
JetScope scope = receiverType == null ? outerScope : receiverType.getMemberScope();
|
||||
JetScope scope = receiverType == null ? outerScope : new ScopeWithReceiver(outerScope, receiverType, typeChecker);
|
||||
|
||||
final FunctionGroup functionGroup = scope.getFunctionGroup(name);
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeChecker;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -11,16 +14,33 @@ public class ScopeWithReceiver extends JetScopeImpl {
|
||||
|
||||
private final JetScope receiverTypeScope;
|
||||
private final JetScope outerScope;
|
||||
private final JetTypeChecker typeChecker;
|
||||
|
||||
public ScopeWithReceiver(JetScope outerScope, JetType receiverType) {
|
||||
public ScopeWithReceiver(JetScope outerScope, JetType receiverType, JetTypeChecker typeChecker) {
|
||||
this.outerScope = outerScope;
|
||||
this.receiverTypeScope = receiverType.getMemberScope();
|
||||
this.typeChecker = typeChecker;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FunctionGroup getFunctionGroup(@NotNull String name) {
|
||||
return receiverTypeScope.getFunctionGroup(name); // TODO
|
||||
FunctionGroup functionGroup = receiverTypeScope.getFunctionGroup(name);
|
||||
if (functionGroup.isEmpty()) {
|
||||
return FunctionDescriptorUtil.filteredFunctionGroup(outerScope.getFunctionGroup(name),
|
||||
new Function<FunctionDescriptor, Boolean>() {
|
||||
@Override
|
||||
public Boolean apply(@Nullable FunctionDescriptor functionDescriptor) {
|
||||
if (functionDescriptor == null) return false;
|
||||
JetType functionReceiverType = functionDescriptor.getReceiverType();
|
||||
if (functionReceiverType == null) {
|
||||
return false;
|
||||
}
|
||||
return typeChecker.isSubtypeOf(receiverTypeScope.getThisType(), functionReceiverType);
|
||||
}
|
||||
});
|
||||
}
|
||||
return functionGroup; // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -249,6 +249,7 @@ public class JavaDescriptorResolver {
|
||||
methodName
|
||||
);
|
||||
functionDescriptor.initialize(
|
||||
null,
|
||||
resolveTypeParameters(method.getTypeParameters()),
|
||||
semanticServices.getDescriptorResolver().resolveParameterDescriptors(functionDescriptor, parameters),
|
||||
semanticServices.getTypeTransformer().transformToType(method.getReturnType())
|
||||
|
||||
@@ -105,6 +105,7 @@ public class ErrorUtils {
|
||||
private static FunctionDescriptor createErrorFunction(List<TypeParameterDescriptor> typeParameters, List<JetType> positionedValueArgumentTypes) {
|
||||
FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(ERROR_CLASS, Collections.<Annotation>emptyList(), "<ERROR FUNCTION>");
|
||||
return functionDescriptor.initialize(
|
||||
null,
|
||||
typeParameters,
|
||||
getValueParameters(functionDescriptor, positionedValueArgumentTypes),
|
||||
createErrorType("<ERROR FUNCTION RETURN>")
|
||||
@@ -117,6 +118,7 @@ public class ErrorUtils {
|
||||
|
||||
private static FunctionDescriptor createErrorFunction(int typeParameterCount, List<JetType> positionedValueParameterTypes) {
|
||||
return new FunctionDescriptorImpl(ERROR_CLASS, Collections.<Annotation>emptyList(), "<ERROR FUNCTION>").initialize(
|
||||
null,
|
||||
Collections.<TypeParameterDescriptor>emptyList(), // TODO
|
||||
Collections.<ValueParameterDescriptor>emptyList(), // TODO
|
||||
createErrorType("<ERROR FUNCTION RETURN TYPE>")
|
||||
|
||||
@@ -1002,7 +1002,7 @@ public class JetTypeInferrer {
|
||||
public void visitWhenConditionCall(JetWhenConditionCall condition) {
|
||||
checkNullSafety(finalSubjectType, condition.getOperationTokenNode());
|
||||
JetExpression callSuffixExpression = condition.getCallSuffixExpression();
|
||||
JetScope compositeScope = new ScopeWithReceiver(scope, finalSubjectType);
|
||||
JetScope compositeScope = new ScopeWithReceiver(scope, finalSubjectType, semanticServices.getTypeChecker());
|
||||
if (callSuffixExpression != null) {
|
||||
JetType selectorReturnType = getType(compositeScope, callSuffixExpression, false);
|
||||
ensureBooleanResultWithCustomSubject(callSuffixExpression, selectorReturnType, "This expression");
|
||||
@@ -1290,11 +1290,12 @@ public class JetTypeInferrer {
|
||||
|
||||
@Override
|
||||
public void visitQualifiedExpression(JetQualifiedExpression expression) {
|
||||
// TODO : functions
|
||||
// TODO : functions as values
|
||||
JetExpression selectorExpression = expression.getSelectorExpression();
|
||||
JetExpression receiverExpression = expression.getReceiverExpression();
|
||||
JetType receiverType = new TypeInferrerVisitorWithNamespaces(scope, false).getType(receiverExpression);
|
||||
if (receiverType != null) {
|
||||
// TODO : extensions to 'Any?'
|
||||
checkNullSafety(receiverType, expression.getOperationTokenNode());
|
||||
JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression);
|
||||
if (expression.getOperationSign() == JetTokens.QUEST) {
|
||||
@@ -1314,7 +1315,7 @@ public class JetTypeInferrer {
|
||||
}
|
||||
|
||||
private JetType getSelectorReturnType(JetType receiverType, JetExpression selectorExpression) {
|
||||
JetScope compositeScope = new ScopeWithReceiver(scope, receiverType);
|
||||
JetScope compositeScope = new ScopeWithReceiver(scope, receiverType, semanticServices.getTypeChecker());
|
||||
if (selectorExpression instanceof JetCallExpression) {
|
||||
JetCallExpression callExpression = (JetCallExpression) selectorExpression;
|
||||
OverloadDomain overloadDomain = getOverloadDomain(compositeScope, callExpression.getCalleeExpression(), callExpression.getValueArgumentList());
|
||||
|
||||
@@ -46,6 +46,17 @@ public class DescriptorRenderer {
|
||||
protected void renderName(DeclarationDescriptor descriptor, StringBuilder stringBuilder) {
|
||||
stringBuilder.append(descriptor.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitTypeParameterDescriptor(TypeParameterDescriptor descriptor, StringBuilder builder) {
|
||||
renderTypeParameter(descriptor, builder);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitValueParameterDescriptor(ValueParameterDescriptor descriptor, StringBuilder builder) {
|
||||
return super.visitVariableDescriptor(descriptor, builder);
|
||||
}
|
||||
};
|
||||
|
||||
private DescriptorRenderer() {}
|
||||
@@ -106,9 +117,18 @@ public class DescriptorRenderer {
|
||||
@Override
|
||||
public Void visitFunctionDescriptor(FunctionDescriptor descriptor, StringBuilder builder) {
|
||||
builder.append(renderKeyword("fun")).append(" ");
|
||||
renderName(descriptor, builder);
|
||||
List<TypeParameterDescriptor> typeParameters = descriptor.getTypeParameters();
|
||||
renderTypeParameters(typeParameters, builder);
|
||||
if (!typeParameters.isEmpty()) {
|
||||
builder.append(" ");
|
||||
}
|
||||
|
||||
JetType receiverType = descriptor.getReceiverType();
|
||||
if (receiverType != null) {
|
||||
builder.append(escape(receiverType.toString())).append(".");
|
||||
}
|
||||
|
||||
renderName(descriptor, builder);
|
||||
builder.append("(");
|
||||
for (Iterator<ValueParameterDescriptor> iterator = descriptor.getUnsubstitutedValueParameters().iterator(); iterator.hasNext(); ) {
|
||||
ValueParameterDescriptor parameterDescriptor = iterator.next();
|
||||
@@ -178,7 +198,7 @@ public class DescriptorRenderer {
|
||||
stringBuilder.append(escape(descriptor.getName()));
|
||||
}
|
||||
|
||||
private void renderTypeParameter(TypeParameterDescriptor descriptor, StringBuilder builder) {
|
||||
protected void renderTypeParameter(TypeParameterDescriptor descriptor, StringBuilder builder) {
|
||||
renderName(descriptor, builder);
|
||||
if (!descriptor.getUpperBounds().isEmpty()) {
|
||||
JetType bound = descriptor.getUpperBounds().iterator().next();
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
fun <~T~T, ~E~E> `T`T.foo(x : `E`E, y : `A`A) : `T`T {
|
||||
y.`+`plus(1)
|
||||
y `+`plus 1
|
||||
y `+1`+ 1.0
|
||||
|
||||
this?.`-`minus<T>(this)
|
||||
|
||||
this
|
||||
}
|
||||
|
||||
~A~class A
|
||||
|
||||
~+1~fun `A`A.plus(a : Any) {
|
||||
1
|
||||
}
|
||||
|
||||
~+~fun `A`A.plus(a : Int) {
|
||||
1
|
||||
}
|
||||
|
||||
~-~fun <T> T.minus(t : T) : Int = 1
|
||||
Reference in New Issue
Block a user