Call resolver refactored to store results in objects of ResolvedCall class

This commit is contained in:
Andrey Breslav
2011-10-05 20:28:28 +04:00
parent d58fa2184b
commit 6e6698006b
25 changed files with 865 additions and 456 deletions
@@ -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;
@@ -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);
}
};
}
@@ -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);
}
}
@@ -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);
// }
}
@@ -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);
@@ -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();
}
}
}