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 org.jetbrains.annotations.NotNull;
020    import org.jetbrains.annotations.Nullable;
021    import org.jetbrains.jet.lang.resolve.BindingTrace;
022    import org.jetbrains.jet.lang.resolve.calls.CallResolverExtension;
023    import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
024    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
025    import org.jetbrains.jet.lang.types.JetType;
026    import org.jetbrains.jet.lang.types.TypeUtils;
027    
028    public abstract class ResolutionContext<Context extends ResolutionContext<Context>> {
029        public final BindingTrace trace;
030        public final JetScope scope;
031        public final JetType expectedType;
032        public final DataFlowInfo dataFlowInfo;
033        public final ContextDependency contextDependency;
034        public final ResolutionResultsCache resolutionResultsCache;
035        public final CallResolverExtension callResolverExtension;
036        public final boolean isAnnotationContext;
037        public final boolean collectAllCandidates;
038    
039        protected ResolutionContext(
040                @NotNull BindingTrace trace,
041                @NotNull JetScope scope,
042                @NotNull JetType expectedType,
043                @NotNull DataFlowInfo dataFlowInfo,
044                @NotNull ContextDependency contextDependency,
045                @NotNull ResolutionResultsCache resolutionResultsCache,
046                @NotNull CallResolverExtension callResolverExtension,
047                boolean isAnnotationContext,
048                boolean collectAllCandidates
049        ) {
050            this.trace = trace;
051            this.scope = scope;
052            this.expectedType = expectedType;
053            this.dataFlowInfo = dataFlowInfo;
054            this.contextDependency = contextDependency;
055            this.resolutionResultsCache = resolutionResultsCache;
056            this.callResolverExtension = callResolverExtension;
057            this.isAnnotationContext = isAnnotationContext;
058            this.collectAllCandidates = collectAllCandidates;
059        }
060    
061        protected abstract Context create(
062                @NotNull BindingTrace trace,
063                @NotNull JetScope scope,
064                @NotNull DataFlowInfo dataFlowInfo,
065                @NotNull JetType expectedType,
066                @NotNull ContextDependency contextDependency,
067                @NotNull ResolutionResultsCache resolutionResultsCache,
068                boolean collectAllCandidates
069        );
070    
071        @NotNull
072        private Context self() {
073            //noinspection unchecked
074            return (Context) this;
075        }
076    
077        @NotNull
078        public Context replaceBindingTrace(@NotNull BindingTrace trace) {
079            if (this.trace == trace) return self();
080            return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, collectAllCandidates);
081        }
082    
083        @NotNull
084        public Context replaceDataFlowInfo(@NotNull DataFlowInfo newDataFlowInfo) {
085            if (newDataFlowInfo == dataFlowInfo) return self();
086            return create(trace, scope, newDataFlowInfo, expectedType, contextDependency, resolutionResultsCache, collectAllCandidates);
087        }
088    
089        @NotNull
090        public Context replaceExpectedType(@Nullable JetType newExpectedType) {
091            if (newExpectedType == null) return replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
092            if (expectedType == newExpectedType) return self();
093            return create(trace, scope, dataFlowInfo, newExpectedType, contextDependency, resolutionResultsCache, collectAllCandidates);
094        }
095    
096        @NotNull
097        public Context replaceScope(@NotNull JetScope newScope) {
098            if (newScope == scope) return self();
099            return create(trace, newScope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, collectAllCandidates);
100        }
101    
102        @NotNull
103        public Context replaceContextDependency(@NotNull ContextDependency newContextDependency) {
104            if (newContextDependency == contextDependency) return self();
105            return create(trace, scope, dataFlowInfo, expectedType, newContextDependency, resolutionResultsCache, collectAllCandidates);
106        }
107    
108        @NotNull
109        public Context replaceResolutionResultsCache(@NotNull ResolutionResultsCache newResolutionResultsCache) {
110            if (newResolutionResultsCache == resolutionResultsCache) return self();
111            return create(trace, scope, dataFlowInfo, expectedType, contextDependency, newResolutionResultsCache, collectAllCandidates);
112        }
113    
114        @NotNull
115        public Context replaceTraceAndCache(@NotNull TemporaryTraceAndCache traceAndCache) {
116            return replaceBindingTrace(traceAndCache.trace).replaceResolutionResultsCache(traceAndCache.cache);
117        }
118    
119        @NotNull
120        public Context replaceCollectAllCandidates(boolean newCollectAllCandidates) {
121            return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, newCollectAllCandidates);
122        }
123    }