001    /*
002     * Copyright 2010-2015 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.kotlin.resolve.calls.context;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.annotations.Nullable;
021    import org.jetbrains.kotlin.resolve.BindingTrace;
022    import org.jetbrains.kotlin.resolve.StatementFilter;
023    import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker;
024    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
025    import org.jetbrains.kotlin.resolve.scopes.JetScope;
026    import org.jetbrains.kotlin.types.JetType;
027    import org.jetbrains.kotlin.types.TypeUtils;
028    
029    public abstract class ResolutionContext<Context extends ResolutionContext<Context>> {
030        @NotNull
031        public final BindingTrace trace;
032        @NotNull
033        public final JetScope scope;
034        @NotNull
035        public final JetType expectedType;
036        @NotNull
037        public final DataFlowInfo dataFlowInfo;
038        @NotNull
039        public final ContextDependency contextDependency;
040        @NotNull
041        public final ResolutionResultsCache resolutionResultsCache;
042        @NotNull
043        public final CallChecker callChecker;
044        @NotNull
045        public final StatementFilter statementFilter;
046    
047        public final boolean isAnnotationContext;
048    
049        public final boolean collectAllCandidates;
050    
051        protected ResolutionContext(
052                @NotNull BindingTrace trace,
053                @NotNull JetScope scope,
054                @NotNull JetType expectedType,
055                @NotNull DataFlowInfo dataFlowInfo,
056                @NotNull ContextDependency contextDependency,
057                @NotNull ResolutionResultsCache resolutionResultsCache,
058                @NotNull CallChecker callChecker,
059                @NotNull StatementFilter statementFilter,
060                boolean isAnnotationContext,
061                boolean collectAllCandidates
062        ) {
063            this.trace = trace;
064            this.scope = scope;
065            this.expectedType = expectedType;
066            this.dataFlowInfo = dataFlowInfo;
067            this.contextDependency = contextDependency;
068            this.resolutionResultsCache = resolutionResultsCache;
069            this.callChecker = callChecker;
070            this.statementFilter = statementFilter;
071            this.isAnnotationContext = isAnnotationContext;
072            this.collectAllCandidates = collectAllCandidates;
073        }
074    
075        protected abstract Context create(
076                @NotNull BindingTrace trace,
077                @NotNull JetScope scope,
078                @NotNull DataFlowInfo dataFlowInfo,
079                @NotNull JetType expectedType,
080                @NotNull ContextDependency contextDependency,
081                @NotNull ResolutionResultsCache resolutionResultsCache,
082                @NotNull StatementFilter statementFilter,
083                boolean collectAllCandidates
084        );
085    
086        @NotNull
087        private Context self() {
088            //noinspection unchecked
089            return (Context) this;
090        }
091    
092        @NotNull
093        public Context replaceBindingTrace(@NotNull BindingTrace trace) {
094            if (this.trace == trace) return self();
095            return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
096                          collectAllCandidates);
097        }
098    
099        @NotNull
100        public Context replaceDataFlowInfo(@NotNull DataFlowInfo newDataFlowInfo) {
101            if (newDataFlowInfo == dataFlowInfo) return self();
102            return create(trace, scope, newDataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
103                          collectAllCandidates);
104        }
105    
106        @NotNull
107        public Context replaceExpectedType(@Nullable JetType newExpectedType) {
108            if (newExpectedType == null) return replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
109            if (expectedType == newExpectedType) return self();
110            return create(trace, scope, dataFlowInfo, newExpectedType, contextDependency, resolutionResultsCache, statementFilter,
111                          collectAllCandidates);
112        }
113    
114        @NotNull
115        public Context replaceScope(@NotNull JetScope newScope) {
116            if (newScope == scope) return self();
117            return create(trace, newScope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
118                          collectAllCandidates);
119        }
120    
121        @NotNull
122        public Context replaceContextDependency(@NotNull ContextDependency newContextDependency) {
123            if (newContextDependency == contextDependency) return self();
124            return create(trace, scope, dataFlowInfo, expectedType, newContextDependency, resolutionResultsCache, statementFilter,
125                          collectAllCandidates);
126        }
127    
128        @NotNull
129        public Context replaceResolutionResultsCache(@NotNull ResolutionResultsCache newResolutionResultsCache) {
130            if (newResolutionResultsCache == resolutionResultsCache) return self();
131            return create(trace, scope, dataFlowInfo, expectedType, contextDependency, newResolutionResultsCache, statementFilter,
132                          collectAllCandidates);
133        }
134    
135        @NotNull
136        public Context replaceTraceAndCache(@NotNull TemporaryTraceAndCache traceAndCache) {
137            return replaceBindingTrace(traceAndCache.trace).replaceResolutionResultsCache(traceAndCache.cache);
138        }
139    
140        @NotNull
141        public Context replaceCollectAllCandidates(boolean newCollectAllCandidates) {
142            return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
143                          newCollectAllCandidates);
144        }
145    
146        @NotNull
147        public Context replacestatementFilter(@NotNull StatementFilter statementFilter) {
148            return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
149                          collectAllCandidates);
150        }
151    }