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