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>>
040 RESOLUTION_RESULTS_FOR_FUNCTION = Slices.createSimpleSlice();
041 public static final WritableSlice<CallKey, OverloadResolutionResultsImpl<VariableDescriptor>> RESOLUTION_RESULTS_FOR_PROPERTY = Slices.createSimpleSlice();
042 public static final WritableSlice<CallKey, DelegatingBindingTrace> TRACE_DELTAS_CACHE = Slices.createSimpleSlice();
043 public static final WritableSlice<CallKey, CallCandidateResolutionContext<? extends CallableDescriptor>> DEFERRED_COMPUTATION_FOR_CALL = Slices.createSimpleSlice();
044 public static final WritableSlice<CallKey, ResolvedCallWithTrace<? extends CallableDescriptor>> RESOLVED_CALL_FOR_ARGUMENT = Slices.createSimpleSlice();
045
046 static {
047 BasicWritableSlice.initSliceDebugNames(ResolutionResultsCacheImpl.class);
048 }
049
050 private final DelegatingBindingTrace trace = new DelegatingBindingTrace(
051 BindingContext.EMPTY, "Internal binding context in resolution results cache");
052
053 @NotNull
054 private static <D extends CallableDescriptor> WritableSlice<CallKey, OverloadResolutionResultsImpl<D>> getSliceByMemberType(@NotNull MemberType<D> memberType) {
055 //noinspection unchecked
056 return (WritableSlice<CallKey, OverloadResolutionResultsImpl<D>>)
057 (memberType == FUNCTION_MEMBER_TYPE ? RESOLUTION_RESULTS_FOR_FUNCTION : RESOLUTION_RESULTS_FOR_PROPERTY);
058 }
059
060 @Override
061 public <D extends CallableDescriptor> void recordResolutionResults(@NotNull CallKey callKey, @NotNull MemberType<D> memberType, @NotNull OverloadResolutionResultsImpl<D> results) {
062 trace.record(getSliceByMemberType(memberType), callKey, results);
063 }
064
065 @Override
066 @Nullable
067 public <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> getResolutionResults(@NotNull CallKey callKey, @NotNull MemberType<D> memberType) {
068 return trace.get(getSliceByMemberType(memberType), callKey);
069 }
070
071 @Override
072 public void recordResolutionTrace(@NotNull CallKey callKey, @NotNull DelegatingBindingTrace delegatingTrace) {
073 trace.record(TRACE_DELTAS_CACHE, callKey, delegatingTrace);
074 }
075
076 @Override
077 @Nullable
078 public DelegatingBindingTrace getResolutionTrace(@NotNull CallKey callKey) {
079 return trace.get(TRACE_DELTAS_CACHE, callKey);
080 }
081
082 @Override
083 public <D extends CallableDescriptor> void recordDeferredComputationForCall(
084 @NotNull CallKey callKey,
085 @NotNull ResolvedCallWithTrace<D> resolvedCall,
086 @NotNull CallCandidateResolutionContext<D> deferredComputation
087 ) {
088 trace.record(DEFERRED_COMPUTATION_FOR_CALL, callKey, deferredComputation);
089 trace.record(RESOLVED_CALL_FOR_ARGUMENT, callKey, resolvedCall);
090 }
091
092 @Override
093 @Nullable
094 public CallCandidateResolutionContext<? extends CallableDescriptor> getDeferredComputation(@Nullable JetExpression expression) {
095 return getValueTryingAllCallTypes(expression, DEFERRED_COMPUTATION_FOR_CALL);
096 }
097
098 @Nullable
099 private <T> T getValueTryingAllCallTypes(
100 @Nullable JetExpression expression,
101 @NotNull WritableSlice<CallKey, T> slice
102 ) {
103 if (expression == null) return null;
104 for (CallType callType : Lists.newArrayList(DEFAULT, ARRAY_GET_METHOD, ARRAY_SET_METHOD)) {
105 CallKey callKey = CallKey.create(callType, expression);
106 T context = trace.get(slice, callKey);
107 if (context != null) {
108 return context;
109 }
110 }
111 return null;
112 }
113
114 @Nullable
115 @Override
116 public ResolvedCallWithTrace<? extends CallableDescriptor> getCallForArgument(@Nullable JetExpression expression) {
117 return getValueTryingAllCallTypes(expression, RESOLVED_CALL_FOR_ARGUMENT);
118 }
119
120 @NotNull
121 public static ResolutionResultsCache create() {
122 return new ResolutionResultsCacheImpl();
123 }
124
125 /*package*/ void addData(@NotNull ResolutionResultsCacheImpl cache) {
126 cache.trace.addAllMyDataTo(this.trace);
127 }
128 }