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.LexicalScope;
026    import org.jetbrains.kotlin.types.KotlinType;
027    import org.jetbrains.kotlin.types.TypeUtils;
028    
029    /**
030     * This class together with its descendants is intended to transfer data flow analysis information
031     * in top-down direction, from AST parents to children.
032     *
033     * NB: all descendants must be immutable!
034     */
035    public abstract class ResolutionContext<Context extends ResolutionContext<Context>> {
036        @NotNull
037        public final BindingTrace trace;
038        @NotNull
039        public final LexicalScope scope;
040        @NotNull
041        public final KotlinType expectedType;
042        @NotNull
043        public final DataFlowInfo dataFlowInfo;
044        @NotNull
045        public final ContextDependency contextDependency;
046        @NotNull
047        public final ResolutionResultsCache resolutionResultsCache;
048        @NotNull
049        public final CallChecker callChecker;
050        @NotNull
051        public final StatementFilter statementFilter;
052    
053        public final boolean isAnnotationContext;
054    
055        public final boolean isDebuggerContext;
056    
057        public final boolean collectAllCandidates;
058    
059        @NotNull
060        public final CallPosition callPosition;
061    
062        protected ResolutionContext(
063                @NotNull BindingTrace trace,
064                @NotNull LexicalScope scope,
065                @NotNull KotlinType expectedType,
066                @NotNull DataFlowInfo dataFlowInfo,
067                @NotNull ContextDependency contextDependency,
068                @NotNull ResolutionResultsCache resolutionResultsCache,
069                @NotNull CallChecker callChecker,
070                @NotNull StatementFilter statementFilter,
071                boolean isAnnotationContext,
072                boolean isDebuggerContext,
073                boolean collectAllCandidates,
074                @NotNull CallPosition callPosition
075        ) {
076            this.trace = trace;
077            this.scope = scope;
078            this.expectedType = expectedType;
079            this.dataFlowInfo = dataFlowInfo;
080            this.contextDependency = contextDependency;
081            this.resolutionResultsCache = resolutionResultsCache;
082            this.callChecker = callChecker;
083            this.statementFilter = statementFilter;
084            this.isAnnotationContext = isAnnotationContext;
085            this.isDebuggerContext = isDebuggerContext;
086            this.collectAllCandidates = collectAllCandidates;
087            this.callPosition = callPosition;
088        }
089    
090        protected abstract Context create(
091                @NotNull BindingTrace trace,
092                @NotNull LexicalScope scope,
093                @NotNull DataFlowInfo dataFlowInfo,
094                @NotNull KotlinType expectedType,
095                @NotNull ContextDependency contextDependency,
096                @NotNull ResolutionResultsCache resolutionResultsCache,
097                @NotNull StatementFilter statementFilter,
098                boolean collectAllCandidates,
099                @NotNull CallPosition callPosition
100        );
101    
102        @NotNull
103        private Context self() {
104            //noinspection unchecked
105            return (Context) this;
106        }
107    
108        @NotNull
109        public Context replaceBindingTrace(@NotNull BindingTrace trace) {
110            if (this.trace == trace) return self();
111            return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
112                          collectAllCandidates, callPosition);
113        }
114    
115        @NotNull
116        public Context replaceDataFlowInfo(@NotNull DataFlowInfo newDataFlowInfo) {
117            if (newDataFlowInfo == dataFlowInfo) return self();
118            return create(trace, scope, newDataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
119                          collectAllCandidates, callPosition);
120        }
121    
122        @NotNull
123        public Context replaceExpectedType(@Nullable KotlinType newExpectedType) {
124            if (newExpectedType == null) return replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
125            if (expectedType == newExpectedType) return self();
126            return create(trace, scope, dataFlowInfo, newExpectedType, contextDependency, resolutionResultsCache, statementFilter,
127                          collectAllCandidates, callPosition);
128        }
129    
130        @NotNull
131        public Context replaceScope(@NotNull LexicalScope newScope) {
132            if (newScope == scope) return self();
133            return create(trace, newScope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
134                          collectAllCandidates, callPosition);
135        }
136    
137        @NotNull
138        public Context replaceContextDependency(@NotNull ContextDependency newContextDependency) {
139            if (newContextDependency == contextDependency) return self();
140            return create(trace, scope, dataFlowInfo, expectedType, newContextDependency, resolutionResultsCache, statementFilter,
141                          collectAllCandidates, callPosition);
142        }
143    
144        @NotNull
145        public Context replaceResolutionResultsCache(@NotNull ResolutionResultsCache newResolutionResultsCache) {
146            if (newResolutionResultsCache == resolutionResultsCache) return self();
147            return create(trace, scope, dataFlowInfo, expectedType, contextDependency, newResolutionResultsCache, statementFilter,
148                          collectAllCandidates, callPosition);
149        }
150    
151        @NotNull
152        public Context replaceTraceAndCache(@NotNull TemporaryTraceAndCache traceAndCache) {
153            return replaceBindingTrace(traceAndCache.trace).replaceResolutionResultsCache(traceAndCache.cache);
154        }
155    
156        @NotNull
157        public Context replaceCollectAllCandidates(boolean newCollectAllCandidates) {
158            return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
159                          newCollectAllCandidates, callPosition);
160        }
161    
162        @NotNull
163        public Context replaceStatementFilter(@NotNull StatementFilter statementFilter) {
164            return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
165                          collectAllCandidates, callPosition);
166        }
167    
168        @NotNull
169        public Context replaceCallPosition(@NotNull CallPosition callPosition) {
170            return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
171                          collectAllCandidates, callPosition);
172        }
173    }