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    }