added TemporaryResolutionResultsCache
to use cache when temporary traces are used
This commit is contained in:
+29
-24
@@ -204,16 +204,16 @@ public class CallExpressionResolver {
|
|||||||
private JetType getVariableType(@NotNull JetSimpleNameExpression nameExpression, @NotNull ReceiverValue receiver,
|
private JetType getVariableType(@NotNull JetSimpleNameExpression nameExpression, @NotNull ReceiverValue receiver,
|
||||||
@Nullable ASTNode callOperationNode, @NotNull ResolutionContext context, @NotNull boolean[] result
|
@Nullable ASTNode callOperationNode, @NotNull ResolutionContext context, @NotNull boolean[] result
|
||||||
) {
|
) {
|
||||||
TemporaryBindingTrace traceForVariable = TemporaryBindingTrace.create(
|
TemporaryTraceAndCache temporaryForVariable = TemporaryTraceAndCache.create(
|
||||||
context.trace, "trace to resolve as local variable or property", nameExpression);
|
context, "trace to resolve as local variable or property", nameExpression);
|
||||||
CallResolver callResolver = expressionTypingServices.getCallResolver();
|
CallResolver callResolver = expressionTypingServices.getCallResolver();
|
||||||
Call call = CallMaker.makePropertyCall(receiver, callOperationNode, nameExpression);
|
Call call = CallMaker.makePropertyCall(receiver, callOperationNode, nameExpression);
|
||||||
BasicCallResolutionContext contextForVariable = BasicCallResolutionContext.create(
|
BasicCallResolutionContext contextForVariable = BasicCallResolutionContext.create(
|
||||||
context.replaceBindingTrace(traceForVariable).replaceResolveMode(ResolveMode.TOP_LEVEL_CALL).
|
context.replaceTraceAndCache(temporaryForVariable),
|
||||||
replaceResolutionResultsCache(), call, CheckValueArgumentsMode.ENABLED);
|
call, CheckValueArgumentsMode.ENABLED);
|
||||||
OverloadResolutionResults<VariableDescriptor> resolutionResult = callResolver.resolveSimpleProperty(contextForVariable);
|
OverloadResolutionResults<VariableDescriptor> resolutionResult = callResolver.resolveSimpleProperty(contextForVariable);
|
||||||
if (!resolutionResult.isNothing()) {
|
if (!resolutionResult.isNothing()) {
|
||||||
traceForVariable.commit();
|
temporaryForVariable.commit();
|
||||||
checkSuper(receiver, resolutionResult, context.trace, nameExpression);
|
checkSuper(receiver, resolutionResult, context.trace, nameExpression);
|
||||||
result[0] = true;
|
result[0] = true;
|
||||||
return resolutionResult.isSingleResult() ? resolutionResult.getResultingDescriptor().getReturnType() : null;
|
return resolutionResult.isSingleResult() ? resolutionResult.getResultingDescriptor().getReturnType() : null;
|
||||||
@@ -222,11 +222,11 @@ public class CallExpressionResolver {
|
|||||||
ResolutionContext newContext = receiver.exists()
|
ResolutionContext newContext = receiver.exists()
|
||||||
? context.replaceScope(receiver.getType().getMemberScope())
|
? context.replaceScope(receiver.getType().getMemberScope())
|
||||||
: context;
|
: context;
|
||||||
TemporaryBindingTrace traceForNamespaceOrClassObject = TemporaryBindingTrace.create(
|
TemporaryTraceAndCache temporaryForNamespaceOrClassObject = TemporaryTraceAndCache.create(
|
||||||
context.trace, "trace to resolve as namespace or class object", nameExpression);
|
context, "trace to resolve as namespace or class object", nameExpression);
|
||||||
JetType jetType = lookupNamespaceOrClassObject(nameExpression, newContext.replaceBindingTrace(traceForNamespaceOrClassObject));
|
JetType jetType = lookupNamespaceOrClassObject(nameExpression, newContext.replaceTraceAndCache(temporaryForNamespaceOrClassObject));
|
||||||
if (jetType != null) {
|
if (jetType != null) {
|
||||||
traceForNamespaceOrClassObject.commit();
|
temporaryForNamespaceOrClassObject.commit();
|
||||||
|
|
||||||
// Uncommitted changes in temp context
|
// Uncommitted changes in temp context
|
||||||
context.trace.record(RESOLUTION_SCOPE, nameExpression, context.scope);
|
context.trace.record(RESOLUTION_SCOPE, nameExpression, context.scope);
|
||||||
@@ -236,6 +236,7 @@ public class CallExpressionResolver {
|
|||||||
result[0] = true;
|
result[0] = true;
|
||||||
return jetType;
|
return jetType;
|
||||||
}
|
}
|
||||||
|
temporaryForVariable.commit();
|
||||||
result[0] = false;
|
result[0] = false;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -246,10 +247,11 @@ public class CallExpressionResolver {
|
|||||||
) {
|
) {
|
||||||
boolean[] result = new boolean[1];
|
boolean[] result = new boolean[1];
|
||||||
|
|
||||||
TemporaryBindingTrace traceForVariable = TemporaryBindingTrace.create(context.trace, "trace to resolve as variable", nameExpression);
|
TemporaryTraceAndCache temporaryForVariable = TemporaryTraceAndCache.create(
|
||||||
JetType type = getVariableType(nameExpression, receiver, callOperationNode, context.replaceBindingTrace(traceForVariable), result);
|
context, "trace to resolve as variable", nameExpression);
|
||||||
|
JetType type = getVariableType(nameExpression, receiver, callOperationNode, context.replaceTraceAndCache(temporaryForVariable), result);
|
||||||
if (result[0]) {
|
if (result[0]) {
|
||||||
traceForVariable.commit();
|
temporaryForVariable.commit();
|
||||||
if (type instanceof NamespaceType && context.expressionPosition == ExpressionPosition.FREE) {
|
if (type instanceof NamespaceType && context.expressionPosition == ExpressionPosition.FREE) {
|
||||||
type = null;
|
type = null;
|
||||||
}
|
}
|
||||||
@@ -257,20 +259,21 @@ 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);
|
TemporaryTraceAndCache temporaryForFunction = TemporaryTraceAndCache.create(
|
||||||
ResolutionContext newContext = context.replaceResolveMode(ResolveMode.TOP_LEVEL_CALL).replaceResolutionResultsCache();
|
context, "trace to resolve as function", nameExpression);
|
||||||
|
ResolutionContext newContext = context.replaceTraceAndCache(temporaryForFunction);
|
||||||
ResolvedCall<FunctionDescriptor> resolvedCall = getResolvedCallForFunction(
|
ResolvedCall<FunctionDescriptor> resolvedCall = getResolvedCallForFunction(
|
||||||
call, nameExpression, newContext, CheckValueArgumentsMode.ENABLED, result);
|
call, nameExpression, newContext, CheckValueArgumentsMode.ENABLED, result);
|
||||||
if (result[0]) {
|
if (result[0]) {
|
||||||
FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null;
|
FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null;
|
||||||
traceForFunction.commit();
|
temporaryForFunction.commit();
|
||||||
boolean hasValueParameters = functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0;
|
boolean hasValueParameters = functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0;
|
||||||
context.trace.report(FUNCTION_CALL_EXPECTED.on(nameExpression, nameExpression, hasValueParameters));
|
context.trace.report(FUNCTION_CALL_EXPECTED.on(nameExpression, nameExpression, hasValueParameters));
|
||||||
type = functionDescriptor != null ? functionDescriptor.getReturnType() : null;
|
type = functionDescriptor != null ? functionDescriptor.getReturnType() : null;
|
||||||
return JetTypeInfo.create(type, context.dataFlowInfo);
|
return JetTypeInfo.create(type, context.dataFlowInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
traceForVariable.commit();
|
temporaryForVariable.commit();
|
||||||
return JetTypeInfo.create(null, context.dataFlowInfo);
|
return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,12 +298,14 @@ public class CallExpressionResolver {
|
|||||||
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);
|
TemporaryTraceAndCache temporaryForFunction = TemporaryTraceAndCache.create(
|
||||||
|
context, "trace to resolve as function call", callExpression);
|
||||||
ResolvedCallWithTrace<FunctionDescriptor> resolvedCall = getResolvedCallForFunction(
|
ResolvedCallWithTrace<FunctionDescriptor> resolvedCall = getResolvedCallForFunction(
|
||||||
call, callExpression, context.replaceBindingTrace(traceForFunction), CheckValueArgumentsMode.ENABLED, result);
|
call, callExpression, context.replaceTraceAndCache(temporaryForFunction),
|
||||||
|
CheckValueArgumentsMode.ENABLED, result);
|
||||||
if (result[0]) {
|
if (result[0]) {
|
||||||
FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null;
|
FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null;
|
||||||
traceForFunction.commit();
|
temporaryForFunction.commit();
|
||||||
if (callExpression.getValueArgumentList() == null && callExpression.getFunctionLiteralArguments().isEmpty()) {
|
if (callExpression.getValueArgumentList() == null && callExpression.getFunctionLiteralArguments().isEmpty()) {
|
||||||
// there are only type arguments
|
// there are only type arguments
|
||||||
boolean hasValueParameters = functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0;
|
boolean hasValueParameters = functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0;
|
||||||
@@ -316,18 +321,18 @@ public class CallExpressionResolver {
|
|||||||
|
|
||||||
JetExpression calleeExpression = callExpression.getCalleeExpression();
|
JetExpression calleeExpression = callExpression.getCalleeExpression();
|
||||||
if (calleeExpression instanceof JetSimpleNameExpression && callExpression.getTypeArgumentList() == null) {
|
if (calleeExpression instanceof JetSimpleNameExpression && callExpression.getTypeArgumentList() == null) {
|
||||||
TemporaryBindingTrace traceForVariable = TemporaryBindingTrace.create(
|
TemporaryTraceAndCache temporaryForVariable = TemporaryTraceAndCache.create(
|
||||||
context.trace, "trace to resolve as variable with 'invoke' call", callExpression);
|
context, "trace to resolve as variable with 'invoke' call", callExpression);
|
||||||
JetType type = getVariableType((JetSimpleNameExpression) calleeExpression, receiver, callOperationNode,
|
JetType type = getVariableType((JetSimpleNameExpression) calleeExpression, receiver, callOperationNode,
|
||||||
context.replaceBindingTrace(traceForVariable), result);
|
context.replaceTraceAndCache(temporaryForVariable), result);
|
||||||
if (result[0]) {
|
if (result[0]) {
|
||||||
traceForVariable.commit();
|
temporaryForVariable.commit();
|
||||||
context.trace.report(FUNCTION_EXPECTED.on((JetReferenceExpression) calleeExpression, calleeExpression,
|
context.trace.report(FUNCTION_EXPECTED.on((JetReferenceExpression) calleeExpression, calleeExpression,
|
||||||
type != null ? type : ErrorUtils.createErrorType("")));
|
type != null ? type : ErrorUtils.createErrorType("")));
|
||||||
return JetTypeInfo.create(null, context.dataFlowInfo);
|
return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
traceForFunction.commit();
|
temporaryForFunction.commit();
|
||||||
return JetTypeInfo.create(null, context.dataFlowInfo);
|
return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ public class CallResolver {
|
|||||||
) {
|
) {
|
||||||
return resolveFunctionCall(BasicCallResolutionContext.create(
|
return resolveFunctionCall(BasicCallResolutionContext.create(
|
||||||
trace, scope, call, expectedType, dataFlowInfo, ResolveMode.TOP_LEVEL_CALL, CheckValueArgumentsMode.ENABLED,
|
trace, scope, call, expectedType, dataFlowInfo, ResolveMode.TOP_LEVEL_CALL, CheckValueArgumentsMode.ENABLED,
|
||||||
ExpressionPosition.FREE, ResolutionResultsCache.create()));
|
ExpressionPosition.FREE, ResolutionResultsCacheImpl.create()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
+3
-4
@@ -67,7 +67,7 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
|
|||||||
if (this.trace == trace) return self();
|
if (this.trace == trace) return self();
|
||||||
return create(trace, scope, dataFlowInfo, expectedType, expressionPosition, resolveMode, resolutionResultsCache);
|
return create(trace, scope, dataFlowInfo, expectedType, expressionPosition, resolveMode, resolutionResultsCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Context replaceExpressionPosition(@NotNull ExpressionPosition expressionPosition) {
|
public Context replaceExpressionPosition(@NotNull ExpressionPosition expressionPosition) {
|
||||||
if (expressionPosition == this.expressionPosition) return self();
|
if (expressionPosition == this.expressionPosition) return self();
|
||||||
@@ -105,8 +105,7 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
|
|||||||
return create(trace, scope, dataFlowInfo, expectedType, expressionPosition, resolveMode, newResolutionResultsCache);
|
return create(trace, scope, dataFlowInfo, expectedType, expressionPosition, resolveMode, newResolutionResultsCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
public Context replaceTraceAndCache(@NotNull TemporaryTraceAndCache traceAndCache) {
|
||||||
public Context replaceResolutionResultsCache() {
|
return replaceBindingTrace(traceAndCache.trace).replaceResolutionResultsCache(traceAndCache.cache);
|
||||||
return replaceResolutionResultsCache(ResolutionResultsCache.create());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+11
-61
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.lang.resolve.calls.context;
|
package org.jetbrains.jet.lang.resolve.calls.context;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||||
@@ -24,80 +23,31 @@ import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
|||||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.CallKey;
|
import org.jetbrains.jet.lang.psi.CallKey;
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
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.DelegatingBindingTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
|
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
|
||||||
import org.jetbrains.jet.util.slicedmap.BasicWritableSlice;
|
|
||||||
import org.jetbrains.jet.util.slicedmap.Slices;
|
|
||||||
import org.jetbrains.jet.util.slicedmap.WritableSlice;
|
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.psi.Call.CallType;
|
public interface ResolutionResultsCache {
|
||||||
|
class MemberType<D extends CallableDescriptor> {}
|
||||||
|
MemberType<FunctionDescriptor> FUNCTION_MEMBER_TYPE = new MemberType<FunctionDescriptor>();
|
||||||
|
MemberType<VariableDescriptor> PROPERTY_MEMBER_TYPE = new MemberType<VariableDescriptor>();
|
||||||
|
|
||||||
public class ResolutionResultsCache {
|
|
||||||
|
|
||||||
public static class MemberType<D extends CallableDescriptor> {}
|
<D extends CallableDescriptor> void recordResolutionResults(@NotNull CallKey callKey, @NotNull MemberType<D> memberType, @NotNull OverloadResolutionResultsImpl<D> results);
|
||||||
public static final MemberType<FunctionDescriptor> FUNCTION_MEMBER_TYPE = new MemberType<FunctionDescriptor>();
|
|
||||||
public static final MemberType<VariableDescriptor> PROPERTY_MEMBER_TYPE = new MemberType<VariableDescriptor>();
|
|
||||||
|
|
||||||
public static final WritableSlice<CallKey, OverloadResolutionResultsImpl<FunctionDescriptor>> RESOLUTION_RESULTS_FOR_FUNCTION = Slices.createSimpleSlice();
|
|
||||||
public static final WritableSlice<CallKey, OverloadResolutionResultsImpl<VariableDescriptor>> RESOLUTION_RESULTS_FOR_PROPERTY = Slices.createSimpleSlice();
|
|
||||||
public static final WritableSlice<CallKey, DelegatingBindingTrace> TRACE_DELTAS_CACHE = Slices.createSimpleSlice();
|
|
||||||
public static final WritableSlice<CallKey, CallCandidateResolutionContext<FunctionDescriptor>> DEFERRED_COMPUTATION_FOR_CALL = Slices.createSimpleSlice();
|
|
||||||
|
|
||||||
static {
|
|
||||||
BasicWritableSlice.initSliceDebugNames(ResolutionResultsCache.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
@Nullable
|
||||||
public <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> getResolutionResults(@NotNull CallKey callKey, @NotNull MemberType<D> memberType) {
|
<D extends CallableDescriptor> OverloadResolutionResultsImpl<D> getResolutionResults(@NotNull CallKey callKey, @NotNull MemberType<D> memberType);
|
||||||
return trace.get(getSliceByMemberType(memberType), callKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void recordResolutionTrace(@NotNull CallKey callKey, @NotNull DelegatingBindingTrace delegatingTrace) {
|
void recordResolutionTrace(@NotNull CallKey callKey, @NotNull DelegatingBindingTrace delegatingTrace);
|
||||||
trace.record(TRACE_DELTAS_CACHE, callKey, delegatingTrace);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public DelegatingBindingTrace getResolutionTrace(@NotNull CallKey callKey) {
|
DelegatingBindingTrace getResolutionTrace(@NotNull CallKey callKey);
|
||||||
return trace.get(TRACE_DELTAS_CACHE, callKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <D extends CallableDescriptor> void recordDeferredComputationForCall(
|
<D extends CallableDescriptor> void recordDeferredComputationForCall(
|
||||||
@NotNull CallKey callKey,
|
@NotNull CallKey callKey,
|
||||||
@NotNull CallCandidateResolutionContext<D> deferredComputation,
|
@NotNull CallCandidateResolutionContext<D> deferredComputation,
|
||||||
@NotNull MemberType memberType
|
@NotNull MemberType memberType
|
||||||
) {
|
);
|
||||||
if (memberType == PROPERTY_MEMBER_TYPE) return;
|
|
||||||
trace.record(DEFERRED_COMPUTATION_FOR_CALL, callKey, (CallCandidateResolutionContext<FunctionDescriptor>) deferredComputation);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public CallCandidateResolutionContext<FunctionDescriptor> getDeferredComputation(@NotNull JetExpression expression) {
|
CallCandidateResolutionContext<FunctionDescriptor> getDeferredComputation(@Nullable JetExpression expression);
|
||||||
for (CallType callType : Lists.newArrayList(CallType.DEFAULT, CallType.ARRAY_GET_METHOD, CallType.ARRAY_SET_METHOD)) {
|
|
||||||
CallKey callKey = CallKey.create(callType, expression);
|
|
||||||
CallCandidateResolutionContext<FunctionDescriptor> context = trace.get(DEFERRED_COMPUTATION_FOR_CALL, callKey);
|
|
||||||
if (context != null) {
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static ResolutionResultsCache create() {
|
|
||||||
return new ResolutionResultsCache();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+112
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.google.common.collect.Lists;
|
||||||
|
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.Call;
|
||||||
|
import org.jetbrains.jet.lang.psi.CallKey;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
|
||||||
|
import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace;
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
|
||||||
|
import org.jetbrains.jet.util.slicedmap.BasicWritableSlice;
|
||||||
|
import org.jetbrains.jet.util.slicedmap.Slices;
|
||||||
|
import org.jetbrains.jet.util.slicedmap.WritableSlice;
|
||||||
|
|
||||||
|
public class ResolutionResultsCacheImpl implements ResolutionResultsCache {
|
||||||
|
public static final WritableSlice<CallKey, OverloadResolutionResultsImpl<FunctionDescriptor>>
|
||||||
|
RESOLUTION_RESULTS_FOR_FUNCTION = Slices.createSimpleSlice();
|
||||||
|
public static final WritableSlice<CallKey, OverloadResolutionResultsImpl<VariableDescriptor>> RESOLUTION_RESULTS_FOR_PROPERTY = Slices.createSimpleSlice();
|
||||||
|
public static final WritableSlice<CallKey, DelegatingBindingTrace> TRACE_DELTAS_CACHE = Slices.createSimpleSlice();
|
||||||
|
public static final WritableSlice<CallKey, CallCandidateResolutionContext<FunctionDescriptor>> DEFERRED_COMPUTATION_FOR_CALL = Slices.createSimpleSlice();
|
||||||
|
|
||||||
|
static {
|
||||||
|
BasicWritableSlice.initSliceDebugNames(ResolutionResultsCacheImpl.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final DelegatingBindingTrace trace = new DelegatingBindingTrace(
|
||||||
|
new BindingTraceContext().getBindingContext(), "Internal binding context in resolution results cache");
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static <D extends CallableDescriptor> WritableSlice<CallKey, OverloadResolutionResultsImpl<D>> getSliceByMemberType(@NotNull MemberType<D> memberType) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (WritableSlice<CallKey, OverloadResolutionResultsImpl<D>>)
|
||||||
|
(memberType == FUNCTION_MEMBER_TYPE ? RESOLUTION_RESULTS_FOR_FUNCTION : RESOLUTION_RESULTS_FOR_PROPERTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <D extends CallableDescriptor> void recordResolutionResults(@NotNull CallKey callKey, @NotNull MemberType<D> memberType, @NotNull OverloadResolutionResultsImpl<D> results) {
|
||||||
|
trace.record(getSliceByMemberType(memberType), callKey, results);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> getResolutionResults(@NotNull CallKey callKey, @NotNull MemberType<D> memberType) {
|
||||||
|
return trace.get(getSliceByMemberType(memberType), callKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recordResolutionTrace(@NotNull CallKey callKey, @NotNull DelegatingBindingTrace delegatingTrace) {
|
||||||
|
trace.record(TRACE_DELTAS_CACHE, callKey, delegatingTrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public DelegatingBindingTrace getResolutionTrace(@NotNull CallKey callKey) {
|
||||||
|
return trace.get(TRACE_DELTAS_CACHE, callKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <D extends CallableDescriptor> void recordDeferredComputationForCall(
|
||||||
|
@NotNull CallKey callKey,
|
||||||
|
@NotNull CallCandidateResolutionContext<D> deferredComputation,
|
||||||
|
@NotNull MemberType memberType
|
||||||
|
) {
|
||||||
|
if (memberType == PROPERTY_MEMBER_TYPE) return;
|
||||||
|
//noinspection unchecked
|
||||||
|
trace.record(DEFERRED_COMPUTATION_FOR_CALL, callKey, (CallCandidateResolutionContext<FunctionDescriptor>) deferredComputation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public CallCandidateResolutionContext<FunctionDescriptor> getDeferredComputation(@Nullable JetExpression expression) {
|
||||||
|
if (expression == null) return null;
|
||||||
|
for (Call.CallType callType : Lists
|
||||||
|
.newArrayList(Call.CallType.DEFAULT, Call.CallType.ARRAY_GET_METHOD, Call.CallType.ARRAY_SET_METHOD)) {
|
||||||
|
CallKey callKey = CallKey.create(callType, expression);
|
||||||
|
CallCandidateResolutionContext<FunctionDescriptor> context = trace.get(DEFERRED_COMPUTATION_FOR_CALL, callKey);
|
||||||
|
if (context != null) {
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static ResolutionResultsCache create() {
|
||||||
|
return new ResolutionResultsCacheImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ void addData(@NotNull ResolutionResultsCacheImpl cache) {
|
||||||
|
cache.trace.addAllMyDataTo(this.trace);
|
||||||
|
}
|
||||||
|
}
|
||||||
+104
@@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* 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.psi.CallKey;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
|
import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace;
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
|
||||||
|
|
||||||
|
public class TemporaryResolutionResultsCache implements ResolutionResultsCache {
|
||||||
|
private final ResolutionResultsCache parentCache;
|
||||||
|
private final ResolutionResultsCacheImpl innerCache;
|
||||||
|
|
||||||
|
public TemporaryResolutionResultsCache(@NotNull ResolutionResultsCache parentCache) {
|
||||||
|
assert parentCache instanceof ResolutionResultsCacheImpl || parentCache instanceof TemporaryResolutionResultsCache :
|
||||||
|
"Unsupported parent cache: " + parentCache;
|
||||||
|
this.parentCache = parentCache;
|
||||||
|
this.innerCache = new ResolutionResultsCacheImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <D extends CallableDescriptor> void recordResolutionResults(
|
||||||
|
@NotNull CallKey callKey,
|
||||||
|
@NotNull MemberType<D> memberType,
|
||||||
|
@NotNull OverloadResolutionResultsImpl<D> results
|
||||||
|
) {
|
||||||
|
innerCache.recordResolutionResults(callKey, memberType, results);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> getResolutionResults(
|
||||||
|
@NotNull CallKey callKey, @NotNull MemberType<D> memberType
|
||||||
|
) {
|
||||||
|
OverloadResolutionResultsImpl<D> results = innerCache.getResolutionResults(callKey, memberType);
|
||||||
|
if (results != null) {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
return parentCache.getResolutionResults(callKey, memberType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recordResolutionTrace(
|
||||||
|
@NotNull CallKey callKey, @NotNull DelegatingBindingTrace delegatingTrace
|
||||||
|
) {
|
||||||
|
innerCache.recordResolutionTrace(callKey, delegatingTrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public DelegatingBindingTrace getResolutionTrace(@NotNull CallKey callKey) {
|
||||||
|
DelegatingBindingTrace trace = innerCache.getResolutionTrace(callKey);
|
||||||
|
if (trace != null) {
|
||||||
|
return trace;
|
||||||
|
}
|
||||||
|
return parentCache.getResolutionTrace(callKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <D extends CallableDescriptor> void recordDeferredComputationForCall(
|
||||||
|
@NotNull CallKey callKey,
|
||||||
|
@NotNull CallCandidateResolutionContext<D> deferredComputation,
|
||||||
|
@NotNull MemberType memberType
|
||||||
|
) {
|
||||||
|
innerCache.recordDeferredComputationForCall(callKey, deferredComputation, memberType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public CallCandidateResolutionContext<FunctionDescriptor> getDeferredComputation(@Nullable JetExpression expression) {
|
||||||
|
CallCandidateResolutionContext<FunctionDescriptor> computation = innerCache.getDeferredComputation(expression);
|
||||||
|
if (computation != null) {
|
||||||
|
return computation;
|
||||||
|
}
|
||||||
|
return parentCache.getDeferredComputation(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void commit() {
|
||||||
|
if (parentCache instanceof ResolutionResultsCacheImpl) {
|
||||||
|
((ResolutionResultsCacheImpl) parentCache).addData(innerCache);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
assert parentCache instanceof TemporaryResolutionResultsCache;
|
||||||
|
((TemporaryResolutionResultsCache) parentCache).innerCache.addData(innerCache);
|
||||||
|
}
|
||||||
|
}
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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.jet.lang.psi.JetExpression;
|
||||||
|
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
|
||||||
|
|
||||||
|
public class TemporaryTraceAndCache {
|
||||||
|
public final TemporaryBindingTrace trace;
|
||||||
|
public final TemporaryResolutionResultsCache cache;
|
||||||
|
|
||||||
|
public TemporaryTraceAndCache(ResolutionContext context, String debugName, JetExpression expression) {
|
||||||
|
trace = TemporaryBindingTrace.create(context.trace, debugName, expression);
|
||||||
|
cache = new TemporaryResolutionResultsCache(context.resolutionResultsCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TemporaryTraceAndCache create(ResolutionContext context, String debugName, JetExpression expression) {
|
||||||
|
return new TemporaryTraceAndCache(context, debugName, expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void commit() {
|
||||||
|
trace.commit();
|
||||||
|
cache.commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
-9
@@ -34,8 +34,7 @@ import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
|||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability;
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode;
|
import org.jetbrains.jet.lang.resolve.calls.context.*;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.context.ExpressionPosition;
|
|
||||||
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.ResolvedCallWithTrace;
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
|
||||||
@@ -672,23 +671,23 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReceiverValue receiver = new TransientReceiver(lhsType);
|
ReceiverValue receiver = new TransientReceiver(lhsType);
|
||||||
TemporaryBindingTrace traceWithReceiver = TemporaryBindingTrace.create(context.trace,
|
TemporaryTraceAndCache temporaryWithReceiver = TemporaryTraceAndCache.create(context,
|
||||||
"trace to resolve callable reference with receiver", reference);
|
"trace to resolve callable reference with receiver", reference);
|
||||||
FunctionDescriptor descriptor =
|
FunctionDescriptor descriptor =
|
||||||
resolveCallableNotCheckingArguments(
|
resolveCallableNotCheckingArguments(
|
||||||
reference, receiver, context.replaceBindingTrace(traceWithReceiver).replaceResolutionResultsCache(), result);
|
reference, receiver, context.replaceTraceAndCache(temporaryWithReceiver), result);
|
||||||
if (result[0]) {
|
if (result[0]) {
|
||||||
traceWithReceiver.commit();
|
temporaryWithReceiver.commit();
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
JetScope staticScope = getStaticNestedClassesScope((ClassDescriptor) classifier);
|
JetScope staticScope = getStaticNestedClassesScope((ClassDescriptor) classifier);
|
||||||
TemporaryBindingTrace traceForStatic = TemporaryBindingTrace.create(context.trace,
|
TemporaryTraceAndCache temporaryForStatic = TemporaryTraceAndCache.create(
|
||||||
"trace to resolve callable reference in static scope", reference);
|
context, "trace to resolve callable reference in static scope", reference);
|
||||||
FunctionDescriptor possibleStaticNestedClassConstructor = resolveCallableNotCheckingArguments(reference, NO_RECEIVER,
|
FunctionDescriptor possibleStaticNestedClassConstructor = resolveCallableNotCheckingArguments(reference, NO_RECEIVER,
|
||||||
context.replaceBindingTrace(traceForStatic).replaceScope(staticScope).replaceResolutionResultsCache(), result);
|
context.replaceTraceAndCache(temporaryForStatic).replaceScope(staticScope), result);
|
||||||
if (result[0]) {
|
if (result[0]) {
|
||||||
traceForStatic.commit();
|
temporaryForStatic.commit();
|
||||||
return possibleStaticNestedClassConstructor;
|
return possibleStaticNestedClassConstructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -41,7 +41,7 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
|
|||||||
@NotNull ExpressionPosition expressionPosition
|
@NotNull ExpressionPosition expressionPosition
|
||||||
) {
|
) {
|
||||||
return newContext(expressionTypingServices, new LabelResolver(), trace, scope, dataFlowInfo, expectedType, expressionPosition,
|
return newContext(expressionTypingServices, new LabelResolver(), trace, scope, dataFlowInfo, expectedType, expressionPosition,
|
||||||
ResolveMode.TOP_LEVEL_CALL, ResolutionResultsCache.create());
|
ResolveMode.TOP_LEVEL_CALL, ResolutionResultsCacheImpl.create());
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
+18
-15
@@ -29,6 +29,7 @@ import org.jetbrains.jet.lang.resolve.ModifiersChecker;
|
|||||||
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
|
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.TopDownAnalyzer;
|
import org.jetbrains.jet.lang.resolve.TopDownAnalyzer;
|
||||||
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.TemporaryTraceAndCache;
|
||||||
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.results.OverloadResolutionResults;
|
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsUtil;
|
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsUtil;
|
||||||
@@ -208,10 +209,10 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
@NotNull
|
@NotNull
|
||||||
protected JetTypeInfo visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
protected JetTypeInfo visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
||||||
//There is a temporary binding trace for an opportunity to resolve set method for array if needed (the initial trace should be used there)
|
//There is a temporary binding trace for an opportunity to resolve set method for array if needed (the initial trace should be used there)
|
||||||
TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(
|
TemporaryTraceAndCache temporary = TemporaryTraceAndCache.create(
|
||||||
contextWithExpectedType.trace, "trace to resolve array set method for binary expression", expression);
|
contextWithExpectedType, "trace to resolve array set method for binary expression", expression);
|
||||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE)
|
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE)
|
||||||
.replaceBindingTrace(temporaryBindingTrace).replaceResolutionResultsCache();
|
.replaceTraceAndCache(temporary);
|
||||||
|
|
||||||
JetSimpleNameExpression operationSign = expression.getOperationReference();
|
JetSimpleNameExpression operationSign = expression.getOperationReference();
|
||||||
IElementType operationType = operationSign.getReferencedNameElementType();
|
IElementType operationType = operationSign.getReferencedNameElementType();
|
||||||
@@ -223,14 +224,14 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
JetExpression right = expression.getRight();
|
JetExpression right = expression.getRight();
|
||||||
JetExpression left = leftOperand == null ? null : JetPsiUtil.deparenthesizeWithNoTypeResolution(leftOperand);
|
JetExpression left = leftOperand == null ? null : JetPsiUtil.deparenthesizeWithNoTypeResolution(leftOperand);
|
||||||
if (right == null || left == null) {
|
if (right == null || left == null) {
|
||||||
temporaryBindingTrace.commit();
|
temporary.commit();
|
||||||
return JetTypeInfo.create(null, dataFlowInfo);
|
return JetTypeInfo.create(null, dataFlowInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (leftType == null) {
|
if (leftType == null) {
|
||||||
dataFlowInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
|
dataFlowInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
|
||||||
context.trace.report(UNRESOLVED_REFERENCE.on(operationSign, operationSign));
|
context.trace.report(UNRESOLVED_REFERENCE.on(operationSign, operationSign));
|
||||||
temporaryBindingTrace.commit();
|
temporary.commit();
|
||||||
return JetTypeInfo.create(null, dataFlowInfo);
|
return JetTypeInfo.create(null, dataFlowInfo);
|
||||||
}
|
}
|
||||||
ExpressionReceiver receiver = new ExpressionReceiver(left, leftType);
|
ExpressionReceiver receiver = new ExpressionReceiver(left, leftType);
|
||||||
@@ -238,21 +239,23 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
// We check that defined only one of '+=' and '+' operations, and call it (in the case '+' we then also assign)
|
// We check that defined only one of '+=' and '+' operations, and call it (in the case '+' we then also assign)
|
||||||
// Check for '+='
|
// Check for '+='
|
||||||
Name name = OperatorConventions.ASSIGNMENT_OPERATIONS.get(operationType);
|
Name name = OperatorConventions.ASSIGNMENT_OPERATIONS.get(operationType);
|
||||||
TemporaryBindingTrace assignmentOperationTrace = TemporaryBindingTrace.create(context.trace, "trace to check assignment operation like '+=' for", expression);
|
TemporaryTraceAndCache temporaryForAssignmentOperation = TemporaryTraceAndCache.create(
|
||||||
|
context, "trace to check assignment operation like '+=' for", expression);
|
||||||
OverloadResolutionResults<FunctionDescriptor> assignmentOperationDescriptors = BasicExpressionTypingVisitor.getResolutionResultsForBinaryCall(
|
OverloadResolutionResults<FunctionDescriptor> assignmentOperationDescriptors = BasicExpressionTypingVisitor.getResolutionResultsForBinaryCall(
|
||||||
scope, name, context.replaceBindingTrace(assignmentOperationTrace).replaceResolutionResultsCache(), expression, receiver);
|
scope, name, context.replaceTraceAndCache(temporaryForAssignmentOperation), expression, receiver);
|
||||||
JetType assignmentOperationType = OverloadResolutionResultsUtil.getResultingType(assignmentOperationDescriptors,
|
JetType assignmentOperationType = OverloadResolutionResultsUtil.getResultingType(assignmentOperationDescriptors,
|
||||||
context.resolveMode);
|
context.resolveMode);
|
||||||
|
|
||||||
// Check for '+'
|
// Check for '+'
|
||||||
Name counterpartName = OperatorConventions.BINARY_OPERATION_NAMES.get(OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(operationType));
|
Name counterpartName = OperatorConventions.BINARY_OPERATION_NAMES.get(OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(operationType));
|
||||||
TemporaryBindingTrace binaryOperationTrace = TemporaryBindingTrace.create(context.trace, "trace to check binary operation like '+' for", expression);
|
TemporaryTraceAndCache temporaryForBinaryOperation = TemporaryTraceAndCache.create(
|
||||||
|
context, "trace to check binary operation like '+' for", expression);
|
||||||
OverloadResolutionResults<FunctionDescriptor> binaryOperationDescriptors = BasicExpressionTypingVisitor.getResolutionResultsForBinaryCall(
|
OverloadResolutionResults<FunctionDescriptor> binaryOperationDescriptors = BasicExpressionTypingVisitor.getResolutionResultsForBinaryCall(
|
||||||
scope, counterpartName, context.replaceBindingTrace(binaryOperationTrace).replaceResolutionResultsCache(), expression, receiver);
|
scope, counterpartName, context.replaceTraceAndCache(temporaryForBinaryOperation), expression, receiver);
|
||||||
JetType binaryOperationType = OverloadResolutionResultsUtil.getResultingType(binaryOperationDescriptors, context.resolveMode);
|
JetType binaryOperationType = OverloadResolutionResultsUtil.getResultingType(binaryOperationDescriptors, context.resolveMode);
|
||||||
|
|
||||||
JetType type = assignmentOperationType != null ? assignmentOperationType : binaryOperationType;
|
JetType type = assignmentOperationType != null ? assignmentOperationType : binaryOperationType;
|
||||||
if (assignmentOperationType != null && binaryOperationType != null) {
|
if (assignmentOperationDescriptors.isSuccess() && binaryOperationDescriptors.isSuccess()) {
|
||||||
// Both 'plus()' and 'plusAssign()' available => ambiguity
|
// Both 'plus()' and 'plusAssign()' available => ambiguity
|
||||||
OverloadResolutionResults<FunctionDescriptor> ambiguityResolutionResults = OverloadResolutionResultsUtil.ambiguity(assignmentOperationDescriptors, binaryOperationDescriptors);
|
OverloadResolutionResults<FunctionDescriptor> ambiguityResolutionResults = OverloadResolutionResultsUtil.ambiguity(assignmentOperationDescriptors, binaryOperationDescriptors);
|
||||||
context.trace.report(ASSIGN_OPERATOR_AMBIGUITY.on(operationSign, ambiguityResolutionResults.getResultingCalls()));
|
context.trace.report(ASSIGN_OPERATOR_AMBIGUITY.on(operationSign, ambiguityResolutionResults.getResultingCalls()));
|
||||||
@@ -263,26 +266,26 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
dataFlowInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
|
dataFlowInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
|
||||||
context.trace.record(AMBIGUOUS_REFERENCE_TARGET, operationSign, descriptors);
|
context.trace.record(AMBIGUOUS_REFERENCE_TARGET, operationSign, descriptors);
|
||||||
}
|
}
|
||||||
else if (assignmentOperationType != null) {
|
else if (assignmentOperationType != null && (assignmentOperationDescriptors.isSuccess() || !binaryOperationDescriptors.isSuccess())) {
|
||||||
// There's 'plusAssign()', so we do a.plusAssign(b)
|
// There's 'plusAssign()', so we do a.plusAssign(b)
|
||||||
assignmentOperationTrace.commit();
|
temporaryForAssignmentOperation.commit();
|
||||||
if (!KotlinBuiltIns.getInstance().isUnit(assignmentOperationType)) {
|
if (!KotlinBuiltIns.getInstance().isUnit(assignmentOperationType)) {
|
||||||
context.trace.report(ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT.on(operationSign, assignmentOperationDescriptors.getResultingDescriptor(), operationSign));
|
context.trace.report(ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT.on(operationSign, assignmentOperationDescriptors.getResultingDescriptor(), operationSign));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// There's only 'plus()', so we try 'a = a + b'
|
// There's only 'plus()', so we try 'a = a + b'
|
||||||
binaryOperationTrace.commit();
|
temporaryForBinaryOperation.commit();
|
||||||
context.trace.record(VARIABLE_REASSIGNMENT, expression);
|
context.trace.record(VARIABLE_REASSIGNMENT, expression);
|
||||||
if (left instanceof JetArrayAccessExpression) {
|
if (left instanceof JetArrayAccessExpression) {
|
||||||
ExpressionTypingContext contextForResolve = context.replaceScope(scope).replaceBindingTrace(TemporaryBindingTrace.create(
|
ExpressionTypingContext contextForResolve = context.replaceScope(scope).replaceBindingTrace(TemporaryBindingTrace.create(
|
||||||
contextWithExpectedType.trace, "trace to resolve array set method for assignment", expression));
|
context.trace, "trace to resolve array set method for assignment", expression));
|
||||||
basic.resolveArrayAccessSetMethod((JetArrayAccessExpression) left, right, contextForResolve, context.trace);
|
basic.resolveArrayAccessSetMethod((JetArrayAccessExpression) left, right, contextForResolve, context.trace);
|
||||||
}
|
}
|
||||||
dataFlowInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
|
dataFlowInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
|
||||||
BasicExpressionTypingVisitor.checkLValue(context.trace, leftOperand);
|
BasicExpressionTypingVisitor.checkLValue(context.trace, leftOperand);
|
||||||
}
|
}
|
||||||
temporaryBindingTrace.commit();
|
temporary.commit();
|
||||||
return JetTypeInfo.create(checkAssignmentType(type, expression, contextWithExpectedType), dataFlowInfo);
|
return JetTypeInfo.create(checkAssignmentType(type, expression, contextWithExpectedType), dataFlowInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user