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