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.Call;
026    import org.jetbrains.jet.lang.psi.CallKey;
027    import org.jetbrains.jet.lang.psi.JetExpression;
028    import org.jetbrains.jet.lang.resolve.BindingTraceContext;
029    import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace;
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    public class ResolutionResultsCacheImpl implements ResolutionResultsCache {
036        public static final WritableSlice<CallKey, OverloadResolutionResultsImpl<FunctionDescriptor>>
037                RESOLUTION_RESULTS_FOR_FUNCTION = Slices.createSimpleSlice();
038        public static final WritableSlice<CallKey, OverloadResolutionResultsImpl<VariableDescriptor>> RESOLUTION_RESULTS_FOR_PROPERTY = Slices.createSimpleSlice();
039        public static final WritableSlice<CallKey, DelegatingBindingTrace> TRACE_DELTAS_CACHE = Slices.createSimpleSlice();
040        public static final WritableSlice<CallKey, CallCandidateResolutionContext<FunctionDescriptor>> DEFERRED_COMPUTATION_FOR_CALL = Slices.createSimpleSlice();
041    
042        static {
043            BasicWritableSlice.initSliceDebugNames(ResolutionResultsCacheImpl.class);
044        }
045    
046        private final DelegatingBindingTrace trace = new DelegatingBindingTrace(
047                new BindingTraceContext().getBindingContext(), "Internal binding context in resolution results cache");
048    
049        @NotNull
050        private static <D extends CallableDescriptor> WritableSlice<CallKey, OverloadResolutionResultsImpl<D>> getSliceByMemberType(@NotNull MemberType<D> memberType) {
051            //noinspection unchecked
052            return (WritableSlice<CallKey, OverloadResolutionResultsImpl<D>>)
053                    (memberType == FUNCTION_MEMBER_TYPE ? RESOLUTION_RESULTS_FOR_FUNCTION : RESOLUTION_RESULTS_FOR_PROPERTY);
054        }
055    
056        @Override
057        public <D extends CallableDescriptor> void recordResolutionResults(@NotNull CallKey callKey, @NotNull MemberType<D> memberType, @NotNull OverloadResolutionResultsImpl<D> results) {
058            trace.record(getSliceByMemberType(memberType), callKey, results);
059        }
060    
061        @Override
062        @Nullable
063        public <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> getResolutionResults(@NotNull CallKey callKey, @NotNull MemberType<D> memberType) {
064            return trace.get(getSliceByMemberType(memberType), callKey);
065        }
066    
067        @Override
068        public void recordResolutionTrace(@NotNull CallKey callKey, @NotNull DelegatingBindingTrace delegatingTrace) {
069            trace.record(TRACE_DELTAS_CACHE, callKey, delegatingTrace);
070        }
071    
072        @Override
073        @Nullable
074        public DelegatingBindingTrace getResolutionTrace(@NotNull CallKey callKey) {
075            return trace.get(TRACE_DELTAS_CACHE, callKey);
076        }
077    
078        @Override
079        public <D extends CallableDescriptor> void recordDeferredComputationForCall(
080                @NotNull CallKey callKey,
081                @NotNull CallCandidateResolutionContext<D> deferredComputation,
082                @NotNull MemberType memberType
083        ) {
084            if (memberType == PROPERTY_MEMBER_TYPE) return;
085            //noinspection unchecked
086            trace.record(DEFERRED_COMPUTATION_FOR_CALL, callKey, (CallCandidateResolutionContext<FunctionDescriptor>) deferredComputation);
087        }
088    
089        @Override
090        @Nullable
091        public CallCandidateResolutionContext<FunctionDescriptor> getDeferredComputation(@Nullable JetExpression expression) {
092            if (expression == null) return null;
093            for (Call.CallType callType : Lists
094                    .newArrayList(Call.CallType.DEFAULT, Call.CallType.ARRAY_GET_METHOD, Call.CallType.ARRAY_SET_METHOD)) {
095                CallKey callKey = CallKey.create(callType, expression);
096                CallCandidateResolutionContext<FunctionDescriptor> context = trace.get(DEFERRED_COMPUTATION_FOR_CALL, callKey);
097                if (context != null) {
098                    return context;
099                }
100            }
101            return null;
102        }
103    
104        @NotNull
105        public static ResolutionResultsCache create() {
106            return new ResolutionResultsCacheImpl();
107        }
108    
109        /*package*/ void addData(@NotNull ResolutionResultsCacheImpl cache) {
110            cache.trace.addAllMyDataTo(this.trace);
111        }
112    }