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
017package org.jetbrains.jet.lang.resolve.calls.context;
018
019import org.jetbrains.annotations.NotNull;
020import org.jetbrains.annotations.Nullable;
021import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
022import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
023import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
024import org.jetbrains.jet.lang.psi.CallKey;
025import org.jetbrains.jet.lang.resolve.BindingTrace;
026import org.jetbrains.jet.lang.resolve.BindingTraceContext;
027import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace;
028import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
029import org.jetbrains.jet.util.slicedmap.BasicWritableSlice;
030import org.jetbrains.jet.util.slicedmap.Slices;
031import org.jetbrains.jet.util.slicedmap.WritableSlice;
032
033public class ResolutionResultsCache {
034
035    public static class MemberType<D extends CallableDescriptor> {}
036    public static final MemberType<FunctionDescriptor> FUNCTION_MEMBER_TYPE = new MemberType<FunctionDescriptor>();
037    public static final MemberType<VariableDescriptor> PROPERTY_MEMBER_TYPE = new MemberType<VariableDescriptor>();
038
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<FunctionDescriptor>> DEFERRED_COMPUTATION_FOR_CALL = Slices.createSimpleSlice();
043
044    static {
045        BasicWritableSlice.initSliceDebugNames(ResolutionResultsCache.class);
046    }
047
048    private final BindingTrace trace = new BindingTraceContext();
049
050    @NotNull
051    private static <D extends CallableDescriptor> WritableSlice<CallKey, OverloadResolutionResultsImpl<D>> getSliceByMemberType(@NotNull MemberType<D> memberType) {
052        return (WritableSlice<CallKey, OverloadResolutionResultsImpl<D>>)
053                (memberType == FUNCTION_MEMBER_TYPE ? RESOLUTION_RESULTS_FOR_FUNCTION : RESOLUTION_RESULTS_FOR_PROPERTY);
054    }
055
056    public <D extends CallableDescriptor> void recordResolutionResults(@NotNull CallKey callKey, @NotNull MemberType<D> memberType, @NotNull OverloadResolutionResultsImpl<D> results) {
057        trace.record(getSliceByMemberType(memberType), callKey, results);
058    }
059
060    @Nullable
061    public <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> getResolutionResults(@NotNull CallKey callKey, @NotNull MemberType<D> memberType) {
062        return trace.get(getSliceByMemberType(memberType), callKey);
063    }
064
065    public void recordResolutionTrace(@NotNull CallKey callKey, @NotNull DelegatingBindingTrace delegatingTrace) {
066        trace.record(TRACE_DELTAS_CACHE, callKey, delegatingTrace);
067    }
068
069    @Nullable
070    public DelegatingBindingTrace getResolutionTrace(@NotNull CallKey callKey) {
071        return trace.get(TRACE_DELTAS_CACHE, callKey);
072    }
073
074    public <D extends CallableDescriptor> void recordDeferredComputationForCall(
075            @NotNull CallKey callKey,
076            @NotNull CallCandidateResolutionContext<D> deferredComputation,
077            @NotNull MemberType memberType
078    ) {
079        if (memberType == PROPERTY_MEMBER_TYPE) return;
080        trace.record(DEFERRED_COMPUTATION_FOR_CALL, callKey, (CallCandidateResolutionContext<FunctionDescriptor>) deferredComputation);
081    }
082
083    @Nullable
084    public CallCandidateResolutionContext<FunctionDescriptor> getDeferredComputation(@NotNull CallKey callKey) {
085        return trace.get(DEFERRED_COMPUTATION_FOR_CALL, callKey);
086    }
087
088    @NotNull
089    public static ResolutionResultsCache create() {
090        return new ResolutionResultsCache();
091    }
092}