Call resolution refactoring (logic hasn't changed)

- interfaces MemberPrioritizer, ResolutionCandidate introduced
- CallTransformationStrategy will be responsible for variable with 'invoke' method as function resolve
This commit is contained in:
Svetlana Isakova
2012-04-20 15:52:27 +04:00
parent 13764c06c0
commit 5ec7617c7a
12 changed files with 506 additions and 244 deletions
@@ -0,0 +1,40 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.psi.Call;
import org.jetbrains.jet.lang.resolve.BindingTrace;
/**
* @author svtk
*/
public final class CallResolutionContext<D extends CallableDescriptor> extends ResolutionContext {
/*package*/ final ResolvedCallImpl<D> candidateCall;
/*package*/ final TracingStrategy tracing;
public CallResolutionContext(@NotNull ResolvedCallImpl<D> candidateCall, @NotNull ResolutionTask<D> task, @NotNull BindingTrace trace, @NotNull TracingStrategy tracing, @NotNull Call call) {
super(trace, task.scope, call, task.expectedType, task.dataFlowInfo);
this.candidateCall = candidateCall;
this.tracing = tracing;
}
public CallResolutionContext(@NotNull ResolvedCallImpl<D> candidateCall, @NotNull ResolutionTask<D> task, @NotNull BindingTrace trace, @NotNull TracingStrategy tracing) {
this(candidateCall, task, trace, tracing, task.call);
}
}
@@ -102,16 +102,16 @@ public class CallResolver {
if (referencedName == null) { if (referencedName == null) {
return OverloadResolutionResultsImpl.nameNotFound(); return OverloadResolutionResultsImpl.nameNotFound();
} }
TaskPrioritizer<VariableDescriptor> task_prioritizer; List<MemberPrioritizer<VariableDescriptor>> memberPrioritizers = Lists.newArrayList();
if (nameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) { if (nameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
referencedName = referencedName.substring(1); referencedName = referencedName.substring(1);
task_prioritizer = TaskPrioritizers.PROPERTY_TASK_PRIORITIZER; memberPrioritizers.add(MemberPrioritizers.PROPERTY_TASK_PRIORITIZER);
} }
else { else {
task_prioritizer = TaskPrioritizers.VARIABLE_TASK_PRIORITIZER; memberPrioritizers.add(MemberPrioritizers.VARIABLE_TASK_PRIORITIZER);
} }
List<ResolutionTask<VariableDescriptor>> prioritizedTasks = task_prioritizer.computePrioritizedTasks(context, referencedName, nameExpression); List<ResolutionTask<VariableDescriptor>> prioritizedTasks = TaskPrioritizer.computePrioritizedTasks(context, referencedName, nameExpression, memberPrioritizers);
return doResolveCall(context, prioritizedTasks, nameExpression); return doResolveCall(context, prioritizedTasks, CallTransformationStrategy.PROPERTY_CALL_TRANSFORMATION_STRATEGY, nameExpression);
} }
@NotNull @NotNull
@@ -119,9 +119,9 @@ public class CallResolver {
@NotNull BasicResolutionContext context, @NotNull BasicResolutionContext context,
@NotNull final JetReferenceExpression functionReference, @NotNull final JetReferenceExpression functionReference,
@NotNull String name) { @NotNull String name) {
List<ResolutionTask<FunctionDescriptor>> tasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks( List<ResolutionTask<FunctionDescriptor>> tasks = TaskPrioritizer.computePrioritizedTasks(
context, name, functionReference); context, name, functionReference, Collections.singletonList(MemberPrioritizers.FUNCTION_TASK_PRIORITIZER));
return doResolveCall(context, tasks, functionReference); return doResolveCall(context, tasks, CallTransformationStrategy.FUNCTION_CALL_TRANSFORMATION_STRATEGY, functionReference);
} }
@NotNull @NotNull
@@ -142,7 +142,7 @@ public class CallResolver {
String name = expression.getReferencedName(); String name = expression.getReferencedName();
if (name == null) return checkArgumentTypesAndFail(context); if (name == null) return checkArgumentTypesAndFail(context);
prioritizedTasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(context, name, functionReference); prioritizedTasks = TaskPrioritizer.computePrioritizedTasks(context, name, functionReference, Collections.singletonList(MemberPrioritizers.FUNCTION_TASK_PRIORITIZER));
ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() { ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() {
@Override @Override
public <D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) { public <D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) {
@@ -184,7 +184,7 @@ public class CallResolver {
context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn)); context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
return checkArgumentTypesAndFail(context); return checkArgumentTypesAndFail(context);
} }
Collection<ResolvedCallImpl<FunctionDescriptor>> candidates = TaskPrioritizer.<FunctionDescriptor>convertWithImpliedThis(context.scope, Collections.<ReceiverDescriptor>singletonList(NO_RECEIVER), constructors); Collection<ResolutionCandidate<FunctionDescriptor>> candidates = TaskPrioritizer.<FunctionDescriptor>convertWithImpliedThis(context.scope, Collections.<ReceiverDescriptor>singletonList(NO_RECEIVER), constructors);
prioritizedTasks.add(new ResolutionTask<FunctionDescriptor>(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY prioritizedTasks.add(new ResolutionTask<FunctionDescriptor>(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY
} }
else { else {
@@ -206,7 +206,7 @@ public class CallResolver {
context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn)); context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
return checkArgumentTypesAndFail(context); return checkArgumentTypesAndFail(context);
} }
List<ResolvedCallImpl<FunctionDescriptor>> candidates = ResolvedCallImpl.<FunctionDescriptor>convertCollection(constructors); List<ResolutionCandidate<FunctionDescriptor>> candidates = ResolutionCandidate.<FunctionDescriptor>convertCollection(constructors);
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY
} }
else if (calleeExpression != null) { else if (calleeExpression != null) {
@@ -223,15 +223,15 @@ public class CallResolver {
FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(context.scope.getContainingDeclaration(), "[for expression " + calleeExpression.getText() + "]"); FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(context.scope.getContainingDeclaration(), "[for expression " + calleeExpression.getText() + "]");
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType, NO_RECEIVER); FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType, NO_RECEIVER);
ResolvedCallImpl<FunctionDescriptor> resolvedCall = ResolvedCallImpl.<FunctionDescriptor>create(functionDescriptor); ResolutionCandidate<FunctionDescriptor> resolutionCandidate = ResolutionCandidate.<FunctionDescriptor>create(functionDescriptor);
resolvedCall.setReceiverArgument(context.call.getExplicitReceiver()); resolutionCandidate.setReceiverArgument(context.call.getExplicitReceiver());
// strictly speaking, this is a hack: // strictly speaking, this is a hack:
// we need to pass a reference, but there's no reference in the PSI, // we need to pass a reference, but there's no reference in the PSI,
// so we wrap what we have into a fake reference and pass it on (unwrap on the other end) // so we wrap what we have into a fake reference and pass it on (unwrap on the other end)
functionReference = new JetFakeReference(calleeExpression); functionReference = new JetFakeReference(calleeExpression);
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(Collections.singleton(resolvedCall), functionReference, context)); prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(Collections.singleton(resolutionCandidate), functionReference, context));
} }
else { else {
// checkTypesWithNoCallee(trace, scope, call); // checkTypesWithNoCallee(trace, scope, call);
@@ -239,7 +239,7 @@ public class CallResolver {
} }
} }
return doResolveCall(context, prioritizedTasks, functionReference); return doResolveCall(context, prioritizedTasks, CallTransformationStrategy.FUNCTION_CALL_TRANSFORMATION_STRATEGY, functionReference);
} }
private <D extends CallableDescriptor> OverloadResolutionResults<D> checkArgumentTypesAndFail(BasicResolutionContext context) { private <D extends CallableDescriptor> OverloadResolutionResults<D> checkArgumentTypesAndFail(BasicResolutionContext context) {
@@ -251,6 +251,7 @@ public class CallResolver {
private <D extends CallableDescriptor> OverloadResolutionResults<D> doResolveCall( private <D extends CallableDescriptor> OverloadResolutionResults<D> doResolveCall(
@NotNull final BasicResolutionContext context, @NotNull final BasicResolutionContext context,
@NotNull final List<ResolutionTask<D>> prioritizedTasks, // high to low priority @NotNull final List<ResolutionTask<D>> prioritizedTasks, // high to low priority
@NotNull CallTransformationStrategy<D, D> callTransformationStrategy,
@NotNull final JetReferenceExpression reference) { @NotNull final JetReferenceExpression reference) {
ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create(); ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create();
@@ -267,7 +268,7 @@ public class CallResolver {
OverloadResolutionResultsImpl<D> resultsForFirstNonemptyCandidateSet = null; OverloadResolutionResultsImpl<D> resultsForFirstNonemptyCandidateSet = null;
for (ResolutionTask<D> task : prioritizedTasks) { for (ResolutionTask<D> task : prioritizedTasks) {
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace); TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace);
OverloadResolutionResultsImpl<D> results = performResolutionGuardedForExtraFunctionLiteralArguments(task.withTrace(temporaryTrace)); OverloadResolutionResultsImpl<D> results = performResolutionGuardedForExtraFunctionLiteralArguments(task.withTrace(temporaryTrace), callTransformationStrategy);
if (results.isSuccess() || results.isAmbiguity()) { if (results.isSuccess() || results.isAmbiguity()) {
temporaryTrace.commit(); temporaryTrace.commit();
@@ -299,8 +300,9 @@ public class CallResolver {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@NotNull @NotNull
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> performResolutionGuardedForExtraFunctionLiteralArguments(ResolutionTask<D> task) { private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> performResolutionGuardedForExtraFunctionLiteralArguments(@NotNull ResolutionTask<D> task,
OverloadResolutionResultsImpl<D> results = performResolution(task); @NotNull CallTransformationStrategy<D, D> callTransformationStrategy) {
OverloadResolutionResultsImpl<D> results = performResolution(task, callTransformationStrategy);
// If resolution fails, we should check for some of the following situations: // If resolution fails, we should check for some of the following situations:
// class A { // class A {
@@ -323,9 +325,9 @@ public class CallResolver {
// We have some candidates that failed for some reason // We have some candidates that failed for some reason
// And we have a suspect: the function literal argument // And we have a suspect: the function literal argument
// Now, we try to remove this argument and see if it helps // Now, we try to remove this argument and see if it helps
Collection<ResolvedCallImpl<D>> newCandidates = Lists.newArrayList(); Collection<ResolutionCandidate<D>> newCandidates = Lists.newArrayList();
for (ResolvedCallImpl<D> candidate : task.getCandidates()) { for (ResolutionCandidate<D> candidate : task.getCandidates()) {
newCandidates.add(ResolvedCallImpl.create(candidate.getCandidateDescriptor())); newCandidates.add(ResolutionCandidate.create(candidate.getDescriptor()));
} }
ResolutionTask<D> newContext = new ResolutionTask<D>(newCandidates, task.reference, TemporaryBindingTrace.create(task.trace), task.scope, new DelegatingCall(task.call) { ResolutionTask<D> newContext = new ResolutionTask<D>(newCandidates, task.reference, TemporaryBindingTrace.create(task.trace), task.scope, new DelegatingCall(task.call) {
@NotNull @NotNull
@@ -334,7 +336,7 @@ public class CallResolver {
return Collections.emptyList(); return Collections.emptyList();
} }
}, task.expectedType, task.dataFlowInfo); }, task.expectedType, task.dataFlowInfo);
OverloadResolutionResultsImpl<D> resultsWithFunctionLiteralsStripped = performResolution(newContext); OverloadResolutionResultsImpl<D> resultsWithFunctionLiteralsStripped = performResolution(newContext, callTransformationStrategy);
if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) { if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) {
task.tracing.danglingFunctionLiteralArgumentSuspected(task.trace, task.call.getFunctionLiteralArguments()); task.tracing.danglingFunctionLiteralArgumentSuspected(task.trace, task.call.getFunctionLiteralArguments());
} }
@@ -344,101 +346,23 @@ public class CallResolver {
} }
@NotNull @NotNull
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> performResolution(ResolutionTask<D> task) { private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> performResolution(@NotNull ResolutionTask<D> task,
for (ResolvedCallImpl<D> candidateCall : task.getCandidates()) { @NotNull CallTransformationStrategy<D, D> callTransformationStrategy) {
D candidate = candidateCall.getCandidateDescriptor();
for (ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) {
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(task.trace); TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(task.trace);
candidateCall.setTrace(temporaryTrace); CallResolutionContext<D> context = callTransformationStrategy.createCallContext(resolutionCandidate, task, temporaryTrace, task.tracing);
performResolutionForCandidateCall(context, task, temporaryTrace);
CallResolutionContext<D> context = new CallResolutionContext<D>(candidateCall, task, temporaryTrace, task.tracing); Collection<ResolvedCallImpl<D>> calls = callTransformationStrategy.transformResultCall(context, this, task);
for (ResolvedCallImpl<D> call : calls) {
context.tracing.bindReference(context.trace, candidateCall); task.getResolvedCallMap().put(resolutionCandidate, call);
if (ErrorUtils.isError(candidate)) {
candidateCall.setStatus(SUCCESS);
checkTypesWithNoCallee(context.toBasic());
continue;
} }
if (!Visibilities.isVisible(candidate, context.scope.getContainingDeclaration())) {
candidateCall.setStatus(OTHER_ERROR);
context.tracing.invisibleMember(context.trace, candidate);
continue;
}
boolean errorInArgumentMapping = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(context.call, context.tracing, candidateCall);
if (errorInArgumentMapping) {
candidateCall.setStatus(OTHER_ERROR);
checkTypesWithNoCallee(context.toBasic());
continue;
}
List<JetTypeProjection> jetTypeArguments = context.call.getTypeArguments();
if (jetTypeArguments.isEmpty()) {
if (!candidate.getTypeParameters().isEmpty()) {
candidateCall.setStatus(inferTypeArguments(context));
}
else {
candidateCall.setStatus(checkAllValueArguments(context));
}
}
else {
// Explicit type arguments passed
List<JetType> typeArguments = new ArrayList<JetType>();
for (JetTypeProjection projection : jetTypeArguments) {
if (projection.getProjectionKind() != JetProjectionKind.NONE) {
context.trace.report(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(projection));
}
JetTypeReference typeReference = projection.getTypeReference();
if (typeReference != null) {
typeArguments.add(typeResolver.resolveType(context.scope, typeReference, context.trace, true));
}
else {
typeArguments.add(ErrorUtils.createErrorType("Star projection in a call"));
}
}
int expectedTypeArgumentCount = candidate.getTypeParameters().size();
if (expectedTypeArgumentCount == jetTypeArguments.size()) {
checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate, context.trace);
Map<TypeConstructor, TypeProjection> substitutionContext = FunctionDescriptorUtil.createSubstitutionContext((FunctionDescriptor) candidate, typeArguments);
D substitutedDescriptor = (D) candidate.substitute(TypeSubstitutor.create(substitutionContext));
candidateCall.setResultingDescriptor(substitutedDescriptor);
replaceValueParametersWithSubstitutedOnes(candidateCall, substitutedDescriptor);
List<TypeParameterDescriptor> typeParameters = candidateCall.getCandidateDescriptor().getTypeParameters();
for (int i = 0; i < typeParameters.size(); i++) {
TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
candidateCall.recordTypeArgument(typeParameterDescriptor, typeArguments.get(i));
}
candidateCall.setStatus(checkAllValueArguments(context));
}
else {
candidateCall.setStatus(OTHER_ERROR);
context.tracing.wrongNumberOfTypeArguments(context.trace, expectedTypeArgumentCount);
}
}
task.performAdvancedChecks(candidate, context.trace, context.tracing);
// 'super' cannot be passed as an argument, for receiver arguments expression typer does not track this
// See TaskPrioritizer for more
JetSuperExpression superExpression = TaskPrioritizer.getReceiverSuper(candidateCall.getReceiverArgument());
if (superExpression != null) {
context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(superExpression, superExpression.getText()));
candidateCall.setStatus(OTHER_ERROR);
}
recordAutoCastIfNecessary(candidateCall.getReceiverArgument(), candidateCall.getTrace());
recordAutoCastIfNecessary(candidateCall.getThisObject(), candidateCall.getTrace());
} }
Set<ResolvedCallImpl<D>> successfulCandidates = Sets.newLinkedHashSet(); Set<ResolvedCallImpl<D>> successfulCandidates = Sets.newLinkedHashSet();
Set<ResolvedCallImpl<D>> failedCandidates = Sets.newLinkedHashSet(); Set<ResolvedCallImpl<D>> failedCandidates = Sets.newLinkedHashSet();
for (ResolvedCallImpl<D> candidateCall : task.getCandidates()) { for (ResolvedCallImpl<D> candidateCall : task.getResolvedCallMap().values()) {
ResolutionStatus status = candidateCall.getStatus(); ResolutionStatus status = candidateCall.getStatus();
if (status.isSuccess()) { if (status.isSuccess()) {
successfulCandidates.add(candidateCall); successfulCandidates.add(candidateCall);
@@ -456,6 +380,99 @@ public class CallResolver {
return results; return results;
} }
private <D extends CallableDescriptor> void performResolutionForCandidateCall(@NotNull CallResolutionContext<D> context,
@NotNull ResolutionTask<D> task,
@NotNull TemporaryBindingTrace temporaryTrace) {
ResolvedCallImpl<D> candidateCall = context.candidateCall;
candidateCall.setTrace(temporaryTrace);
D candidate = candidateCall.getCandidateDescriptor();
context.tracing.bindReference(context.trace, candidateCall);
if (ErrorUtils.isError(candidate)) {
candidateCall.setStatus(SUCCESS);
checkTypesWithNoCallee(context.toBasic());
return;
}
if (!Visibilities.isVisible(candidate, context.scope.getContainingDeclaration())) {
candidateCall.setStatus(OTHER_ERROR);
context.tracing.invisibleMember(context.trace, candidate);
return;
}
boolean errorInArgumentMapping = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(context.call, context.tracing, candidateCall);
if (errorInArgumentMapping) {
candidateCall.setStatus(OTHER_ERROR);
checkTypesWithNoCallee(context.toBasic());
return;
}
List<JetTypeProjection> jetTypeArguments = context.call.getTypeArguments();
if (jetTypeArguments.isEmpty()) {
if (!candidate.getTypeParameters().isEmpty()) {
candidateCall.setStatus(inferTypeArguments(context));
}
else {
candidateCall.setStatus(checkAllValueArguments(context));
}
}
else {
// Explicit type arguments passed
List<JetType> typeArguments = new ArrayList<JetType>();
for (JetTypeProjection projection : jetTypeArguments) {
if (projection.getProjectionKind() != JetProjectionKind.NONE) {
context.trace.report(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(projection));
}
JetTypeReference typeReference = projection.getTypeReference();
if (typeReference != null) {
typeArguments.add(typeResolver.resolveType(context.scope, typeReference, context.trace, true));
}
else {
typeArguments.add(ErrorUtils.createErrorType("Star projection in a call"));
}
}
int expectedTypeArgumentCount = candidate.getTypeParameters().size();
if (expectedTypeArgumentCount == jetTypeArguments.size()) {
checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate, context.trace);
Map<TypeConstructor, TypeProjection>
substitutionContext = FunctionDescriptorUtil.createSubstitutionContext((FunctionDescriptor)candidate, typeArguments);
D substitutedDescriptor = (D) candidate.substitute(TypeSubstitutor.create(substitutionContext));
candidateCall.setResultingDescriptor(substitutedDescriptor);
replaceValueParametersWithSubstitutedOnes(candidateCall, substitutedDescriptor);
List<TypeParameterDescriptor> typeParameters = candidateCall.getCandidateDescriptor().getTypeParameters();
for (int i = 0; i < typeParameters.size(); i++) {
TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
candidateCall.recordTypeArgument(typeParameterDescriptor, typeArguments.get(i));
}
candidateCall.setStatus(checkAllValueArguments(context));
}
else {
candidateCall.setStatus(OTHER_ERROR);
context.tracing.wrongNumberOfTypeArguments(context.trace, expectedTypeArgumentCount);
}
}
task.performAdvancedChecks(candidate, context.trace, context.tracing);
// 'super' cannot be passed as an argument, for receiver arguments expression typer does not track this
// See TaskPrioritizer for more
JetSuperExpression superExpression = TaskPrioritizer.getReceiverSuper(candidateCall.getReceiverArgument());
if (superExpression != null) {
context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(superExpression, superExpression.getText()));
candidateCall.setStatus(OTHER_ERROR);
}
recordAutoCastIfNecessary(candidateCall.getReceiverArgument(), candidateCall.getTrace());
recordAutoCastIfNecessary(candidateCall.getThisObject(), candidateCall.getTrace());
}
private <D extends CallableDescriptor> ResolutionStatus inferTypeArguments(CallResolutionContext<D> context) { private <D extends CallableDescriptor> ResolutionStatus inferTypeArguments(CallResolutionContext<D> context) {
ResolvedCallImpl<D> candidateCall = context.candidateCall; ResolvedCallImpl<D> candidateCall = context.candidateCall;
D candidate = candidateCall.getCandidateDescriptor(); D candidate = candidateCall.getCandidateDescriptor();
@@ -843,25 +860,26 @@ public class CallResolver {
@NotNull @NotNull
public OverloadResolutionResults<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<ResolvedCallImpl<FunctionDescriptor>> result = findCandidatesByExactSignature(scope, receiver, name, parameterTypes); List<ResolutionCandidate<FunctionDescriptor>> candidates = findCandidatesByExactSignature(scope, receiver, name, parameterTypes);
BindingTraceContext trace = new BindingTraceContext(); BindingTraceContext trace = new BindingTraceContext();
TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(trace); TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(trace);
Set<ResolvedCallImpl<FunctionDescriptor>> candidates = Sets.newLinkedHashSet(); Set<ResolvedCallImpl<FunctionDescriptor>> calls = Sets.newLinkedHashSet();
for (ResolvedCallImpl<FunctionDescriptor> call : result) { for (ResolutionCandidate<FunctionDescriptor> candidate : candidates) {
ResolvedCallImpl<FunctionDescriptor> call = ResolvedCallImpl.create(candidate);
call.setTrace(temporaryBindingTrace); call.setTrace(temporaryBindingTrace);
candidates.add(call); calls.add(call);
} }
return computeResultAndReportErrors(trace, TracingStrategy.EMPTY, candidates, Collections.<ResolvedCallImpl<FunctionDescriptor>>emptySet()); return computeResultAndReportErrors(trace, TracingStrategy.EMPTY, calls, Collections.<ResolvedCallImpl<FunctionDescriptor>>emptySet());
} }
private List<ResolvedCallImpl<FunctionDescriptor>> findCandidatesByExactSignature(JetScope scope, ReceiverDescriptor receiver, private List<ResolutionCandidate<FunctionDescriptor>> findCandidatesByExactSignature(JetScope scope, ReceiverDescriptor receiver,
String name, List<JetType> parameterTypes) { String name, List<JetType> parameterTypes) {
List<ResolvedCallImpl<FunctionDescriptor>> result = Lists.newArrayList(); List<ResolutionCandidate<FunctionDescriptor>> result = Lists.newArrayList();
if (receiver.exists()) { if (receiver.exists()) {
Collection<ResolvedCallImpl<FunctionDescriptor>> extensionFunctionDescriptors = ResolvedCallImpl.convertCollection(scope.getFunctions(name)); Collection<ResolutionCandidate<FunctionDescriptor>> extensionFunctionDescriptors = ResolutionCandidate.convertCollection(scope.getFunctions(name));
List<ResolvedCallImpl<FunctionDescriptor>> nonlocal = Lists.newArrayList(); List<ResolutionCandidate<FunctionDescriptor>> nonlocal = Lists.newArrayList();
List<ResolvedCallImpl<FunctionDescriptor>> local = Lists.newArrayList(); List<ResolutionCandidate<FunctionDescriptor>> local = Lists.newArrayList();
TaskPrioritizer.splitLexicallyLocalDescriptors(extensionFunctionDescriptors, scope.getContainingDeclaration(), local, nonlocal); TaskPrioritizer.splitLexicallyLocalDescriptors(extensionFunctionDescriptors, scope.getContainingDeclaration(), local, nonlocal);
@@ -869,7 +887,7 @@ public class CallResolver {
return result; return result;
} }
Collection<ResolvedCallImpl<FunctionDescriptor>> functionDescriptors = ResolvedCallImpl.convertCollection(receiver.getType().getMemberScope().getFunctions(name)); Collection<ResolutionCandidate<FunctionDescriptor>> functionDescriptors = ResolutionCandidate.convertCollection(receiver.getType().getMemberScope().getFunctions(name));
if (lookupExactSignature(functionDescriptors, parameterTypes, result)) { if (lookupExactSignature(functionDescriptors, parameterTypes, result)) {
return result; return result;
@@ -878,16 +896,16 @@ public class CallResolver {
return result; return result;
} }
else { else {
lookupExactSignature(ResolvedCallImpl.convertCollection(scope.getFunctions(name)), parameterTypes, result); lookupExactSignature(ResolutionCandidate.convertCollection(scope.getFunctions(name)), parameterTypes, result);
return result; return result;
} }
} }
private static boolean lookupExactSignature(Collection<ResolvedCallImpl<FunctionDescriptor>> candidates, List<JetType> parameterTypes, private static boolean lookupExactSignature(Collection<ResolutionCandidate<FunctionDescriptor>> candidates, List<JetType> parameterTypes,
List<ResolvedCallImpl<FunctionDescriptor>> result) { List<ResolutionCandidate<FunctionDescriptor>> result) {
boolean found = false; boolean found = false;
for (ResolvedCallImpl<FunctionDescriptor> resolvedCall : candidates) { for (ResolutionCandidate<FunctionDescriptor> resolvedCall : candidates) {
FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor(); FunctionDescriptor functionDescriptor = resolvedCall.getDescriptor();
if (functionDescriptor.getReceiverParameter().exists()) continue; if (functionDescriptor.getReceiverParameter().exists()) continue;
if (!functionDescriptor.getTypeParameters().isEmpty()) continue; if (!functionDescriptor.getTypeParameters().isEmpty()) continue;
if (!checkValueParameters(functionDescriptor, parameterTypes)) continue; if (!checkValueParameters(functionDescriptor, parameterTypes)) continue;
@@ -897,17 +915,17 @@ public class CallResolver {
return found; return found;
} }
private boolean findExtensionFunctions(Collection<ResolvedCallImpl<FunctionDescriptor>> candidates, ReceiverDescriptor receiver, private boolean findExtensionFunctions(Collection<ResolutionCandidate<FunctionDescriptor>> candidates, ReceiverDescriptor receiver,
List<JetType> parameterTypes, List<ResolvedCallImpl<FunctionDescriptor>> result) { List<JetType> parameterTypes, List<ResolutionCandidate<FunctionDescriptor>> result) {
boolean found = false; boolean found = false;
for (ResolvedCallImpl<FunctionDescriptor> resolvedCall : candidates) { for (ResolutionCandidate<FunctionDescriptor> candidate : candidates) {
FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor(); FunctionDescriptor functionDescriptor = candidate.getDescriptor();
ReceiverDescriptor functionReceiver = functionDescriptor.getReceiverParameter(); ReceiverDescriptor functionReceiver = functionDescriptor.getReceiverParameter();
if (!functionReceiver.exists()) continue; if (!functionReceiver.exists()) continue;
if (!functionDescriptor.getTypeParameters().isEmpty()) continue; if (!functionDescriptor.getTypeParameters().isEmpty()) continue;
if (!typeChecker.isSubtypeOf(receiver.getType(), functionReceiver.getType())) continue; if (!typeChecker.isSubtypeOf(receiver.getType(), functionReceiver.getType())) continue;
if (!checkValueParameters(functionDescriptor, parameterTypes))continue; if (!checkValueParameters(functionDescriptor, parameterTypes))continue;
result.add(resolvedCall); result.add(candidate);
found = true; found = true;
} }
return found; return found;
@@ -923,15 +941,4 @@ public class CallResolver {
} }
return true; return true;
} }
private static final class CallResolutionContext<D extends CallableDescriptor> extends ResolutionContext {
/*package*/ final ResolvedCallImpl<D> candidateCall;
/*package*/ final TracingStrategy tracing;
public CallResolutionContext(ResolvedCallImpl<D> candidateCall, ResolutionTask<D> task, BindingTrace trace, TracingStrategy tracing) {
super(trace, task.scope, task.call, task.expectedType, task.dataFlowInfo);
this.candidateCall = candidateCall;
this.tracing = tracing;
}
}
} }
@@ -0,0 +1,118 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* @author svtk
*/
public interface CallTransformationStrategy<D extends CallableDescriptor, R extends D> {
@NotNull
CallResolutionContext<D> createCallContext(@NotNull ResolutionCandidate<D> candidate,
@NotNull ResolutionTask<D> task,
@NotNull BindingTrace trace,
@NotNull TracingStrategy tracing);
@NotNull
Collection<ResolvedCallImpl<R>> transformResultCall(@NotNull CallResolutionContext<D> callResolutionContext,
@NotNull CallResolver callResolver,
@NotNull ResolutionTask<D> task);
CallTransformationStrategy<VariableDescriptor, VariableDescriptor>
PROPERTY_CALL_TRANSFORMATION_STRATEGY = new CallTransformationStrategy<VariableDescriptor, VariableDescriptor>() {
@NotNull
@Override
public CallResolutionContext<VariableDescriptor> createCallContext(@NotNull ResolutionCandidate<VariableDescriptor> candidate,
@NotNull ResolutionTask<VariableDescriptor> task, @NotNull BindingTrace trace, @NotNull TracingStrategy tracing) {
ResolvedCallImpl<VariableDescriptor> candidateCall = ResolvedCallImpl.create(candidate);
return new CallResolutionContext<VariableDescriptor>(candidateCall, task, trace, tracing);
}
@NotNull
@Override
public Collection<ResolvedCallImpl<VariableDescriptor>> transformResultCall(@NotNull CallResolutionContext<VariableDescriptor> context,
@NotNull CallResolver callResolver, @NotNull ResolutionTask<VariableDescriptor> task) {
return Collections.singleton(context.candidateCall);
}
};
CallTransformationStrategy<FunctionDescriptor, FunctionDescriptor>
FUNCTION_CALL_TRANSFORMATION_STRATEGY = new CallTransformationStrategy<FunctionDescriptor, FunctionDescriptor>() {
@NotNull
@Override
public CallResolutionContext<FunctionDescriptor> createCallContext(@NotNull ResolutionCandidate<FunctionDescriptor> candidate,
@NotNull ResolutionTask<FunctionDescriptor> task,
@NotNull BindingTrace trace,
@NotNull TracingStrategy tracing) {
if (candidate.getDescriptor() instanceof FunctionDescriptor) {
return new CallResolutionContext<FunctionDescriptor>(ResolvedCallImpl.create(candidate), task, trace, tracing);
}
assert candidate.getDescriptor() instanceof VariableDescriptor;
Call propertyCall = new DelegatingCall(task.call) {
@Override
public JetValueArgumentList getValueArgumentList() {
return null;
}
@NotNull
@Override
public List<JetExpression> getFunctionLiteralArguments() {
return Collections.emptyList();
}
@NotNull
@Override
public List<JetTypeProjection> getTypeArguments() {
return Collections.emptyList();
}
@Override
public JetTypeArgumentList getTypeArgumentList() {
return null;
}
};
return new CallResolutionContext<FunctionDescriptor>(ResolvedCallImpl.create(candidate), task, trace, tracing, propertyCall);
}
@NotNull
@Override
public Collection<ResolvedCallImpl<FunctionDescriptor>> transformResultCall(@NotNull CallResolutionContext<FunctionDescriptor> context,
@NotNull CallResolver callResolver, @NotNull ResolutionTask<FunctionDescriptor> task) {
FunctionDescriptor descriptor = context.candidateCall.getCandidateDescriptor();
if (descriptor instanceof FunctionDescriptor) {
return Collections.singleton(context.candidateCall);
}
assert descriptor instanceof VariableDescriptor;
BasicResolutionContext basicResolutionContext =
BasicResolutionContext.create(context.trace, context.scope, task.call, context.expectedType, context.dataFlowInfo);
OverloadResolutionResults<FunctionDescriptor> results =
callResolver.resolveCallWithGivenName(basicResolutionContext, task.reference, "invoke");
return ((OverloadResolutionResultsImpl<FunctionDescriptor>)results).getResultingCalls();
}
};
}
@@ -0,0 +1,38 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collection;
/**
* @author svtk
*/
public interface MemberPrioritizer<D extends CallableDescriptor> {
@NotNull
Collection<D> getNonExtensionsByName(JetScope scope, String name);
@NotNull
Collection<D> getMembersByName(@NotNull JetType receiver, String name);
@NotNull
Collection<D> getExtensionsByName(JetScope scope, String name);
}
@@ -34,14 +34,15 @@ import java.util.*;
/** /**
* @author abreslav * @author abreslav
*/ */
public class TaskPrioritizers { public class MemberPrioritizers {
/*package*/ static TaskPrioritizer<FunctionDescriptor> FUNCTION_TASK_PRIORITIZER = new TaskPrioritizer<FunctionDescriptor>() { /*package*/ static MemberPrioritizer<FunctionDescriptor> FUNCTION_TASK_PRIORITIZER = new MemberPrioritizer<FunctionDescriptor>() {
@NotNull @NotNull
@Override @Override
protected Collection<FunctionDescriptor> getNonExtensionsByName(JetScope scope, String name) { public Collection<FunctionDescriptor> getNonExtensionsByName(JetScope scope, String name) {
Set<FunctionDescriptor> functions = Sets.newLinkedHashSet(scope.getFunctions(name)); Set<FunctionDescriptor> functions = Sets.newLinkedHashSet(scope.getFunctions(name));
for (Iterator<FunctionDescriptor> iterator = functions.iterator(); iterator.hasNext(); ) { for (Iterator<FunctionDescriptor> iterator = functions.iterator(); iterator.hasNext(); ) {
FunctionDescriptor functionDescriptor = iterator.next(); FunctionDescriptor functionDescriptor = iterator.next();
@@ -57,7 +58,7 @@ public class TaskPrioritizers {
@NotNull @NotNull
@Override @Override
protected Collection<FunctionDescriptor> getMembersByName(@NotNull JetType receiverType, String name) { public Collection<FunctionDescriptor> getMembersByName(@NotNull JetType receiverType, String name) {
JetScope receiverScope = receiverType.getMemberScope(); JetScope receiverScope = receiverType.getMemberScope();
Set<FunctionDescriptor> members = Sets.newHashSet(receiverScope.getFunctions(name)); Set<FunctionDescriptor> members = Sets.newHashSet(receiverScope.getFunctions(name));
addConstructors(receiverScope, name, members); addConstructors(receiverScope, name, members);
@@ -67,7 +68,7 @@ public class TaskPrioritizers {
@NotNull @NotNull
@Override @Override
protected Collection<FunctionDescriptor> getExtensionsByName(JetScope scope, String name) { public Collection<FunctionDescriptor> getExtensionsByName(JetScope scope, String name) {
Set<FunctionDescriptor> extensionFunctions = Sets.newHashSet(scope.getFunctions(name)); Set<FunctionDescriptor> extensionFunctions = Sets.newHashSet(scope.getFunctions(name));
for (Iterator<FunctionDescriptor> iterator = extensionFunctions.iterator(); iterator.hasNext(); ) { for (Iterator<FunctionDescriptor> iterator = extensionFunctions.iterator(); iterator.hasNext(); ) {
FunctionDescriptor descriptor = iterator.next(); FunctionDescriptor descriptor = iterator.next();
@@ -104,11 +105,11 @@ public class TaskPrioritizers {
} }
}; };
/*package*/ static TaskPrioritizer<VariableDescriptor> VARIABLE_TASK_PRIORITIZER = new TaskPrioritizer<VariableDescriptor>() { /*package*/ static MemberPrioritizer<VariableDescriptor> VARIABLE_TASK_PRIORITIZER = new MemberPrioritizer<VariableDescriptor>() {
@NotNull @NotNull
@Override @Override
protected Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, String name) { public Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, String name) {
VariableDescriptor descriptor = scope.getLocalVariable(name); VariableDescriptor descriptor = scope.getLocalVariable(name);
if (descriptor == null) { if (descriptor == null) {
descriptor = DescriptorUtils.filterNonExtensionProperty(scope.getProperties(name)); descriptor = DescriptorUtils.filterNonExtensionProperty(scope.getProperties(name));
@@ -119,13 +120,13 @@ public class TaskPrioritizers {
@NotNull @NotNull
@Override @Override
protected Collection<VariableDescriptor> getMembersByName(@NotNull JetType receiverType, String name) { public Collection<VariableDescriptor> getMembersByName(@NotNull JetType receiverType, String name) {
return receiverType.getMemberScope().getProperties(name); return receiverType.getMemberScope().getProperties(name);
} }
@NotNull @NotNull
@Override @Override
protected Collection<VariableDescriptor> getExtensionsByName(JetScope scope, String name) { public Collection<VariableDescriptor> getExtensionsByName(JetScope scope, String name) {
return Collections2.filter(scope.getProperties(name), new Predicate<VariableDescriptor>() { return Collections2.filter(scope.getProperties(name), new Predicate<VariableDescriptor>() {
@Override @Override
public boolean apply(@Nullable VariableDescriptor variableDescriptor) { public boolean apply(@Nullable VariableDescriptor variableDescriptor) {
@@ -135,7 +136,7 @@ public class TaskPrioritizers {
} }
}; };
/*package*/ static TaskPrioritizer<VariableDescriptor> PROPERTY_TASK_PRIORITIZER = new TaskPrioritizer<VariableDescriptor>() { /*package*/ static MemberPrioritizer<VariableDescriptor> PROPERTY_TASK_PRIORITIZER = new MemberPrioritizer<VariableDescriptor>() {
private Collection<VariableDescriptor> filterProperties(Collection<? extends VariableDescriptor> variableDescriptors) { private Collection<VariableDescriptor> filterProperties(Collection<? extends VariableDescriptor> variableDescriptors) {
ArrayList<VariableDescriptor> properties = Lists.newArrayList(); ArrayList<VariableDescriptor> properties = Lists.newArrayList();
for (VariableDescriptor descriptor : variableDescriptors) { for (VariableDescriptor descriptor : variableDescriptors) {
@@ -148,19 +149,19 @@ public class TaskPrioritizers {
@NotNull @NotNull
@Override @Override
protected Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, String name) { public Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, String name) {
return filterProperties(VARIABLE_TASK_PRIORITIZER.getNonExtensionsByName(scope, name)); return filterProperties(VARIABLE_TASK_PRIORITIZER.getNonExtensionsByName(scope, name));
} }
@NotNull @NotNull
@Override @Override
protected Collection<VariableDescriptor> getMembersByName(@NotNull JetType receiver, String name) { public Collection<VariableDescriptor> getMembersByName(@NotNull JetType receiver, String name) {
return filterProperties(VARIABLE_TASK_PRIORITIZER.getMembersByName(receiver, name)); return filterProperties(VARIABLE_TASK_PRIORITIZER.getMembersByName(receiver, name));
} }
@NotNull @NotNull
@Override @Override
protected Collection<VariableDescriptor> getExtensionsByName(JetScope scope, String name) { public Collection<VariableDescriptor> getExtensionsByName(JetScope scope, String name) {
return filterProperties(VARIABLE_TASK_PRIORITIZER.getExtensionsByName(scope, name)); return filterProperties(VARIABLE_TASK_PRIORITIZER.getExtensionsByName(scope, name));
} }
}; };
@@ -0,0 +1,77 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.calls;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import java.util.Collection;
import java.util.List;
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
/**
* @author svtk
*/
public class ResolutionCandidate<D extends CallableDescriptor> {
private final D candidateDescriptor;
private ReceiverDescriptor thisObject = NO_RECEIVER; // receiver object of a method
private ReceiverDescriptor receiverArgument = NO_RECEIVER; // receiver of an extension function
private ResolutionCandidate(@NotNull D descriptor) {
candidateDescriptor = descriptor;
}
public static <D extends CallableDescriptor> ResolutionCandidate<D> create(@NotNull D descriptor) {
return new ResolutionCandidate<D>(descriptor);
}
public void setThisObject(@NotNull ReceiverDescriptor thisObject) {
this.thisObject = thisObject;
}
public void setReceiverArgument(@NotNull ReceiverDescriptor receiverArgument) {
this.receiverArgument = receiverArgument;
}
@NotNull
public D getDescriptor() {
return candidateDescriptor;
}
@NotNull
public ReceiverDescriptor getThisObject() {
return thisObject;
}
@NotNull
public ReceiverDescriptor getReceiverArgument() {
return receiverArgument;
}
@NotNull
public static <D extends CallableDescriptor> List<ResolutionCandidate<D>> convertCollection(@NotNull Collection<? extends D> descriptors) {
List<ResolutionCandidate<D>> result = Lists.newArrayList();
for (D descriptor : descriptors) {
result.add(create(descriptor));
}
return result;
}
}
@@ -16,6 +16,8 @@
package org.jetbrains.jet.lang.resolve.calls; package org.jetbrains.jet.lang.resolve.calls;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.intellij.lang.ASTNode; import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
@@ -39,10 +41,7 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.diagnostics.Errors.DANGLING_FUNCTION_LITERAL_ARGUMENT_SUSPECTED; import static org.jetbrains.jet.lang.resolve.BindingContext.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET;
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLVED_CALL;
/** /**
* Stores candidates for call resolution. * Stores candidates for call resolution.
@@ -50,26 +49,32 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLVED_CALL;
* @author abreslav * @author abreslav
*/ */
public class ResolutionTask<D extends CallableDescriptor> extends ResolutionContext { public class ResolutionTask<D extends CallableDescriptor> extends ResolutionContext {
private final Collection<ResolvedCallImpl<D>> candidates; private final Collection<ResolutionCandidate<D>> candidates;
private final Multimap<ResolutionCandidate<D>, ResolvedCallImpl<D>> resolvedCallMap = HashMultimap.create();
/*package*/ final JetReferenceExpression reference; /*package*/ final JetReferenceExpression reference;
private DescriptorCheckStrategy checkingStrategy; private DescriptorCheckStrategy checkingStrategy;
public ResolutionTask(@NotNull Collection<ResolvedCallImpl<D>> candidates, @NotNull JetReferenceExpression reference, public ResolutionTask(@NotNull Collection<ResolutionCandidate<D>> candidates, @NotNull JetReferenceExpression reference,
BindingTrace trace, JetScope scope, Call call, JetType expectedType, DataFlowInfo dataFlowInfo) { BindingTrace trace, JetScope scope, Call call, JetType expectedType, DataFlowInfo dataFlowInfo) {
super(trace, scope, call, expectedType, dataFlowInfo); super(trace, scope, call, expectedType, dataFlowInfo);
this.candidates = candidates; this.candidates = candidates;
this.reference = reference; this.reference = reference;
} }
public ResolutionTask(@NotNull Collection<ResolvedCallImpl<D>> candidates, @NotNull JetReferenceExpression reference, @NotNull BasicResolutionContext context) { public ResolutionTask(@NotNull Collection<ResolutionCandidate<D>> candidates, @NotNull JetReferenceExpression reference, @NotNull BasicResolutionContext context) {
this(candidates, reference, context.trace, context.scope, context.call, context.expectedType, context.dataFlowInfo); this(candidates, reference, context.trace, context.scope, context.call, context.expectedType, context.dataFlowInfo);
} }
@NotNull @NotNull
public Collection<ResolvedCallImpl<D>> getCandidates() { public Collection<ResolutionCandidate<D>> getCandidates() {
return candidates; return candidates;
} }
@NotNull
public Multimap<ResolutionCandidate<D>, ResolvedCallImpl<D>> getResolvedCallMap() {
return resolvedCallMap;
}
public void setCheckingStrategy(DescriptorCheckStrategy strategy) { public void setCheckingStrategy(DescriptorCheckStrategy strategy) {
checkingStrategy = strategy; checkingStrategy = strategy;
} }
@@ -34,35 +34,35 @@ import java.util.List;
public class ResolutionTaskHolder<D extends CallableDescriptor> { public class ResolutionTaskHolder<D extends CallableDescriptor> {
private final JetReferenceExpression reference; private final JetReferenceExpression reference;
private final BasicResolutionContext basicResolutionContext; private final BasicResolutionContext basicResolutionContext;
private final Predicate<ResolvedCallImpl<D>> visibleStrategy; private final Predicate<ResolutionCandidate<D>> visibleStrategy;
private final Collection<Collection<ResolvedCallImpl<D>>> localExtensions = Sets.newLinkedHashSet(); private final Collection<Collection<ResolutionCandidate<D>>> localExtensions = Sets.newLinkedHashSet();
private final Collection<Collection<ResolvedCallImpl<D>>> members = Sets.newLinkedHashSet(); private final Collection<Collection<ResolutionCandidate<D>>> members = Sets.newLinkedHashSet();
private final Collection<Collection<ResolvedCallImpl<D>>> nonLocalExtensions = Sets.newLinkedHashSet(); private final Collection<Collection<ResolutionCandidate<D>>> nonLocalExtensions = Sets.newLinkedHashSet();
private List<ResolutionTask<D>> tasks = null; private List<ResolutionTask<D>> tasks = null;
public ResolutionTaskHolder(@NotNull JetReferenceExpression reference, public ResolutionTaskHolder(@NotNull JetReferenceExpression reference,
@NotNull BasicResolutionContext basicResolutionContext, @NotNull BasicResolutionContext basicResolutionContext,
@NotNull Predicate<ResolvedCallImpl<D>> visibleStrategy) { @NotNull Predicate<ResolutionCandidate<D>> visibleStrategy) {
this.reference = reference; this.reference = reference;
this.basicResolutionContext = basicResolutionContext; this.basicResolutionContext = basicResolutionContext;
this.visibleStrategy = visibleStrategy; this.visibleStrategy = visibleStrategy;
} }
public void addLocalExtensions(@NotNull Collection<ResolvedCallImpl<D>> candidates) { public void addLocalExtensions(@NotNull Collection<ResolutionCandidate<D>> candidates) {
if (!candidates.isEmpty()) { if (!candidates.isEmpty()) {
localExtensions.add(candidates); localExtensions.add(candidates);
} }
} }
public void addMembers(@NotNull Collection<ResolvedCallImpl<D>> candidates) { public void addMembers(@NotNull Collection<ResolutionCandidate<D>> candidates) {
if (!candidates.isEmpty()) { if (!candidates.isEmpty()) {
members.add(candidates); members.add(candidates);
} }
} }
public void addNonLocalExtensions(@NotNull Collection<ResolvedCallImpl<D>> candidates) { public void addNonLocalExtensions(@NotNull Collection<ResolutionCandidate<D>> candidates) {
if (!candidates.isEmpty()) { if (!candidates.isEmpty()) {
nonLocalExtensions.add(candidates); nonLocalExtensions.add(candidates);
} }
@@ -71,7 +71,7 @@ public class ResolutionTaskHolder<D extends CallableDescriptor> {
public List<ResolutionTask<D>> getTasks() { public List<ResolutionTask<D>> getTasks() {
if (tasks == null) { if (tasks == null) {
tasks = Lists.newArrayList(); tasks = Lists.newArrayList();
List<Collection<ResolvedCallImpl<D>>> candidateList = Lists.newArrayList(); List<Collection<ResolutionCandidate<D>>> candidateList = Lists.newArrayList();
// If the call is of the form super.foo(), it can actually be only a member // If the call is of the form super.foo(), it can actually be only a member
// But if there's no appropriate member, we would like to report that super cannot be a receiver for an extension // But if there's no appropriate member, we would like to report that super cannot be a receiver for an extension
// Thus, put members first // Thus, put members first
@@ -85,9 +85,9 @@ public class ResolutionTaskHolder<D extends CallableDescriptor> {
} }
candidateList.addAll(nonLocalExtensions); candidateList.addAll(nonLocalExtensions);
for (Predicate<ResolvedCallImpl<D>> visibilityStrategy : Lists.newArrayList(visibleStrategy, Predicates.not(visibleStrategy))) { for (Predicate<ResolutionCandidate<D>> visibilityStrategy : Lists.newArrayList(visibleStrategy, Predicates.not(visibleStrategy))) {
for (Collection<ResolvedCallImpl<D>> candidates : candidateList) { for (Collection<ResolutionCandidate<D>> candidates : candidateList) {
Collection<ResolvedCallImpl<D>> filteredCandidates = Collections2.filter(candidates, visibilityStrategy); Collection<ResolutionCandidate<D>> filteredCandidates = Collections2.filter(candidates, visibilityStrategy);
if (!filteredCandidates.isEmpty()) { if (!filteredCandidates.isEmpty()) {
tasks.add(new ResolutionTask<D>(filteredCandidates, reference, basicResolutionContext)); tasks.add(new ResolutionTask<D>(filteredCandidates, reference, basicResolutionContext));
} }
@@ -33,7 +33,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import static org.jetbrains.jet.lang.resolve.calls.ResolutionStatus.UNKNOWN_STATUS; import static org.jetbrains.jet.lang.resolve.calls.ResolutionStatus.UNKNOWN_STATUS;
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
/** /**
* @author abreslav * @author abreslav
@@ -55,23 +54,14 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
}; };
@NotNull @NotNull
public static <D extends CallableDescriptor> ResolvedCallImpl<D> create(@NotNull D descriptor) { public static <D extends CallableDescriptor> ResolvedCallImpl<D> create(@NotNull ResolutionCandidate<D> candidate) {
return new ResolvedCallImpl<D>(descriptor); return new ResolvedCallImpl<D>(candidate.getDescriptor(), candidate.getThisObject(), candidate.getReceiverArgument());
}
@NotNull
public static <D extends CallableDescriptor> List<ResolvedCallImpl<D>> convertCollection(@NotNull Collection<? extends D> descriptors) {
List<ResolvedCallImpl<D>> result = Lists.newArrayList();
for (D descriptor : descriptors) {
result.add(create(descriptor));
}
return result;
} }
private final D candidateDescriptor; private final D candidateDescriptor;
private D resultingDescriptor; // Probably substituted private D resultingDescriptor; // Probably substituted
private ReceiverDescriptor thisObject = NO_RECEIVER; // receiver object of a method private final ReceiverDescriptor thisObject; // receiver object of a method
private ReceiverDescriptor receiverArgument = NO_RECEIVER; // receiver of an extension function private final ReceiverDescriptor receiverArgument; // receiver of an extension function
private final Map<TypeParameterDescriptor, JetType> typeArguments = Maps.newLinkedHashMap(); private final Map<TypeParameterDescriptor, JetType> typeArguments = Maps.newLinkedHashMap();
private final Map<ValueParameterDescriptor, JetType> autoCasts = Maps.newHashMap(); private final Map<ValueParameterDescriptor, JetType> autoCasts = Maps.newHashMap();
@@ -80,8 +70,10 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
private TemporaryBindingTrace trace; private TemporaryBindingTrace trace;
private ResolutionStatus status = UNKNOWN_STATUS; private ResolutionStatus status = UNKNOWN_STATUS;
private ResolvedCallImpl(@NotNull D candidateDescriptor) { private ResolvedCallImpl(@NotNull D candidateDescriptor, @NotNull ReceiverDescriptor thisObject, @NotNull ReceiverDescriptor receiverArgument) {
this.candidateDescriptor = candidateDescriptor; this.candidateDescriptor = candidateDescriptor;
this.thisObject = thisObject;
this.receiverArgument = receiverArgument;
} }
@NotNull @NotNull
@@ -140,20 +132,12 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
return receiverArgument; return receiverArgument;
} }
public void setReceiverArgument(@NotNull ReceiverDescriptor receiverParameter) {
this.receiverArgument = receiverParameter;
}
@Override @Override
@NotNull @NotNull
public ReceiverDescriptor getThisObject() { public ReceiverDescriptor getThisObject() {
return thisObject; return thisObject;
} }
public void setThisObject(@NotNull ReceiverDescriptor thisObject) {
this.thisObject = thisObject;
}
@Override @Override
@NotNull @NotNull
public Map<ValueParameterDescriptor, ResolvedValueArgument> getValueArguments() { public Map<ValueParameterDescriptor, ResolvedValueArgument> getValueArguments() {
@@ -31,7 +31,6 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.NamespaceType; import org.jetbrains.jet.lang.types.NamespaceType;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
@@ -44,16 +43,16 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
/** /**
* @author abreslav * @author abreslav
*/ */
/*package*/ abstract class TaskPrioritizer<D extends CallableDescriptor> { /*package*/ abstract class TaskPrioritizer {
public static <D extends CallableDescriptor> void splitLexicallyLocalDescriptors( public static <D extends CallableDescriptor> void splitLexicallyLocalDescriptors(
@NotNull Collection<ResolvedCallImpl<D>> allDescriptors, @NotNull Collection<ResolutionCandidate<D>> allDescriptors,
@NotNull DeclarationDescriptor containerOfTheCurrentLocality, @NotNull DeclarationDescriptor containerOfTheCurrentLocality,
@NotNull Collection<ResolvedCallImpl<D>> local, @NotNull Collection<ResolutionCandidate<D>> local,
@NotNull Collection<ResolvedCallImpl<D>> nonlocal @NotNull Collection<ResolutionCandidate<D>> nonlocal
) { ) {
for (ResolvedCallImpl<D> resolvedCall : allDescriptors) { for (ResolutionCandidate<D> resolvedCall : allDescriptors) {
if (DescriptorUtils.isLocal(containerOfTheCurrentLocality, resolvedCall.getCandidateDescriptor())) { if (DescriptorUtils.isLocal(containerOfTheCurrentLocality, resolvedCall.getDescriptor())) {
local.add(resolvedCall); local.add(resolvedCall);
} }
else { else {
@@ -75,8 +74,8 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
} }
@NotNull @NotNull
public List<ResolutionTask<D>> computePrioritizedTasks(@NotNull BasicResolutionContext context, @NotNull String name, public static <D extends CallableDescriptor> List<ResolutionTask<D>> computePrioritizedTasks(@NotNull BasicResolutionContext context, @NotNull String name,
@NotNull JetReferenceExpression functionReference) { @NotNull JetReferenceExpression functionReference, @NotNull List<MemberPrioritizer<D>> memberPrioritizers) {
ReceiverDescriptor explicitReceiver = context.call.getExplicitReceiver(); ReceiverDescriptor explicitReceiver = context.call.getExplicitReceiver();
final JetScope scope; final JetScope scope;
if (explicitReceiver.exists() && explicitReceiver.getType() instanceof NamespaceType) { if (explicitReceiver.exists() && explicitReceiver.getType() instanceof NamespaceType) {
@@ -87,40 +86,41 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
else { else {
scope = context.scope; scope = context.scope;
} }
final Predicate<ResolvedCallImpl<D>> visibleStrategy = new Predicate<ResolvedCallImpl<D>>() { final Predicate<ResolutionCandidate<D>> visibleStrategy = new Predicate<ResolutionCandidate<D>>() {
@Override @Override
public boolean apply(@Nullable ResolvedCallImpl<D> call) { public boolean apply(@Nullable ResolutionCandidate<D> call) {
if (call == null) return false; if (call == null) return false;
D candidateDescriptor = call.getCandidateDescriptor(); D candidateDescriptor = call.getDescriptor();
if (ErrorUtils.isError(candidateDescriptor)) return true; if (ErrorUtils.isError(candidateDescriptor)) return true;
return Visibilities.isVisible(candidateDescriptor, scope.getContainingDeclaration()); return Visibilities.isVisible(candidateDescriptor, scope.getContainingDeclaration());
} }
}; };
ResolutionTaskHolder<D> result = new ResolutionTaskHolder<D>(functionReference, context, visibleStrategy ); ResolutionTaskHolder<D> result = new ResolutionTaskHolder<D>(functionReference, context, visibleStrategy );
doComputeTasks(scope, explicitReceiver, name, result, context); doComputeTasks(scope, explicitReceiver, name, result, context, memberPrioritizers);
return result.getTasks(); return result.getTasks();
} }
private void doComputeTasks(@NotNull JetScope scope, @NotNull ReceiverDescriptor receiver, private static <D extends CallableDescriptor> void doComputeTasks(@NotNull JetScope scope, @NotNull ReceiverDescriptor receiver,
@NotNull String name, @NotNull ResolutionTaskHolder<D> result, @NotNull String name, @NotNull ResolutionTaskHolder<D> result,
@NotNull BasicResolutionContext context) { @NotNull BasicResolutionContext context, @NotNull List<MemberPrioritizer<D>> memberPrioritizers) {
MemberPrioritizer<D> memberPrioritizer = memberPrioritizers.get(0);
AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(context.dataFlowInfo, context.trace.getBindingContext()); AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(context.dataFlowInfo, context.trace.getBindingContext());
List<ReceiverDescriptor> implicitReceivers = Lists.newArrayList(); List<ReceiverDescriptor> implicitReceivers = Lists.newArrayList();
scope.getImplicitReceiversHierarchy(implicitReceivers); scope.getImplicitReceiversHierarchy(implicitReceivers);
if (receiver.exists()) { if (receiver.exists()) {
List<ReceiverDescriptor> variantsForExplicitReceiver = autoCastService.getVariantsForReceiver(receiver); List<ReceiverDescriptor> variantsForExplicitReceiver = autoCastService.getVariantsForReceiver(receiver);
Collection<ResolvedCallImpl<D>> extensionFunctions = convertWithImpliedThis(scope, variantsForExplicitReceiver, getExtensionsByName(scope, name)); Collection<ResolutionCandidate<D>> extensionFunctions = convertWithImpliedThis(scope, variantsForExplicitReceiver, memberPrioritizer.getExtensionsByName(scope, name));
List<ResolvedCallImpl<D>> nonlocals = Lists.newArrayList(); List<ResolutionCandidate<D>> nonlocals = Lists.newArrayList();
List<ResolvedCallImpl<D>> locals = Lists.newArrayList(); List<ResolutionCandidate<D>> locals = Lists.newArrayList();
//noinspection unchecked,RedundantTypeArguments //noinspection unchecked,RedundantTypeArguments
TaskPrioritizer.<D>splitLexicallyLocalDescriptors(extensionFunctions, scope.getContainingDeclaration(), locals, nonlocals); TaskPrioritizer.<D>splitLexicallyLocalDescriptors(extensionFunctions, scope.getContainingDeclaration(), locals, nonlocals);
Collection<ResolvedCallImpl<D>> members = Lists.newArrayList(); Collection<ResolutionCandidate<D>> members = Lists.newArrayList();
for (ReceiverDescriptor variant : variantsForExplicitReceiver) { for (ReceiverDescriptor variant : variantsForExplicitReceiver) {
Collection<D> membersForThisVariant = getMembersByName(variant.getType(), name); Collection<D> membersForThisVariant = memberPrioritizer.getMembersByName(variant.getType(), name);
convertWithReceivers(membersForThisVariant, Collections.singletonList(variant), Collections.singletonList(NO_RECEIVER), members); convertWithReceivers(membersForThisVariant, Collections.singletonList(variant), Collections.singletonList(NO_RECEIVER), members);
} }
@@ -128,7 +128,7 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
result.addMembers(members); result.addMembers(members);
for (ReceiverDescriptor implicitReceiver : implicitReceivers) { for (ReceiverDescriptor implicitReceiver : implicitReceivers) {
Collection<D> memberExtensions = getExtensionsByName(implicitReceiver.getType().getMemberScope(), name); Collection<D> memberExtensions = memberPrioritizer.getExtensionsByName(implicitReceiver.getType().getMemberScope(), name);
List<ReceiverDescriptor> variantsForImplicitReceiver = autoCastService.getVariantsForReceiver(implicitReceiver); List<ReceiverDescriptor> variantsForImplicitReceiver = autoCastService.getVariantsForReceiver(implicitReceiver);
result.addNonLocalExtensions(convertWithReceivers(memberExtensions, variantsForImplicitReceiver, variantsForExplicitReceiver)); result.addNonLocalExtensions(convertWithReceivers(memberExtensions, variantsForImplicitReceiver, variantsForExplicitReceiver));
} }
@@ -136,10 +136,10 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
result.addNonLocalExtensions(nonlocals); result.addNonLocalExtensions(nonlocals);
} }
else { else {
Collection<ResolvedCallImpl<D>> functions = convertWithImpliedThis(scope, Collections.singletonList(receiver), getNonExtensionsByName(scope, name)); Collection<ResolutionCandidate<D>> functions = convertWithImpliedThis(scope, Collections.singletonList(receiver), memberPrioritizer.getNonExtensionsByName(scope, name));
List<ResolvedCallImpl<D>> nonlocals = Lists.newArrayList(); List<ResolutionCandidate<D>> nonlocals = Lists.newArrayList();
List<ResolvedCallImpl<D>> locals = Lists.newArrayList(); List<ResolutionCandidate<D>> locals = Lists.newArrayList();
//noinspection unchecked,RedundantTypeArguments //noinspection unchecked,RedundantTypeArguments
TaskPrioritizer.<D>splitLexicallyLocalDescriptors(functions, scope.getContainingDeclaration(), locals, nonlocals); TaskPrioritizer.<D>splitLexicallyLocalDescriptors(functions, scope.getContainingDeclaration(), locals, nonlocals);
@@ -147,22 +147,22 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
result.addNonLocalExtensions(nonlocals); result.addNonLocalExtensions(nonlocals);
for (ReceiverDescriptor implicitReceiver : implicitReceivers) { for (ReceiverDescriptor implicitReceiver : implicitReceivers) {
doComputeTasks(scope, implicitReceiver, name, result, context); doComputeTasks(scope, implicitReceiver, name, result, context, memberPrioritizers);
} }
} }
} }
private Collection<ResolvedCallImpl<D>> convertWithReceivers(Collection<D> descriptors, Iterable<ReceiverDescriptor> thisObjects, Iterable<ReceiverDescriptor> receiverParameters) { private static <D extends CallableDescriptor> Collection<ResolutionCandidate<D>> convertWithReceivers(Collection<D> descriptors, Iterable<ReceiverDescriptor> thisObjects, Iterable<ReceiverDescriptor> receiverParameters) {
Collection<ResolvedCallImpl<D>> result = Lists.newArrayList(); Collection<ResolutionCandidate<D>> result = Lists.newArrayList();
convertWithReceivers(descriptors, thisObjects, receiverParameters, result); convertWithReceivers(descriptors, thisObjects, receiverParameters, result);
return result; return result;
} }
private void convertWithReceivers(Collection<D> descriptors, Iterable<ReceiverDescriptor> thisObjects, Iterable<ReceiverDescriptor> receiverParameters, Collection<ResolvedCallImpl<D>> result) { private static <D extends CallableDescriptor> void convertWithReceivers(Collection<D> descriptors, Iterable<ReceiverDescriptor> thisObjects, Iterable<ReceiverDescriptor> receiverParameters, Collection<ResolutionCandidate<D>> result) {
for (ReceiverDescriptor thisObject : thisObjects) { for (ReceiverDescriptor thisObject : thisObjects) {
for (ReceiverDescriptor receiverParameter : receiverParameters) { for (ReceiverDescriptor receiverParameter : receiverParameters) {
for (D extension : descriptors) { for (D extension : descriptors) {
ResolvedCallImpl<D> resolvedCall = ResolvedCallImpl.create(extension); ResolutionCandidate<D> resolvedCall = ResolutionCandidate.create(extension);
resolvedCall.setThisObject(thisObject); resolvedCall.setThisObject(thisObject);
resolvedCall.setReceiverArgument(receiverParameter); resolvedCall.setReceiverArgument(receiverParameter);
result.add(resolvedCall); result.add(resolvedCall);
@@ -171,11 +171,11 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
} }
} }
public static <D extends CallableDescriptor> Collection<ResolvedCallImpl<D>> convertWithImpliedThis(JetScope scope, Iterable<ReceiverDescriptor> receiverParameters, Collection<? extends D> descriptors) { public static <D extends CallableDescriptor> Collection<ResolutionCandidate<D>> convertWithImpliedThis(JetScope scope, Iterable<ReceiverDescriptor> receiverParameters, Collection<? extends D> descriptors) {
Collection<ResolvedCallImpl<D>> result = Lists.newArrayList(); Collection<ResolutionCandidate<D>> result = Lists.newArrayList();
for (ReceiverDescriptor receiverParameter : receiverParameters) { for (ReceiverDescriptor receiverParameter : receiverParameters) {
for (D descriptor : descriptors) { for (D descriptor : descriptors) {
ResolvedCallImpl<D> resolvedCall = ResolvedCallImpl.create(descriptor); ResolutionCandidate<D> resolvedCall = ResolutionCandidate.create(descriptor);
resolvedCall.setReceiverArgument(receiverParameter); resolvedCall.setReceiverArgument(receiverParameter);
if (setImpliedThis(scope, resolvedCall)) { if (setImpliedThis(scope, resolvedCall)) {
result.add(resolvedCall); result.add(resolvedCall);
@@ -190,7 +190,7 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
containingDeclaration = containingDeclaration.getContainingDeclaration(); containingDeclaration = containingDeclaration.getContainingDeclaration();
} }
if (containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor) containingDeclaration).getKind() == ClassKind.OBJECT) { if (containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor) containingDeclaration).getKind() == ClassKind.OBJECT) {
ResolvedCallImpl<D> resolvedCall = ResolvedCallImpl.create(descriptor); ResolutionCandidate<D> resolvedCall = ResolutionCandidate.create(descriptor);
resolvedCall.setThisObject(new ClassReceiver((ClassDescriptor) containingDeclaration)); resolvedCall.setThisObject(new ClassReceiver((ClassDescriptor) containingDeclaration));
result.add(resolvedCall); result.add(resolvedCall);
} }
@@ -199,8 +199,8 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
return result; return result;
} }
private static <D extends CallableDescriptor> boolean setImpliedThis(@NotNull JetScope scope, ResolvedCallImpl<D> resolvedCall) { private static <D extends CallableDescriptor> boolean setImpliedThis(@NotNull JetScope scope, ResolutionCandidate<D> resolvedCall) {
ReceiverDescriptor expectedThisObject = resolvedCall.getCandidateDescriptor().getExpectedThisObject(); ReceiverDescriptor expectedThisObject = resolvedCall.getDescriptor().getExpectedThisObject();
if (!expectedThisObject.exists()) return true; if (!expectedThisObject.exists()) return true;
List<ReceiverDescriptor> receivers = Lists.newArrayList(); List<ReceiverDescriptor> receivers = Lists.newArrayList();
scope.getImplicitReceiversHierarchy(receivers); scope.getImplicitReceiversHierarchy(receivers);
@@ -213,13 +213,4 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
} }
return false; return false;
} }
@NotNull
protected abstract Collection<D> getNonExtensionsByName(JetScope scope, String name);
@NotNull
protected abstract Collection<D> getMembersByName(@NotNull JetType receiver, String name);
@NotNull
protected abstract Collection<D> getExtensionsByName(JetScope scope, String name);
} }
@@ -194,7 +194,7 @@ public class ResolveToolwindow extends JPanel implements Disposable {
if (debugInfo != null) { if (debugInfo != null) {
List<? extends ResolutionTask<? extends CallableDescriptor>> resolutionTasks = debugInfo.get(TASKS); List<? extends ResolutionTask<? extends CallableDescriptor>> resolutionTasks = debugInfo.get(TASKS);
for (ResolutionTask<? extends CallableDescriptor> resolutionTask : resolutionTasks) { for (ResolutionTask<? extends CallableDescriptor> resolutionTask : resolutionTasks) {
for (ResolvedCallImpl<? extends CallableDescriptor> resolvedCall : resolutionTask.getCandidates()) { for (ResolvedCallImpl<? extends CallableDescriptor> resolvedCall : resolutionTask.getResolvedCallMap().values()) {
renderResolutionLogForCall(debugInfo, resolvedCall, result); renderResolutionLogForCall(debugInfo, resolvedCall, result);
} }
} }
@@ -21,6 +21,7 @@ import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.resolve.calls.ResolutionCandidate;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl; import org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl;
import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.context.TranslationContext;
@@ -103,7 +104,7 @@ public final class CallBuilder {
private CallTranslator finish() { private CallTranslator finish() {
if (resolvedCall == null) { if (resolvedCall == null) {
assert descriptor != null; assert descriptor != null;
resolvedCall = ResolvedCallImpl.create(descriptor); resolvedCall = ResolvedCallImpl.create(ResolutionCandidate.create(descriptor));
} }
if (descriptor == null) { if (descriptor == null) {
descriptor = resolvedCall.getCandidateDescriptor().getOriginal(); descriptor = resolvedCall.getCandidateDescriptor().getOriginal();