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