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.JetType;
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 JetType 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 collectAllCandidates;
056
057 // True if we are inside call chain like x?.foo()!!.bar()?.gav()
058 public final boolean insideCallChain;
059
060 protected ResolutionContext(
061 @NotNull BindingTrace trace,
062 @NotNull LexicalScope scope,
063 @NotNull JetType expectedType,
064 @NotNull DataFlowInfo dataFlowInfo,
065 @NotNull ContextDependency contextDependency,
066 @NotNull ResolutionResultsCache resolutionResultsCache,
067 @NotNull CallChecker callChecker,
068 @NotNull StatementFilter statementFilter,
069 boolean isAnnotationContext,
070 boolean collectAllCandidates,
071 boolean insideCallChain
072 ) {
073 this.trace = trace;
074 this.scope = scope;
075 this.expectedType = expectedType;
076 this.dataFlowInfo = dataFlowInfo;
077 this.contextDependency = contextDependency;
078 this.resolutionResultsCache = resolutionResultsCache;
079 this.callChecker = callChecker;
080 this.statementFilter = statementFilter;
081 this.isAnnotationContext = isAnnotationContext;
082 this.collectAllCandidates = collectAllCandidates;
083 this.insideCallChain = insideCallChain;
084 }
085
086 protected abstract Context create(
087 @NotNull BindingTrace trace,
088 @NotNull LexicalScope scope,
089 @NotNull DataFlowInfo dataFlowInfo,
090 @NotNull JetType expectedType,
091 @NotNull ContextDependency contextDependency,
092 @NotNull ResolutionResultsCache resolutionResultsCache,
093 @NotNull StatementFilter statementFilter,
094 boolean collectAllCandidates,
095 boolean insideSafeCallChain
096 );
097
098 @NotNull
099 private Context self() {
100 //noinspection unchecked
101 return (Context) this;
102 }
103
104 @NotNull
105 public Context replaceBindingTrace(@NotNull BindingTrace trace) {
106 if (this.trace == trace) return self();
107 return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
108 collectAllCandidates, insideCallChain);
109 }
110
111 @NotNull
112 public Context replaceDataFlowInfo(@NotNull DataFlowInfo newDataFlowInfo) {
113 if (newDataFlowInfo == dataFlowInfo) return self();
114 return create(trace, scope, newDataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
115 collectAllCandidates, insideCallChain);
116 }
117
118 @NotNull
119 public Context replaceExpectedType(@Nullable JetType newExpectedType) {
120 if (newExpectedType == null) return replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
121 if (expectedType == newExpectedType) return self();
122 return create(trace, scope, dataFlowInfo, newExpectedType, contextDependency, resolutionResultsCache, statementFilter,
123 collectAllCandidates, insideCallChain);
124 }
125
126 @NotNull
127 public Context replaceScope(@NotNull LexicalScope newScope) {
128 if (newScope == scope) return self();
129 return create(trace, newScope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
130 collectAllCandidates, insideCallChain);
131 }
132
133 @NotNull
134 public Context replaceContextDependency(@NotNull ContextDependency newContextDependency) {
135 if (newContextDependency == contextDependency) return self();
136 return create(trace, scope, dataFlowInfo, expectedType, newContextDependency, resolutionResultsCache, statementFilter,
137 collectAllCandidates, insideCallChain);
138 }
139
140 @NotNull
141 public Context replaceResolutionResultsCache(@NotNull ResolutionResultsCache newResolutionResultsCache) {
142 if (newResolutionResultsCache == resolutionResultsCache) return self();
143 return create(trace, scope, dataFlowInfo, expectedType, contextDependency, newResolutionResultsCache, statementFilter,
144 collectAllCandidates, insideCallChain);
145 }
146
147 @NotNull
148 public Context replaceTraceAndCache(@NotNull TemporaryTraceAndCache traceAndCache) {
149 return replaceBindingTrace(traceAndCache.trace).replaceResolutionResultsCache(traceAndCache.cache);
150 }
151
152 @NotNull
153 public Context replaceCollectAllCandidates(boolean newCollectAllCandidates) {
154 return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
155 newCollectAllCandidates, insideCallChain);
156 }
157
158 @NotNull
159 public Context replaceStatementFilter(@NotNull StatementFilter statementFilter) {
160 return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
161 collectAllCandidates, insideCallChain);
162 }
163
164 @NotNull
165 public Context replaceInsideCallChain(boolean insideSafeCallChain) {
166 return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
167 collectAllCandidates, insideSafeCallChain);
168
169 }
170 }