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