added ResolutionResultsCache

all resolution results are written to it instead of trace
This commit is contained in:
Svetlana Isakova
2013-03-13 17:37:17 +04:00
parent 1b1ee18f97
commit 180149b1c1
16 changed files with 200 additions and 113 deletions
@@ -78,7 +78,6 @@ public interface BindingContext {
WritableSlice<JetExpression, JetType> EXPRESSION_TYPE = new BasicWritableSlice<JetExpression, JetType>(DO_NOTHING); WritableSlice<JetExpression, JetType> EXPRESSION_TYPE = new BasicWritableSlice<JetExpression, JetType>(DO_NOTHING);
WritableSlice<JetExpression, DataFlowInfo> EXPRESSION_DATA_FLOW_INFO = new BasicWritableSlice<JetExpression, DataFlowInfo>(DO_NOTHING); WritableSlice<JetExpression, DataFlowInfo> EXPRESSION_DATA_FLOW_INFO = new BasicWritableSlice<JetExpression, DataFlowInfo>(DO_NOTHING);
WritableSlice<JetExpression, DataFlowInfo> DATAFLOW_INFO_AFTER_CONDITION = Slices.createSimpleSlice(); WritableSlice<JetExpression, DataFlowInfo> DATAFLOW_INFO_AFTER_CONDITION = Slices.createSimpleSlice();
WritableSlice<JetExpression, CallCandidateResolutionContext<FunctionDescriptor>> DEFERRED_COMPUTATION_FOR_CALL = Slices.createSimpleSlice();
WritableSlice<JetReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET = WritableSlice<JetReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET =
new BasicWritableSlice<JetReferenceExpression, DeclarationDescriptor>(DO_NOTHING); new BasicWritableSlice<JetReferenceExpression, DeclarationDescriptor>(DO_NOTHING);
@@ -89,8 +88,6 @@ public interface BindingContext {
WritableSlice<JetReferenceExpression, Collection<? extends DeclarationDescriptor>> AMBIGUOUS_REFERENCE_TARGET = WritableSlice<JetReferenceExpression, Collection<? extends DeclarationDescriptor>> AMBIGUOUS_REFERENCE_TARGET =
new BasicWritableSlice<JetReferenceExpression, Collection<? extends DeclarationDescriptor>>(DO_NOTHING); new BasicWritableSlice<JetReferenceExpression, Collection<? extends DeclarationDescriptor>>(DO_NOTHING);
WritableSlice<CallKey, OverloadResolutionResultsImpl<FunctionDescriptor>> RESOLUTION_RESULTS_FOR_FUNCTION = Slices.createSimpleSlice();
WritableSlice<CallKey, OverloadResolutionResultsImpl<VariableDescriptor>> RESOLUTION_RESULTS_FOR_PROPERTY = Slices.createSimpleSlice();
WritableSlice<JetExpression, DelegatingBindingTrace> TRACE_DELTAS_CACHE = Slices.createSimpleSlice(); WritableSlice<JetExpression, DelegatingBindingTrace> TRACE_DELTAS_CACHE = Slices.createSimpleSlice();
WritableSlice<JetExpression, ResolvedCall<FunctionDescriptor>> LOOP_RANGE_ITERATOR_RESOLVED_CALL = Slices.createSimpleSlice(); WritableSlice<JetExpression, ResolvedCall<FunctionDescriptor>> LOOP_RANGE_ITERATOR_RESOLVED_CALL = Slices.createSimpleSlice();
@@ -25,6 +25,8 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.context.ResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.context.ResolutionResultsCache;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall; import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
@@ -276,17 +278,6 @@ public class BindingContextUtils {
trace.report(AMBIGUOUS_LABEL.on(targetLabel)); trace.report(AMBIGUOUS_LABEL.on(targetLabel));
} }
public static void commitResolutionCacheData(@NotNull DelegatingBindingTrace trace, @NotNull BindingTrace traceForResolutionCache) {
trace.addAllMyDataTo(traceForResolutionCache, new TraceEntryFilter() {
@Override
public boolean accept(@NotNull WritableSlice<?, ?> slice, Object key) {
return slice == BindingContext.RESOLUTION_RESULTS_FOR_FUNCTION ||
slice == BindingContext.RESOLUTION_RESULTS_FOR_PROPERTY ||
slice == BindingContext.TRACE_DELTAS_CACHE;
}
}, false);
}
public static void recordExpressionType( public static void recordExpressionType(
@NotNull JetExpression expression, @NotNull BindingTrace trace, @NotNull JetExpression expression, @NotNull BindingTrace trace,
@NotNull JetScope resolutionScope, @NotNull JetTypeInfo result @NotNull JetScope resolutionScope, @NotNull JetTypeInfo result
@@ -187,17 +187,18 @@ public class ArgumentTypeResolver {
if (expression instanceof JetCallExpression) { if (expression instanceof JetCallExpression) {
result = callExpressionResolver.getCallExpressionTypeInfoForCall( result = callExpressionResolver.getCallExpressionTypeInfoForCall(
(JetCallExpression) expression, ReceiverValue.NO_RECEIVER, null, (JetCallExpression) expression, ReceiverValue.NO_RECEIVER, null,
context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE), ResolveMode.NESTED_CALL); context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE), ResolveMode.NESTED_CALL, context.resolutionResultsCache);
} }
else { // expression instanceof JetQualifiedExpression else { // expression instanceof JetQualifiedExpression
result = callExpressionResolver.getQualifiedExpressionExtendedTypeInfo( result = callExpressionResolver.getQualifiedExpressionExtendedTypeInfo(
(JetQualifiedExpression) expression, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE), ResolveMode.NESTED_CALL); (JetQualifiedExpression) expression, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE),
ResolveMode.NESTED_CALL, context.resolutionResultsCache);
} }
recordExpressionType(expression, context.trace, context.scope, result.getTypeInfo()); recordExpressionType(expression, context.trace, context.scope, result.getTypeInfo());
CallCandidateResolutionContext<FunctionDescriptor> deferredContext = result.getCallCandidateResolutionContext(); CallCandidateResolutionContext<FunctionDescriptor> deferredContext = result.getCallCandidateResolutionContext();
if (deferredContext != null) { if (deferredContext != null) {
context.trace.record(BindingContext.DEFERRED_COMPUTATION_FOR_CALL, expression, deferredContext); context.resolutionResultsCache.recordDeferredComputationForCall(expression, deferredContext);
} }
if (traceToCommitForCall != null) { if (traceToCommitForCall != null) {
traceToCommitForCall.commit(); traceToCommitForCall.commit();
@@ -24,6 +24,7 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace; import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
import org.jetbrains.jet.lang.resolve.TraceUtil;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.context.*; import org.jetbrains.jet.lang.resolve.calls.context.*;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem; import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
@@ -173,11 +174,12 @@ public class CallExpressionResolver {
@Nullable @Nullable
private ResolvedCallWithTrace<FunctionDescriptor> getResolvedCallForFunction( private ResolvedCallWithTrace<FunctionDescriptor> getResolvedCallForFunction(
@NotNull Call call, @NotNull JetExpression callExpression, @NotNull ReceiverValue receiver, @NotNull Call call, @NotNull JetExpression callExpression, @NotNull ReceiverValue receiver,
@NotNull ResolutionContext context, @NotNull ResolveMode resolveMode, @NotNull boolean[] result @NotNull ResolutionContext context, @NotNull ResolveMode resolveMode,
@NotNull ResolutionResultsCache resolutionResultsCache, @NotNull boolean[] result
) { ) {
CallResolver callResolver = expressionTypingServices.getCallResolver(); CallResolver callResolver = expressionTypingServices.getCallResolver();
OverloadResolutionResultsImpl<FunctionDescriptor> results = callResolver.resolveFunctionCall( OverloadResolutionResultsImpl<FunctionDescriptor> results = callResolver.resolveFunctionCall(
BasicCallResolutionContext.create(context, call, resolveMode)); BasicCallResolutionContext.create(context, call, resolveMode, resolutionResultsCache));
if (!results.isNothing()) { if (!results.isNothing()) {
checkSuper(receiver, results, context.trace, callExpression); checkSuper(receiver, results, context.trace, callExpression);
result[0] = true; result[0] = true;
@@ -205,7 +207,8 @@ public class CallExpressionResolver {
CallResolver callResolver = expressionTypingServices.getCallResolver(); CallResolver callResolver = expressionTypingServices.getCallResolver();
Call call = CallMaker.makePropertyCall(receiver, callOperationNode, nameExpression); Call call = CallMaker.makePropertyCall(receiver, callOperationNode, nameExpression);
OverloadResolutionResults<VariableDescriptor> resolutionResult = callResolver.resolveSimpleProperty( OverloadResolutionResults<VariableDescriptor> resolutionResult = callResolver.resolveSimpleProperty(
BasicCallResolutionContext.create(context.replaceBindingTrace(traceForVariable), call, ResolveMode.TOP_LEVEL_CALL)); BasicCallResolutionContext.create(context.replaceBindingTrace(traceForVariable), call, ResolveMode.TOP_LEVEL_CALL,
ResolutionResultsCache.create()));
if (!resolutionResult.isNothing()) { if (!resolutionResult.isNothing()) {
traceForVariable.commit(); traceForVariable.commit();
checkSuper(receiver, resolutionResult, context.trace, nameExpression); checkSuper(receiver, resolutionResult, context.trace, nameExpression);
@@ -252,7 +255,9 @@ public class CallExpressionResolver {
Call call = CallMaker.makeCall(nameExpression, receiver, callOperationNode, nameExpression, Collections.<ValueArgument>emptyList()); Call call = CallMaker.makeCall(nameExpression, receiver, callOperationNode, nameExpression, Collections.<ValueArgument>emptyList());
TemporaryBindingTrace traceForFunction = TemporaryBindingTrace.create(context.trace, "trace to resolve as function", nameExpression); TemporaryBindingTrace traceForFunction = TemporaryBindingTrace.create(context.trace, "trace to resolve as function", nameExpression);
ResolvedCall<FunctionDescriptor> resolvedCall = getResolvedCallForFunction(call, nameExpression, receiver, context, ResolveMode.TOP_LEVEL_CALL, result); ResolvedCall<FunctionDescriptor> resolvedCall = getResolvedCallForFunction(
call, nameExpression, receiver, context, ResolveMode.TOP_LEVEL_CALL,
ResolutionResultsCache.create(), result);
if (result[0]) { if (result[0]) {
FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null; FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null;
traceForFunction.commit(); traceForFunction.commit();
@@ -269,16 +274,18 @@ public class CallExpressionResolver {
@NotNull @NotNull
public JetTypeInfo getCallExpressionTypeInfo(@NotNull JetCallExpression callExpression, @NotNull ReceiverValue receiver, public JetTypeInfo getCallExpressionTypeInfo(@NotNull JetCallExpression callExpression, @NotNull ReceiverValue receiver,
@Nullable ASTNode callOperationNode, @NotNull ResolutionContext context) { @Nullable ASTNode callOperationNode, @NotNull ResolutionContext context) {
return getCallExpressionTypeInfoForCall(callExpression, receiver, callOperationNode, context, ResolveMode.TOP_LEVEL_CALL).getTypeInfo(); return getCallExpressionTypeInfoForCall(callExpression, receiver, callOperationNode, context, ResolveMode.TOP_LEVEL_CALL,
ResolutionResultsCache.create()).getTypeInfo();
} }
@NotNull @NotNull
public TypeInfoForCall getCallExpressionTypeInfoForCall( public <D extends CallableDescriptor> TypeInfoForCall getCallExpressionTypeInfoForCall(
@NotNull JetCallExpression callExpression, @NotNull ReceiverValue receiver, @NotNull JetCallExpression callExpression, @NotNull ReceiverValue receiver,
@Nullable ASTNode callOperationNode, @NotNull ResolutionContext context, @NotNull ResolveMode resolveMode @Nullable ASTNode callOperationNode, @NotNull ResolutionContext context, @NotNull ResolveMode resolveMode,
@NotNull ResolutionResultsCache resolutionResultsCache
) { ) {
TypeInfoForCall typeInfoForCall = getCallExpressionTypeInfoForCallWithoutFinalTypeCheck(callExpression, receiver, callOperationNode, TypeInfoForCall typeInfoForCall = getCallExpressionTypeInfoForCallWithoutFinalTypeCheck(
context, resolveMode); callExpression, receiver, callOperationNode, context, resolveMode, resolutionResultsCache);
if (resolveMode == ResolveMode.TOP_LEVEL_CALL) { if (resolveMode == ResolveMode.TOP_LEVEL_CALL) {
DataFlowUtils.checkType(typeInfoForCall.getType(), callExpression, context, typeInfoForCall.getDataFlowInfo()); DataFlowUtils.checkType(typeInfoForCall.getType(), callExpression, context, typeInfoForCall.getDataFlowInfo());
} }
@@ -286,16 +293,17 @@ public class CallExpressionResolver {
} }
@NotNull @NotNull
public TypeInfoForCall getCallExpressionTypeInfoForCallWithoutFinalTypeCheck( public <D extends CallableDescriptor> TypeInfoForCall getCallExpressionTypeInfoForCallWithoutFinalTypeCheck(
@NotNull JetCallExpression callExpression, @NotNull ReceiverValue receiver, @NotNull JetCallExpression callExpression, @NotNull ReceiverValue receiver,
@Nullable ASTNode callOperationNode, @NotNull ResolutionContext context, @NotNull ResolveMode resolveMode @Nullable ASTNode callOperationNode, @NotNull ResolutionContext context, @NotNull ResolveMode resolveMode,
@NotNull ResolutionResultsCache resolutionResultsCache
) { ) {
boolean[] result = new boolean[1]; boolean[] result = new boolean[1];
Call call = CallMaker.makeCall(receiver, callOperationNode, callExpression); Call call = CallMaker.makeCall(receiver, callOperationNode, callExpression);
TemporaryBindingTrace traceForFunction = TemporaryBindingTrace.create(context.trace, "trace to resolve as function call", callExpression); TemporaryBindingTrace traceForFunction = TemporaryBindingTrace.create(context.trace, "trace to resolve as function call", callExpression);
ResolvedCallWithTrace<FunctionDescriptor> resolvedCall = getResolvedCallForFunction( ResolvedCallWithTrace<FunctionDescriptor> resolvedCall = getResolvedCallForFunction(
call, callExpression, receiver, context.replaceBindingTrace(traceForFunction), resolveMode, result); call, callExpression, receiver, context.replaceBindingTrace(traceForFunction), resolveMode, resolutionResultsCache, result);
if (result[0]) { if (result[0]) {
FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null; FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null;
traceForFunction.commit(); traceForFunction.commit();
@@ -309,7 +317,7 @@ public class CallExpressionResolver {
} }
JetType type = functionDescriptor.getReturnType(); JetType type = functionDescriptor.getReturnType();
return TypeInfoForCall.create(type, resolvedCall.getDataFlowInfo(), resolvedCall, call, context, resolveMode); return TypeInfoForCall.create(type, resolvedCall.getDataFlowInfo(), resolvedCall, call, context, resolveMode, resolutionResultsCache);
} }
JetExpression calleeExpression = callExpression.getCalleeExpression(); JetExpression calleeExpression = callExpression.getCalleeExpression();
@@ -348,11 +356,12 @@ public class CallExpressionResolver {
@Nullable ASTNode callOperationNode, @Nullable ASTNode callOperationNode,
@NotNull JetExpression selectorExpression, @NotNull JetExpression selectorExpression,
@NotNull ResolutionContext context, @NotNull ResolutionContext context,
@NotNull ResolveMode resolveMode @NotNull ResolveMode resolveMode,
@NotNull ResolutionResultsCache resolutionResultsCache
) { ) {
if (selectorExpression instanceof JetCallExpression) { if (selectorExpression instanceof JetCallExpression) {
return getCallExpressionTypeInfoForCallWithoutFinalTypeCheck((JetCallExpression) selectorExpression, receiver, return getCallExpressionTypeInfoForCallWithoutFinalTypeCheck((JetCallExpression) selectorExpression, receiver,
callOperationNode, context, resolveMode); callOperationNode, context, resolveMode, resolutionResultsCache);
} }
else if (selectorExpression instanceof JetSimpleNameExpression) { else if (selectorExpression instanceof JetSimpleNameExpression) {
return TypeInfoForCall.create( return TypeInfoForCall.create(
@@ -362,7 +371,7 @@ public class CallExpressionResolver {
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) selectorExpression; JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) selectorExpression;
JetExpression newReceiverExpression = qualifiedExpression.getReceiverExpression(); JetExpression newReceiverExpression = qualifiedExpression.getReceiverExpression();
TypeInfoForCall newReceiverTypeInfo = getSelectorReturnTypeInfo( TypeInfoForCall newReceiverTypeInfo = getSelectorReturnTypeInfo(
receiver, callOperationNode, newReceiverExpression, context.replaceExpectedType(NO_EXPECTED_TYPE), resolveMode); receiver, callOperationNode, newReceiverExpression, context.replaceExpectedType(NO_EXPECTED_TYPE), resolveMode, resolutionResultsCache);
JetType newReceiverType = newReceiverTypeInfo.getType(); JetType newReceiverType = newReceiverTypeInfo.getType();
DataFlowInfo newReceiverDataFlowInfo = newReceiverTypeInfo.getDataFlowInfo(); DataFlowInfo newReceiverDataFlowInfo = newReceiverTypeInfo.getDataFlowInfo();
JetExpression newSelectorExpression = qualifiedExpression.getSelectorExpression(); JetExpression newSelectorExpression = qualifiedExpression.getSelectorExpression();
@@ -370,7 +379,7 @@ public class CallExpressionResolver {
ExpressionReceiver expressionReceiver = new ExpressionReceiver(newReceiverExpression, newReceiverType); ExpressionReceiver expressionReceiver = new ExpressionReceiver(newReceiverExpression, newReceiverType);
return getSelectorReturnTypeInfo( return getSelectorReturnTypeInfo(
expressionReceiver, qualifiedExpression.getOperationTokenNode(), expressionReceiver, qualifiedExpression.getOperationTokenNode(),
newSelectorExpression, context.replaceDataFlowInfo(newReceiverDataFlowInfo), resolveMode); newSelectorExpression, context.replaceDataFlowInfo(newReceiverDataFlowInfo), resolveMode, resolutionResultsCache);
} }
} }
else { else {
@@ -381,12 +390,13 @@ public class CallExpressionResolver {
@NotNull @NotNull
public JetTypeInfo getQualifiedExpressionTypeInfo(@NotNull JetQualifiedExpression expression, @NotNull ResolutionContext context) { public JetTypeInfo getQualifiedExpressionTypeInfo(@NotNull JetQualifiedExpression expression, @NotNull ResolutionContext context) {
return getQualifiedExpressionExtendedTypeInfo(expression, context, ResolveMode.TOP_LEVEL_CALL).getTypeInfo(); return getQualifiedExpressionExtendedTypeInfo(expression, context, ResolveMode.TOP_LEVEL_CALL, ResolutionResultsCache.create()).getTypeInfo();
} }
@NotNull @NotNull
public TypeInfoForCall getQualifiedExpressionExtendedTypeInfo( public TypeInfoForCall getQualifiedExpressionExtendedTypeInfo(
@NotNull JetQualifiedExpression expression, @NotNull ResolutionContext context, @NotNull ResolveMode resolveMode @NotNull JetQualifiedExpression expression, @NotNull ResolutionContext context, @NotNull ResolveMode resolveMode,
@NotNull ResolutionResultsCache resolutionResultsCache
) { ) {
// TODO : functions as values // TODO : functions as values
JetExpression selectorExpression = expression.getSelectorExpression(); JetExpression selectorExpression = expression.getSelectorExpression();
@@ -404,7 +414,8 @@ public class CallExpressionResolver {
} }
TypeInfoForCall selectorReturnTypeInfo = getSelectorReturnTypeInfo( TypeInfoForCall selectorReturnTypeInfo = getSelectorReturnTypeInfo(
new ExpressionReceiver(receiverExpression, receiverType), expression.getOperationTokenNode(), selectorExpression, context, resolveMode); new ExpressionReceiver(receiverExpression, receiverType),
expression.getOperationTokenNode(), selectorExpression, context, resolveMode, resolutionResultsCache);
JetType selectorReturnType = selectorReturnTypeInfo.getType(); JetType selectorReturnType = selectorReturnTypeInfo.getType();
//TODO move further //TODO move further
@@ -26,10 +26,7 @@ import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorUtil;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext; import org.jetbrains.jet.lang.resolve.calls.context.*;
import org.jetbrains.jet.lang.resolve.calls.context.CallCandidateResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.context.ExpressionPosition;
import org.jetbrains.jet.lang.resolve.calls.context.ResolveMode;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
@@ -47,7 +44,6 @@ import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.util.slicedmap.WritableSlice;
import javax.inject.Inject; import javax.inject.Inject;
import java.util.*; import java.util.*;
@@ -106,8 +102,8 @@ public class CallResolver {
List<ResolutionTask<VariableDescriptor, VariableDescriptor>> prioritizedTasks = List<ResolutionTask<VariableDescriptor, VariableDescriptor>> prioritizedTasks =
TaskPrioritizer.<VariableDescriptor, VariableDescriptor>computePrioritizedTasks(context, referencedName, nameExpression, TaskPrioritizer.<VariableDescriptor, VariableDescriptor>computePrioritizedTasks(context, referencedName, nameExpression,
callableDescriptorCollectors); callableDescriptorCollectors);
return doResolveCallOrGetCachedResults(RESOLUTION_RESULTS_FOR_PROPERTY, context, prioritizedTasks, return doResolveCallOrGetCachedResults(ResolutionResultsCache.PROPERTY_MEMBER_TYPE,
CallTransformer.PROPERTY_CALL_TRANSFORMER, nameExpression); context, prioritizedTasks, CallTransformer.PROPERTY_CALL_TRANSFORMER, nameExpression);
} }
@NotNull @NotNull
@@ -117,8 +113,8 @@ public class CallResolver {
@NotNull Name name) { @NotNull Name name) {
List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks = List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasks(context, name, functionReference, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES); TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasks(context, name, functionReference, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES);
return doResolveCallOrGetCachedResults(RESOLUTION_RESULTS_FOR_FUNCTION, context, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, return doResolveCallOrGetCachedResults(ResolutionResultsCache.FUNCTION_MEMBER_TYPE,
functionReference); context, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, functionReference);
} }
@NotNull @NotNull
@@ -129,7 +125,9 @@ public class CallResolver {
@NotNull JetType expectedType, @NotNull JetType expectedType,
@NotNull DataFlowInfo dataFlowInfo @NotNull DataFlowInfo dataFlowInfo
) { ) {
return resolveFunctionCall(BasicCallResolutionContext.create(trace, scope, call, expectedType, dataFlowInfo, ResolveMode.TOP_LEVEL_CALL, ExpressionPosition.FREE)); return resolveFunctionCall(BasicCallResolutionContext.create(
trace, scope, call, expectedType, dataFlowInfo, ResolveMode.TOP_LEVEL_CALL, ExpressionPosition.FREE,
ResolutionResultsCache.create()));
} }
@NotNull @NotNull
@@ -256,14 +254,14 @@ public class CallResolver {
} }
} }
return doResolveCallOrGetCachedResults(RESOLUTION_RESULTS_FOR_FUNCTION, context, prioritizedTasks, return doResolveCallOrGetCachedResults(ResolutionResultsCache.FUNCTION_MEMBER_TYPE, context, prioritizedTasks,
CallTransformer.FUNCTION_CALL_TRANSFORMER, functionReference); CallTransformer.FUNCTION_CALL_TRANSFORMER, functionReference);
} }
private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCallOrGetCachedResults( private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCallOrGetCachedResults(
@NotNull WritableSlice<CallKey, OverloadResolutionResultsImpl<F>> resolutionResultsSlice, @NotNull ResolutionResultsCache.MemberType<F> memberType,
@NotNull BasicCallResolutionContext context, @NotNull final BasicCallResolutionContext context,
@NotNull List<ResolutionTask<D, F>> prioritizedTasks, @NotNull final List<ResolutionTask<D, F>> prioritizedTasks,
@NotNull CallTransformer<D, F> callTransformer, @NotNull CallTransformer<D, F> callTransformer,
@NotNull JetReferenceExpression reference @NotNull JetReferenceExpression reference
) { ) {
@@ -272,9 +270,9 @@ public class CallResolver {
TemporaryBindingTrace traceToResolveCall = TemporaryBindingTrace.create(context.trace, "trace to resolve call", context.call); TemporaryBindingTrace traceToResolveCall = TemporaryBindingTrace.create(context.trace, "trace to resolve call", context.call);
if (element instanceof JetExpression) { if (element instanceof JetExpression) {
CallKey key = CallKey.create(context.call.getCallType(), (JetExpression) element); CallKey key = CallKey.create(context.call.getCallType(), (JetExpression) element);
OverloadResolutionResultsImpl<F> cachedResults = context.trace.get(resolutionResultsSlice, key); OverloadResolutionResultsImpl<F> cachedResults = context.resolutionResultsCache.getResolutionResults(key, memberType);
if (cachedResults != null) { if (cachedResults != null) {
DelegatingBindingTrace deltasTraceForResolve = context.trace.get(TRACE_DELTAS_CACHE, (JetExpression) element); DelegatingBindingTrace deltasTraceForResolve = context.resolutionResultsCache.getResolutionTrace((JetExpression) element);
assert deltasTraceForResolve != null; assert deltasTraceForResolve != null;
deltasTraceForResolve.addAllMyDataTo(traceToResolveCall); deltasTraceForResolve.addAllMyDataTo(traceToResolveCall);
results = cachedResults; results = cachedResults;
@@ -288,7 +286,7 @@ public class CallResolver {
deltasTraceForTypeInference.addAllMyDataTo(traceToResolveCall); deltasTraceForTypeInference.addAllMyDataTo(traceToResolveCall);
} }
completeTypeInferenceDependentOnFunctionLiterals(newContext, results, TracingStrategy.EMPTY); completeTypeInferenceDependentOnFunctionLiterals(newContext, results, TracingStrategy.EMPTY);
cacheResults(resolutionResultsSlice, context, results, traceToResolveCall); cacheResults(memberType, context, results, traceToResolveCall);
} }
traceToResolveCall.commit(); traceToResolveCall.commit();
@@ -351,16 +349,10 @@ public class CallResolver {
return OverloadResolutionResultsImpl.incompleteTypeInference(copy); return OverloadResolutionResultsImpl.incompleteTypeInference(copy);
} }
private <F extends CallableDescriptor> void cacheResults(@NotNull WritableSlice<CallKey, OverloadResolutionResultsImpl<F>> resolutionResultsSlice, private static <F extends CallableDescriptor> void cacheResults(
@NotNull ResolutionResultsCache.MemberType<F> memberType,
@NotNull BasicCallResolutionContext context, @NotNull OverloadResolutionResultsImpl<F> results, @NotNull BasicCallResolutionContext context, @NotNull OverloadResolutionResultsImpl<F> results,
@NotNull DelegatingBindingTrace traceToResolveCall) { @NotNull DelegatingBindingTrace traceToResolveCall) {
//boolean canBeCached = true;
//for (ResolvedCall<? extends CallableDescriptor> call : results.getResultingCalls()) {
// if (!call.getCandidateDescriptor().getTypeParameters().isEmpty()) {
// canBeCached = false;
// }
//}
//if (!canBeCached) return;
PsiElement callElement = context.call.getCallElement(); PsiElement callElement = context.call.getCallElement();
if (!(callElement instanceof JetExpression)) return; if (!(callElement instanceof JetExpression)) return;
@@ -368,9 +360,9 @@ public class CallResolver {
new BindingTraceContext().getBindingContext(), "delta trace for caching resolve of", context.call); new BindingTraceContext().getBindingContext(), "delta trace for caching resolve of", context.call);
traceToResolveCall.addAllMyDataTo(deltasTraceToCacheResolve); traceToResolveCall.addAllMyDataTo(deltasTraceToCacheResolve);
context.resolutionResultsCache.recordResolutionResults(
context.trace.record(resolutionResultsSlice, CallKey.create(context.call.getCallType(), (JetExpression) callElement), results); CallKey.create(context.call.getCallType(), (JetExpression) callElement), memberType, results);
context.trace.record(TRACE_DELTAS_CACHE, (JetExpression) callElement, deltasTraceToCacheResolve); context.resolutionResultsCache.recordResolutionTrace((JetExpression) callElement, deltasTraceToCacheResolve);
} }
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> checkArgumentTypesAndFail(BasicCallResolutionContext context) { private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> checkArgumentTypesAndFail(BasicCallResolutionContext context) {
@@ -489,7 +481,7 @@ public class CallResolver {
public List<JetExpression> getFunctionLiteralArguments() { public List<JetExpression> getFunctionLiteralArguments() {
return Collections.emptyList(); return Collections.emptyList();
} }
}, task.expectedType, task.dataFlowInfo, task.resolveMode, task.expressionPosition); }, task.expectedType, task.dataFlowInfo, task.resolveMode, task.expressionPosition, task.resolutionResultsCache);
OverloadResolutionResultsImpl<F> resultsWithFunctionLiteralsStripped = performResolution(newTask, callTransformer, traceForResolutionCache); OverloadResolutionResultsImpl<F> resultsWithFunctionLiteralsStripped = performResolution(newTask, callTransformer, traceForResolutionCache);
if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) { if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) {
task.tracing.danglingFunctionLiteralArgumentSuspected(task.trace, task.call.getFunctionLiteralArguments()); task.tracing.danglingFunctionLiteralArgumentSuspected(task.trace, task.call.getFunctionLiteralArguments());
@@ -524,8 +516,6 @@ public class CallResolver {
task.tracing.bindResolvedCall(call.getTrace(), call); task.tracing.bindResolvedCall(call.getTrace(), call);
task.getResolvedCalls().add(call); task.getResolvedCalls().add(call);
} }
BindingContextUtils.commitResolutionCacheData(context.candidateCall.getTrace(), traceForResolutionCache);
} }
} }
@@ -193,7 +193,8 @@ public class CallTransformer<D extends CallableDescriptor, F extends D> {
DelegatingBindingTrace variableCallTrace = context.candidateCall.getTrace(); DelegatingBindingTrace variableCallTrace = context.candidateCall.getTrace();
BasicCallResolutionContext basicCallResolutionContext = BasicCallResolutionContext.create( BasicCallResolutionContext basicCallResolutionContext = BasicCallResolutionContext.create(
variableCallTrace, context.scope, functionCall, context.expectedType, context.dataFlowInfo, context.resolveMode, context.expressionPosition); variableCallTrace, context.scope, functionCall, context.expectedType, context.dataFlowInfo,
context.resolveMode, context.expressionPosition, context.resolutionResultsCache);
// 'invoke' call resolve // 'invoke' call resolve
OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveCallWithGivenName(basicCallResolutionContext, task.reference, Name.identifier("invoke")); OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveCallWithGivenName(basicCallResolutionContext, task.reference, Name.identifier("invoke"));
@@ -291,7 +291,7 @@ public class CandidateResolver {
: effectiveExpectedType; : effectiveExpectedType;
CallCandidateResolutionContext<FunctionDescriptor> storedContextForArgument = CallCandidateResolutionContext<FunctionDescriptor> storedContextForArgument =
context.trace.get(BindingContext.DEFERRED_COMPUTATION_FOR_CALL, expression); context.resolutionResultsCache.getDeferredComputation(expression);
if (storedContextForArgument == null) continue; if (storedContextForArgument == null) continue;
CallCandidateResolutionContext<FunctionDescriptor> contextForArgument = CallCandidateResolutionContext<FunctionDescriptor> contextForArgument =
@@ -358,7 +358,6 @@ public class CandidateResolver {
traceToResolveFunctionLiteral.commit(); traceToResolveFunctionLiteral.commit();
return; return;
} }
BindingContextUtils.commitResolutionCacheData(traceToResolveFunctionLiteral, context.trace);
} }
JetType expectedTypeWithoutReturnType = hasExpectedReturnType ? CallResolverUtil.replaceReturnTypeByUnknown(expectedType) : expectedType; JetType expectedTypeWithoutReturnType = hasExpectedReturnType ? CallResolverUtil.replaceReturnTypeByUnknown(expectedType) : expectedType;
CallCandidateResolutionContext<D> newContext = context.replaceExpectedType(expectedTypeWithoutReturnType); CallCandidateResolutionContext<D> newContext = context.replaceExpectedType(expectedTypeWithoutReturnType);
@@ -32,20 +32,23 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
@NotNull JetType expectedType, @NotNull JetType expectedType,
@NotNull DataFlowInfo dataFlowInfo, @NotNull DataFlowInfo dataFlowInfo,
@NotNull ResolveMode resolveMode, @NotNull ResolveMode resolveMode,
@NotNull ExpressionPosition expressionPosition @NotNull ExpressionPosition expressionPosition,
@NotNull ResolutionResultsCache resolutionResultsCache
) { ) {
return new BasicCallResolutionContext(trace, scope, call, expectedType, dataFlowInfo, resolveMode, expressionPosition); return new BasicCallResolutionContext(trace, scope, call, expectedType, dataFlowInfo, resolveMode, expressionPosition, resolutionResultsCache);
} }
@NotNull @NotNull
public static BasicCallResolutionContext create(@NotNull ResolutionContext context, @NotNull Call call, @NotNull ResolveMode resolveMode) { public static BasicCallResolutionContext create(
return create(context.trace, context.scope, call, context.expectedType, context.dataFlowInfo, resolveMode, context.expressionPosition); @NotNull ResolutionContext context, @NotNull Call call, @NotNull ResolveMode resolveMode, @NotNull ResolutionResultsCache resolutionResultsCache
) {
return create(context.trace, context.scope, call, context.expectedType, context.dataFlowInfo, resolveMode, context.expressionPosition, resolutionResultsCache);
} }
private BasicCallResolutionContext( private BasicCallResolutionContext(
BindingTrace trace, JetScope scope, Call call, JetType expectedType, BindingTrace trace, JetScope scope, Call call, JetType expectedType,
DataFlowInfo dataFlowInfo, ResolveMode resolveMode, ExpressionPosition expressionPosition DataFlowInfo dataFlowInfo, ResolveMode resolveMode, ExpressionPosition expressionPosition, ResolutionResultsCache resolutionResultsCache
) { ) {
super(trace, scope, call, expectedType, dataFlowInfo, resolveMode, expressionPosition); super(trace, scope, call, expectedType, dataFlowInfo, resolveMode, expressionPosition, resolutionResultsCache);
} }
@Override @Override
@@ -56,7 +59,7 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
@NotNull JetType expectedType, @NotNull JetType expectedType,
@NotNull ExpressionPosition expressionPosition @NotNull ExpressionPosition expressionPosition
) { ) {
return create(trace, scope, call, expectedType, dataFlowInfo, resolveMode, expressionPosition); return create(trace, scope, call, expectedType, dataFlowInfo, resolveMode, expressionPosition, resolutionResultsCache);
} }
@Override @Override
@@ -22,7 +22,6 @@ import org.jetbrains.jet.lang.psi.Call;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionTask;
import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategy; import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategy;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
@@ -42,23 +41,25 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
@NotNull JetType expectedType, @NotNull JetType expectedType,
@NotNull DataFlowInfo dataFlowInfo, @NotNull DataFlowInfo dataFlowInfo,
@NotNull ResolveMode resolveMode, @NotNull ResolveMode resolveMode,
@NotNull ExpressionPosition expressionPosition @NotNull ExpressionPosition expressionPosition,
@NotNull ResolutionResultsCache resolutionResultsCache
) { ) {
super(trace, scope, call, expectedType, dataFlowInfo, resolveMode, expressionPosition); super(trace, scope, call, expectedType, dataFlowInfo, resolveMode, expressionPosition, resolutionResultsCache);
this.candidateCall = candidateCall; this.candidateCall = candidateCall;
this.tracing = tracing; this.tracing = tracing;
} }
public static <D extends CallableDescriptor> CallCandidateResolutionContext<D> create( public static <D extends CallableDescriptor> CallCandidateResolutionContext<D> create(
@NotNull ResolvedCallImpl<D> candidateCall, @NotNull CallResolutionContext context, @NotNull BindingTrace trace, @NotNull ResolvedCallImpl<D> candidateCall, @NotNull CallResolutionContext<?> context, @NotNull BindingTrace trace,
@NotNull TracingStrategy tracing, @NotNull Call call) { @NotNull TracingStrategy tracing, @NotNull Call call) {
candidateCall.setInitialDataFlowInfo(context.dataFlowInfo); candidateCall.setInitialDataFlowInfo(context.dataFlowInfo);
return new CallCandidateResolutionContext<D>(candidateCall, tracing, trace, context.scope, call, context.expectedType, return new CallCandidateResolutionContext<D>(
context.dataFlowInfo, context.resolveMode, context.expressionPosition); candidateCall, tracing, trace, context.scope, call, context.expectedType,
context.dataFlowInfo, context.resolveMode, context.expressionPosition, context.resolutionResultsCache);
} }
public static <D extends CallableDescriptor> CallCandidateResolutionContext<D> create( public static <D extends CallableDescriptor> CallCandidateResolutionContext<D> create(
@NotNull ResolvedCallImpl<D> candidateCall, @NotNull CallResolutionContext context, @NotNull BindingTrace trace, @NotNull ResolvedCallImpl<D> candidateCall, @NotNull CallResolutionContext<?> context, @NotNull BindingTrace trace,
@NotNull TracingStrategy tracing) { @NotNull TracingStrategy tracing) {
return create(candidateCall, context, trace, tracing, context.call); return create(candidateCall, context, trace, tracing, context.call);
} }
@@ -66,15 +67,16 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
public static <D extends CallableDescriptor> CallCandidateResolutionContext<D> createForCallBeingAnalyzed( public static <D extends CallableDescriptor> CallCandidateResolutionContext<D> createForCallBeingAnalyzed(
@NotNull ResolvedCallImpl<D> candidateCall, @NotNull BasicCallResolutionContext context, @NotNull TracingStrategy tracing @NotNull ResolvedCallImpl<D> candidateCall, @NotNull BasicCallResolutionContext context, @NotNull TracingStrategy tracing
) { ) {
return createForCallBeingAnalyzed(candidateCall, context, context.call, context.resolveMode, tracing); return createForCallBeingAnalyzed(candidateCall, context, context.call, context.resolveMode, tracing, context.resolutionResultsCache);
} }
public static <D extends CallableDescriptor> CallCandidateResolutionContext<D> createForCallBeingAnalyzed( public static <D extends CallableDescriptor> CallCandidateResolutionContext<D> createForCallBeingAnalyzed(
@NotNull ResolvedCallImpl<D> candidateCall, @NotNull ResolutionContext context, @NotNull Call call, @NotNull ResolvedCallImpl<D> candidateCall, @NotNull ResolutionContext context, @NotNull Call call,
@NotNull ResolveMode resolveMode, @NotNull TracingStrategy tracing @NotNull ResolveMode resolveMode, @NotNull TracingStrategy tracing, @NotNull ResolutionResultsCache resolutionResultsCache
) { ) {
return new CallCandidateResolutionContext<D>(candidateCall, tracing, context.trace, context.scope, call, return new CallCandidateResolutionContext<D>(
context.expectedType, context.dataFlowInfo, resolveMode, context.expressionPosition); candidateCall, tracing, context.trace, context.scope, call, context.expectedType,
context.dataFlowInfo, resolveMode, context.expressionPosition, resolutionResultsCache);
} }
@Override @Override
@@ -86,7 +88,8 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
@NotNull ExpressionPosition expressionPosition @NotNull ExpressionPosition expressionPosition
) { ) {
return new CallCandidateResolutionContext<D>( return new CallCandidateResolutionContext<D>(
candidateCall, tracing, trace, scope, call, expectedType, dataFlowInfo, resolveMode, expressionPosition); candidateCall, tracing, trace, scope, call, expectedType, dataFlowInfo, resolveMode, expressionPosition,
resolutionResultsCache);
} }
@Override @Override
@@ -98,6 +101,7 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
public CallCandidateResolutionContext<D> replaceResolveMode(@NotNull ResolveMode newResolveMode) { public CallCandidateResolutionContext<D> replaceResolveMode(@NotNull ResolveMode newResolveMode) {
if (newResolveMode == resolveMode) return this; if (newResolveMode == resolveMode) return this;
return new CallCandidateResolutionContext<D>( return new CallCandidateResolutionContext<D>(
candidateCall, tracing, trace, scope, call, expectedType, dataFlowInfo, newResolveMode, expressionPosition); candidateCall, tracing, trace, scope, call, expectedType, dataFlowInfo, newResolveMode, expressionPosition,
resolutionResultsCache);
} }
} }
@@ -26,6 +26,7 @@ import org.jetbrains.jet.lang.types.JetType;
public abstract class CallResolutionContext<Context extends CallResolutionContext> extends ResolutionContext<Context> { public abstract class CallResolutionContext<Context extends CallResolutionContext> extends ResolutionContext<Context> {
public final Call call; public final Call call;
public final ResolveMode resolveMode; public final ResolveMode resolveMode;
public final ResolutionResultsCache resolutionResultsCache;
protected CallResolutionContext( protected CallResolutionContext(
@NotNull BindingTrace trace, @NotNull BindingTrace trace,
@@ -34,14 +35,16 @@ public abstract class CallResolutionContext<Context extends CallResolutionContex
@NotNull JetType expectedType, @NotNull JetType expectedType,
@NotNull DataFlowInfo dataFlowInfo, @NotNull DataFlowInfo dataFlowInfo,
@NotNull ResolveMode resolveMode, @NotNull ResolveMode resolveMode,
@NotNull ExpressionPosition expressionPosition @NotNull ExpressionPosition expressionPosition,
@NotNull ResolutionResultsCache resolutionResultsCache
) { ) {
super(trace, scope, expectedType, dataFlowInfo, expressionPosition); super(trace, scope, expectedType, dataFlowInfo, expressionPosition);
this.call = call; this.call = call;
this.resolveMode = resolveMode; this.resolveMode = resolveMode;
this.resolutionResultsCache = resolutionResultsCache;
} }
public BasicCallResolutionContext toBasic() { public BasicCallResolutionContext toBasic() {
return BasicCallResolutionContext.create(trace, scope, call, expectedType, dataFlowInfo, resolveMode, expressionPosition); return BasicCallResolutionContext.create(this, call, resolveMode, resolutionResultsCache);
} }
} }
@@ -0,0 +1,87 @@
/*
* Copyright 2010-2013 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.context;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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.CallKey;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
import org.jetbrains.jet.util.slicedmap.Slices;
import org.jetbrains.jet.util.slicedmap.WritableSlice;
public class ResolutionResultsCache {
public static class MemberType<D extends CallableDescriptor> {}
private static class FunctionMemberType extends MemberType<FunctionDescriptor> {}
private static class PropertyMemberType extends MemberType<VariableDescriptor> {}
public static final FunctionMemberType FUNCTION_MEMBER_TYPE = new FunctionMemberType();
public static final PropertyMemberType PROPERTY_MEMBER_TYPE = new PropertyMemberType();
private static final WritableSlice<CallKey, OverloadResolutionResultsImpl<FunctionDescriptor>> RESOLUTION_RESULTS_FOR_FUNCTION = Slices.createSimpleSlice();
private static final WritableSlice<CallKey, OverloadResolutionResultsImpl<VariableDescriptor>> RESOLUTION_RESULTS_FOR_PROPERTY = Slices.createSimpleSlice();
private static final WritableSlice<JetExpression, DelegatingBindingTrace> TRACE_DELTAS_CACHE = Slices.createSimpleSlice();
private static final WritableSlice<JetExpression, CallCandidateResolutionContext<FunctionDescriptor>> DEFERRED_COMPUTATION_FOR_CALL = Slices.createSimpleSlice();
private final BindingTrace trace = new BindingTraceContext();
@NotNull
private static <D extends CallableDescriptor> WritableSlice<CallKey, OverloadResolutionResultsImpl<D>> getSliceByMemberType(@NotNull MemberType<D> memberType) {
return (WritableSlice<CallKey, OverloadResolutionResultsImpl<D>>)
(memberType == FUNCTION_MEMBER_TYPE ? RESOLUTION_RESULTS_FOR_FUNCTION : RESOLUTION_RESULTS_FOR_PROPERTY);
}
public <D extends CallableDescriptor> void recordResolutionResults(@NotNull CallKey callKey, @NotNull MemberType<D> memberType, @NotNull OverloadResolutionResultsImpl<D> results) {
trace.record(getSliceByMemberType(memberType), callKey, results);
}
@Nullable
public <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> getResolutionResults(@NotNull CallKey callKey, @NotNull MemberType<D> memberType) {
return trace.get(getSliceByMemberType(memberType), callKey);
}
public void recordResolutionTrace(@NotNull JetExpression expression, @NotNull DelegatingBindingTrace delegatingTrace) {
trace.record(TRACE_DELTAS_CACHE, expression, delegatingTrace);
}
@Nullable
public DelegatingBindingTrace getResolutionTrace(@NotNull JetExpression expression) {
return trace.get(TRACE_DELTAS_CACHE, expression);
}
public void recordDeferredComputationForCall(@NotNull JetExpression expression, @NotNull CallCandidateResolutionContext<FunctionDescriptor> deferredComputation) {
trace.record(DEFERRED_COMPUTATION_FOR_CALL, expression, deferredComputation);
}
@Nullable
public CallCandidateResolutionContext<FunctionDescriptor> getDeferredComputation(@NotNull JetExpression expression) {
return trace.get(DEFERRED_COMPUTATION_FOR_CALL, expression);
}
@NotNull
public static ResolutionResultsCache create() {
return new ResolutionResultsCache();
}
}
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.psi.Call; import org.jetbrains.jet.lang.psi.Call;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.TraceUtil; import org.jetbrains.jet.lang.resolve.TraceUtil;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
@@ -48,13 +49,14 @@ public class TypeInfoForCall {
@NotNull ResolvedCallWithTrace<FunctionDescriptor> resolvedCall, @NotNull ResolvedCallWithTrace<FunctionDescriptor> resolvedCall,
@NotNull Call call, @NotNull Call call,
@NotNull ResolutionContext context, @NotNull ResolutionContext context,
@NotNull ResolveMode resolveMode @NotNull ResolveMode resolveMode,
@NotNull ResolutionResultsCache resolutionResultsCache
) { ) {
JetTypeInfo typeInfo = JetTypeInfo.create(type, dataFlowInfo); JetTypeInfo typeInfo = JetTypeInfo.create(type, dataFlowInfo);
ResolvedCallImpl<FunctionDescriptor> resolvedCallToComplete = resolvedCall.getCallToCompleteTypeArgumentInference(); ResolvedCallImpl<FunctionDescriptor> resolvedCallToComplete = resolvedCall.getCallToCompleteTypeArgumentInference();
CallCandidateResolutionContext<FunctionDescriptor> callCandidateResolutionContext = createForCallBeingAnalyzed( CallCandidateResolutionContext<FunctionDescriptor> callCandidateResolutionContext = createForCallBeingAnalyzed(
resolvedCallToComplete, context.replaceBindingTrace(TraceUtil.TRACE_STUB), resolvedCallToComplete, context.replaceBindingTrace(TraceUtil.TRACE_STUB),
call, resolveMode, resolvedCallToComplete.getTracing()); call, resolveMode, resolvedCallToComplete.getTracing(), resolutionResultsCache);
return new TypeInfoForCall(typeInfo, callCandidateResolutionContext); return new TypeInfoForCall(typeInfo, callCandidateResolutionContext);
} }
@@ -23,10 +23,7 @@ import org.jetbrains.jet.lang.psi.Call;
import org.jetbrains.jet.lang.psi.JetReferenceExpression; import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext; import org.jetbrains.jet.lang.resolve.calls.context.*;
import org.jetbrains.jet.lang.resolve.calls.context.CallResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.context.ExpressionPosition;
import org.jetbrains.jet.lang.resolve.calls.context.ResolveMode;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
@@ -45,16 +42,19 @@ public class ResolutionTask<D extends CallableDescriptor, F extends D> extends C
public final TracingStrategy tracing; public final TracingStrategy tracing;
public ResolutionTask( public ResolutionTask(
@NotNull Collection<ResolutionCandidate<D>> candidates, @NotNull JetReferenceExpression reference, @NotNull TracingStrategy tracing, @NotNull Collection<ResolutionCandidate<D>> candidates, @NotNull JetReferenceExpression reference,
BindingTrace trace, JetScope scope, Call call, JetType expectedType, DataFlowInfo dataFlowInfo, ResolveMode resolveMode, ExpressionPosition expressionPosition) { @NotNull TracingStrategy tracing, BindingTrace trace, JetScope scope, Call call, JetType expectedType,
super(trace, scope, call, expectedType, dataFlowInfo, resolveMode, expressionPosition); DataFlowInfo dataFlowInfo, ResolveMode resolveMode, ExpressionPosition expressionPosition, ResolutionResultsCache resolutionResultsCache
) {
super(trace, scope, call, expectedType, dataFlowInfo, resolveMode, expressionPosition, resolutionResultsCache);
this.candidates = candidates; this.candidates = candidates;
this.reference = reference; this.reference = reference;
this.tracing = tracing; this.tracing = tracing;
} }
public ResolutionTask(@NotNull Collection<ResolutionCandidate<D>> candidates, @NotNull JetReferenceExpression reference, @NotNull BasicCallResolutionContext context) { public ResolutionTask(@NotNull Collection<ResolutionCandidate<D>> candidates, @NotNull JetReferenceExpression reference, @NotNull BasicCallResolutionContext context) {
this(candidates, reference, TracingStrategyImpl.create(reference, context.call), context.trace, context.scope, context.call, context.expectedType, context.dataFlowInfo, context.resolveMode, context.expressionPosition); this(candidates, reference, TracingStrategyImpl.create(reference, context.call), context.trace, context.scope, context.call,
context.expectedType, context.dataFlowInfo, context.resolveMode, context.expressionPosition, context.resolutionResultsCache);
} }
@NotNull @NotNull
@@ -86,7 +86,9 @@ public class ResolutionTask<D extends CallableDescriptor, F extends D> extends C
@NotNull JetType expectedType, @NotNull JetType expectedType,
@NotNull ExpressionPosition expressionPosition @NotNull ExpressionPosition expressionPosition
) { ) {
ResolutionTask<D, F> newTask = new ResolutionTask<D, F>(candidates, reference, tracing, trace, scope, call, expectedType, dataFlowInfo, resolveMode, expressionPosition); ResolutionTask<D, F> newTask = new ResolutionTask<D, F>(
candidates, reference, tracing, trace, scope, call, expectedType, dataFlowInfo, resolveMode, expressionPosition,
resolutionResultsCache);
newTask.setCheckingStrategy(checkingStrategy); newTask.setCheckingStrategy(checkingStrategy);
return newTask; return newTask;
} }
@@ -247,8 +247,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor {
temporaryTrace.commit(new TraceEntryFilter() { temporaryTrace.commit(new TraceEntryFilter() {
@Override @Override
public boolean accept(@NotNull WritableSlice<?, ?> slice, Object key) { public boolean accept(@NotNull WritableSlice<?, ?> slice, Object key) {
return (slice != BindingContext.RESOLUTION_RESULTS_FOR_FUNCTION && slice != BindingContext.RESOLUTION_RESULTS_FOR_PROPERTY && return (slice != BindingContext.TRACE_DELTAS_CACHE);
slice != BindingContext.TRACE_DELTAS_CACHE);
} }
}, true); }, true);
@@ -21,11 +21,9 @@ import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.psi.Call; import org.jetbrains.jet.lang.psi.Call;
import org.jetbrains.jet.lang.psi.JetReferenceExpression; import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.TraceUtil;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext; import org.jetbrains.jet.lang.resolve.calls.context.*;
import org.jetbrains.jet.lang.resolve.calls.context.ExpressionPosition;
import org.jetbrains.jet.lang.resolve.calls.context.ResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.context.ResolveMode;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults; import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
@@ -107,6 +105,6 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
@NotNull @NotNull
public OverloadResolutionResults<FunctionDescriptor> resolveCallWithGivenName(@NotNull Call call, @NotNull JetReferenceExpression functionReference, @NotNull Name name) { public OverloadResolutionResults<FunctionDescriptor> resolveCallWithGivenName(@NotNull Call call, @NotNull JetReferenceExpression functionReference, @NotNull Name name) {
return expressionTypingServices.getCallResolver().resolveCallWithGivenName( return expressionTypingServices.getCallResolver().resolveCallWithGivenName(
BasicCallResolutionContext.create(this, call, ResolveMode.TOP_LEVEL_CALL), functionReference, name); BasicCallResolutionContext.create(this, call, ResolveMode.TOP_LEVEL_CALL, ResolutionResultsCache.create()), functionReference, name);
} }
} }
@@ -319,8 +319,7 @@ public class ExpressionTypingUtils {
@Override @Override
public boolean accept(@NotNull WritableSlice<?, ?> slice, Object key) { public boolean accept(@NotNull WritableSlice<?, ?> slice, Object key) {
// excluding all entries related to fake expression // excluding all entries related to fake expression
// keys in RESOLUTION_RESULTS_FOR_FUNCTION slice have fake expression inside return key != fake;
return key != fake && slice != RESOLUTION_RESULTS_FOR_FUNCTION;
} }
}, false); }, false);
} }