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 }