Call resolver refactored to store results in objects of ResolvedCall class
This commit is contained in:
+1
-1
@@ -132,7 +132,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
|
||||
TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(getTypeParameters(), originalSubstitutor, substitutedDescriptor, substitutedTypeParameters);
|
||||
|
||||
JetType substitutedReceiverType = null;
|
||||
if (receiver != NO_RECEIVER) {
|
||||
if (receiver.exists()) {
|
||||
substitutedReceiverType = substitutor.substitute(getReceiver().getType(), Variance.IN_VARIANCE);
|
||||
if (substitutedReceiverType == null) {
|
||||
return null;
|
||||
|
||||
+6
-5
@@ -1,7 +1,8 @@
|
||||
package org.jetbrains.jet.lang.diagnostics;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -9,7 +10,7 @@ import java.util.Collection;
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class AmbiguousDescriptorDiagnosticFactory extends ParameterizedDiagnosticFactory1<Collection<? extends CallableDescriptor>> {
|
||||
public class AmbiguousDescriptorDiagnosticFactory extends ParameterizedDiagnosticFactory1<Collection<? extends ResolvedCall<? extends DeclarationDescriptor>>> {
|
||||
public static AmbiguousDescriptorDiagnosticFactory create(String messageTemplate) {
|
||||
return new AmbiguousDescriptorDiagnosticFactory(messageTemplate);
|
||||
}
|
||||
@@ -19,10 +20,10 @@ public class AmbiguousDescriptorDiagnosticFactory extends ParameterizedDiagnosti
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String makeMessageFor(@NotNull Collection<? extends CallableDescriptor> argument) {
|
||||
protected String makeMessageFor(@NotNull Collection<? extends ResolvedCall<? extends DeclarationDescriptor>> argument) {
|
||||
StringBuilder stringBuilder = new StringBuilder("\n");
|
||||
for (CallableDescriptor descriptor : argument) {
|
||||
stringBuilder.append(DescriptorRenderer.TEXT.render(descriptor)).append("\n");
|
||||
for (ResolvedCall<? extends DeclarationDescriptor> call : argument) {
|
||||
stringBuilder.append(DescriptorRenderer.TEXT.render(call.getResultingDescriptor())).append("\n");
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lexer.JetKeywordToken;
|
||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||
@@ -352,8 +353,8 @@ public interface Errors {
|
||||
ParameterizedDiagnosticFactory3<String, JetType, JetType> RESULT_TYPE_MISMATCH = ParameterizedDiagnosticFactory3.create(ERROR, "{0} must return {1} but returns {2}");
|
||||
ParameterizedDiagnosticFactory3<String, String, String> UNSAFE_INFIX_CALL = ParameterizedDiagnosticFactory3.create(ERROR, "Infix call corresponds to a dot-qualified call ''{0}.{1}({2})' which is not allowed on a nullable receiver ''{0}''. Use '?.'-qualified call instead");
|
||||
|
||||
ParameterizedDiagnosticFactory1<Collection<? extends CallableDescriptor>> OVERLOAD_RESOLUTION_AMBIGUITY = new AmbiguousDescriptorDiagnosticFactory("Overload resolution ambiguity: {0}");
|
||||
ParameterizedDiagnosticFactory1<Collection<? extends CallableDescriptor>> NONE_APPLICABLE = new AmbiguousDescriptorDiagnosticFactory("None of the following functions can be called with the arguments supplied: {0}");
|
||||
AmbiguousDescriptorDiagnosticFactory OVERLOAD_RESOLUTION_AMBIGUITY = new AmbiguousDescriptorDiagnosticFactory("Overload resolution ambiguity: {0}");
|
||||
AmbiguousDescriptorDiagnosticFactory NONE_APPLICABLE = new AmbiguousDescriptorDiagnosticFactory("None of the following functions can be called with the arguments supplied: {0}");
|
||||
ParameterizedDiagnosticFactory1<ValueParameterDescriptor> NO_VALUE_FOR_PARAMETER = ParameterizedDiagnosticFactory1.create(ERROR, "No value passed for parameter {0}", DescriptorRenderer.TEXT);
|
||||
ParameterizedDiagnosticFactory1<JetType> MISSING_RECEIVER = ParameterizedDiagnosticFactory1.create(ERROR, "A receiver of type {0} is required");
|
||||
SimpleDiagnosticFactory NO_RECEIVER_ADMITTED = SimpleDiagnosticFactory.create(ERROR, "No receiver can be passed to this function or property");
|
||||
|
||||
@@ -9,9 +9,11 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetAnnotationEntry;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetModifierList;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallResolver;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.DataFlowInfo;
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeInferrer;
|
||||
@@ -27,11 +29,15 @@ import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
|
||||
public class AnnotationResolver {
|
||||
|
||||
private final BindingTrace trace;
|
||||
private final JetTypeInferrer typeInferrer;
|
||||
// private final JetTypeInferrer typeInferrer;
|
||||
private final CallResolver callResolver;
|
||||
// private final JetTypeInferrer.Services services;
|
||||
|
||||
public AnnotationResolver(JetSemanticServices semanticServices, BindingTrace trace) {
|
||||
this.typeInferrer = new JetTypeInferrer(JetFlowInformationProvider.THROW_EXCEPTION, semanticServices);
|
||||
this.trace = trace;
|
||||
// this.typeInferrer = new JetTypeInferrer(JetFlowInformationProvider.THROW_EXCEPTION, semanticServices);
|
||||
// this.services = typeInferrer.getServices(this.trace);
|
||||
this.callResolver = new CallResolver(semanticServices, new JetTypeInferrer(JetFlowInformationProvider.THROW_EXCEPTION, semanticServices), DataFlowInfo.getEmpty());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -47,7 +53,7 @@ public class AnnotationResolver {
|
||||
}
|
||||
|
||||
public void resolveAnnotationStub(@NotNull JetScope scope, @NotNull JetAnnotationEntry entryElement, @NotNull AnnotationDescriptor descriptor) {
|
||||
JetType jetType = typeInferrer.getCallResolver().resolveCall(trace, scope, ReceiverDescriptor.NO_RECEIVER, entryElement, NO_EXPECTED_TYPE);
|
||||
JetType jetType = callResolver.resolveCall(trace, scope, ReceiverDescriptor.NO_RECEIVER, entryElement, NO_EXPECTED_TYPE);
|
||||
descriptor.setAnnotationType(jetType == null ? ErrorUtils.createErrorType("Unresolved annotation type") : jetType);
|
||||
}
|
||||
|
||||
@@ -112,4 +118,4 @@ public class AnnotationResolver {
|
||||
}
|
||||
return createAnnotationStubs(modifierList.getAnnotationEntries());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
@@ -28,7 +29,7 @@ public interface BindingContext {
|
||||
WritableSlice<JetExpression, JetType> EXPRESSION_TYPE = new BasicWritableSlice<JetExpression, JetType>("EXPRESSION_TYPE", RewritePolicy.DO_NOTHING);
|
||||
|
||||
WritableSlice<JetReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET = new BasicWritableSlice<JetReferenceExpression, DeclarationDescriptor>("REFERENCE_TARGET", RewritePolicy.DO_NOTHING);
|
||||
WritableSlice<JetReferenceExpression, Collection<? extends DeclarationDescriptor>> AMBIGUOUS_REFERENCE_TARGET = new BasicWritableSlice<JetReferenceExpression, Collection<? extends DeclarationDescriptor>>("AMBIGUOUS_REFERENCE_TARGET", RewritePolicy.DO_NOTHING);
|
||||
WritableSlice<JetReferenceExpression, Collection<? extends ResolvedCall<? extends DeclarationDescriptor>>> AMBIGUOUS_REFERENCE_TARGET = new BasicWritableSlice<JetReferenceExpression, Collection<? extends ResolvedCall<? extends DeclarationDescriptor>>>("AMBIGUOUS_REFERENCE_TARGET", RewritePolicy.DO_NOTHING);
|
||||
|
||||
WritableSlice<JetExpression, FunctionDescriptor> LOOP_RANGE_ITERATOR = Slices.createSimpleSlice("LOOP_RANGE_ITERATOR");
|
||||
WritableSlice<JetExpression, CallableDescriptor> LOOP_RANGE_HAS_NEXT = Slices.createSimpleSlice("LOOP_RANGE_HAS_NEXT");
|
||||
|
||||
@@ -334,7 +334,7 @@ public class BodyResolver {
|
||||
public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) {
|
||||
JetTypeReference typeReference = call.getTypeReference();
|
||||
if (typeReference != null) {
|
||||
typeInferrerForInitializers.getCallResolver().resolveCall(context.getTrace(), functionInnerScope, null, call, NO_EXPECTED_TYPE);
|
||||
typeInferrerForInitializers.getCallResolver().resolveCall(context.getTrace(), functionInnerScope, ReceiverDescriptor.NO_RECEIVER, call, NO_EXPECTED_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.util.Function;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
@@ -37,24 +38,31 @@ public class OverridingUtil {
|
||||
}
|
||||
|
||||
public static <D extends CallableDescriptor> Set<D> filterOverrides(Set<D> candidateSet) {
|
||||
return filterOverrides(candidateSet, Function.ID);
|
||||
}
|
||||
|
||||
public static <D> Set<D> filterOverrides(Set<D> candidateSet, Function<? super D, ? extends CallableDescriptor> transform) {
|
||||
Set<D> candidates = Sets.newLinkedHashSet();
|
||||
outerLoop:
|
||||
for (D me : candidateSet) {
|
||||
for (D other : candidateSet) {
|
||||
for (D meD : candidateSet) {
|
||||
CallableDescriptor me = transform.fun(meD);
|
||||
for (D otherD : candidateSet) {
|
||||
CallableDescriptor other = transform.fun(otherD);
|
||||
if (me == other) continue;
|
||||
if (overrides(other, me)) {
|
||||
continue outerLoop;
|
||||
}
|
||||
}
|
||||
for (D other : candidates) {
|
||||
for (D otherD : candidates) {
|
||||
CallableDescriptor other = transform.fun(otherD);
|
||||
if (me.getOriginal() == other.getOriginal()
|
||||
&& isOverridableBy(other, me).isSuccess()
|
||||
&& isOverridableBy(me, other).isSuccess()) {
|
||||
&& isOverridableBy(other, me).isSuccess()
|
||||
&& isOverridableBy(me, other).isSuccess()) {
|
||||
continue outerLoop;
|
||||
}
|
||||
}
|
||||
// System.out.println(me);
|
||||
candidates.add(me);
|
||||
candidates.add(meD);
|
||||
}
|
||||
// Set<D> candidates = Sets.newLinkedHashSet(candidateSet);
|
||||
// for (D descriptor : candidateSet) {
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
package org.jetbrains.jet.lang.resolve.calls;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.JetBinaryExpressionWithTypeRHS;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetThisExpression;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.*;
|
||||
import org.jetbrains.jet.lang.types.DataFlowInfo;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class AutoCastUtils {
|
||||
|
||||
private AutoCastUtils() {}
|
||||
|
||||
public static List<? extends ReceiverDescriptor> getAutocastVariants(@NotNull final BindingContext bindingContext, @NotNull final DataFlowInfo dataFlowInfo, @NotNull ReceiverDescriptor receiverToCast) {
|
||||
return receiverToCast.accept(new ReceiverDescriptorVisitor<List<? extends ReceiverDescriptor>, Object>() {
|
||||
@Override
|
||||
public List<? extends ReceiverDescriptor> visitNoReceiver(ReceiverDescriptor noReceiver, Object data) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends ReceiverDescriptor> visitTransientReceiver(TransientReceiver receiver, Object data) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends ReceiverDescriptor> visitExtensionReceiver(ExtensionReceiver receiver, Object data) {
|
||||
return castThis(dataFlowInfo, receiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends ReceiverDescriptor> visitClassReceiver(ClassReceiver receiver, Object data) {
|
||||
return castThis(dataFlowInfo, receiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends ReceiverDescriptor> visitExpressionReceiver(ExpressionReceiver receiver, Object data) {
|
||||
JetExpression expression = receiver.getExpression();
|
||||
VariableDescriptor variableDescriptor = getVariableDescriptorFromSimpleName(bindingContext, expression);
|
||||
if (variableDescriptor != null && isAutocastable(variableDescriptor)) {
|
||||
List<ReceiverDescriptor> result = Lists.newArrayList();
|
||||
for (JetType possibleType : dataFlowInfo.getPossibleTypesForVariable(variableDescriptor)) {
|
||||
result.add(new AutocastReceiver(receiver, possibleType));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else if (expression instanceof JetThisExpression) {
|
||||
return castThis(dataFlowInfo, receiver);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
|
||||
private static List<? extends ReceiverDescriptor> castThis(@NotNull DataFlowInfo dataFlowInfo, @NotNull ReceiverDescriptor receiver) {
|
||||
assert receiver.exists();
|
||||
List<ReceiverDescriptor> result = Lists.newArrayList();
|
||||
for (JetType possibleType : dataFlowInfo.getPossibleTypesForReceiver(receiver)) {
|
||||
result.add(new AutocastReceiver(receiver, possibleType));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static VariableDescriptor getVariableDescriptorFromSimpleName(@NotNull BindingContext bindingContext, @NotNull JetExpression receiverExpression) {
|
||||
if (receiverExpression instanceof JetBinaryExpressionWithTypeRHS) {
|
||||
JetBinaryExpressionWithTypeRHS expression = (JetBinaryExpressionWithTypeRHS) receiverExpression;
|
||||
if (expression.getOperationSign().getReferencedNameElementType() == JetTokens.COLON) {
|
||||
return getVariableDescriptorFromSimpleName(bindingContext, expression.getLeft());
|
||||
}
|
||||
}
|
||||
VariableDescriptor variableDescriptor = null;
|
||||
if (receiverExpression instanceof JetSimpleNameExpression) {
|
||||
JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) receiverExpression;
|
||||
DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, nameExpression);
|
||||
if (declarationDescriptor instanceof VariableDescriptor) {
|
||||
variableDescriptor = (VariableDescriptor) declarationDescriptor;
|
||||
}
|
||||
}
|
||||
return variableDescriptor;
|
||||
}
|
||||
|
||||
public static boolean isAutocastable(@NotNull VariableDescriptor variableDescriptor) {
|
||||
if (variableDescriptor.isVar()) return false;
|
||||
if (variableDescriptor instanceof PropertyDescriptor) {
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variableDescriptor;
|
||||
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
||||
if (containingDeclaration instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
|
||||
if (classDescriptor.getModality().isOverridable() && propertyDescriptor.getModality().isOverridable()) return false;
|
||||
}
|
||||
else {
|
||||
assert !propertyDescriptor.getModality().isOverridable() : "Property outside a class must not be overridable";
|
||||
}
|
||||
PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
|
||||
if (getter == null || !getter.isDefault()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.jetbrains.jet.lang.resolve.calls;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.AbstractReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptorVisitor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class AutocastReceiver extends AbstractReceiverDescriptor {
|
||||
private final ReceiverDescriptor original;
|
||||
|
||||
public AutocastReceiver(@NotNull ReceiverDescriptor original, @NotNull JetType castTo) {
|
||||
super(castTo);
|
||||
this.original = original;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ReceiverDescriptor getOriginal() {
|
||||
return original;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, D> R accept(@NotNull ReceiverDescriptorVisitor<R, D> visitor, D data) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.*;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.inference.ConstraintSystem;
|
||||
@@ -21,9 +22,9 @@ import org.jetbrains.jet.lang.types.inference.ConstraintSystem;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.RECEIVER;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCall.MAP_TO_CANDIDATE;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCall.MAP_TO_RESULT;
|
||||
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
|
||||
import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
|
||||
|
||||
@@ -35,11 +36,13 @@ public class CallResolver {
|
||||
private final JetTypeInferrer typeInferrer;
|
||||
private final JetSemanticServices semanticServices;
|
||||
private final OverloadingConflictResolver overloadingConflictResolver;
|
||||
private final DataFlowInfo dataFlowInfo;
|
||||
|
||||
public CallResolver(JetSemanticServices semanticServices, JetTypeInferrer typeInferrer) {
|
||||
public CallResolver(JetSemanticServices semanticServices, JetTypeInferrer typeInferrer, DataFlowInfo dataFlowInfo) {
|
||||
this.typeInferrer = typeInferrer;
|
||||
this.semanticServices = semanticServices;
|
||||
this.overloadingConflictResolver = new OverloadingConflictResolver(semanticServices);
|
||||
this.dataFlowInfo = dataFlowInfo;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -54,7 +57,7 @@ public class CallResolver {
|
||||
return null;
|
||||
}
|
||||
Call call = CallMaker.makePropertyCall(nameExpression);
|
||||
List<ResolutionTask<VariableDescriptor>> prioritizedTasks = PROPERTY_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiver, call, referencedName);
|
||||
List<ResolutionTask<VariableDescriptor>> prioritizedTasks = TaskPrioritizers.PROPERTY_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiver, call, referencedName, trace.getBindingContext(), dataFlowInfo);
|
||||
return resolveCallToDescriptor(trace, scope, call, nameExpression.getNode(), expectedType, prioritizedTasks, nameExpression);
|
||||
}
|
||||
|
||||
@@ -80,9 +83,7 @@ public class CallResolver {
|
||||
@NotNull String name,
|
||||
@NotNull ReceiverDescriptor receiver,
|
||||
@NotNull JetType expectedType) {
|
||||
// TODO : autocasts
|
||||
// TODO : nullability
|
||||
List<ResolutionTask<FunctionDescriptor>> tasks = FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiver, call, name);
|
||||
List<ResolutionTask<FunctionDescriptor>> tasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiver, call, name, trace.getBindingContext(), dataFlowInfo);
|
||||
return resolveCallToDescriptor(trace, scope, call, functionReference.getNode(), expectedType, tasks, functionReference);
|
||||
}
|
||||
|
||||
@@ -105,7 +106,7 @@ public class CallResolver {
|
||||
String name = expression.getReferencedName();
|
||||
if (name == null) return checkArgumentTypesAndFail(trace, scope, call);
|
||||
|
||||
prioritizedTasks = FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiver, call, name);
|
||||
prioritizedTasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiver, call, name, trace.getBindingContext(), dataFlowInfo);
|
||||
ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() {
|
||||
@Override
|
||||
public <D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) {
|
||||
@@ -128,7 +129,7 @@ public class CallResolver {
|
||||
JetValueArgumentList valueArgumentList = call.getValueArgumentList();
|
||||
ASTNode reportAbsenceOn = valueArgumentList == null ? call.getNode() : valueArgumentList.getNode();
|
||||
if (calleeExpression instanceof JetConstructorCalleeExpression) {
|
||||
assert receiver == NO_RECEIVER;
|
||||
assert !receiver.exists();
|
||||
|
||||
prioritizedTasks = Lists.newArrayList();
|
||||
|
||||
@@ -149,7 +150,7 @@ public class CallResolver {
|
||||
trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
|
||||
return checkArgumentTypesAndFail(trace, scope, call);
|
||||
}
|
||||
prioritizedTasks.add(new ResolutionTask<FunctionDescriptor>(constructors, NO_RECEIVER, call));
|
||||
prioritizedTasks.add(new ResolutionTask<FunctionDescriptor>(ResolvedCall.convertCollection(constructors), NO_RECEIVER, call));
|
||||
}
|
||||
else {
|
||||
// trace.getErrorHandler().genericError(calleeExpression.getNode(), "Not a class");
|
||||
@@ -163,14 +164,13 @@ public class CallResolver {
|
||||
assert containingDeclaration instanceof ClassDescriptor;
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
|
||||
|
||||
|
||||
Set<FunctionDescriptor> constructors = classDescriptor.getConstructors();
|
||||
if (constructors.isEmpty()) {
|
||||
// trace.getErrorHandler().genericError(reportAbsenceOn, "This class does not have a constructor");
|
||||
trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
|
||||
return checkArgumentTypesAndFail(trace, scope, call);
|
||||
}
|
||||
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(constructors, NO_RECEIVER, call));
|
||||
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(ResolvedCall.convertCollection(constructors), NO_RECEIVER, call));
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("Type argument inference not implemented for " + call.getText());
|
||||
@@ -185,6 +185,7 @@ public class CallResolver {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private <D extends CallableDescriptor> D resolveCallToDescriptor(
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull JetScope scope,
|
||||
@@ -193,17 +194,38 @@ public class CallResolver {
|
||||
@NotNull JetType expectedType,
|
||||
@NotNull final List<ResolutionTask<D>> prioritizedTasks, // high to low priority
|
||||
@NotNull final JetReferenceExpression reference) {
|
||||
ResolvedCall<D> resolvedCall = doResolveCall(trace, scope, call, callNode, expectedType, prioritizedTasks, reference);
|
||||
return resolvedCall == null ? null : resolvedCall.getResultingDescriptor();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private <D extends CallableDescriptor> ResolvedCall<D> doResolveCall(
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull JetScope scope,
|
||||
@NotNull final Call call,
|
||||
@NotNull final ASTNode callNode,
|
||||
@NotNull JetType expectedType,
|
||||
@NotNull final List<ResolutionTask<D>> prioritizedTasks, // high to low priority
|
||||
@NotNull final JetReferenceExpression reference) {
|
||||
TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
|
||||
OverloadResolutionResult<D> resultForFirstNonemptyCandidateSet = null;
|
||||
OverloadResolutionResults<D> resultsForFirstNonemptyCandidateSet = null;
|
||||
TracingStrategy tracing = new TracingStrategy() {
|
||||
@Override
|
||||
public void bindReference(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor receiver, @NotNull CallableDescriptor descriptor) {
|
||||
trace.record(REFERENCE_TARGET, reference, descriptor);
|
||||
trace.record(RECEIVER, reference, receiver);
|
||||
if (receiver instanceof AutocastReceiver) {
|
||||
AutocastReceiver autoCastReceiver = (AutocastReceiver) receiver;
|
||||
ReceiverDescriptor original = autoCastReceiver.getOriginal();
|
||||
if (original instanceof ExpressionReceiver) {
|
||||
ExpressionReceiver expressionReceiver = (ExpressionReceiver) original;
|
||||
trace.record(AUTOCAST, expressionReceiver.getExpression(), autoCastReceiver.getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<D> candidates) {
|
||||
public <D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<ResolvedCall<D>> candidates) {
|
||||
trace.record(AMBIGUOUS_REFERENCE_TARGET, reference, candidates);
|
||||
}
|
||||
|
||||
@@ -254,12 +276,12 @@ public class CallResolver {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ambiguity(@NotNull BindingTrace trace, @NotNull Set<? extends CallableDescriptor> descriptors) {
|
||||
public <D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Set<ResolvedCall<D>> descriptors) {
|
||||
trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(callNode, descriptors));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void noneApplicable(@NotNull BindingTrace trace, @NotNull Set<? extends CallableDescriptor> descriptors) {
|
||||
public <D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Set<ResolvedCall<D>> descriptors) {
|
||||
trace.report(NONE_APPLICABLE.on(callNode, descriptors));
|
||||
}
|
||||
|
||||
@@ -276,20 +298,20 @@ public class CallResolver {
|
||||
};
|
||||
for (ResolutionTask<D> task : prioritizedTasks) {
|
||||
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace);
|
||||
OverloadResolutionResult<D> result = performResolution(temporaryTrace, scope, expectedType, task, tracing);
|
||||
if (result.isSuccess()) {
|
||||
OverloadResolutionResults<D> results = performResolution(temporaryTrace, scope, expectedType, task, tracing);
|
||||
if (results.isSuccess()) {
|
||||
temporaryTrace.commit();
|
||||
return result.getDescriptor();
|
||||
return results.getResult();
|
||||
}
|
||||
if (traceForFirstNonemptyCandidateSet == null && !task.getCandidates().isEmpty()) {
|
||||
traceForFirstNonemptyCandidateSet = temporaryTrace;
|
||||
resultForFirstNonemptyCandidateSet = result;
|
||||
resultsForFirstNonemptyCandidateSet = results;
|
||||
}
|
||||
}
|
||||
if (traceForFirstNonemptyCandidateSet != null) {
|
||||
traceForFirstNonemptyCandidateSet.commit();
|
||||
if (resultForFirstNonemptyCandidateSet.singleDescriptor()) {
|
||||
return resultForFirstNonemptyCandidateSet.getDescriptor();
|
||||
if (resultsForFirstNonemptyCandidateSet.singleDescriptor()) {
|
||||
return resultsForFirstNonemptyCandidateSet.getResult();
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -302,45 +324,43 @@ public class CallResolver {
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@NotNull
|
||||
private <D extends CallableDescriptor> OverloadResolutionResult<D> performResolution(@NotNull BindingTrace trace, @NotNull JetScope scope, @NotNull JetType expectedType, @NotNull ResolutionTask<D> task, @NotNull TracingStrategy tracing) {
|
||||
Map<D, D> successfulCandidates = Maps.newLinkedHashMap();
|
||||
Set<D> failedCandidates = Sets.newLinkedHashSet();
|
||||
Set<D> dirtyCandidates = Sets.newLinkedHashSet();
|
||||
// Map<D, ConstraintSystem.Solution> solutions = Maps.newHashMap();
|
||||
Map<D, TemporaryBindingTrace> traces = Maps.newHashMap();
|
||||
private <D extends CallableDescriptor> OverloadResolutionResults<D> performResolution(@NotNull BindingTrace trace, @NotNull JetScope scope, @NotNull JetType expectedType, @NotNull ResolutionTask<D> task, @NotNull TracingStrategy tracing) {
|
||||
Set<ResolvedCall<D>> successfulCandidates = Sets.newLinkedHashSet();
|
||||
Set<ResolvedCall<D>> failedCandidates = Sets.newLinkedHashSet();
|
||||
Set<ResolvedCall<D>> dirtyCandidates = Sets.newLinkedHashSet();
|
||||
|
||||
for (D candidate : task.getCandidates()) {
|
||||
for (ResolvedCall<D> candidateCall : task.getCandidates()) {
|
||||
D candidate = candidateCall.getCandidateDescriptor();
|
||||
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace);
|
||||
traces.put(candidate, temporaryTrace);
|
||||
JetTypeInferrer.Services temporaryServices = typeInferrer.getServices(temporaryTrace);
|
||||
candidateCall.setTrace(temporaryTrace);
|
||||
|
||||
tracing.bindReference(temporaryTrace, task.getReceiver(), candidate);
|
||||
|
||||
if (ErrorUtils.isError(candidate)) {
|
||||
successfulCandidates.put(candidate, candidate);
|
||||
successfulCandidates.add(candidateCall.setResultingDescriptor(candidate));
|
||||
checkTypesWithNoCallee(temporaryTrace, scope, task.getTypeArguments(), task.getValueArguments(), task.getFunctionLiteralArguments());
|
||||
continue;
|
||||
}
|
||||
|
||||
Ref<Boolean> dirty = new Ref<Boolean>(false);
|
||||
|
||||
Map<ValueArgument, ValueParameterDescriptor> argumentsToParameters = Maps.newHashMap();
|
||||
boolean error = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(task, tracing, candidate, temporaryTrace, argumentsToParameters);
|
||||
|
||||
if (error) {
|
||||
failedCandidates.add(candidate);
|
||||
failedCandidates.add(candidateCall);
|
||||
checkTypesWithNoCallee(temporaryTrace, scope, task.getTypeArguments(), task.getValueArguments(), task.getFunctionLiteralArguments());
|
||||
continue;
|
||||
}
|
||||
|
||||
Ref<Boolean> dirty = new Ref<Boolean>(false);
|
||||
if (task.getTypeArguments().isEmpty()) {
|
||||
if (candidate.getTypeParameters().isEmpty()) {
|
||||
if (checkValueArgumentTypes(scope, temporaryServices, argumentsToParameters, dirty, Functions.<ValueParameterDescriptor>identity())
|
||||
if (checkValueArgumentTypes(scope, temporaryTrace, argumentsToParameters, dirty, Functions.<ValueParameterDescriptor>identity())
|
||||
&& checkReceiver(task, tracing, candidate, temporaryTrace)) {
|
||||
successfulCandidates.put(candidate, candidate);
|
||||
successfulCandidates.add(candidateCall.setResultingDescriptor(candidate));
|
||||
}
|
||||
else {
|
||||
failedCandidates.add(candidate);
|
||||
failedCandidates.add(candidateCall);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -357,6 +377,7 @@ public class CallResolver {
|
||||
|
||||
JetExpression expression = valueArgument.getArgumentExpression();
|
||||
// TODO : more attempts, with different expected types
|
||||
JetTypeInferrer.Services temporaryServices = typeInferrer.getServices(temporaryTrace);
|
||||
JetType type = temporaryServices.getType(scope, expression, NO_EXPECTED_TYPE);
|
||||
if (type != null) {
|
||||
constraintSystem.addSubtypingConstraint(type, valueParameterDescriptor.getOutType());
|
||||
@@ -370,7 +391,7 @@ public class CallResolver {
|
||||
// Error is already reported if something is missing
|
||||
ReceiverDescriptor receiver = task.getReceiver();
|
||||
ReceiverDescriptor candidateReceiver = candidate.getReceiver();
|
||||
if (receiver != NO_RECEIVER && candidateReceiver != NO_RECEIVER) {
|
||||
if (receiver.exists() && candidateReceiver.exists()) {
|
||||
constraintSystem.addSubtypingConstraint(receiver.getType(), candidateReceiver.getType());
|
||||
}
|
||||
|
||||
@@ -383,11 +404,11 @@ public class CallResolver {
|
||||
if (solution.isSuccessful()) {
|
||||
D substitute = (D) candidate.substitute(solution.getSubstitutor());
|
||||
assert substitute != null;
|
||||
successfulCandidates.put(candidate, substitute);
|
||||
successfulCandidates.add(candidateCall.setResultingDescriptor(substitute));
|
||||
}
|
||||
else {
|
||||
tracing.typeInferenceFailed(temporaryTrace);
|
||||
failedCandidates.add(candidate);
|
||||
failedCandidates.add(candidateCall);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -420,32 +441,32 @@ public class CallResolver {
|
||||
D substitutedFunctionDescriptor = (D) candidate.substitute(TypeSubstitutor.create(substitutionContext));
|
||||
|
||||
Function<ValueParameterDescriptor, ValueParameterDescriptor> mapFunction = createMapFunction(substitutedFunctionDescriptor);
|
||||
if (checkValueArgumentTypes(scope, temporaryServices, argumentsToParameters, dirty, mapFunction)
|
||||
if (checkValueArgumentTypes(scope, temporaryTrace, argumentsToParameters, dirty, mapFunction)
|
||||
&& checkReceiver(task, tracing, substitutedFunctionDescriptor, temporaryTrace)) {
|
||||
successfulCandidates.put(candidate, substitutedFunctionDescriptor);
|
||||
successfulCandidates.add(candidateCall.setResultingDescriptor(substitutedFunctionDescriptor));
|
||||
}
|
||||
else {
|
||||
failedCandidates.add(candidate);
|
||||
failedCandidates.add(candidateCall);
|
||||
}
|
||||
}
|
||||
else {
|
||||
failedCandidates.add(candidate);
|
||||
failedCandidates.add(candidateCall);
|
||||
// tracing.reportWrongTypeArguments(temporaryTrace, "Number of type arguments does not match " + DescriptorRenderer.TEXT.render(candidate));
|
||||
tracing.wrongNumberOfTypeArguments(temporaryTrace, expectedTypeArgumentCount);
|
||||
}
|
||||
}
|
||||
|
||||
if (dirty.get()) {
|
||||
dirtyCandidates.add(candidate);
|
||||
dirtyCandidates.add(candidateCall);
|
||||
}
|
||||
task.performAdvancedChecks(candidate, temporaryTrace, tracing);
|
||||
}
|
||||
|
||||
OverloadResolutionResult<D> result = computeResultAndReportErrors(trace, tracing, successfulCandidates, failedCandidates, dirtyCandidates, traces);
|
||||
if (!result.singleDescriptor()) {
|
||||
OverloadResolutionResults<D> results = computeResultAndReportErrors(trace, tracing, successfulCandidates, failedCandidates, dirtyCandidates);
|
||||
if (!results.singleDescriptor()) {
|
||||
checkTypesWithNoCallee(trace, scope, task.getTypeArguments(), task.getValueArguments(), task.getFunctionLiteralArguments());
|
||||
}
|
||||
return result;
|
||||
return results;
|
||||
}
|
||||
|
||||
private void checkTypesWithNoCallee(BindingTrace trace, JetScope scope, List<JetTypeProjection> typeArguments, List<? extends ValueArgument> valueArguments, List<JetExpression> functionLiteralArguments) {
|
||||
@@ -484,8 +505,8 @@ public class CallResolver {
|
||||
if (!checkReceiverAbsence(task, tracing, candidate, temporaryTrace)) return false;
|
||||
ReceiverDescriptor receiver = task.getReceiver();
|
||||
ReceiverDescriptor candidateReceiver = candidate.getReceiver();
|
||||
if (receiver != NO_RECEIVER
|
||||
&& candidateReceiver != NO_RECEIVER
|
||||
if (receiver.exists()
|
||||
&& candidateReceiver.exists()
|
||||
&& !semanticServices.getTypeChecker().isSubtypeOf(receiver.getType(), candidateReceiver.getType())) {
|
||||
tracing.missingReceiver(temporaryTrace, candidateReceiver);
|
||||
return false;
|
||||
@@ -496,13 +517,13 @@ public class CallResolver {
|
||||
private <D extends CallableDescriptor> boolean checkReceiverAbsence(ResolutionTask<D> task, TracingStrategy tracing, D candidate, TemporaryBindingTrace temporaryTrace) {
|
||||
ReceiverDescriptor receiver = task.getReceiver();
|
||||
ReceiverDescriptor candidateReceiver = candidate.getReceiver();
|
||||
if (receiver != NO_RECEIVER) {
|
||||
if (candidateReceiver == NO_RECEIVER) {
|
||||
if (receiver.exists()) {
|
||||
if (!candidateReceiver.exists()) {
|
||||
tracing.noReceiverAllowed(temporaryTrace);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (candidateReceiver != NO_RECEIVER) {
|
||||
else if (candidateReceiver.exists()) {
|
||||
tracing.missingReceiver(temporaryTrace, candidateReceiver);
|
||||
return false;
|
||||
}
|
||||
@@ -510,26 +531,31 @@ public class CallResolver {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private <D extends CallableDescriptor> OverloadResolutionResult<D> computeResultAndReportErrors(BindingTrace trace, TracingStrategy tracing, Map<D, D> successfulCandidates, Set<D> failedCandidates, Set<D> dirtyCandidates, Map<D, TemporaryBindingTrace> traces) {
|
||||
private <D extends CallableDescriptor> OverloadResolutionResults<D> computeResultAndReportErrors(
|
||||
BindingTrace trace,
|
||||
TracingStrategy tracing,
|
||||
Set<ResolvedCall<D>> successfulCandidates, // original -> substituted
|
||||
Set<ResolvedCall<D>> failedCandidates,
|
||||
Set<ResolvedCall<D>> dirtyCandidates) {
|
||||
// TODO : maybe it's better to filter overrides out first, and only then look for the maximally specific
|
||||
if (successfulCandidates.size() > 0) {
|
||||
if (successfulCandidates.size() != 1) {
|
||||
Map<D, D> cleanCandidates = Maps.newLinkedHashMap(successfulCandidates);
|
||||
cleanCandidates.keySet().removeAll(dirtyCandidates);
|
||||
Set<ResolvedCall<D>> cleanCandidates = Sets.newLinkedHashSet(successfulCandidates);
|
||||
cleanCandidates.removeAll(dirtyCandidates);
|
||||
if (cleanCandidates.isEmpty()) {
|
||||
cleanCandidates = successfulCandidates;
|
||||
}
|
||||
D maximallySpecific = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, traces, false);
|
||||
ResolvedCall<D> maximallySpecific = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, false);
|
||||
if (maximallySpecific != null) {
|
||||
return OverloadResolutionResult.success(maximallySpecific);
|
||||
return OverloadResolutionResults.success(maximallySpecific);
|
||||
}
|
||||
|
||||
D maximallySpecificGenericsDiscriminated = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, traces, true);
|
||||
ResolvedCall<D> maximallySpecificGenericsDiscriminated = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, true);
|
||||
if (maximallySpecificGenericsDiscriminated != null) {
|
||||
return OverloadResolutionResult.success(maximallySpecificGenericsDiscriminated);
|
||||
return OverloadResolutionResults.success(maximallySpecificGenericsDiscriminated);
|
||||
}
|
||||
|
||||
Set<D> noOverrides = OverridingUtil.filterOverrides(successfulCandidates.keySet());
|
||||
Set<ResolvedCall<D>> noOverrides = OverridingUtil.filterOverrides(successfulCandidates, MAP_TO_RESULT);
|
||||
if (dirtyCandidates.isEmpty()) {
|
||||
// tracing.reportOverallResolutionError(trace, "Overload resolution ambiguity: "
|
||||
// + makeErrorMessageForMultipleDescriptors(noOverrides));
|
||||
@@ -538,42 +564,44 @@ public class CallResolver {
|
||||
|
||||
tracing.recordAmbiguity(trace, noOverrides);
|
||||
|
||||
return OverloadResolutionResult.ambiguity(noOverrides);
|
||||
return OverloadResolutionResults.ambiguity(noOverrides);
|
||||
}
|
||||
else {
|
||||
Map.Entry<D, D> entry = successfulCandidates.entrySet().iterator().next();
|
||||
D functionDescriptor = entry.getKey();
|
||||
D result = entry.getValue();
|
||||
ResolvedCall<D> result = successfulCandidates.iterator().next();
|
||||
|
||||
TemporaryBindingTrace temporaryTrace = traces.get(functionDescriptor);
|
||||
TemporaryBindingTrace temporaryTrace = result.getTrace();
|
||||
temporaryTrace.commit();
|
||||
return OverloadResolutionResult.success(result);
|
||||
return OverloadResolutionResults.success(result);
|
||||
}
|
||||
}
|
||||
else if (!failedCandidates.isEmpty()) {
|
||||
if (failedCandidates.size() != 1) {
|
||||
Set<D> noOverrides = OverridingUtil.filterOverrides(failedCandidates);
|
||||
Set<ResolvedCall<D>> noOverrides = OverridingUtil.filterOverrides(failedCandidates, MAP_TO_CANDIDATE);
|
||||
if (noOverrides.size() != 1) {
|
||||
// tracing.reportOverallResolutionError(trace, "None of the following functions can be called with the arguments supplied: "
|
||||
// + makeErrorMessageForMultipleDescriptors(noOverrides));
|
||||
tracing.noneApplicable(trace, noOverrides);
|
||||
tracing.recordAmbiguity(trace, noOverrides);
|
||||
return OverloadResolutionResult.manyFailedCandidates(noOverrides);
|
||||
return OverloadResolutionResults.manyFailedCandidates(noOverrides);
|
||||
}
|
||||
failedCandidates = noOverrides;
|
||||
}
|
||||
D functionDescriptor = failedCandidates.iterator().next();
|
||||
TemporaryBindingTrace temporaryTrace = traces.get(functionDescriptor);
|
||||
temporaryTrace.commit();
|
||||
return OverloadResolutionResult.singleFailedCandidate(failedCandidates.iterator().next());
|
||||
ResolvedCall<D> failed = failedCandidates.iterator().next();
|
||||
failed.getTrace().commit();
|
||||
return OverloadResolutionResults.singleFailedCandidate(failed);
|
||||
}
|
||||
else {
|
||||
tracing.unresolvedReference(trace);
|
||||
return OverloadResolutionResult.nameNotFound();
|
||||
return OverloadResolutionResults.nameNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkValueArgumentTypes(JetScope scope, JetTypeInferrer.Services temporaryServices, Map<ValueArgument, ValueParameterDescriptor> argumentsToParameters, Ref<Boolean> dirty, Function<ValueParameterDescriptor, ValueParameterDescriptor> parameterMap) {
|
||||
private boolean checkValueArgumentTypes(
|
||||
JetScope scope,
|
||||
BindingTrace temporaryTrace,
|
||||
Map<ValueArgument, ValueParameterDescriptor> argumentsToParameters,
|
||||
Ref<Boolean> dirty,
|
||||
Function<ValueParameterDescriptor, ValueParameterDescriptor> parameterMap) {
|
||||
boolean result = true;
|
||||
for (Map.Entry<ValueArgument, ValueParameterDescriptor> entry : argumentsToParameters.entrySet()) {
|
||||
ValueArgument valueArgument = entry.getKey();
|
||||
@@ -586,12 +614,34 @@ public class CallResolver {
|
||||
JetType parameterType = substitutedParameter.getOutType();
|
||||
JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
||||
if (argumentExpression != null) {
|
||||
JetTypeInferrer.Services temporaryServices = typeInferrer.getServices(temporaryTrace);
|
||||
JetType type = temporaryServices.getType(scope, argumentExpression, parameterType);
|
||||
if (type == null) {
|
||||
dirty.set(true);
|
||||
}
|
||||
else if (!semanticServices.getTypeChecker().isSubtypeOf(type, parameterType)) {
|
||||
result = false;
|
||||
// VariableDescriptor variableDescriptor = AutoCastUtils.getVariableDescriptorFromSimpleName(temporaryTrace.getBindingContext(), argumentExpression);
|
||||
// if (variableDescriptor != null) {
|
||||
// JetType autoCastType = null;
|
||||
// for (JetType possibleType : dataFlowInfo.getPossibleTypesForVariable(variableDescriptor)) {
|
||||
// if (semanticServices.getTypeChecker().isSubtypeOf(type, parameterType)) {
|
||||
// autoCastType = possibleType;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (autoCastType != null) {
|
||||
// if (AutoCastUtils.isAutocastable(variableDescriptor)) {
|
||||
// temporaryTrace.record(AUTOCAST, argumentExpression, autoCastType);
|
||||
// }
|
||||
// else {
|
||||
// temporaryTrace.report(AUTOCAST_IMPOSSIBLE.on(argumentExpression, autoCastType, variableDescriptor));
|
||||
// result = false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
result = false;
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -618,23 +668,23 @@ public class CallResolver {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public OverloadResolutionResult<FunctionDescriptor> resolveExactSignature(@NotNull JetScope scope, @NotNull ReceiverDescriptor receiver, @NotNull String name, @NotNull List<JetType> parameterTypes) {
|
||||
public OverloadResolutionResults<FunctionDescriptor> resolveExactSignature(@NotNull JetScope scope, @NotNull ReceiverDescriptor receiver, @NotNull String name, @NotNull List<JetType> parameterTypes) {
|
||||
List<FunctionDescriptor> result = findCandidatesByExactSignature(scope, receiver, name, parameterTypes);
|
||||
|
||||
BindingTraceContext trace = new BindingTraceContext();
|
||||
TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(trace);
|
||||
Map<FunctionDescriptor, TemporaryBindingTrace> traces = Maps.newHashMap();
|
||||
Map<FunctionDescriptor, FunctionDescriptor> candidates = Maps.newLinkedHashMap();
|
||||
Set<ResolvedCall<FunctionDescriptor>> candidates = Sets.newLinkedHashSet();
|
||||
for (FunctionDescriptor functionDescriptor : result) {
|
||||
candidates.put(functionDescriptor, functionDescriptor);
|
||||
traces.put(functionDescriptor, temporaryBindingTrace);
|
||||
ResolvedCall<FunctionDescriptor> resolvedCall = ResolvedCall.create(functionDescriptor);
|
||||
candidates.add(resolvedCall.setResultingDescriptor(functionDescriptor));
|
||||
resolvedCall.setTrace(temporaryBindingTrace);
|
||||
}
|
||||
return computeResultAndReportErrors(trace, TracingStrategy.EMPTY, candidates, Collections.<FunctionDescriptor>emptySet(), Collections.<FunctionDescriptor>emptySet(), traces);
|
||||
return computeResultAndReportErrors(trace, TracingStrategy.EMPTY, candidates, Collections.<ResolvedCall<FunctionDescriptor>>emptySet(), Collections.<ResolvedCall<FunctionDescriptor>>emptySet());
|
||||
}
|
||||
|
||||
private List<FunctionDescriptor> findCandidatesByExactSignature(JetScope scope, ReceiverDescriptor receiver, String name, List<JetType> parameterTypes) {
|
||||
List<FunctionDescriptor> result = Lists.newArrayList();
|
||||
if (receiver != NO_RECEIVER) {
|
||||
if (receiver.exists()) {
|
||||
Set<FunctionDescriptor> extensionFunctionDescriptors = scope.getFunctions(name);
|
||||
List<FunctionDescriptor> nonlocal = Lists.newArrayList();
|
||||
List<FunctionDescriptor> local = Lists.newArrayList();
|
||||
@@ -662,7 +712,7 @@ public class CallResolver {
|
||||
private boolean lookupExactSignature(Set<FunctionDescriptor> candidates, List<JetType> parameterTypes, List<FunctionDescriptor> result) {
|
||||
boolean found = false;
|
||||
for (FunctionDescriptor functionDescriptor : candidates) {
|
||||
if (functionDescriptor.getReceiver() != NO_RECEIVER) continue;
|
||||
if (functionDescriptor.getReceiver().exists()) continue;
|
||||
if (!functionDescriptor.getTypeParameters().isEmpty()) continue;
|
||||
if (!checkValueParameters(functionDescriptor, parameterTypes)) continue;
|
||||
result.add(functionDescriptor);
|
||||
@@ -675,7 +725,7 @@ public class CallResolver {
|
||||
boolean found = false;
|
||||
for (FunctionDescriptor functionDescriptor : candidates) {
|
||||
ReceiverDescriptor functionReceiver = functionDescriptor.getReceiver();
|
||||
if (functionReceiver == NO_RECEIVER) continue;
|
||||
if (!functionReceiver.exists()) continue;
|
||||
if (!functionDescriptor.getTypeParameters().isEmpty()) continue;
|
||||
if (!semanticServices.getTypeChecker().isSubtypeOf(receiver.getType(), functionReceiver.getType())) continue;
|
||||
if (!checkValueParameters(functionDescriptor, parameterTypes))continue;
|
||||
@@ -695,113 +745,4 @@ public class CallResolver {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static TaskPrioritizer<FunctionDescriptor> FUNCTION_TASK_PRIORITIZER = new TaskPrioritizer<FunctionDescriptor>() {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Collection<FunctionDescriptor> getNonExtensionsByName(JetScope scope, String name) {
|
||||
Set<FunctionDescriptor> functions = Sets.newLinkedHashSet(scope.getFunctions(name));
|
||||
for (Iterator<FunctionDescriptor> iterator = functions.iterator(); iterator.hasNext(); ) {
|
||||
FunctionDescriptor functionDescriptor = iterator.next();
|
||||
if (functionDescriptor.getReceiver() != NO_RECEIVER) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
addConstructors(scope, name, functions);
|
||||
|
||||
addVariableAsFunction(scope, name, functions, false);
|
||||
return functions;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Collection<FunctionDescriptor> getMembersByName(@NotNull ReceiverDescriptor receiver, String name) {
|
||||
JetScope receiverScope = receiver.getType().getMemberScope();
|
||||
Set<FunctionDescriptor> members = Sets.newHashSet(receiverScope.getFunctions(name));
|
||||
addConstructors(receiverScope, name, members);
|
||||
addVariableAsFunction(receiverScope, name, members, false);
|
||||
return members;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Collection<FunctionDescriptor> getExtensionsByName(JetScope scope, String name) {
|
||||
Set<FunctionDescriptor> extensionFunctions = Sets.newHashSet(scope.getFunctions(name));
|
||||
for (Iterator<FunctionDescriptor> iterator = extensionFunctions.iterator(); iterator.hasNext(); ) {
|
||||
FunctionDescriptor descriptor = iterator.next();
|
||||
if (descriptor.getReceiver() == NO_RECEIVER) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
addVariableAsFunction(scope, name, extensionFunctions, true);
|
||||
return extensionFunctions;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected ResolutionTask<FunctionDescriptor> createTask(@NotNull ReceiverDescriptor receiver, Call call, Collection<FunctionDescriptor> candidates) {
|
||||
return new ResolutionTask<FunctionDescriptor>(candidates, receiver, call);
|
||||
}
|
||||
|
||||
private void addConstructors(JetScope scope, String name, Collection<FunctionDescriptor> functions) {
|
||||
ClassifierDescriptor classifier = scope.getClassifier(name);
|
||||
if (classifier instanceof ClassDescriptor && !ErrorUtils.isError(classifier.getTypeConstructor())) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) classifier;
|
||||
functions.addAll(classDescriptor.getConstructors());
|
||||
}
|
||||
}
|
||||
|
||||
private void addVariableAsFunction(JetScope scope, String name, Set<FunctionDescriptor> functions, boolean receiverNeeded) {
|
||||
VariableDescriptor variable = scope.getVariable(name);
|
||||
if (variable != null && variable.getReceiver() == NO_RECEIVER) {
|
||||
JetType outType = variable.getOutType();
|
||||
if (outType != null && JetStandardClasses.isFunctionType(outType)) {
|
||||
VariableAsFunctionDescriptor functionDescriptor = VariableAsFunctionDescriptor.create(variable);
|
||||
if ((functionDescriptor.getReceiver() != NO_RECEIVER) == receiverNeeded) {
|
||||
functions.add(functionDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static TaskPrioritizer<VariableDescriptor> PROPERTY_TASK_PRIORITIZER = new TaskPrioritizer<VariableDescriptor>() {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, String name) {
|
||||
VariableDescriptor variable = scope.getVariable(name);
|
||||
if (variable != null && variable.getReceiver() == NO_RECEIVER) {
|
||||
return Collections.singleton(variable);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Collection<VariableDescriptor> getMembersByName(@NotNull ReceiverDescriptor receiver, String name) {
|
||||
VariableDescriptor variable = receiver.getType().getMemberScope().getVariable(name);
|
||||
if (variable != null) {
|
||||
return Collections.singleton(variable);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Collection<VariableDescriptor> getExtensionsByName(JetScope scope, String name) {
|
||||
VariableDescriptor variable = scope.getVariable(name);
|
||||
if (variable != null && variable.getReceiver() != NO_RECEIVER) {
|
||||
return Collections.singleton(variable);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected ResolutionTask<VariableDescriptor> createTask(@NotNull ReceiverDescriptor receiver, Call call, Collection<VariableDescriptor> candidates) {
|
||||
return new ResolutionTask<VariableDescriptor>(candidates, receiver, call);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
-96
@@ -1,96 +0,0 @@
|
||||
package org.jetbrains.jet.lang.resolve.calls;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class OverloadResolutionResult<D> {
|
||||
public enum Code {
|
||||
SUCCESS(true),
|
||||
NAME_NOT_FOUND(false),
|
||||
SINGLE_CANDIDATE_ARGUMENT_MISMATCH(false),
|
||||
AMBIGUITY(false),
|
||||
MANY_FAILED_CANDIDATES(false);
|
||||
|
||||
private final boolean success;
|
||||
|
||||
Code(boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static <D> OverloadResolutionResult<D> success(@NotNull D descriptor) {
|
||||
return new OverloadResolutionResult<D>(Code.SUCCESS, Collections.singleton(descriptor));
|
||||
}
|
||||
|
||||
public static <D> OverloadResolutionResult<D> nameNotFound() {
|
||||
return new OverloadResolutionResult<D>(Code.NAME_NOT_FOUND, Collections.<D>emptyList());
|
||||
}
|
||||
|
||||
public static <D> OverloadResolutionResult<D> singleFailedCandidate(D candidate) {
|
||||
return new OverloadResolutionResult<D>(Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH, Collections.singleton(candidate));
|
||||
}
|
||||
public static <D> OverloadResolutionResult<D> manyFailedCandidates(Set<D> failedCandidates) {
|
||||
return new OverloadResolutionResult<D>(Code.MANY_FAILED_CANDIDATES, failedCandidates);
|
||||
}
|
||||
|
||||
public static <D> OverloadResolutionResult<D> ambiguity(Collection<D> descriptors) {
|
||||
return new OverloadResolutionResult<D>(Code.AMBIGUITY, descriptors);
|
||||
}
|
||||
|
||||
private final Collection<D> descriptors;
|
||||
|
||||
private final Code resultCode;
|
||||
|
||||
public OverloadResolutionResult(@NotNull Code resultCode, @NotNull Collection<D> descriptors) {
|
||||
this.descriptors = descriptors;
|
||||
this.resultCode = resultCode;
|
||||
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<D> getDescriptors() {
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public D getDescriptor() {
|
||||
assert singleDescriptor();
|
||||
return descriptors.iterator().next();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Code getResultCode() {
|
||||
return resultCode;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return resultCode.isSuccess();
|
||||
}
|
||||
|
||||
public boolean singleDescriptor() {
|
||||
return isSuccess() || resultCode == Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH;
|
||||
}
|
||||
|
||||
public boolean isNothing() {
|
||||
return resultCode == Code.NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
public boolean isAmbiguity() {
|
||||
return resultCode == Code.AMBIGUITY;
|
||||
}
|
||||
|
||||
public OverloadResolutionResult<D> newContents(@NotNull Collection<D> functionDescriptors) {
|
||||
return new OverloadResolutionResult<D>(resultCode, functionDescriptors);
|
||||
}
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
package org.jetbrains.jet.lang.resolve.calls;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class OverloadResolutionResults<D extends CallableDescriptor> {
|
||||
public enum Code {
|
||||
SUCCESS(true),
|
||||
NAME_NOT_FOUND(false),
|
||||
SINGLE_CANDIDATE_ARGUMENT_MISMATCH(false),
|
||||
AMBIGUITY(false),
|
||||
MANY_FAILED_CANDIDATES(false);
|
||||
|
||||
private final boolean success;
|
||||
|
||||
Code(boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static <D extends CallableDescriptor> OverloadResolutionResults<D> success(@NotNull ResolvedCall<D> descriptor) {
|
||||
return new OverloadResolutionResults<D>(Code.SUCCESS, Collections.singleton(descriptor));
|
||||
}
|
||||
|
||||
public static <D extends CallableDescriptor> OverloadResolutionResults<D> nameNotFound() {
|
||||
return new OverloadResolutionResults<D>(Code.NAME_NOT_FOUND, Collections.<ResolvedCall<D>>emptyList());
|
||||
}
|
||||
|
||||
public static <D extends CallableDescriptor> OverloadResolutionResults<D> singleFailedCandidate(ResolvedCall<D> candidate) {
|
||||
return new OverloadResolutionResults<D>(Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH, Collections.singleton(candidate));
|
||||
}
|
||||
public static <D extends CallableDescriptor> OverloadResolutionResults<D> manyFailedCandidates(Set<ResolvedCall<D>> failedCandidates) {
|
||||
return new OverloadResolutionResults<D>(Code.MANY_FAILED_CANDIDATES, failedCandidates);
|
||||
}
|
||||
|
||||
public static <D extends CallableDescriptor> OverloadResolutionResults<D> ambiguity(Collection<ResolvedCall<D>> descriptors) {
|
||||
return new OverloadResolutionResults<D>(Code.AMBIGUITY, descriptors);
|
||||
}
|
||||
|
||||
private final Collection<ResolvedCall<D>> results;
|
||||
private final Code resultCode;
|
||||
|
||||
private OverloadResolutionResults(@NotNull Code resultCode, @NotNull Collection<ResolvedCall<D>> results) {
|
||||
this.results = results;
|
||||
this.resultCode = resultCode;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<ResolvedCall<D>> getResults() {
|
||||
return results;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ResolvedCall<D> getResult() {
|
||||
assert singleDescriptor();
|
||||
return results.iterator().next();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Code getResultCode() {
|
||||
return resultCode;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return resultCode.isSuccess();
|
||||
}
|
||||
|
||||
public boolean singleDescriptor() {
|
||||
return isSuccess() || resultCode == Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH;
|
||||
}
|
||||
|
||||
public boolean isNothing() {
|
||||
return resultCode == Code.NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
public boolean isAmbiguity() {
|
||||
return resultCode == Code.AMBIGUITY;
|
||||
}
|
||||
//
|
||||
// public OverloadResolutionResults<D> newContents(@NotNull Collection<D> functionDescriptors) {
|
||||
// return new OverloadResolutionResults<D>(resultCode, functionDescriptors);
|
||||
// }
|
||||
}
|
||||
+15
-14
@@ -1,6 +1,6 @@
|
||||
package org.jetbrains.jet.lang.resolve.calls;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||
@@ -8,13 +8,12 @@ import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.OverridingUtil;
|
||||
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -28,22 +27,24 @@ public class OverloadingConflictResolver {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public <Descriptor extends CallableDescriptor> Descriptor findMaximallySpecific(Map<Descriptor, Descriptor> candidates, Map<Descriptor, TemporaryBindingTrace> traces, boolean discriminateGenericDescriptors) {
|
||||
Map<Descriptor, TemporaryBindingTrace> maximallySpecific = Maps.newHashMap();
|
||||
public <D extends CallableDescriptor> ResolvedCall<D> findMaximallySpecific(Set<ResolvedCall<D>> candidates, boolean discriminateGenericDescriptors) {
|
||||
Set<ResolvedCall<D>> maximallySpecific = Sets.newHashSet();
|
||||
meLoop:
|
||||
for (Map.Entry<Descriptor, Descriptor> myEntry : candidates.entrySet()) {
|
||||
Descriptor me = myEntry.getValue();
|
||||
TemporaryBindingTrace myTrace = traces.get(myEntry.getKey());
|
||||
for (Descriptor other : candidates.values()) {
|
||||
for (ResolvedCall<D> candidateCall : candidates) {
|
||||
D me = candidateCall.getResultingDescriptor();
|
||||
for (ResolvedCall<D> otherCall : candidates) {
|
||||
D other = otherCall.getResultingDescriptor();
|
||||
if (other == me) continue;
|
||||
if (!moreSpecific(me, other, discriminateGenericDescriptors) || moreSpecific(other, me, discriminateGenericDescriptors)) continue meLoop;
|
||||
if (!moreSpecific(me, other, discriminateGenericDescriptors) || moreSpecific(other, me, discriminateGenericDescriptors)) {
|
||||
continue meLoop;
|
||||
}
|
||||
}
|
||||
maximallySpecific.put(me, myTrace);
|
||||
maximallySpecific.add(candidateCall);
|
||||
}
|
||||
if (maximallySpecific.size() == 1) {
|
||||
Map.Entry<Descriptor, TemporaryBindingTrace> result = maximallySpecific.entrySet().iterator().next();
|
||||
result.getValue().commit();
|
||||
return result.getKey();
|
||||
ResolvedCall<D> result = maximallySpecific.iterator().next();
|
||||
result.getTrace().commit();
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.jetbrains.jet.lang.resolve.calls;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.Call;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
@@ -9,7 +8,6 @@ import org.jetbrains.jet.lang.psi.JetTypeProjection;
|
||||
import org.jetbrains.jet.lang.psi.ValueArgument;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -17,8 +15,8 @@ import java.util.List;
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
/*package*/ class ResolutionTask<Descriptor extends CallableDescriptor> {
|
||||
private final Collection<Descriptor> candidates;
|
||||
/*package*/ class ResolutionTask<D extends CallableDescriptor> {
|
||||
private final Collection<ResolvedCall<D>> candidates;
|
||||
private final ReceiverDescriptor receiver;
|
||||
private final List<JetTypeProjection> typeArguments;
|
||||
private final List<? extends ValueArgument> valueArguments;
|
||||
@@ -26,7 +24,7 @@ import java.util.List;
|
||||
private DescriptorCheckStrategy checkingStrategy;
|
||||
|
||||
public ResolutionTask(
|
||||
@NotNull Collection<Descriptor> candidates,
|
||||
@NotNull Collection<ResolvedCall<D>> candidates,
|
||||
@NotNull ReceiverDescriptor receiver,
|
||||
@NotNull List<JetTypeProjection> typeArguments,
|
||||
@NotNull List<? extends ValueArgument> valueArguments,
|
||||
@@ -39,7 +37,7 @@ import java.util.List;
|
||||
}
|
||||
|
||||
public ResolutionTask(
|
||||
@NotNull Collection<Descriptor> candidates,
|
||||
@NotNull Collection<ResolvedCall<D>> candidates,
|
||||
@NotNull ReceiverDescriptor receiver,
|
||||
@NotNull Call call
|
||||
) {
|
||||
@@ -47,7 +45,7 @@ import java.util.List;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<Descriptor> getCandidates() {
|
||||
public Collection<ResolvedCall<D>> getCandidates() {
|
||||
return candidates;
|
||||
}
|
||||
|
||||
@@ -75,7 +73,7 @@ import java.util.List;
|
||||
checkingStrategy = strategy;
|
||||
}
|
||||
|
||||
public boolean performAdvancedChecks(Descriptor descriptor, BindingTrace trace, TracingStrategy tracing) {
|
||||
public boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) {
|
||||
if (checkingStrategy != null && !checkingStrategy.performAdvancedChecks(descriptor, trace, tracing)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
package org.jetbrains.jet.lang.resolve.calls;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.intellij.util.Function;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class ResolvedCall<D extends CallableDescriptor> {
|
||||
|
||||
public static final Function<ResolvedCall<? extends CallableDescriptor>, CallableDescriptor> MAP_TO_CANDIDATE = new Function<ResolvedCall<? extends CallableDescriptor>, CallableDescriptor>() {
|
||||
@Override
|
||||
public CallableDescriptor fun(ResolvedCall<? extends CallableDescriptor> resolvedCall) {
|
||||
return resolvedCall.getCandidateDescriptor();
|
||||
}
|
||||
};
|
||||
|
||||
public static final Function<ResolvedCall<? extends CallableDescriptor>, CallableDescriptor> MAP_TO_RESULT = new Function<ResolvedCall<? extends CallableDescriptor>, CallableDescriptor>() {
|
||||
@Override
|
||||
public CallableDescriptor fun(ResolvedCall<? extends CallableDescriptor> resolvedCall) {
|
||||
return resolvedCall.getResultingDescriptor();
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull
|
||||
public static <D extends CallableDescriptor> ResolvedCall<D> create(@NotNull D descriptor) {
|
||||
return new ResolvedCall<D>(descriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <D extends CallableDescriptor> List<ResolvedCall<D>> convertCollection(@NotNull Collection<D> descriptors) {
|
||||
List<ResolvedCall<D>> result = Lists.newArrayList();
|
||||
for (D descriptor : descriptors) {
|
||||
result.add(create(descriptor));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private final D candidateDescriptor;
|
||||
private D resultingDescriptor; // Probably substituted
|
||||
private ReceiverDescriptor thisObject; // receiver object of a method
|
||||
private ReceiverDescriptor receiverParameter; // receiver of an extension function
|
||||
private final Map<TypeParameterDescriptor, JetType> typeArguments = Maps.newHashMap();
|
||||
private final Map<ValueParameterDescriptor, JetType> autoCasts = Maps.newHashMap();
|
||||
private final Map<ValueParameterDescriptor, ResolvedValueArgument> valueArguments = Maps.newHashMap();
|
||||
private TemporaryBindingTrace trace;
|
||||
|
||||
private ResolvedCall(@NotNull D candidateDescriptor) {
|
||||
this.candidateDescriptor = candidateDescriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TemporaryBindingTrace getTrace() {
|
||||
return trace;
|
||||
}
|
||||
|
||||
public void setTrace(@NotNull TemporaryBindingTrace trace) {
|
||||
this.trace = trace;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public D getCandidateDescriptor() {
|
||||
return candidateDescriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public D getResultingDescriptor() {
|
||||
return resultingDescriptor == null ? candidateDescriptor : resultingDescriptor;
|
||||
}
|
||||
|
||||
public ResolvedCall<D> setResultingDescriptor(@NotNull D resultingDescriptor) {
|
||||
this.resultingDescriptor = resultingDescriptor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void recordTypeArgument(@NotNull TypeParameterDescriptor typeParameter, @NotNull JetType typeArgument) {
|
||||
assert !typeArguments.containsKey(typeParameter);
|
||||
typeArguments.put(typeParameter, typeArgument);
|
||||
}
|
||||
|
||||
public void recordValueArgument(@NotNull ValueParameterDescriptor valueParameter, @NotNull ResolvedValueArgument valueArgument) {
|
||||
assert !valueArguments.containsKey(valueParameter);
|
||||
valueArguments.put(valueParameter, valueArgument);
|
||||
}
|
||||
|
||||
public void autoCastValueArgument(@NotNull ValueParameterDescriptor parameter, @NotNull JetType target) {
|
||||
assert !autoCasts.containsKey(parameter);
|
||||
autoCasts.put(parameter, target);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ReceiverDescriptor getReceiverParameter() {
|
||||
return receiverParameter;
|
||||
}
|
||||
|
||||
public void setReceiverParameter(@NotNull ReceiverDescriptor receiverParameter) {
|
||||
this.receiverParameter = receiverParameter;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ReceiverDescriptor getThisObject() {
|
||||
return thisObject;
|
||||
}
|
||||
|
||||
public void setThisObject(@NotNull ReceiverDescriptor thisObject) {
|
||||
this.thisObject = thisObject;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.jetbrains.jet.lang.resolve.calls;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public interface ResolvedValueArgument {
|
||||
|
||||
}
|
||||
@@ -2,17 +2,21 @@ package org.jetbrains.jet.lang.resolve.calls;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.Call;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.DataFlowInfo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
@@ -62,16 +66,30 @@ import java.util.List;
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<ResolutionTask<D>> computePrioritizedTasks(@NotNull JetScope scope, @NotNull ReceiverDescriptor receiver, @NotNull Call call, @NotNull String name) {
|
||||
// public List<ResolutionTask<D>> computePrioritizedTasks(@NotNull JetScope scope, @NotNull ReceiverDescriptor receiver, @NotNull Call call, @NotNull String name) {
|
||||
// List<ResolutionTask<D>> result = Lists.newArrayList();
|
||||
// doComputeTasks(scope, receiver, call, name, result);
|
||||
// return result;
|
||||
// }
|
||||
|
||||
public List<ResolutionTask<D>> computePrioritizedTasks(@NotNull JetScope scope, @NotNull ReceiverDescriptor receiver, @NotNull Call call, @NotNull String name, @NotNull BindingContext bindingContext, @NotNull DataFlowInfo dataFlowInfo) {
|
||||
List<ResolutionTask<D>> result = Lists.newArrayList();
|
||||
|
||||
doComputeTasks(scope, receiver, call, name, result);
|
||||
|
||||
// ReceiverDescriptor receiverToCast = receiver.exists() ? receiver : scope.getImplicitReceiver();
|
||||
// if (receiverToCast.exists()) {
|
||||
// for (ReceiverDescriptor castReceiver : AutoCastUtils.getAutocastVariants(bindingContext, dataFlowInfo, receiverToCast)) {
|
||||
// doComputeTasks(scope, castReceiver, call, name, result);
|
||||
// }
|
||||
// }
|
||||
return result;
|
||||
}
|
||||
|
||||
private void doComputeTasks(JetScope scope, ReceiverDescriptor receiver, Call call, String name, List<ResolutionTask<D>> result) {
|
||||
List<ReceiverDescriptor> implicitReceivers = Lists.newArrayList();
|
||||
scope.getImplicitReceiversHierarchy(implicitReceivers);
|
||||
if (receiver != ReceiverDescriptor.NO_RECEIVER) {
|
||||
if (receiver.exists()) {
|
||||
Collection<D> extensionFunctions = getExtensionsByName(scope, name);
|
||||
List<D> nonlocals = Lists.newArrayList();
|
||||
List<D> locals = Lists.newArrayList();
|
||||
@@ -81,7 +99,7 @@ import java.util.List;
|
||||
Collection<D> members = getMembersByName(receiver, name);
|
||||
|
||||
addTask(result, receiver, call, locals);
|
||||
addTask(result, ReceiverDescriptor.NO_RECEIVER, call, members);
|
||||
addTask(result, NO_RECEIVER, call, members);
|
||||
|
||||
for (ReceiverDescriptor implicitReceiver : implicitReceivers) {
|
||||
Collection<D> memberExtensions = getExtensionsByName(implicitReceiver.getType().getMemberScope(), name);
|
||||
@@ -108,6 +126,11 @@ import java.util.List;
|
||||
}
|
||||
}
|
||||
|
||||
private void addTask(@NotNull List<ResolutionTask<D>> result, @NotNull ReceiverDescriptor receiver, @NotNull Call call, @NotNull Collection<D> candidateDescriptors) {
|
||||
if (candidateDescriptors.isEmpty()) return;
|
||||
result.add(createTask(receiver, call, ResolvedCall.convertCollection(candidateDescriptors)));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected abstract Collection<D> getNonExtensionsByName(JetScope scope, String name);
|
||||
|
||||
@@ -117,12 +140,7 @@ import java.util.List;
|
||||
@NotNull
|
||||
protected abstract Collection<D> getExtensionsByName(JetScope scope, String name);
|
||||
|
||||
private void addTask(@NotNull List<ResolutionTask<D>> result, @NotNull ReceiverDescriptor receiver, @NotNull Call call, @NotNull Collection<D> candidates) {
|
||||
if (candidates.isEmpty()) return;
|
||||
result.add(createTask(receiver, call, candidates));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected abstract ResolutionTask<D> createTask(ReceiverDescriptor receiver, Call call, Collection<D> candidates);
|
||||
protected abstract ResolutionTask<D> createTask(ReceiverDescriptor receiver, Call call, Collection<ResolvedCall<D>> candidates);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
package org.jetbrains.jet.lang.resolve.calls;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.Call;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class TaskPrioritizers {
|
||||
|
||||
|
||||
/*package*/ static TaskPrioritizer<FunctionDescriptor> FUNCTION_TASK_PRIORITIZER = new TaskPrioritizer<FunctionDescriptor>() {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Collection<FunctionDescriptor> getNonExtensionsByName(JetScope scope, String name) {
|
||||
Set<FunctionDescriptor> functions = Sets.newLinkedHashSet(scope.getFunctions(name));
|
||||
for (Iterator<FunctionDescriptor> iterator = functions.iterator(); iterator.hasNext(); ) {
|
||||
FunctionDescriptor functionDescriptor = iterator.next();
|
||||
if (functionDescriptor.getReceiver().exists()) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
addConstructors(scope, name, functions);
|
||||
|
||||
addVariableAsFunction(scope, name, functions, false);
|
||||
return functions;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Collection<FunctionDescriptor> getMembersByName(@NotNull ReceiverDescriptor receiver, String name) {
|
||||
JetScope receiverScope = receiver.getType().getMemberScope();
|
||||
Set<FunctionDescriptor> members = Sets.newHashSet(receiverScope.getFunctions(name));
|
||||
addConstructors(receiverScope, name, members);
|
||||
addVariableAsFunction(receiverScope, name, members, false);
|
||||
return members;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Collection<FunctionDescriptor> getExtensionsByName(JetScope scope, String name) {
|
||||
Set<FunctionDescriptor> extensionFunctions = Sets.newHashSet(scope.getFunctions(name));
|
||||
for (Iterator<FunctionDescriptor> iterator = extensionFunctions.iterator(); iterator.hasNext(); ) {
|
||||
FunctionDescriptor descriptor = iterator.next();
|
||||
if (!descriptor.getReceiver().exists()) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
addVariableAsFunction(scope, name, extensionFunctions, true);
|
||||
return extensionFunctions;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected ResolutionTask<FunctionDescriptor> createTask(@NotNull ReceiverDescriptor receiver, Call call, Collection<ResolvedCall<FunctionDescriptor>> candidates) {
|
||||
return new ResolutionTask<FunctionDescriptor>(candidates, receiver, call);
|
||||
}
|
||||
|
||||
private void addConstructors(JetScope scope, String name, Collection<FunctionDescriptor> functions) {
|
||||
ClassifierDescriptor classifier = scope.getClassifier(name);
|
||||
if (classifier instanceof ClassDescriptor && !ErrorUtils.isError(classifier.getTypeConstructor())) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) classifier;
|
||||
functions.addAll(classDescriptor.getConstructors());
|
||||
}
|
||||
}
|
||||
|
||||
private void addVariableAsFunction(JetScope scope, String name, Set<FunctionDescriptor> functions, boolean receiverNeeded) {
|
||||
VariableDescriptor variable = scope.getVariable(name);
|
||||
if (variable != null && !variable.getReceiver().exists()) {
|
||||
JetType outType = variable.getOutType();
|
||||
if (outType != null && JetStandardClasses.isFunctionType(outType)) {
|
||||
VariableAsFunctionDescriptor functionDescriptor = VariableAsFunctionDescriptor.create(variable);
|
||||
if ((functionDescriptor.getReceiver().exists()) == receiverNeeded) {
|
||||
functions.add(functionDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*package*/ static TaskPrioritizer<VariableDescriptor> PROPERTY_TASK_PRIORITIZER = new TaskPrioritizer<VariableDescriptor>() {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, String name) {
|
||||
VariableDescriptor variable = scope.getVariable(name);
|
||||
if (variable != null && !variable.getReceiver().exists()) {
|
||||
return Collections.singleton(variable);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Collection<VariableDescriptor> getMembersByName(@NotNull ReceiverDescriptor receiver, String name) {
|
||||
VariableDescriptor variable = receiver.getType().getMemberScope().getVariable(name);
|
||||
if (variable != null) {
|
||||
return Collections.singleton(variable);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Collection<VariableDescriptor> getExtensionsByName(JetScope scope, String name) {
|
||||
VariableDescriptor variable = scope.getVariable(name);
|
||||
if (variable != null && variable.getReceiver().exists()) {
|
||||
return Collections.singleton(variable);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected ResolutionTask<VariableDescriptor> createTask(@NotNull ReceiverDescriptor receiver, Call call, Collection<ResolvedCall<VariableDescriptor>> candidates) {
|
||||
return new ResolutionTask<VariableDescriptor>(candidates, receiver, call);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -21,7 +21,7 @@ import java.util.Set;
|
||||
public void unresolvedReference(@NotNull BindingTrace trace) {}
|
||||
|
||||
@Override
|
||||
public <D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<D> candidates) {}
|
||||
public <D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<ResolvedCall<D>> candidates) {}
|
||||
|
||||
@Override
|
||||
public void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver) {}
|
||||
@@ -36,10 +36,10 @@ import java.util.Set;
|
||||
public void wrongNumberOfTypeArguments(@NotNull BindingTrace trace, int expectedTypeArgumentCount) {}
|
||||
|
||||
@Override
|
||||
public void ambiguity(@NotNull BindingTrace trace, @NotNull Set<? extends CallableDescriptor> descriptors) {}
|
||||
public <D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Set<ResolvedCall<D>> descriptors) {}
|
||||
|
||||
@Override
|
||||
public void noneApplicable(@NotNull BindingTrace trace, @NotNull Set<? extends CallableDescriptor> descriptors) {}
|
||||
public <D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Set<ResolvedCall<D>> descriptors) {}
|
||||
|
||||
@Override
|
||||
public void instantiationOfAbstractClass(@NotNull BindingTrace trace) {}
|
||||
@@ -52,7 +52,7 @@ import java.util.Set;
|
||||
|
||||
void unresolvedReference(@NotNull BindingTrace trace);
|
||||
|
||||
<D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<D> candidates);
|
||||
<D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<ResolvedCall<D>> candidates);
|
||||
|
||||
void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver);
|
||||
|
||||
@@ -62,9 +62,9 @@ import java.util.Set;
|
||||
|
||||
void wrongNumberOfTypeArguments(@NotNull BindingTrace trace, int expectedTypeArgumentCount);
|
||||
|
||||
void ambiguity(@NotNull BindingTrace trace, @NotNull Set<? extends CallableDescriptor> descriptors);
|
||||
<D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Set<ResolvedCall<D>> descriptors);
|
||||
|
||||
void noneApplicable(@NotNull BindingTrace trace, @NotNull Set<? extends CallableDescriptor> descriptors);
|
||||
<D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Set<ResolvedCall<D>> descriptors);
|
||||
|
||||
void instantiationOfAbstractClass(@NotNull BindingTrace trace);
|
||||
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ public class ReceiverDescriptorVisitor<R, D> {
|
||||
return null;
|
||||
}
|
||||
|
||||
public R visitClassReceiver(ClassReceiver classReceiver, D data) {
|
||||
public R visitClassReceiver(ClassReceiver receiver, D data) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.google.common.collect.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.util.CommonSuppliers;
|
||||
|
||||
import java.util.*;
|
||||
@@ -14,9 +15,9 @@ import java.util.*;
|
||||
public class DataFlowInfo {
|
||||
|
||||
public static abstract class CompositionOperator {
|
||||
|
||||
public abstract DataFlowInfo compose(DataFlowInfo a, DataFlowInfo b);
|
||||
}
|
||||
|
||||
public static final CompositionOperator AND = new CompositionOperator() {
|
||||
@Override
|
||||
public DataFlowInfo compose(DataFlowInfo a, DataFlowInfo b) {
|
||||
@@ -31,7 +32,7 @@ public class DataFlowInfo {
|
||||
}
|
||||
};
|
||||
|
||||
private static DataFlowInfo EMPTY = new DataFlowInfo(ImmutableMap.<VariableDescriptor, NullabilityFlags>of(), Multimaps.newListMultimap(Collections.<VariableDescriptor, Collection<JetType>>emptyMap(), CommonSuppliers.<JetType>getArrayListSupplier()));
|
||||
private static DataFlowInfo EMPTY = new DataFlowInfo(ImmutableMap.<Object, NullabilityFlags>of(), Multimaps.newListMultimap(Collections.<Object, Collection<JetType>>emptyMap(), CommonSuppliers.<JetType>getArrayListSupplier()));
|
||||
|
||||
public static DataFlowInfo getEmpty() {
|
||||
return EMPTY;
|
||||
@@ -39,10 +40,11 @@ public class DataFlowInfo {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private final ImmutableMap<VariableDescriptor, NullabilityFlags> nullabilityInfo;
|
||||
private final ListMultimap<VariableDescriptor, JetType> typeInfo;
|
||||
private final ImmutableMap<Object, NullabilityFlags> nullabilityInfo;
|
||||
|
||||
private DataFlowInfo(ImmutableMap<VariableDescriptor, NullabilityFlags> nullabilityInfo, ListMultimap<VariableDescriptor, JetType> typeInfo) {
|
||||
private final ListMultimap<Object, JetType> typeInfo;
|
||||
|
||||
private DataFlowInfo(ImmutableMap<Object, NullabilityFlags> nullabilityInfo, ListMultimap<Object, JetType> typeInfo) {
|
||||
this.nullabilityInfo = nullabilityInfo;
|
||||
this.typeInfo = typeInfo;
|
||||
}
|
||||
@@ -60,9 +62,9 @@ public class DataFlowInfo {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<JetType> getPossibleTypes(VariableDescriptor variableDescriptor) {
|
||||
List<JetType> types = typeInfo.get(variableDescriptor);
|
||||
NullabilityFlags nullabilityFlags = nullabilityInfo.get(variableDescriptor);
|
||||
private List<JetType> getPossibleTypes(Object key) {
|
||||
List<JetType> types = typeInfo.get(key);
|
||||
NullabilityFlags nullabilityFlags = nullabilityInfo.get(key);
|
||||
if (nullabilityFlags == null || nullabilityFlags.canBeNull()) {
|
||||
return types;
|
||||
}
|
||||
@@ -78,21 +80,30 @@ public class DataFlowInfo {
|
||||
return enrichedTypes;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<JetType> getPossibleTypesForVariable(VariableDescriptor variableDescriptor) {
|
||||
return getPossibleTypes(variableDescriptor);
|
||||
}
|
||||
|
||||
public List<JetType> getPossibleTypesForReceiver(@NotNull ReceiverDescriptor receiver) {
|
||||
return getPossibleTypes(receiver);
|
||||
}
|
||||
|
||||
public DataFlowInfo equalsToNull(@NotNull VariableDescriptor variableDescriptor, boolean notNull) {
|
||||
return new DataFlowInfo(getEqualsToNullMap(variableDescriptor, notNull), typeInfo);
|
||||
}
|
||||
|
||||
private ImmutableMap<VariableDescriptor, NullabilityFlags> getEqualsToNullMap(VariableDescriptor variableDescriptor, boolean notNull) {
|
||||
Map<VariableDescriptor, NullabilityFlags> builder = Maps.newHashMap(nullabilityInfo);
|
||||
private ImmutableMap<Object, NullabilityFlags> getEqualsToNullMap(VariableDescriptor variableDescriptor, boolean notNull) {
|
||||
Map<Object, NullabilityFlags> builder = Maps.newHashMap(nullabilityInfo);
|
||||
NullabilityFlags nullabilityFlags = nullabilityInfo.get(variableDescriptor);
|
||||
boolean varNotNull = notNull || (nullabilityFlags != null && !nullabilityFlags.canBeNull);
|
||||
builder.put(variableDescriptor, new NullabilityFlags(!varNotNull, varNotNull));
|
||||
return ImmutableMap.copyOf(builder);
|
||||
}
|
||||
|
||||
private ImmutableMap<VariableDescriptor, NullabilityFlags> getEqualsToNullMap(VariableDescriptor[] variableDescriptors, boolean notNull) {
|
||||
private ImmutableMap<Object, NullabilityFlags> getEqualsToNullMap(VariableDescriptor[] variableDescriptors, boolean notNull) {
|
||||
if (variableDescriptors.length == 0) return nullabilityInfo;
|
||||
Map<VariableDescriptor, NullabilityFlags> builder = Maps.newHashMap(nullabilityInfo);
|
||||
Map<Object, NullabilityFlags> builder = Maps.newHashMap(nullabilityInfo);
|
||||
for (VariableDescriptor variableDescriptor : variableDescriptors) {
|
||||
if (variableDescriptor != null) {
|
||||
NullabilityFlags nullabilityFlags = nullabilityInfo.get(variableDescriptor);
|
||||
@@ -104,14 +115,14 @@ public class DataFlowInfo {
|
||||
}
|
||||
|
||||
public DataFlowInfo isInstanceOf(@NotNull VariableDescriptor variableDescriptor, @NotNull JetType type) {
|
||||
ListMultimap<VariableDescriptor, JetType> newTypeInfo = copyTypeInfo();
|
||||
ListMultimap<Object, JetType> newTypeInfo = copyTypeInfo();
|
||||
newTypeInfo.put(variableDescriptor, type);
|
||||
return new DataFlowInfo(getEqualsToNullMap(variableDescriptor, !type.isNullable()), newTypeInfo);
|
||||
}
|
||||
|
||||
public DataFlowInfo isInstanceOf(@NotNull VariableDescriptor[] variableDescriptors, @NotNull JetType type) {
|
||||
if (variableDescriptors.length == 0) return this;
|
||||
ListMultimap<VariableDescriptor, JetType> newTypeInfo = copyTypeInfo();
|
||||
ListMultimap<Object, JetType> newTypeInfo = copyTypeInfo();
|
||||
for (VariableDescriptor variableDescriptor : variableDescriptors) {
|
||||
if (variableDescriptor != null) {
|
||||
newTypeInfo.put(variableDescriptor, type);
|
||||
@@ -121,55 +132,55 @@ public class DataFlowInfo {
|
||||
}
|
||||
|
||||
public DataFlowInfo and(DataFlowInfo other) {
|
||||
Map<VariableDescriptor, NullabilityFlags> nullabilityMapBuilder = Maps.newHashMap();
|
||||
Map<Object, NullabilityFlags> nullabilityMapBuilder = Maps.newHashMap();
|
||||
nullabilityMapBuilder.putAll(nullabilityInfo);
|
||||
for (Map.Entry<VariableDescriptor, NullabilityFlags> entry : other.nullabilityInfo.entrySet()) {
|
||||
VariableDescriptor variableDescriptor = entry.getKey();
|
||||
for (Map.Entry<Object, NullabilityFlags> entry : other.nullabilityInfo.entrySet()) {
|
||||
Object key = entry.getKey();
|
||||
NullabilityFlags otherFlags = entry.getValue();
|
||||
NullabilityFlags thisFlags = nullabilityInfo.get(variableDescriptor);
|
||||
NullabilityFlags thisFlags = nullabilityInfo.get(key);
|
||||
if (thisFlags != null) {
|
||||
nullabilityMapBuilder.put(variableDescriptor, thisFlags.and(otherFlags));
|
||||
nullabilityMapBuilder.put(key, thisFlags.and(otherFlags));
|
||||
}
|
||||
else {
|
||||
nullabilityMapBuilder.put(variableDescriptor, otherFlags);
|
||||
nullabilityMapBuilder.put(key, otherFlags);
|
||||
}
|
||||
}
|
||||
|
||||
ListMultimap<VariableDescriptor, JetType> newTypeInfo = copyTypeInfo();
|
||||
ListMultimap<Object, JetType> newTypeInfo = copyTypeInfo();
|
||||
newTypeInfo.putAll(other.typeInfo);
|
||||
return new DataFlowInfo(ImmutableMap.copyOf(nullabilityMapBuilder), newTypeInfo);
|
||||
}
|
||||
|
||||
private ListMultimap<VariableDescriptor, JetType> copyTypeInfo() {
|
||||
ListMultimap<VariableDescriptor, JetType> newTypeInfo = Multimaps.newListMultimap(Maps.<VariableDescriptor, Collection<JetType>>newHashMap(), CommonSuppliers.<JetType>getArrayListSupplier());
|
||||
private ListMultimap<Object, JetType> copyTypeInfo() {
|
||||
ListMultimap<Object, JetType> newTypeInfo = Multimaps.newListMultimap(Maps.<Object, Collection<JetType>>newHashMap(), CommonSuppliers.<JetType>getArrayListSupplier());
|
||||
newTypeInfo.putAll(typeInfo);
|
||||
return newTypeInfo;
|
||||
}
|
||||
|
||||
public DataFlowInfo or(DataFlowInfo other) {
|
||||
Map<VariableDescriptor, NullabilityFlags> builder = Maps.newHashMap(nullabilityInfo);
|
||||
Map<Object, NullabilityFlags> builder = Maps.newHashMap(nullabilityInfo);
|
||||
builder.keySet().retainAll(other.nullabilityInfo.keySet());
|
||||
for (Map.Entry<VariableDescriptor, NullabilityFlags> entry : builder.entrySet()) {
|
||||
VariableDescriptor variableDescriptor = entry.getKey();
|
||||
for (Map.Entry<Object, NullabilityFlags> entry : builder.entrySet()) {
|
||||
Object key = entry.getKey();
|
||||
NullabilityFlags thisFlags = entry.getValue();
|
||||
NullabilityFlags otherFlags = other.nullabilityInfo.get(variableDescriptor);
|
||||
NullabilityFlags otherFlags = other.nullabilityInfo.get(key);
|
||||
assert (otherFlags != null);
|
||||
builder.put(variableDescriptor, thisFlags.or(otherFlags));
|
||||
builder.put(key, thisFlags.or(otherFlags));
|
||||
}
|
||||
|
||||
ListMultimap<VariableDescriptor, JetType> newTypeInfo = Multimaps.newListMultimap(Maps.<VariableDescriptor, Collection<JetType>>newHashMap(), CommonSuppliers.<JetType>getArrayListSupplier());
|
||||
ListMultimap<Object, JetType> newTypeInfo = Multimaps.newListMultimap(Maps.<Object, Collection<JetType>>newHashMap(), CommonSuppliers.<JetType>getArrayListSupplier());
|
||||
|
||||
Set<VariableDescriptor> keys = newTypeInfo.keySet();
|
||||
Set<Object> keys = newTypeInfo.keySet();
|
||||
keys.retainAll(other.typeInfo.keySet());
|
||||
|
||||
for (VariableDescriptor variableDescriptor : keys) {
|
||||
Collection<JetType> thisTypes = typeInfo.get(variableDescriptor);
|
||||
Collection<JetType> otherTypes = other.typeInfo.get(variableDescriptor);
|
||||
for (Object key : keys) {
|
||||
Collection<JetType> thisTypes = typeInfo.get(key);
|
||||
Collection<JetType> otherTypes = other.typeInfo.get(key);
|
||||
|
||||
Collection<JetType> newTypes = Sets.newHashSet(thisTypes);
|
||||
newTypes.retainAll(otherTypes);
|
||||
|
||||
newTypeInfo.putAll(variableDescriptor, newTypes);
|
||||
newTypeInfo.putAll(key, newTypes);
|
||||
}
|
||||
|
||||
return new DataFlowInfo(ImmutableMap.copyOf(builder), newTypeInfo);
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallResolver;
|
||||
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResult;
|
||||
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
|
||||
import org.jetbrains.jet.lang.resolve.constants.*;
|
||||
import org.jetbrains.jet.lang.resolve.constants.StringValue;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
@@ -161,7 +161,6 @@ public class JetTypeInferrer {
|
||||
|
||||
private final JetSemanticServices semanticServices;
|
||||
private final JetFlowInformationProvider flowInformationProvider;
|
||||
private final CallResolver callResolver;
|
||||
private final Map<JetPattern, DataFlowInfo> patternsToDataFlowInfo = Maps.newHashMap();
|
||||
|
||||
private final Map<JetPattern, List<VariableDescriptor>> patternsToBoundVariableLists = Maps.newHashMap();
|
||||
@@ -169,29 +168,26 @@ public class JetTypeInferrer {
|
||||
public JetTypeInferrer(@NotNull JetFlowInformationProvider flowInformationProvider, @NotNull JetSemanticServices semanticServices) {
|
||||
this.semanticServices = semanticServices;
|
||||
this.flowInformationProvider = flowInformationProvider;
|
||||
this.callResolver = new CallResolver(semanticServices, this);
|
||||
}
|
||||
|
||||
public Services getServices(@NotNull BindingTrace trace) {
|
||||
return new Services(trace);
|
||||
}
|
||||
|
||||
public CallResolver getCallResolver() {
|
||||
return callResolver;
|
||||
}
|
||||
|
||||
public class Services {
|
||||
private final BindingTrace trace;
|
||||
private final CompileTimeConstantResolver compileTimeConstantResolver;
|
||||
|
||||
private final TypeInferrerVisitor typeInferrerVisitor;
|
||||
private final TypeInferrerVisitorWithNamespaces typeInferrerVisitorWithNamespaces;
|
||||
private final CallResolver callResolver;
|
||||
|
||||
private Services(BindingTrace trace) {
|
||||
this.trace = trace;
|
||||
this.compileTimeConstantResolver = new CompileTimeConstantResolver(semanticServices, trace);
|
||||
this.typeInferrerVisitor = new TypeInferrerVisitor();
|
||||
this.typeInferrerVisitorWithNamespaces = new TypeInferrerVisitorWithNamespaces();
|
||||
this.callResolver = new CallResolver(semanticServices, JetTypeInferrer.this, DataFlowInfo.getEmpty());
|
||||
}
|
||||
|
||||
public TypeInferrerVisitorWithWritableScope newTypeInferrerVisitorWithWritableScope(WritableScope scope) {
|
||||
@@ -516,7 +512,7 @@ public class JetTypeInferrer {
|
||||
VariableDescriptor variableDescriptor = getVariableDescriptorFromSimpleName(expression, context);
|
||||
boolean appropriateTypeFound = false;
|
||||
if (variableDescriptor != null) {
|
||||
List<JetType> possibleTypes = Lists.newArrayList(context.dataFlowInfo.getPossibleTypes(variableDescriptor));
|
||||
List<JetType> possibleTypes = Lists.newArrayList(context.dataFlowInfo.getPossibleTypesForVariable(variableDescriptor));
|
||||
Collections.reverse(possibleTypes);
|
||||
for (JetType possibleType : possibleTypes) {
|
||||
if (semanticServices.getTypeChecker().isSubtypeOf(possibleType, context.expectedType)) {
|
||||
@@ -612,6 +608,9 @@ public class JetTypeInferrer {
|
||||
public final JetType expectedType;
|
||||
public final JetType expectedReturnType;
|
||||
|
||||
@Deprecated // Use a getter
|
||||
private CallResolver callResolver;
|
||||
|
||||
@Deprecated // Only factory methods
|
||||
private TypeInferenceContext(
|
||||
@NotNull BindingTrace trace,
|
||||
@@ -666,6 +665,34 @@ public class JetTypeInferrer {
|
||||
if (expectedType == newExpectedType && expectedReturnType == newExpectedReturnType) return this;
|
||||
return newContext(trace, scope, dataFlowInfo, newExpectedType, newExpectedReturnType);
|
||||
}
|
||||
|
||||
public CallResolver getCallResolver() {
|
||||
if (callResolver == null) {
|
||||
callResolver = new CallResolver(semanticServices, JetTypeInferrer.this, this.dataFlowInfo);
|
||||
}
|
||||
return callResolver;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FunctionDescriptor resolveCallWithGivenName(@NotNull Call call, @NotNull JetReferenceExpression functionReference, @NotNull String name, @NotNull ReceiverDescriptor receiver) {
|
||||
return getCallResolver().resolveCallWithGivenName(trace, scope, call, functionReference, name, receiver, expectedType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JetType resolveCall(@NotNull ReceiverDescriptor receiver, @NotNull JetCallElement call) {
|
||||
return getCallResolver().resolveCall(trace, scope, receiver, call, expectedType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public VariableDescriptor resolveSimpleProperty(@NotNull ReceiverDescriptor receiver, @NotNull JetSimpleNameExpression nameExpression) {
|
||||
return getCallResolver().resolveSimpleProperty(trace, scope, receiver, nameExpression, expectedType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public OverloadResolutionResults<FunctionDescriptor> resolveExactSignature(@NotNull ReceiverDescriptor receiver, @NotNull String name, @NotNull List<JetType> parameterTypes) {
|
||||
return getCallResolver().resolveExactSignature(scope, receiver, name, parameterTypes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class TypeInferrerVisitor extends JetVisitor<JetType, TypeInferenceContext> {
|
||||
@@ -1899,9 +1926,9 @@ public class JetTypeInferrer {
|
||||
@Nullable
|
||||
private JetType checkIterableConvention(@NotNull ExpressionReceiver loopRange, TypeInferenceContext context) {
|
||||
JetExpression loopRangeExpression = loopRange.getExpression();
|
||||
OverloadResolutionResult<FunctionDescriptor> iteratorResolutionResult = callResolver.resolveExactSignature(context.scope, loopRange, "iterator", Collections.<JetType>emptyList());
|
||||
if (iteratorResolutionResult.isSuccess()) {
|
||||
FunctionDescriptor iteratorFunction = iteratorResolutionResult.getDescriptor();
|
||||
OverloadResolutionResults<FunctionDescriptor> iteratorResolutionResults = context.resolveExactSignature(loopRange, "iterator", Collections.<JetType>emptyList());
|
||||
if (iteratorResolutionResults.isSuccess()) {
|
||||
FunctionDescriptor iteratorFunction = iteratorResolutionResults.getResult().getResultingDescriptor();
|
||||
|
||||
context.trace.record(LOOP_RANGE_ITERATOR, loopRangeExpression, iteratorFunction);
|
||||
|
||||
@@ -1923,27 +1950,27 @@ public class JetTypeInferrer {
|
||||
context.trace.record(LOOP_RANGE_HAS_NEXT, loopRange.getExpression(), hasNextFunctionSupported ? hasNextFunction : hasNextProperty);
|
||||
}
|
||||
|
||||
OverloadResolutionResult<FunctionDescriptor> nextResolutionResult = callResolver.resolveExactSignature(context.scope, new TransientReceiver(iteratorType), "next", Collections.<JetType>emptyList());
|
||||
if (nextResolutionResult.isAmbiguity()) {
|
||||
OverloadResolutionResults<FunctionDescriptor> nextResolutionResults = context.resolveExactSignature(new TransientReceiver(iteratorType), "next", Collections.<JetType>emptyList());
|
||||
if (nextResolutionResults.isAmbiguity()) {
|
||||
// context.trace.getErrorHandler().genericError(reportErrorsOn, "Method 'iterator().next()' is ambiguous for this expression");
|
||||
context.trace.report(NEXT_AMBIGUITY.on(loopRangeExpression));
|
||||
} else if (nextResolutionResult.isNothing()) {
|
||||
} else if (nextResolutionResults.isNothing()) {
|
||||
// context.trace.getErrorHandler().genericError(reportErrorsOn, "Loop range must have an 'iterator().next()' method");
|
||||
context.trace.report(NEXT_MISSING.on(loopRangeExpression));
|
||||
} else {
|
||||
FunctionDescriptor nextFunction = nextResolutionResult.getDescriptor();
|
||||
FunctionDescriptor nextFunction = nextResolutionResults.getResult().getResultingDescriptor();
|
||||
context.trace.record(LOOP_RANGE_NEXT, loopRange.getExpression(), nextFunction);
|
||||
return nextFunction.getReturnType();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (iteratorResolutionResult.isAmbiguity()) {
|
||||
if (iteratorResolutionResults.isAmbiguity()) {
|
||||
// StringBuffer stringBuffer = new StringBuffer("Method 'iterator()' is ambiguous for this expression: ");
|
||||
// for (FunctionDescriptor functionDescriptor : iteratorResolutionResult.getDescriptors()) {
|
||||
// for (FunctionDescriptor functionDescriptor : iteratorResolutionResults.getResults()) {
|
||||
// stringBuffer.append(DescriptorRenderer.TEXT.render(functionDescriptor)).append(" ");
|
||||
// }
|
||||
// errorMessage = stringBuffer.toString();
|
||||
context.trace.report(ITERATOR_AMBIGUITY.on(loopRangeExpression, iteratorResolutionResult.getDescriptors()));
|
||||
context.trace.report(ITERATOR_AMBIGUITY.on(loopRangeExpression, iteratorResolutionResults.getResults()));
|
||||
}
|
||||
else {
|
||||
// context.trace.getErrorHandler().genericError(reportErrorsOn, errorMessage);
|
||||
@@ -1955,21 +1982,21 @@ public class JetTypeInferrer {
|
||||
|
||||
@Nullable
|
||||
private FunctionDescriptor checkHasNextFunctionSupport(@NotNull JetExpression loopRange, @NotNull JetType iteratorType, TypeInferenceContext context) {
|
||||
OverloadResolutionResult<FunctionDescriptor> hasNextResolutionResult = callResolver.resolveExactSignature(context.scope, new TransientReceiver(iteratorType), "hasNext", Collections.<JetType>emptyList());
|
||||
if (hasNextResolutionResult.isAmbiguity()) {
|
||||
OverloadResolutionResults<FunctionDescriptor> hasNextResolutionResults = context.resolveExactSignature(new TransientReceiver(iteratorType), "hasNext", Collections.<JetType>emptyList());
|
||||
if (hasNextResolutionResults.isAmbiguity()) {
|
||||
// context.trace.getErrorHandler().genericError(loopRange.getNode(), "Method 'iterator().hasNext()' is ambiguous for this expression");
|
||||
context.trace.report(HAS_NEXT_FUNCTION_AMBIGUITY.on(loopRange));
|
||||
} else if (hasNextResolutionResult.isNothing()) {
|
||||
} else if (hasNextResolutionResults.isNothing()) {
|
||||
return null;
|
||||
} else {
|
||||
assert hasNextResolutionResult.isSuccess();
|
||||
JetType hasNextReturnType = hasNextResolutionResult.getDescriptor().getReturnType();
|
||||
assert hasNextResolutionResults.isSuccess();
|
||||
JetType hasNextReturnType = hasNextResolutionResults.getResult().getResultingDescriptor().getReturnType();
|
||||
if (!isBoolean(hasNextReturnType)) {
|
||||
// context.trace.getErrorHandler().genericError(loopRange.getNode(), "The 'iterator().hasNext()' method of the loop range must return Boolean, but returns " + hasNextReturnType);
|
||||
context.trace.report(HAS_NEXT_FUNCTION_TYPE_MISMATCH.on(loopRange, hasNextReturnType));
|
||||
}
|
||||
}
|
||||
return hasNextResolutionResult.getDescriptor();
|
||||
return hasNextResolutionResults.getResult().getResultingDescriptor();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -2032,7 +2059,7 @@ public class JetTypeInferrer {
|
||||
VariableDescriptor variableDescriptor = cleanResolutionContext.services.getVariableDescriptorFromSimpleName(receiverExpression, context);
|
||||
boolean somethingFound = false;
|
||||
if (variableDescriptor != null) {
|
||||
List<JetType> possibleTypes = Lists.newArrayList(context.dataFlowInfo.getPossibleTypes(variableDescriptor));
|
||||
List<JetType> possibleTypes = Lists.newArrayList(context.dataFlowInfo.getPossibleTypesForVariable(variableDescriptor));
|
||||
Collections.reverse(possibleTypes);
|
||||
|
||||
TemporaryBindingTrace autocastResolutionTrace = TemporaryBindingTrace.create(context.trace);
|
||||
@@ -2163,13 +2190,13 @@ public class JetTypeInferrer {
|
||||
@Nullable
|
||||
private JetType getSelectorReturnType(@NotNull ReceiverDescriptor receiver, @NotNull JetExpression selectorExpression, @NotNull TypeInferenceContext context) {
|
||||
if (selectorExpression instanceof JetCallExpression) {
|
||||
return callResolver.resolveCall(context.trace, context.scope, receiver, (JetCallExpression) selectorExpression, context.expectedType);
|
||||
return context.resolveCall(receiver, (JetCallExpression) selectorExpression);
|
||||
}
|
||||
else if (selectorExpression instanceof JetSimpleNameExpression) {
|
||||
JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) selectorExpression;
|
||||
|
||||
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace);
|
||||
VariableDescriptor variableDescriptor = callResolver.resolveSimpleProperty(temporaryTrace, context.scope, receiver, nameExpression, context.expectedType);
|
||||
VariableDescriptor variableDescriptor = context.replaceBindingTrace(temporaryTrace).resolveSimpleProperty(receiver, nameExpression);
|
||||
if (variableDescriptor != null) {
|
||||
temporaryTrace.commit();
|
||||
return context.services.checkEnrichedType(variableDescriptor.getOutType(), nameExpression, context);
|
||||
@@ -2202,7 +2229,7 @@ public class JetTypeInferrer {
|
||||
|
||||
@Override
|
||||
public JetType visitCallExpression(JetCallExpression expression, TypeInferenceContext context) {
|
||||
JetType expressionType = callResolver.resolveCall(context.trace, context.scope, ReceiverDescriptor.NO_RECEIVER, expression, context.expectedType);
|
||||
JetType expressionType = context.resolveCall(ReceiverDescriptor.NO_RECEIVER, expression);
|
||||
return context.services.checkType(expressionType, expression, context);
|
||||
}
|
||||
|
||||
@@ -2239,14 +2266,11 @@ public class JetTypeInferrer {
|
||||
ExpressionReceiver receiver = getExpressionReceiver(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceScope(context.scope));
|
||||
if (receiver == null) return null;
|
||||
|
||||
FunctionDescriptor functionDescriptor = callResolver.resolveCallWithGivenName(
|
||||
context.trace,
|
||||
context.scope,
|
||||
FunctionDescriptor functionDescriptor = context.resolveCallWithGivenName(
|
||||
CallMaker.makeCall(expression),
|
||||
expression.getOperationSign(),
|
||||
name,
|
||||
receiver,
|
||||
context.expectedType);
|
||||
receiver);
|
||||
|
||||
if (functionDescriptor == null) return null;
|
||||
JetType returnType = functionDescriptor.getReturnType();
|
||||
@@ -2317,24 +2341,24 @@ public class JetTypeInferrer {
|
||||
String name = "equals";
|
||||
if (right != null) {
|
||||
ExpressionReceiver receiver = safeGetExpressionReceiver(left, context.replaceScope(context.scope));
|
||||
OverloadResolutionResult<FunctionDescriptor> resolutionResult = callResolver.resolveExactSignature(
|
||||
context.scope, receiver, "equals",
|
||||
OverloadResolutionResults<FunctionDescriptor> resolutionResults = context.resolveExactSignature(
|
||||
receiver, "equals",
|
||||
Collections.singletonList(JetStandardClasses.getNullableAnyType()));
|
||||
if (resolutionResult.isSuccess()) {
|
||||
FunctionDescriptor equals = resolutionResult.getDescriptor();
|
||||
if (resolutionResults.isSuccess()) {
|
||||
FunctionDescriptor equals = resolutionResults.getResult().getResultingDescriptor();
|
||||
context.trace.record(REFERENCE_TARGET, operationSign, equals);
|
||||
if (ensureBooleanResult(operationSign, name, equals.getReturnType(), context)) {
|
||||
ensureNonemptyIntersectionOfOperandTypes(expression, context);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (resolutionResult.isAmbiguity()) {
|
||||
if (resolutionResults.isAmbiguity()) {
|
||||
// StringBuilder stringBuilder = new StringBuilder();
|
||||
// for (FunctionDescriptor functionDescriptor : resolutionResult.getDescriptors()) {
|
||||
// for (FunctionDescriptor functionDescriptor : resolutionResults.getResults()) {
|
||||
// stringBuilder.append(DescriptorRenderer.TEXT.render(functionDescriptor)).append(" ");
|
||||
// }
|
||||
// context.trace.getErrorHandler().genericError(operationSign.getNode(), "Ambiguous function: " + stringBuilder);
|
||||
context.trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(operationSign, resolutionResult.getDescriptors()));
|
||||
context.trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(operationSign, resolutionResults.getResults()));
|
||||
}
|
||||
else {
|
||||
// context.trace.getErrorHandler().genericError(operationSign.getNode(), "No method 'equals(Any?) : Boolean' available");
|
||||
@@ -2398,12 +2422,10 @@ public class JetTypeInferrer {
|
||||
private void checkInExpression(JetSimpleNameExpression operationSign, JetExpression left, JetExpression right, TypeInferenceContext context) {
|
||||
String name = "contains";
|
||||
ExpressionReceiver receiver = safeGetExpressionReceiver(right, context.replaceExpectedType(NO_EXPECTED_TYPE));
|
||||
FunctionDescriptor functionDescriptor = callResolver.resolveCallWithGivenName(
|
||||
context.trace,
|
||||
context.scope,
|
||||
FunctionDescriptor functionDescriptor = context.resolveCallWithGivenName(
|
||||
CallMaker.makeCall(operationSign, Collections.singletonList(left)),
|
||||
operationSign,
|
||||
name, receiver, context.expectedType);
|
||||
name, receiver);
|
||||
JetType containsType = functionDescriptor != null ? functionDescriptor.getReturnType() : null;
|
||||
ensureBooleanResult(operationSign, name, containsType, context);
|
||||
}
|
||||
@@ -2469,14 +2491,11 @@ public class JetTypeInferrer {
|
||||
ExpressionReceiver receiver = getExpressionReceiver(arrayExpression, context.replaceScope(context.scope));
|
||||
|
||||
if (receiver != null) {
|
||||
FunctionDescriptor functionDescriptor = callResolver.resolveCallWithGivenName(
|
||||
context.trace,
|
||||
context.scope,
|
||||
FunctionDescriptor functionDescriptor = context.resolveCallWithGivenName(
|
||||
CallMaker.makeCall(expression, expression.getIndexExpressions()),
|
||||
expression,
|
||||
expression,
|
||||
"get",
|
||||
receiver,
|
||||
context.expectedType);
|
||||
receiver);
|
||||
if (functionDescriptor != null) {
|
||||
return context.services.checkType(functionDescriptor.getReturnType(), expression, contextWithExpectedType);
|
||||
}
|
||||
@@ -2487,14 +2506,11 @@ public class JetTypeInferrer {
|
||||
@Nullable
|
||||
protected JetType getTypeForBinaryCall(JetScope scope, String name, TypeInferenceContext context, JetBinaryExpression binaryExpression) {
|
||||
ExpressionReceiver receiver = safeGetExpressionReceiver(binaryExpression.getLeft(), context.replaceScope(scope));
|
||||
FunctionDescriptor functionDescriptor = callResolver.resolveCallWithGivenName(
|
||||
context.trace,
|
||||
scope,
|
||||
FunctionDescriptor functionDescriptor = context.replaceScope(scope).resolveCallWithGivenName(
|
||||
CallMaker.makeCall(binaryExpression),
|
||||
binaryExpression.getOperationReference(),
|
||||
name,
|
||||
receiver,
|
||||
context.expectedType);
|
||||
receiver);
|
||||
if (functionDescriptor != null) {
|
||||
if (receiver.getType().isNullable()) {
|
||||
// TODO : better error message for '1 + nullableVar' case
|
||||
@@ -2746,12 +2762,10 @@ public class JetTypeInferrer {
|
||||
// call,
|
||||
// arrayAccessExpression,
|
||||
// "set", arrayAccessExpression.getArrayExpression(), NO_EXPECTED_TYPE);
|
||||
FunctionDescriptor functionDescriptor = callResolver.resolveCallWithGivenName(
|
||||
context.trace,
|
||||
scope,
|
||||
FunctionDescriptor functionDescriptor = context.replaceScope(scope).replaceExpectedType(NO_EXPECTED_TYPE).resolveCallWithGivenName(
|
||||
call,
|
||||
arrayAccessExpression,
|
||||
"set", receiver, NO_EXPECTED_TYPE);
|
||||
"set", receiver);
|
||||
if (functionDescriptor == null) return null;
|
||||
context.trace.record(REFERENCE_TARGET, operationSign, functionDescriptor);
|
||||
return context.services.checkType(functionDescriptor.getReturnType(), arrayAccessExpression, context);
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
||||
import org.jetbrains.jet.lang.diagnostics.UnresolvedReferenceDiagnostic;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.plugin.AnalyzerFacade;
|
||||
@@ -91,7 +92,7 @@ public class DebugInfoAnnotator implements Annotator {
|
||||
target = labelTarget.getText();
|
||||
}
|
||||
else {
|
||||
Collection<? extends DeclarationDescriptor> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, expression);
|
||||
Collection<? extends ResolvedCall<? extends DeclarationDescriptor>> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, expression);
|
||||
if (declarationDescriptors != null) {
|
||||
target = "[" + declarationDescriptors.size() + " descriptors]";
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||
import org.jetbrains.jet.plugin.AnalyzerFacade;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -80,7 +81,7 @@ public abstract class JetPsiReference implements PsiPolyVariantReference {
|
||||
if (psiElement != null) {
|
||||
return psiElement;
|
||||
}
|
||||
Collection<? extends DeclarationDescriptor> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression);
|
||||
Collection<? extends ResolvedCall<? extends DeclarationDescriptor>> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression);
|
||||
if (declarationDescriptors != null) return null;
|
||||
return file;
|
||||
}
|
||||
@@ -88,12 +89,12 @@ public abstract class JetPsiReference implements PsiPolyVariantReference {
|
||||
protected ResolveResult[] doMultiResolve() {
|
||||
JetFile file = (JetFile) getElement().getContainingFile();
|
||||
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
|
||||
Collection<? extends DeclarationDescriptor> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression);
|
||||
if (declarationDescriptors == null) return ResolveResult.EMPTY_ARRAY;
|
||||
ResolveResult[] results = new ResolveResult[declarationDescriptors.size()];
|
||||
Collection<? extends ResolvedCall<? extends DeclarationDescriptor>> resolvedCalls = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression);
|
||||
if (resolvedCalls == null) return ResolveResult.EMPTY_ARRAY;
|
||||
ResolveResult[] results = new ResolveResult[resolvedCalls.size()];
|
||||
int i = 0;
|
||||
for (DeclarationDescriptor descriptor : declarationDescriptors) {
|
||||
PsiElement element = bindingContext.get(DESCRIPTOR_TO_DECLARATION, descriptor);
|
||||
for (ResolvedCall<? extends DeclarationDescriptor> resolvedCall : resolvedCalls) {
|
||||
PsiElement element = bindingContext.get(DESCRIPTOR_TO_DECLARATION, resolvedCall.getResultingDescriptor());
|
||||
if (element != null) {
|
||||
results[i] = new PsiElementResolveResult(element, true);
|
||||
i++;
|
||||
|
||||
@@ -15,7 +15,8 @@ import org.jetbrains.jet.lang.JetSemanticServices;
|
||||
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
|
||||
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResult;
|
||||
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
|
||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.parsing.JetParsingTest;
|
||||
@@ -107,14 +108,14 @@ public class JetResolveTest extends ExtensibleResolveTestCase {
|
||||
List<JetType> parameterTypeList = Arrays.asList(parameterType);
|
||||
JetTypeInferrer.Services typeInferrerServices = JetSemanticServices.createSemanticServices(getProject()).getTypeInferrerServices(new BindingTraceContext(), JetFlowInformationProvider.NONE);
|
||||
|
||||
OverloadResolutionResult<FunctionDescriptor> functions = typeInferrerServices.getCallResolver().resolveExactSignature(
|
||||
OverloadResolutionResults<FunctionDescriptor> functions = typeInferrerServices.getCallResolver().resolveExactSignature(
|
||||
classDescriptor.getMemberScope(typeArguments), ReceiverDescriptor.NO_RECEIVER, name, parameterTypeList);
|
||||
for (FunctionDescriptor function : functions.getDescriptors()) {
|
||||
List<ValueParameterDescriptor> unsubstitutedValueParameters = function.getValueParameters();
|
||||
for (ResolvedCall<FunctionDescriptor> resolvedCall : functions.getResults()) {
|
||||
List<ValueParameterDescriptor> unsubstitutedValueParameters = resolvedCall.getResultingDescriptor().getValueParameters();
|
||||
for (int i = 0, unsubstitutedValueParametersSize = unsubstitutedValueParameters.size(); i < unsubstitutedValueParametersSize; i++) {
|
||||
ValueParameterDescriptor unsubstitutedValueParameter = unsubstitutedValueParameters.get(i);
|
||||
if (unsubstitutedValueParameter.getOutType().equals(parameterType[i])) {
|
||||
return function;
|
||||
return resolvedCall.getResultingDescriptor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user