001 /*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.jet.lang.resolve.calls.context;
018
019 import com.google.common.collect.Lists;
020 import org.jetbrains.annotations.NotNull;
021 import org.jetbrains.annotations.Nullable;
022 import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
023 import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
024 import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
025 import org.jetbrains.jet.lang.psi.CallKey;
026 import org.jetbrains.jet.lang.psi.JetExpression;
027 import org.jetbrains.jet.lang.resolve.BindingContext;
028 import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace;
029 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
030 import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
031 import org.jetbrains.jet.util.slicedmap.BasicWritableSlice;
032 import org.jetbrains.jet.util.slicedmap.Slices;
033 import org.jetbrains.jet.util.slicedmap.WritableSlice;
034
035 import static org.jetbrains.jet.lang.psi.Call.CallType;
036 import static org.jetbrains.jet.lang.psi.Call.CallType.*;
037
038 public class ResolutionResultsCacheImpl implements ResolutionResultsCache {
039 public static final WritableSlice<CallKey, OverloadResolutionResultsImpl<FunctionDescriptor>> RESOLUTION_RESULTS_FOR_FUNCTION = Slices.createSimpleSlice();
040 public static final WritableSlice<CallKey, OverloadResolutionResultsImpl<VariableDescriptor>> RESOLUTION_RESULTS_FOR_PROPERTY = Slices.createSimpleSlice();
041 public static final WritableSlice<CallKey, DelegatingBindingTrace> TRACE_DELTAS_CACHE = Slices.createSimpleSlice();
042 public static final WritableSlice<CallKey, CallCandidateResolutionContext<?>> DEFERRED_COMPUTATION_FOR_CALL = Slices.createSimpleSlice();
043 public static final WritableSlice<CallKey, ResolvedCallWithTrace<?>> RESOLVED_CALL_FOR_ARGUMENT = Slices.createSimpleSlice();
044
045 static {
046 BasicWritableSlice.initSliceDebugNames(ResolutionResultsCacheImpl.class);
047 }
048
049 private final DelegatingBindingTrace trace = new DelegatingBindingTrace(
050 BindingContext.EMPTY, "Internal binding context in resolution results cache");
051
052 @NotNull
053 private static <D extends CallableDescriptor> WritableSlice<CallKey, OverloadResolutionResultsImpl<D>> getSliceByMemberType(@NotNull MemberType<D> memberType) {
054 //noinspection unchecked
055 return (WritableSlice<CallKey, OverloadResolutionResultsImpl<D>>)
056 (memberType == FUNCTION_MEMBER_TYPE ? RESOLUTION_RESULTS_FOR_FUNCTION : RESOLUTION_RESULTS_FOR_PROPERTY);
057 }
058
059 @Override
060 public <D extends CallableDescriptor> void recordResolutionResults(@NotNull CallKey callKey, @NotNull MemberType<D> memberType, @NotNull OverloadResolutionResultsImpl<D> results) {
061 trace.record(getSliceByMemberType(memberType), callKey, results);
062 }
063
064 @Override
065 @Nullable
066 public <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> getResolutionResults(@NotNull CallKey callKey, @NotNull MemberType<D> memberType) {
067 return trace.get(getSliceByMemberType(memberType), callKey);
068 }
069
070 @Override
071 public void recordResolutionTrace(@NotNull CallKey callKey, @NotNull DelegatingBindingTrace delegatingTrace) {
072 trace.record(TRACE_DELTAS_CACHE, callKey, delegatingTrace);
073 }
074
075 @Override
076 @Nullable
077 public DelegatingBindingTrace getResolutionTrace(@NotNull CallKey callKey) {
078 return trace.get(TRACE_DELTAS_CACHE, callKey);
079 }
080
081 @Override
082 public <D extends CallableDescriptor> void recordDeferredComputationForCall(
083 @NotNull CallKey callKey,
084 @NotNull ResolvedCallWithTrace<D> resolvedCall,
085 @NotNull CallCandidateResolutionContext<D> deferredComputation
086 ) {
087 trace.record(DEFERRED_COMPUTATION_FOR_CALL, callKey, deferredComputation);
088 trace.record(RESOLVED_CALL_FOR_ARGUMENT, callKey, resolvedCall);
089 }
090
091 @Override
092 @Nullable
093 public CallCandidateResolutionContext<?> getDeferredComputation(@Nullable JetExpression expression) {
094 return getValueTryingAllCallTypes(expression, DEFERRED_COMPUTATION_FOR_CALL);
095 }
096
097 @Nullable
098 private <T> T getValueTryingAllCallTypes(
099 @Nullable JetExpression expression,
100 @NotNull WritableSlice<CallKey, T> slice
101 ) {
102 if (expression == null) return null;
103 for (CallType callType : Lists.newArrayList(DEFAULT, ARRAY_GET_METHOD, ARRAY_SET_METHOD, INVOKE)) {
104 CallKey callKey = CallKey.create(callType, expression);
105 T context = trace.get(slice, callKey);
106 if (context != null) {
107 return context;
108 }
109 }
110 return null;
111 }
112
113 @Nullable
114 @Override
115 public ResolvedCallWithTrace<?> getCallForArgument(@Nullable JetExpression expression) {
116 return getValueTryingAllCallTypes(expression, RESOLVED_CALL_FOR_ARGUMENT);
117 }
118
119 @NotNull
120 public static ResolutionResultsCache create() {
121 return new ResolutionResultsCacheImpl();
122 }
123
124 /*package*/ void addData(@NotNull ResolutionResultsCacheImpl cache) {
125 cache.trace.addAllMyDataTo(this.trace);
126 }
127 }