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) {
return OverloadResolutionResultsImpl.nameNotFound();
}
TaskPrioritizer<VariableDescriptor> task_prioritizer;
List<MemberPrioritizer<VariableDescriptor>> memberPrioritizers = Lists.newArrayList();
if (nameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
referencedName = referencedName.substring(1);
task_prioritizer = TaskPrioritizers.PROPERTY_TASK_PRIORITIZER;
memberPrioritizers.add(MemberPrioritizers.PROPERTY_TASK_PRIORITIZER);
}
else {
task_prioritizer = TaskPrioritizers.VARIABLE_TASK_PRIORITIZER;
memberPrioritizers.add(MemberPrioritizers.VARIABLE_TASK_PRIORITIZER);
}
List<ResolutionTask<VariableDescriptor>> prioritizedTasks = task_prioritizer.computePrioritizedTasks(context, referencedName, nameExpression);
return doResolveCall(context, prioritizedTasks, nameExpression);
List<ResolutionTask<VariableDescriptor>> prioritizedTasks = TaskPrioritizer.computePrioritizedTasks(context, referencedName, nameExpression, memberPrioritizers);
return doResolveCall(context, prioritizedTasks, CallTransformationStrategy.PROPERTY_CALL_TRANSFORMATION_STRATEGY, nameExpression);
}
@NotNull
@@ -119,9 +119,9 @@ public class CallResolver {
@NotNull BasicResolutionContext context,
@NotNull final JetReferenceExpression functionReference,
@NotNull String name) {
List<ResolutionTask<FunctionDescriptor>> tasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(
context, name, functionReference);
return doResolveCall(context, tasks, functionReference);
List<ResolutionTask<FunctionDescriptor>> tasks = TaskPrioritizer.computePrioritizedTasks(
context, name, functionReference, Collections.singletonList(MemberPrioritizers.FUNCTION_TASK_PRIORITIZER));
return doResolveCall(context, tasks, CallTransformationStrategy.FUNCTION_CALL_TRANSFORMATION_STRATEGY, functionReference);
}
@NotNull
@@ -142,7 +142,7 @@ public class CallResolver {
String name = expression.getReferencedName();
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() {
@Override
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));
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
}
else {
@@ -206,7 +206,7 @@ public class CallResolver {
context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
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
}
else if (calleeExpression != null) {
@@ -223,15 +223,15 @@ public class CallResolver {
FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(context.scope.getContainingDeclaration(), "[for expression " + calleeExpression.getText() + "]");
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType, NO_RECEIVER);
ResolvedCallImpl<FunctionDescriptor> resolvedCall = ResolvedCallImpl.<FunctionDescriptor>create(functionDescriptor);
resolvedCall.setReceiverArgument(context.call.getExplicitReceiver());
ResolutionCandidate<FunctionDescriptor> resolutionCandidate = ResolutionCandidate.<FunctionDescriptor>create(functionDescriptor);
resolutionCandidate.setReceiverArgument(context.call.getExplicitReceiver());
// strictly speaking, this is a hack:
// 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)
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 {
// 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) {
@@ -251,6 +251,7 @@ public class CallResolver {
private <D extends CallableDescriptor> OverloadResolutionResults<D> doResolveCall(
@NotNull final BasicResolutionContext context,
@NotNull final List<ResolutionTask<D>> prioritizedTasks, // high to low priority
@NotNull CallTransformationStrategy<D, D> callTransformationStrategy,
@NotNull final JetReferenceExpression reference) {
ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create();
@@ -267,7 +268,7 @@ public class CallResolver {
OverloadResolutionResultsImpl<D> resultsForFirstNonemptyCandidateSet = null;
for (ResolutionTask<D> task : prioritizedTasks) {
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()) {
temporaryTrace.commit();
@@ -299,8 +300,9 @@ public class CallResolver {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@NotNull
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> performResolutionGuardedForExtraFunctionLiteralArguments(ResolutionTask<D> task) {
OverloadResolutionResultsImpl<D> results = performResolution(task);
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> performResolutionGuardedForExtraFunctionLiteralArguments(@NotNull ResolutionTask<D> task,
@NotNull CallTransformationStrategy<D, D> callTransformationStrategy) {
OverloadResolutionResultsImpl<D> results = performResolution(task, callTransformationStrategy);
// If resolution fails, we should check for some of the following situations:
// class A {
@@ -323,9 +325,9 @@ public class CallResolver {
// We have some candidates that failed for some reason
// And we have a suspect: the function literal argument
// Now, we try to remove this argument and see if it helps
Collection<ResolvedCallImpl<D>> newCandidates = Lists.newArrayList();
for (ResolvedCallImpl<D> candidate : task.getCandidates()) {
newCandidates.add(ResolvedCallImpl.create(candidate.getCandidateDescriptor()));
Collection<ResolutionCandidate<D>> newCandidates = Lists.newArrayList();
for (ResolutionCandidate<D> candidate : task.getCandidates()) {
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) {
@NotNull
@@ -334,7 +336,7 @@ public class CallResolver {
return Collections.emptyList();
}
}, task.expectedType, task.dataFlowInfo);
OverloadResolutionResultsImpl<D> resultsWithFunctionLiteralsStripped = performResolution(newContext);
OverloadResolutionResultsImpl<D> resultsWithFunctionLiteralsStripped = performResolution(newContext, callTransformationStrategy);
if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) {
task.tracing.danglingFunctionLiteralArgumentSuspected(task.trace, task.call.getFunctionLiteralArguments());
}
@@ -344,101 +346,23 @@ public class CallResolver {
}
@NotNull
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> performResolution(ResolutionTask<D> task) {
for (ResolvedCallImpl<D> candidateCall : task.getCandidates()) {
D candidate = candidateCall.getCandidateDescriptor();
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> performResolution(@NotNull ResolutionTask<D> task,
@NotNull CallTransformationStrategy<D, D> callTransformationStrategy) {
for (ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) {
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);
context.tracing.bindReference(context.trace, candidateCall);
if (ErrorUtils.isError(candidate)) {
candidateCall.setStatus(SUCCESS);
checkTypesWithNoCallee(context.toBasic());
continue;
Collection<ResolvedCallImpl<D>> calls = callTransformationStrategy.transformResultCall(context, this, task);
for (ResolvedCallImpl<D> call : calls) {
task.getResolvedCallMap().put(resolutionCandidate, call);
}
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>> failedCandidates = Sets.newLinkedHashSet();
for (ResolvedCallImpl<D> candidateCall : task.getCandidates()) {
for (ResolvedCallImpl<D> candidateCall : task.getResolvedCallMap().values()) {
ResolutionStatus status = candidateCall.getStatus();
if (status.isSuccess()) {
successfulCandidates.add(candidateCall);
@@ -456,6 +380,99 @@ public class CallResolver {
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) {
ResolvedCallImpl<D> candidateCall = context.candidateCall;
D candidate = candidateCall.getCandidateDescriptor();
@@ -843,25 +860,26 @@ public class CallResolver {
@NotNull
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();
TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(trace);
Set<ResolvedCallImpl<FunctionDescriptor>> candidates = Sets.newLinkedHashSet();
for (ResolvedCallImpl<FunctionDescriptor> call : result) {
Set<ResolvedCallImpl<FunctionDescriptor>> calls = Sets.newLinkedHashSet();
for (ResolutionCandidate<FunctionDescriptor> candidate : candidates) {
ResolvedCallImpl<FunctionDescriptor> call = ResolvedCallImpl.create(candidate);
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) {
List<ResolvedCallImpl<FunctionDescriptor>> result = Lists.newArrayList();
List<ResolutionCandidate<FunctionDescriptor>> result = Lists.newArrayList();
if (receiver.exists()) {
Collection<ResolvedCallImpl<FunctionDescriptor>> extensionFunctionDescriptors = ResolvedCallImpl.convertCollection(scope.getFunctions(name));
List<ResolvedCallImpl<FunctionDescriptor>> nonlocal = Lists.newArrayList();
List<ResolvedCallImpl<FunctionDescriptor>> local = Lists.newArrayList();
Collection<ResolutionCandidate<FunctionDescriptor>> extensionFunctionDescriptors = ResolutionCandidate.convertCollection(scope.getFunctions(name));
List<ResolutionCandidate<FunctionDescriptor>> nonlocal = Lists.newArrayList();
List<ResolutionCandidate<FunctionDescriptor>> local = Lists.newArrayList();
TaskPrioritizer.splitLexicallyLocalDescriptors(extensionFunctionDescriptors, scope.getContainingDeclaration(), local, nonlocal);
@@ -869,7 +887,7 @@ public class CallResolver {
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)) {
return result;
@@ -878,16 +896,16 @@ public class CallResolver {
return result;
}
else {
lookupExactSignature(ResolvedCallImpl.convertCollection(scope.getFunctions(name)), parameterTypes, result);
lookupExactSignature(ResolutionCandidate.convertCollection(scope.getFunctions(name)), parameterTypes, result);
return result;
}
}
private static boolean lookupExactSignature(Collection<ResolvedCallImpl<FunctionDescriptor>> candidates, List<JetType> parameterTypes,
List<ResolvedCallImpl<FunctionDescriptor>> result) {
private static boolean lookupExactSignature(Collection<ResolutionCandidate<FunctionDescriptor>> candidates, List<JetType> parameterTypes,
List<ResolutionCandidate<FunctionDescriptor>> result) {
boolean found = false;
for (ResolvedCallImpl<FunctionDescriptor> resolvedCall : candidates) {
FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor();
for (ResolutionCandidate<FunctionDescriptor> resolvedCall : candidates) {
FunctionDescriptor functionDescriptor = resolvedCall.getDescriptor();
if (functionDescriptor.getReceiverParameter().exists()) continue;
if (!functionDescriptor.getTypeParameters().isEmpty()) continue;
if (!checkValueParameters(functionDescriptor, parameterTypes)) continue;
@@ -897,17 +915,17 @@ public class CallResolver {
return found;
}
private boolean findExtensionFunctions(Collection<ResolvedCallImpl<FunctionDescriptor>> candidates, ReceiverDescriptor receiver,
List<JetType> parameterTypes, List<ResolvedCallImpl<FunctionDescriptor>> result) {
private boolean findExtensionFunctions(Collection<ResolutionCandidate<FunctionDescriptor>> candidates, ReceiverDescriptor receiver,
List<JetType> parameterTypes, List<ResolutionCandidate<FunctionDescriptor>> result) {
boolean found = false;
for (ResolvedCallImpl<FunctionDescriptor> resolvedCall : candidates) {
FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor();
for (ResolutionCandidate<FunctionDescriptor> candidate : candidates) {
FunctionDescriptor functionDescriptor = candidate.getDescriptor();
ReceiverDescriptor functionReceiver = functionDescriptor.getReceiverParameter();
if (!functionReceiver.exists()) continue;
if (!functionDescriptor.getTypeParameters().isEmpty()) continue;
if (!typeChecker.isSubtypeOf(receiver.getType(), functionReceiver.getType())) continue;
if (!checkValueParameters(functionDescriptor, parameterTypes))continue;
result.add(resolvedCall);
result.add(candidate);
found = true;
}
return found;
@@ -923,15 +941,4 @@ public class CallResolver {
}
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
*/
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
@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));
for (Iterator<FunctionDescriptor> iterator = functions.iterator(); iterator.hasNext(); ) {
FunctionDescriptor functionDescriptor = iterator.next();
@@ -57,7 +58,7 @@ public class TaskPrioritizers {
@NotNull
@Override
protected Collection<FunctionDescriptor> getMembersByName(@NotNull JetType receiverType, String name) {
public Collection<FunctionDescriptor> getMembersByName(@NotNull JetType receiverType, String name) {
JetScope receiverScope = receiverType.getMemberScope();
Set<FunctionDescriptor> members = Sets.newHashSet(receiverScope.getFunctions(name));
addConstructors(receiverScope, name, members);
@@ -67,7 +68,7 @@ public class TaskPrioritizers {
@NotNull
@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));
for (Iterator<FunctionDescriptor> iterator = extensionFunctions.iterator(); iterator.hasNext(); ) {
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
@Override
protected Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, String name) {
public Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, String name) {
VariableDescriptor descriptor = scope.getLocalVariable(name);
if (descriptor == null) {
descriptor = DescriptorUtils.filterNonExtensionProperty(scope.getProperties(name));
@@ -119,13 +120,13 @@ public class TaskPrioritizers {
@NotNull
@Override
protected Collection<VariableDescriptor> getMembersByName(@NotNull JetType receiverType, String name) {
public Collection<VariableDescriptor> getMembersByName(@NotNull JetType receiverType, String name) {
return receiverType.getMemberScope().getProperties(name);
}
@NotNull
@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>() {
@Override
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) {
ArrayList<VariableDescriptor> properties = Lists.newArrayList();
for (VariableDescriptor descriptor : variableDescriptors) {
@@ -148,19 +149,19 @@ public class TaskPrioritizers {
@NotNull
@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));
}
@NotNull
@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));
}
@NotNull
@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));
}
};
@@ -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;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
@@ -39,10 +41,7 @@ import java.util.Collection;
import java.util.List;
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.AMBIGUOUS_REFERENCE_TARGET;
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLVED_CALL;
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
/**
* Stores candidates for call resolution.
@@ -50,26 +49,32 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLVED_CALL;
* @author abreslav
*/
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;
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) {
super(trace, scope, call, expectedType, dataFlowInfo);
this.candidates = candidates;
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);
}
@NotNull
public Collection<ResolvedCallImpl<D>> getCandidates() {
public Collection<ResolutionCandidate<D>> getCandidates() {
return candidates;
}
@NotNull
public Multimap<ResolutionCandidate<D>, ResolvedCallImpl<D>> getResolvedCallMap() {
return resolvedCallMap;
}
public void setCheckingStrategy(DescriptorCheckStrategy strategy) {
checkingStrategy = strategy;
}
@@ -34,35 +34,35 @@ import java.util.List;
public class ResolutionTaskHolder<D extends CallableDescriptor> {
private final JetReferenceExpression reference;
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<ResolvedCallImpl<D>>> members = Sets.newLinkedHashSet();
private final Collection<Collection<ResolvedCallImpl<D>>> nonLocalExtensions = Sets.newLinkedHashSet();
private final Collection<Collection<ResolutionCandidate<D>>> localExtensions = Sets.newLinkedHashSet();
private final Collection<Collection<ResolutionCandidate<D>>> members = Sets.newLinkedHashSet();
private final Collection<Collection<ResolutionCandidate<D>>> nonLocalExtensions = Sets.newLinkedHashSet();
private List<ResolutionTask<D>> tasks = null;
public ResolutionTaskHolder(@NotNull JetReferenceExpression reference,
@NotNull BasicResolutionContext basicResolutionContext,
@NotNull Predicate<ResolvedCallImpl<D>> visibleStrategy) {
@NotNull Predicate<ResolutionCandidate<D>> visibleStrategy) {
this.reference = reference;
this.basicResolutionContext = basicResolutionContext;
this.visibleStrategy = visibleStrategy;
}
public void addLocalExtensions(@NotNull Collection<ResolvedCallImpl<D>> candidates) {
public void addLocalExtensions(@NotNull Collection<ResolutionCandidate<D>> candidates) {
if (!candidates.isEmpty()) {
localExtensions.add(candidates);
}
}
public void addMembers(@NotNull Collection<ResolvedCallImpl<D>> candidates) {
public void addMembers(@NotNull Collection<ResolutionCandidate<D>> candidates) {
if (!candidates.isEmpty()) {
members.add(candidates);
}
}
public void addNonLocalExtensions(@NotNull Collection<ResolvedCallImpl<D>> candidates) {
public void addNonLocalExtensions(@NotNull Collection<ResolutionCandidate<D>> candidates) {
if (!candidates.isEmpty()) {
nonLocalExtensions.add(candidates);
}
@@ -71,7 +71,7 @@ public class ResolutionTaskHolder<D extends CallableDescriptor> {
public List<ResolutionTask<D>> getTasks() {
if (tasks == null) {
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
// 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
@@ -85,9 +85,9 @@ public class ResolutionTaskHolder<D extends CallableDescriptor> {
}
candidateList.addAll(nonLocalExtensions);
for (Predicate<ResolvedCallImpl<D>> visibilityStrategy : Lists.newArrayList(visibleStrategy, Predicates.not(visibleStrategy))) {
for (Collection<ResolvedCallImpl<D>> candidates : candidateList) {
Collection<ResolvedCallImpl<D>> filteredCandidates = Collections2.filter(candidates, visibilityStrategy);
for (Predicate<ResolutionCandidate<D>> visibilityStrategy : Lists.newArrayList(visibleStrategy, Predicates.not(visibleStrategy))) {
for (Collection<ResolutionCandidate<D>> candidates : candidateList) {
Collection<ResolutionCandidate<D>> filteredCandidates = Collections2.filter(candidates, visibilityStrategy);
if (!filteredCandidates.isEmpty()) {
tasks.add(new ResolutionTask<D>(filteredCandidates, reference, basicResolutionContext));
}
@@ -33,7 +33,6 @@ import java.util.List;
import java.util.Map;
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
@@ -55,23 +54,14 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
};
@NotNull
public static <D extends CallableDescriptor> ResolvedCallImpl<D> create(@NotNull D descriptor) {
return new ResolvedCallImpl<D>(descriptor);
}
@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;
public static <D extends CallableDescriptor> ResolvedCallImpl<D> create(@NotNull ResolutionCandidate<D> candidate) {
return new ResolvedCallImpl<D>(candidate.getDescriptor(), candidate.getThisObject(), candidate.getReceiverArgument());
}
private final D candidateDescriptor;
private D resultingDescriptor; // Probably substituted
private ReceiverDescriptor thisObject = NO_RECEIVER; // receiver object of a method
private ReceiverDescriptor receiverArgument = NO_RECEIVER; // receiver of an extension function
private final ReceiverDescriptor thisObject; // receiver object of a method
private final ReceiverDescriptor receiverArgument; // receiver of an extension function
private final Map<TypeParameterDescriptor, JetType> typeArguments = Maps.newLinkedHashMap();
private final Map<ValueParameterDescriptor, JetType> autoCasts = Maps.newHashMap();
@@ -80,8 +70,10 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
private TemporaryBindingTrace trace;
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.thisObject = thisObject;
this.receiverArgument = receiverArgument;
}
@NotNull
@@ -140,20 +132,12 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
return receiverArgument;
}
public void setReceiverArgument(@NotNull ReceiverDescriptor receiverParameter) {
this.receiverArgument = receiverParameter;
}
@Override
@NotNull
public ReceiverDescriptor getThisObject() {
return thisObject;
}
public void setThisObject(@NotNull ReceiverDescriptor thisObject) {
this.thisObject = thisObject;
}
@Override
@NotNull
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.ReceiverDescriptor;
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.checker.JetTypeChecker;
@@ -44,16 +43,16 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
/**
* @author abreslav
*/
/*package*/ abstract class TaskPrioritizer<D extends CallableDescriptor> {
/*package*/ abstract class TaskPrioritizer {
public static <D extends CallableDescriptor> void splitLexicallyLocalDescriptors(
@NotNull Collection<ResolvedCallImpl<D>> allDescriptors,
@NotNull Collection<ResolutionCandidate<D>> allDescriptors,
@NotNull DeclarationDescriptor containerOfTheCurrentLocality,
@NotNull Collection<ResolvedCallImpl<D>> local,
@NotNull Collection<ResolvedCallImpl<D>> nonlocal
@NotNull Collection<ResolutionCandidate<D>> local,
@NotNull Collection<ResolutionCandidate<D>> nonlocal
) {
for (ResolvedCallImpl<D> resolvedCall : allDescriptors) {
if (DescriptorUtils.isLocal(containerOfTheCurrentLocality, resolvedCall.getCandidateDescriptor())) {
for (ResolutionCandidate<D> resolvedCall : allDescriptors) {
if (DescriptorUtils.isLocal(containerOfTheCurrentLocality, resolvedCall.getDescriptor())) {
local.add(resolvedCall);
}
else {
@@ -75,8 +74,8 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
}
@NotNull
public List<ResolutionTask<D>> computePrioritizedTasks(@NotNull BasicResolutionContext context, @NotNull String name,
@NotNull JetReferenceExpression functionReference) {
public static <D extends CallableDescriptor> List<ResolutionTask<D>> computePrioritizedTasks(@NotNull BasicResolutionContext context, @NotNull String name,
@NotNull JetReferenceExpression functionReference, @NotNull List<MemberPrioritizer<D>> memberPrioritizers) {
ReceiverDescriptor explicitReceiver = context.call.getExplicitReceiver();
final JetScope scope;
if (explicitReceiver.exists() && explicitReceiver.getType() instanceof NamespaceType) {
@@ -87,40 +86,41 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
else {
scope = context.scope;
}
final Predicate<ResolvedCallImpl<D>> visibleStrategy = new Predicate<ResolvedCallImpl<D>>() {
final Predicate<ResolutionCandidate<D>> visibleStrategy = new Predicate<ResolutionCandidate<D>>() {
@Override
public boolean apply(@Nullable ResolvedCallImpl<D> call) {
public boolean apply(@Nullable ResolutionCandidate<D> call) {
if (call == null) return false;
D candidateDescriptor = call.getCandidateDescriptor();
D candidateDescriptor = call.getDescriptor();
if (ErrorUtils.isError(candidateDescriptor)) return true;
return Visibilities.isVisible(candidateDescriptor, scope.getContainingDeclaration());
}
};
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();
}
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 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());
List<ReceiverDescriptor> implicitReceivers = Lists.newArrayList();
scope.getImplicitReceiversHierarchy(implicitReceivers);
if (receiver.exists()) {
List<ReceiverDescriptor> variantsForExplicitReceiver = autoCastService.getVariantsForReceiver(receiver);
Collection<ResolvedCallImpl<D>> extensionFunctions = convertWithImpliedThis(scope, variantsForExplicitReceiver, getExtensionsByName(scope, name));
List<ResolvedCallImpl<D>> nonlocals = Lists.newArrayList();
List<ResolvedCallImpl<D>> locals = Lists.newArrayList();
Collection<ResolutionCandidate<D>> extensionFunctions = convertWithImpliedThis(scope, variantsForExplicitReceiver, memberPrioritizer.getExtensionsByName(scope, name));
List<ResolutionCandidate<D>> nonlocals = Lists.newArrayList();
List<ResolutionCandidate<D>> locals = Lists.newArrayList();
//noinspection unchecked,RedundantTypeArguments
TaskPrioritizer.<D>splitLexicallyLocalDescriptors(extensionFunctions, scope.getContainingDeclaration(), locals, nonlocals);
Collection<ResolvedCallImpl<D>> members = Lists.newArrayList();
Collection<ResolutionCandidate<D>> members = Lists.newArrayList();
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);
}
@@ -128,7 +128,7 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
result.addMembers(members);
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);
result.addNonLocalExtensions(convertWithReceivers(memberExtensions, variantsForImplicitReceiver, variantsForExplicitReceiver));
}
@@ -136,10 +136,10 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
result.addNonLocalExtensions(nonlocals);
}
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<ResolvedCallImpl<D>> locals = Lists.newArrayList();
List<ResolutionCandidate<D>> nonlocals = Lists.newArrayList();
List<ResolutionCandidate<D>> locals = Lists.newArrayList();
//noinspection unchecked,RedundantTypeArguments
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);
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) {
Collection<ResolvedCallImpl<D>> result = Lists.newArrayList();
private static <D extends CallableDescriptor> Collection<ResolutionCandidate<D>> convertWithReceivers(Collection<D> descriptors, Iterable<ReceiverDescriptor> thisObjects, Iterable<ReceiverDescriptor> receiverParameters) {
Collection<ResolutionCandidate<D>> result = Lists.newArrayList();
convertWithReceivers(descriptors, thisObjects, receiverParameters, 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 receiverParameter : receiverParameters) {
for (D extension : descriptors) {
ResolvedCallImpl<D> resolvedCall = ResolvedCallImpl.create(extension);
ResolutionCandidate<D> resolvedCall = ResolutionCandidate.create(extension);
resolvedCall.setThisObject(thisObject);
resolvedCall.setReceiverArgument(receiverParameter);
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) {
Collection<ResolvedCallImpl<D>> result = Lists.newArrayList();
public static <D extends CallableDescriptor> Collection<ResolutionCandidate<D>> convertWithImpliedThis(JetScope scope, Iterable<ReceiverDescriptor> receiverParameters, Collection<? extends D> descriptors) {
Collection<ResolutionCandidate<D>> result = Lists.newArrayList();
for (ReceiverDescriptor receiverParameter : receiverParameters) {
for (D descriptor : descriptors) {
ResolvedCallImpl<D> resolvedCall = ResolvedCallImpl.create(descriptor);
ResolutionCandidate<D> resolvedCall = ResolutionCandidate.create(descriptor);
resolvedCall.setReceiverArgument(receiverParameter);
if (setImpliedThis(scope, resolvedCall)) {
result.add(resolvedCall);
@@ -190,7 +190,7 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
containingDeclaration = containingDeclaration.getContainingDeclaration();
}
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));
result.add(resolvedCall);
}
@@ -199,8 +199,8 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
return result;
}
private static <D extends CallableDescriptor> boolean setImpliedThis(@NotNull JetScope scope, ResolvedCallImpl<D> resolvedCall) {
ReceiverDescriptor expectedThisObject = resolvedCall.getCandidateDescriptor().getExpectedThisObject();
private static <D extends CallableDescriptor> boolean setImpliedThis(@NotNull JetScope scope, ResolutionCandidate<D> resolvedCall) {
ReceiverDescriptor expectedThisObject = resolvedCall.getDescriptor().getExpectedThisObject();
if (!expectedThisObject.exists()) return true;
List<ReceiverDescriptor> receivers = Lists.newArrayList();
scope.getImplicitReceiversHierarchy(receivers);
@@ -213,13 +213,4 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
}
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) {
List<? extends ResolutionTask<? extends CallableDescriptor>> resolutionTasks = debugInfo.get(TASKS);
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);
}
}
@@ -21,6 +21,7 @@ import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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.ResolvedCallImpl;
import org.jetbrains.k2js.translate.context.TranslationContext;
@@ -103,7 +104,7 @@ public final class CallBuilder {
private CallTranslator finish() {
if (resolvedCall == null) {
assert descriptor != null;
resolvedCall = ResolvedCallImpl.create(descriptor);
resolvedCall = ResolvedCallImpl.create(ResolutionCandidate.create(descriptor));
}
if (descriptor == null) {
descriptor = resolvedCall.getCandidateDescriptor().getOriginal();