From 5ec7617c7a3e502febfecc78f59b86c8ee6d1dcc Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Fri, 20 Apr 2012 15:52:27 +0400 Subject: [PATCH] Call resolution refactoring (logic hasn't changed) - interfaces MemberPrioritizer, ResolutionCandidate introduced - CallTransformationStrategy will be responsible for variable with 'invoke' method as function resolve --- .../resolve/calls/CallResolutionContext.java | 40 +++ .../jet/lang/resolve/calls/CallResolver.java | 291 +++++++++--------- .../calls/CallTransformationStrategy.java | 118 +++++++ .../lang/resolve/calls/MemberPrioritizer.java | 38 +++ ...oritizers.java => MemberPrioritizers.java} | 27 +- .../resolve/calls/ResolutionCandidate.java | 77 +++++ .../lang/resolve/calls/ResolutionTask.java | 21 +- .../resolve/calls/ResolutionTaskHolder.java | 24 +- .../lang/resolve/calls/ResolvedCallImpl.java | 30 +- .../lang/resolve/calls/TaskPrioritizer.java | 79 +++-- .../resolvewindow/ResolveToolwindow.java | 2 +- .../k2js/translate/reference/CallBuilder.java | 3 +- 12 files changed, 506 insertions(+), 244 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolutionContext.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallTransformationStrategy.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/MemberPrioritizer.java rename compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/{TaskPrioritizers.java => MemberPrioritizers.java} (82%) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionCandidate.java diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolutionContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolutionContext.java new file mode 100644 index 00000000000..03c5013330a --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolutionContext.java @@ -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 extends ResolutionContext { + /*package*/ final ResolvedCallImpl candidateCall; + /*package*/ final TracingStrategy tracing; + + public CallResolutionContext(@NotNull ResolvedCallImpl candidateCall, @NotNull ResolutionTask 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 candidateCall, @NotNull ResolutionTask task, @NotNull BindingTrace trace, @NotNull TracingStrategy tracing) { + this(candidateCall, task, trace, tracing, task.call); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index 5b62fdadd2a..990d6298b69 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -102,16 +102,16 @@ public class CallResolver { if (referencedName == null) { return OverloadResolutionResultsImpl.nameNotFound(); } - TaskPrioritizer task_prioritizer; + List> 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> prioritizedTasks = task_prioritizer.computePrioritizedTasks(context, referencedName, nameExpression); - return doResolveCall(context, prioritizedTasks, nameExpression); + List> 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> tasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks( - context, name, functionReference); - return doResolveCall(context, tasks, functionReference); + List> 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 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> candidates = TaskPrioritizer.convertWithImpliedThis(context.scope, Collections.singletonList(NO_RECEIVER), constructors); + Collection> candidates = TaskPrioritizer.convertWithImpliedThis(context.scope, Collections.singletonList(NO_RECEIVER), constructors); prioritizedTasks.add(new ResolutionTask(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY } else { @@ -206,7 +206,7 @@ public class CallResolver { context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn)); return checkArgumentTypesAndFail(context); } - List> candidates = ResolvedCallImpl.convertCollection(constructors); + List> candidates = ResolutionCandidate.convertCollection(constructors); prioritizedTasks = Collections.singletonList(new ResolutionTask(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 resolvedCall = ResolvedCallImpl.create(functionDescriptor); - resolvedCall.setReceiverArgument(context.call.getExplicitReceiver()); + ResolutionCandidate resolutionCandidate = ResolutionCandidate.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(Collections.singleton(resolvedCall), functionReference, context)); + prioritizedTasks = Collections.singletonList(new ResolutionTask(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 OverloadResolutionResults checkArgumentTypesAndFail(BasicResolutionContext context) { @@ -251,6 +251,7 @@ public class CallResolver { private OverloadResolutionResults doResolveCall( @NotNull final BasicResolutionContext context, @NotNull final List> prioritizedTasks, // high to low priority + @NotNull CallTransformationStrategy callTransformationStrategy, @NotNull final JetReferenceExpression reference) { ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create(); @@ -267,7 +268,7 @@ public class CallResolver { OverloadResolutionResultsImpl resultsForFirstNonemptyCandidateSet = null; for (ResolutionTask task : prioritizedTasks) { TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace); - OverloadResolutionResultsImpl results = performResolutionGuardedForExtraFunctionLiteralArguments(task.withTrace(temporaryTrace)); + OverloadResolutionResultsImpl results = performResolutionGuardedForExtraFunctionLiteralArguments(task.withTrace(temporaryTrace), callTransformationStrategy); if (results.isSuccess() || results.isAmbiguity()) { temporaryTrace.commit(); @@ -299,8 +300,9 @@ public class CallResolver { ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @NotNull - private OverloadResolutionResultsImpl performResolutionGuardedForExtraFunctionLiteralArguments(ResolutionTask task) { - OverloadResolutionResultsImpl results = performResolution(task); + private OverloadResolutionResultsImpl performResolutionGuardedForExtraFunctionLiteralArguments(@NotNull ResolutionTask task, + @NotNull CallTransformationStrategy callTransformationStrategy) { + OverloadResolutionResultsImpl 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> newCandidates = Lists.newArrayList(); - for (ResolvedCallImpl candidate : task.getCandidates()) { - newCandidates.add(ResolvedCallImpl.create(candidate.getCandidateDescriptor())); + Collection> newCandidates = Lists.newArrayList(); + for (ResolutionCandidate candidate : task.getCandidates()) { + newCandidates.add(ResolutionCandidate.create(candidate.getDescriptor())); } ResolutionTask newContext = new ResolutionTask(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 resultsWithFunctionLiteralsStripped = performResolution(newContext); + OverloadResolutionResultsImpl 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 OverloadResolutionResultsImpl performResolution(ResolutionTask task) { - for (ResolvedCallImpl candidateCall : task.getCandidates()) { - D candidate = candidateCall.getCandidateDescriptor(); + private OverloadResolutionResultsImpl performResolution(@NotNull ResolutionTask task, + @NotNull CallTransformationStrategy callTransformationStrategy) { + + for (ResolutionCandidate resolutionCandidate : task.getCandidates()) { TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(task.trace); - candidateCall.setTrace(temporaryTrace); + CallResolutionContext context = callTransformationStrategy.createCallContext(resolutionCandidate, task, temporaryTrace, task.tracing); + performResolutionForCandidateCall(context, task, temporaryTrace); - CallResolutionContext context = new CallResolutionContext(candidateCall, task, temporaryTrace, task.tracing); - - context.tracing.bindReference(context.trace, candidateCall); - - if (ErrorUtils.isError(candidate)) { - candidateCall.setStatus(SUCCESS); - checkTypesWithNoCallee(context.toBasic()); - continue; + Collection> calls = callTransformationStrategy.transformResultCall(context, this, task); + for (ResolvedCallImpl 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 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 typeArguments = new ArrayList(); - 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 substitutionContext = FunctionDescriptorUtil.createSubstitutionContext((FunctionDescriptor) candidate, typeArguments); - D substitutedDescriptor = (D) candidate.substitute(TypeSubstitutor.create(substitutionContext)); - - candidateCall.setResultingDescriptor(substitutedDescriptor); - replaceValueParametersWithSubstitutedOnes(candidateCall, substitutedDescriptor); - - List 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> successfulCandidates = Sets.newLinkedHashSet(); Set> failedCandidates = Sets.newLinkedHashSet(); - for (ResolvedCallImpl candidateCall : task.getCandidates()) { + for (ResolvedCallImpl candidateCall : task.getResolvedCallMap().values()) { ResolutionStatus status = candidateCall.getStatus(); if (status.isSuccess()) { successfulCandidates.add(candidateCall); @@ -456,6 +380,99 @@ public class CallResolver { return results; } + private void performResolutionForCandidateCall(@NotNull CallResolutionContext context, + @NotNull ResolutionTask task, + @NotNull TemporaryBindingTrace temporaryTrace) { + ResolvedCallImpl 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 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 typeArguments = new ArrayList(); + 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 + substitutionContext = FunctionDescriptorUtil.createSubstitutionContext((FunctionDescriptor)candidate, typeArguments); + D substitutedDescriptor = (D) candidate.substitute(TypeSubstitutor.create(substitutionContext)); + + candidateCall.setResultingDescriptor(substitutedDescriptor); + replaceValueParametersWithSubstitutedOnes(candidateCall, substitutedDescriptor); + + List 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 ResolutionStatus inferTypeArguments(CallResolutionContext context) { ResolvedCallImpl candidateCall = context.candidateCall; D candidate = candidateCall.getCandidateDescriptor(); @@ -843,25 +860,26 @@ public class CallResolver { @NotNull public OverloadResolutionResults resolveExactSignature(@NotNull JetScope scope, @NotNull ReceiverDescriptor receiver, @NotNull String name, @NotNull List parameterTypes) { - List> result = findCandidatesByExactSignature(scope, receiver, name, parameterTypes); + List> candidates = findCandidatesByExactSignature(scope, receiver, name, parameterTypes); BindingTraceContext trace = new BindingTraceContext(); TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(trace); - Set> candidates = Sets.newLinkedHashSet(); - for (ResolvedCallImpl call : result) { + Set> calls = Sets.newLinkedHashSet(); + for (ResolutionCandidate candidate : candidates) { + ResolvedCallImpl call = ResolvedCallImpl.create(candidate); call.setTrace(temporaryBindingTrace); - candidates.add(call); + calls.add(call); } - return computeResultAndReportErrors(trace, TracingStrategy.EMPTY, candidates, Collections.>emptySet()); + return computeResultAndReportErrors(trace, TracingStrategy.EMPTY, calls, Collections.>emptySet()); } - private List> findCandidatesByExactSignature(JetScope scope, ReceiverDescriptor receiver, + private List> findCandidatesByExactSignature(JetScope scope, ReceiverDescriptor receiver, String name, List parameterTypes) { - List> result = Lists.newArrayList(); + List> result = Lists.newArrayList(); if (receiver.exists()) { - Collection> extensionFunctionDescriptors = ResolvedCallImpl.convertCollection(scope.getFunctions(name)); - List> nonlocal = Lists.newArrayList(); - List> local = Lists.newArrayList(); + Collection> extensionFunctionDescriptors = ResolutionCandidate.convertCollection(scope.getFunctions(name)); + List> nonlocal = Lists.newArrayList(); + List> local = Lists.newArrayList(); TaskPrioritizer.splitLexicallyLocalDescriptors(extensionFunctionDescriptors, scope.getContainingDeclaration(), local, nonlocal); @@ -869,7 +887,7 @@ public class CallResolver { return result; } - Collection> functionDescriptors = ResolvedCallImpl.convertCollection(receiver.getType().getMemberScope().getFunctions(name)); + Collection> 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> candidates, List parameterTypes, - List> result) { + private static boolean lookupExactSignature(Collection> candidates, List parameterTypes, + List> result) { boolean found = false; - for (ResolvedCallImpl resolvedCall : candidates) { - FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor(); + for (ResolutionCandidate 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> candidates, ReceiverDescriptor receiver, - List parameterTypes, List> result) { + private boolean findExtensionFunctions(Collection> candidates, ReceiverDescriptor receiver, + List parameterTypes, List> result) { boolean found = false; - for (ResolvedCallImpl resolvedCall : candidates) { - FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor(); + for (ResolutionCandidate 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 extends ResolutionContext { - /*package*/ final ResolvedCallImpl candidateCall; - /*package*/ final TracingStrategy tracing; - - public CallResolutionContext(ResolvedCallImpl candidateCall, ResolutionTask task, BindingTrace trace, TracingStrategy tracing) { - super(trace, task.scope, task.call, task.expectedType, task.dataFlowInfo); - this.candidateCall = candidateCall; - this.tracing = tracing; - } - } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallTransformationStrategy.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallTransformationStrategy.java new file mode 100644 index 00000000000..5fc68364ae5 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallTransformationStrategy.java @@ -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 { + + @NotNull + CallResolutionContext createCallContext(@NotNull ResolutionCandidate candidate, + @NotNull ResolutionTask task, + @NotNull BindingTrace trace, + @NotNull TracingStrategy tracing); + + @NotNull + Collection> transformResultCall(@NotNull CallResolutionContext callResolutionContext, + @NotNull CallResolver callResolver, + @NotNull ResolutionTask task); + + CallTransformationStrategy + PROPERTY_CALL_TRANSFORMATION_STRATEGY = new CallTransformationStrategy() { + @NotNull + @Override + public CallResolutionContext createCallContext(@NotNull ResolutionCandidate candidate, + @NotNull ResolutionTask task, @NotNull BindingTrace trace, @NotNull TracingStrategy tracing) { + ResolvedCallImpl candidateCall = ResolvedCallImpl.create(candidate); + return new CallResolutionContext(candidateCall, task, trace, tracing); + } + + @NotNull + @Override + public Collection> transformResultCall(@NotNull CallResolutionContext context, + @NotNull CallResolver callResolver, @NotNull ResolutionTask task) { + return Collections.singleton(context.candidateCall); + } + }; + + CallTransformationStrategy + FUNCTION_CALL_TRANSFORMATION_STRATEGY = new CallTransformationStrategy() { + @NotNull + @Override + public CallResolutionContext createCallContext(@NotNull ResolutionCandidate candidate, + @NotNull ResolutionTask task, + @NotNull BindingTrace trace, + @NotNull TracingStrategy tracing) { + if (candidate.getDescriptor() instanceof FunctionDescriptor) { + return new CallResolutionContext(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 getFunctionLiteralArguments() { + return Collections.emptyList(); + } + + @NotNull + @Override + public List getTypeArguments() { + return Collections.emptyList(); + } + + @Override + public JetTypeArgumentList getTypeArgumentList() { + return null; + } + }; + return new CallResolutionContext(ResolvedCallImpl.create(candidate), task, trace, tracing, propertyCall); + } + + @NotNull + @Override + public Collection> transformResultCall(@NotNull CallResolutionContext context, + @NotNull CallResolver callResolver, @NotNull ResolutionTask 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 results = + callResolver.resolveCallWithGivenName(basicResolutionContext, task.reference, "invoke"); + return ((OverloadResolutionResultsImpl)results).getResultingCalls(); + } + }; +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/MemberPrioritizer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/MemberPrioritizer.java new file mode 100644 index 00000000000..14dace99c4d --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/MemberPrioritizer.java @@ -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 { + @NotNull + Collection getNonExtensionsByName(JetScope scope, String name); + + @NotNull + Collection getMembersByName(@NotNull JetType receiver, String name); + + @NotNull + Collection getExtensionsByName(JetScope scope, String name); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizers.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/MemberPrioritizers.java similarity index 82% rename from compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizers.java rename to compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/MemberPrioritizers.java index 48e16fb27c1..a7e793dcb4a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizers.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/MemberPrioritizers.java @@ -34,14 +34,15 @@ import java.util.*; /** * @author abreslav */ -public class TaskPrioritizers { +public class MemberPrioritizers { - /*package*/ static TaskPrioritizer FUNCTION_TASK_PRIORITIZER = new TaskPrioritizer() { + /*package*/ static MemberPrioritizer FUNCTION_TASK_PRIORITIZER = new MemberPrioritizer() { + @NotNull @Override - protected Collection getNonExtensionsByName(JetScope scope, String name) { + public Collection getNonExtensionsByName(JetScope scope, String name) { Set functions = Sets.newLinkedHashSet(scope.getFunctions(name)); for (Iterator iterator = functions.iterator(); iterator.hasNext(); ) { FunctionDescriptor functionDescriptor = iterator.next(); @@ -57,7 +58,7 @@ public class TaskPrioritizers { @NotNull @Override - protected Collection getMembersByName(@NotNull JetType receiverType, String name) { + public Collection getMembersByName(@NotNull JetType receiverType, String name) { JetScope receiverScope = receiverType.getMemberScope(); Set members = Sets.newHashSet(receiverScope.getFunctions(name)); addConstructors(receiverScope, name, members); @@ -67,7 +68,7 @@ public class TaskPrioritizers { @NotNull @Override - protected Collection getExtensionsByName(JetScope scope, String name) { + public Collection getExtensionsByName(JetScope scope, String name) { Set extensionFunctions = Sets.newHashSet(scope.getFunctions(name)); for (Iterator iterator = extensionFunctions.iterator(); iterator.hasNext(); ) { FunctionDescriptor descriptor = iterator.next(); @@ -104,11 +105,11 @@ public class TaskPrioritizers { } }; - /*package*/ static TaskPrioritizer VARIABLE_TASK_PRIORITIZER = new TaskPrioritizer() { + /*package*/ static MemberPrioritizer VARIABLE_TASK_PRIORITIZER = new MemberPrioritizer() { @NotNull @Override - protected Collection getNonExtensionsByName(JetScope scope, String name) { + public Collection 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 getMembersByName(@NotNull JetType receiverType, String name) { + public Collection getMembersByName(@NotNull JetType receiverType, String name) { return receiverType.getMemberScope().getProperties(name); } @NotNull @Override - protected Collection getExtensionsByName(JetScope scope, String name) { + public Collection getExtensionsByName(JetScope scope, String name) { return Collections2.filter(scope.getProperties(name), new Predicate() { @Override public boolean apply(@Nullable VariableDescriptor variableDescriptor) { @@ -135,7 +136,7 @@ public class TaskPrioritizers { } }; - /*package*/ static TaskPrioritizer PROPERTY_TASK_PRIORITIZER = new TaskPrioritizer() { + /*package*/ static MemberPrioritizer PROPERTY_TASK_PRIORITIZER = new MemberPrioritizer() { private Collection filterProperties(Collection variableDescriptors) { ArrayList properties = Lists.newArrayList(); for (VariableDescriptor descriptor : variableDescriptors) { @@ -148,19 +149,19 @@ public class TaskPrioritizers { @NotNull @Override - protected Collection getNonExtensionsByName(JetScope scope, String name) { + public Collection getNonExtensionsByName(JetScope scope, String name) { return filterProperties(VARIABLE_TASK_PRIORITIZER.getNonExtensionsByName(scope, name)); } @NotNull @Override - protected Collection getMembersByName(@NotNull JetType receiver, String name) { + public Collection getMembersByName(@NotNull JetType receiver, String name) { return filterProperties(VARIABLE_TASK_PRIORITIZER.getMembersByName(receiver, name)); } @NotNull @Override - protected Collection getExtensionsByName(JetScope scope, String name) { + public Collection getExtensionsByName(JetScope scope, String name) { return filterProperties(VARIABLE_TASK_PRIORITIZER.getExtensionsByName(scope, name)); } }; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionCandidate.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionCandidate.java new file mode 100644 index 00000000000..829185e3e31 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionCandidate.java @@ -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 { + 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 ResolutionCandidate create(@NotNull D descriptor) { + return new ResolutionCandidate(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 List> convertCollection(@NotNull Collection descriptors) { + List> result = Lists.newArrayList(); + for (D descriptor : descriptors) { + result.add(create(descriptor)); + } + return result; + } + +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTask.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTask.java index 32f3873ee83..5e3f7fdbac2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTask.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTask.java @@ -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 extends ResolutionContext { - private final Collection> candidates; + private final Collection> candidates; + private final Multimap, ResolvedCallImpl> resolvedCallMap = HashMultimap.create(); /*package*/ final JetReferenceExpression reference; private DescriptorCheckStrategy checkingStrategy; - public ResolutionTask(@NotNull Collection> candidates, @NotNull JetReferenceExpression reference, + public ResolutionTask(@NotNull Collection> 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> candidates, @NotNull JetReferenceExpression reference, @NotNull BasicResolutionContext context) { + public ResolutionTask(@NotNull Collection> candidates, @NotNull JetReferenceExpression reference, @NotNull BasicResolutionContext context) { this(candidates, reference, context.trace, context.scope, context.call, context.expectedType, context.dataFlowInfo); } @NotNull - public Collection> getCandidates() { + public Collection> getCandidates() { return candidates; } + @NotNull + public Multimap, ResolvedCallImpl> getResolvedCallMap() { + return resolvedCallMap; + } + public void setCheckingStrategy(DescriptorCheckStrategy strategy) { checkingStrategy = strategy; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTaskHolder.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTaskHolder.java index 4b27a266b07..4e39c8ccfde 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTaskHolder.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTaskHolder.java @@ -34,35 +34,35 @@ import java.util.List; public class ResolutionTaskHolder { private final JetReferenceExpression reference; private final BasicResolutionContext basicResolutionContext; - private final Predicate> visibleStrategy; + private final Predicate> visibleStrategy; - private final Collection>> localExtensions = Sets.newLinkedHashSet(); - private final Collection>> members = Sets.newLinkedHashSet(); - private final Collection>> nonLocalExtensions = Sets.newLinkedHashSet(); + private final Collection>> localExtensions = Sets.newLinkedHashSet(); + private final Collection>> members = Sets.newLinkedHashSet(); + private final Collection>> nonLocalExtensions = Sets.newLinkedHashSet(); private List> tasks = null; public ResolutionTaskHolder(@NotNull JetReferenceExpression reference, @NotNull BasicResolutionContext basicResolutionContext, - @NotNull Predicate> visibleStrategy) { + @NotNull Predicate> visibleStrategy) { this.reference = reference; this.basicResolutionContext = basicResolutionContext; this.visibleStrategy = visibleStrategy; } - public void addLocalExtensions(@NotNull Collection> candidates) { + public void addLocalExtensions(@NotNull Collection> candidates) { if (!candidates.isEmpty()) { localExtensions.add(candidates); } } - public void addMembers(@NotNull Collection> candidates) { + public void addMembers(@NotNull Collection> candidates) { if (!candidates.isEmpty()) { members.add(candidates); } } - public void addNonLocalExtensions(@NotNull Collection> candidates) { + public void addNonLocalExtensions(@NotNull Collection> candidates) { if (!candidates.isEmpty()) { nonLocalExtensions.add(candidates); } @@ -71,7 +71,7 @@ public class ResolutionTaskHolder { public List> getTasks() { if (tasks == null) { tasks = Lists.newArrayList(); - List>> candidateList = Lists.newArrayList(); + List>> 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 { } candidateList.addAll(nonLocalExtensions); - for (Predicate> visibilityStrategy : Lists.newArrayList(visibleStrategy, Predicates.not(visibleStrategy))) { - for (Collection> candidates : candidateList) { - Collection> filteredCandidates = Collections2.filter(candidates, visibilityStrategy); + for (Predicate> visibilityStrategy : Lists.newArrayList(visibleStrategy, Predicates.not(visibleStrategy))) { + for (Collection> candidates : candidateList) { + Collection> filteredCandidates = Collections2.filter(candidates, visibilityStrategy); if (!filteredCandidates.isEmpty()) { tasks.add(new ResolutionTask(filteredCandidates, reference, basicResolutionContext)); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolvedCallImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolvedCallImpl.java index 771cca8c841..7f7d1b84411 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolvedCallImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolvedCallImpl.java @@ -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 implements ResolvedC }; @NotNull - public static ResolvedCallImpl create(@NotNull D descriptor) { - return new ResolvedCallImpl(descriptor); - } - - @NotNull - public static List> convertCollection(@NotNull Collection descriptors) { - List> result = Lists.newArrayList(); - for (D descriptor : descriptors) { - result.add(create(descriptor)); - } - return result; + public static ResolvedCallImpl create(@NotNull ResolutionCandidate candidate) { + return new ResolvedCallImpl(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 typeArguments = Maps.newLinkedHashMap(); private final Map autoCasts = Maps.newHashMap(); @@ -80,8 +70,10 @@ public class ResolvedCallImpl 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 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 getValueArguments() { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizer.java index 5492bb2c921..6a1cd61c00f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizer.java @@ -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 { +/*package*/ abstract class TaskPrioritizer { public static void splitLexicallyLocalDescriptors( - @NotNull Collection> allDescriptors, + @NotNull Collection> allDescriptors, @NotNull DeclarationDescriptor containerOfTheCurrentLocality, - @NotNull Collection> local, - @NotNull Collection> nonlocal + @NotNull Collection> local, + @NotNull Collection> nonlocal ) { - for (ResolvedCallImpl resolvedCall : allDescriptors) { - if (DescriptorUtils.isLocal(containerOfTheCurrentLocality, resolvedCall.getCandidateDescriptor())) { + for (ResolutionCandidate 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> computePrioritizedTasks(@NotNull BasicResolutionContext context, @NotNull String name, - @NotNull JetReferenceExpression functionReference) { + public static List> computePrioritizedTasks(@NotNull BasicResolutionContext context, @NotNull String name, + @NotNull JetReferenceExpression functionReference, @NotNull List> 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> visibleStrategy = new Predicate>() { + final Predicate> visibleStrategy = new Predicate>() { @Override - public boolean apply(@Nullable ResolvedCallImpl call) { + public boolean apply(@Nullable ResolutionCandidate 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 result = new ResolutionTaskHolder(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 void doComputeTasks(@NotNull JetScope scope, @NotNull ReceiverDescriptor receiver, @NotNull String name, @NotNull ResolutionTaskHolder result, - @NotNull BasicResolutionContext context) { + @NotNull BasicResolutionContext context, @NotNull List> memberPrioritizers) { + MemberPrioritizer memberPrioritizer = memberPrioritizers.get(0); AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(context.dataFlowInfo, context.trace.getBindingContext()); List implicitReceivers = Lists.newArrayList(); scope.getImplicitReceiversHierarchy(implicitReceivers); if (receiver.exists()) { List variantsForExplicitReceiver = autoCastService.getVariantsForReceiver(receiver); - Collection> extensionFunctions = convertWithImpliedThis(scope, variantsForExplicitReceiver, getExtensionsByName(scope, name)); - List> nonlocals = Lists.newArrayList(); - List> locals = Lists.newArrayList(); + Collection> extensionFunctions = convertWithImpliedThis(scope, variantsForExplicitReceiver, memberPrioritizer.getExtensionsByName(scope, name)); + List> nonlocals = Lists.newArrayList(); + List> locals = Lists.newArrayList(); //noinspection unchecked,RedundantTypeArguments TaskPrioritizer.splitLexicallyLocalDescriptors(extensionFunctions, scope.getContainingDeclaration(), locals, nonlocals); - Collection> members = Lists.newArrayList(); + Collection> members = Lists.newArrayList(); for (ReceiverDescriptor variant : variantsForExplicitReceiver) { - Collection membersForThisVariant = getMembersByName(variant.getType(), name); + Collection 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 memberExtensions = getExtensionsByName(implicitReceiver.getType().getMemberScope(), name); + Collection memberExtensions = memberPrioritizer.getExtensionsByName(implicitReceiver.getType().getMemberScope(), name); List 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> functions = convertWithImpliedThis(scope, Collections.singletonList(receiver), getNonExtensionsByName(scope, name)); + Collection> functions = convertWithImpliedThis(scope, Collections.singletonList(receiver), memberPrioritizer.getNonExtensionsByName(scope, name)); - List> nonlocals = Lists.newArrayList(); - List> locals = Lists.newArrayList(); + List> nonlocals = Lists.newArrayList(); + List> locals = Lists.newArrayList(); //noinspection unchecked,RedundantTypeArguments TaskPrioritizer.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> convertWithReceivers(Collection descriptors, Iterable thisObjects, Iterable receiverParameters) { - Collection> result = Lists.newArrayList(); + private static Collection> convertWithReceivers(Collection descriptors, Iterable thisObjects, Iterable receiverParameters) { + Collection> result = Lists.newArrayList(); convertWithReceivers(descriptors, thisObjects, receiverParameters, result); return result; } - private void convertWithReceivers(Collection descriptors, Iterable thisObjects, Iterable receiverParameters, Collection> result) { + private static void convertWithReceivers(Collection descriptors, Iterable thisObjects, Iterable receiverParameters, Collection> result) { for (ReceiverDescriptor thisObject : thisObjects) { for (ReceiverDescriptor receiverParameter : receiverParameters) { for (D extension : descriptors) { - ResolvedCallImpl resolvedCall = ResolvedCallImpl.create(extension); + ResolutionCandidate 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 Collection> convertWithImpliedThis(JetScope scope, Iterable receiverParameters, Collection descriptors) { - Collection> result = Lists.newArrayList(); + public static Collection> convertWithImpliedThis(JetScope scope, Iterable receiverParameters, Collection descriptors) { + Collection> result = Lists.newArrayList(); for (ReceiverDescriptor receiverParameter : receiverParameters) { for (D descriptor : descriptors) { - ResolvedCallImpl resolvedCall = ResolvedCallImpl.create(descriptor); + ResolutionCandidate 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 resolvedCall = ResolvedCallImpl.create(descriptor); + ResolutionCandidate 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 boolean setImpliedThis(@NotNull JetScope scope, ResolvedCallImpl resolvedCall) { - ReceiverDescriptor expectedThisObject = resolvedCall.getCandidateDescriptor().getExpectedThisObject(); + private static boolean setImpliedThis(@NotNull JetScope scope, ResolutionCandidate resolvedCall) { + ReceiverDescriptor expectedThisObject = resolvedCall.getDescriptor().getExpectedThisObject(); if (!expectedThisObject.exists()) return true; List 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 getNonExtensionsByName(JetScope scope, String name); - - @NotNull - protected abstract Collection getMembersByName(@NotNull JetType receiver, String name); - - @NotNull - protected abstract Collection getExtensionsByName(JetScope scope, String name); } diff --git a/idea/src/org/jetbrains/jet/plugin/internal/resolvewindow/ResolveToolwindow.java b/idea/src/org/jetbrains/jet/plugin/internal/resolvewindow/ResolveToolwindow.java index 6cf342f93da..d674edd60e0 100644 --- a/idea/src/org/jetbrains/jet/plugin/internal/resolvewindow/ResolveToolwindow.java +++ b/idea/src/org/jetbrains/jet/plugin/internal/resolvewindow/ResolveToolwindow.java @@ -194,7 +194,7 @@ public class ResolveToolwindow extends JPanel implements Disposable { if (debugInfo != null) { List> resolutionTasks = debugInfo.get(TASKS); for (ResolutionTask resolutionTask : resolutionTasks) { - for (ResolvedCallImpl resolvedCall : resolutionTask.getCandidates()) { + for (ResolvedCallImpl resolvedCall : resolutionTask.getResolvedCallMap().values()) { renderResolutionLogForCall(debugInfo, resolvedCall, result); } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallBuilder.java b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallBuilder.java index 0955dc23522..85a09258840 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallBuilder.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallBuilder.java @@ -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();