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.types.expressions;
018
019 import com.intellij.psi.tree.IElementType;
020 import kotlin.jvm.functions.Function1;
021 import org.jetbrains.annotations.NotNull;
022 import org.jetbrains.annotations.Nullable;
023 import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
024 import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
025 import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
026 import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
027 import org.jetbrains.kotlin.lexer.KtTokens;
028 import org.jetbrains.kotlin.psi.*;
029 import org.jetbrains.kotlin.resolve.*;
030 import org.jetbrains.kotlin.resolve.calls.context.ContextDependency;
031 import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
032 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
033 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
034 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
035 import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
036 import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind;
037 import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope;
038 import org.jetbrains.kotlin.resolve.scopes.TraceBasedLocalRedeclarationChecker;
039 import org.jetbrains.kotlin.types.ErrorUtils;
040 import org.jetbrains.kotlin.types.KotlinType;
041 import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
042
043 import java.util.Iterator;
044 import java.util.List;
045
046 import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
047 import static org.jetbrains.kotlin.types.TypeUtils.UNIT_EXPECTED_TYPE;
048 import static org.jetbrains.kotlin.types.expressions.CoercionStrategy.COERCION_TO_UNIT;
049
050 public class ExpressionTypingServices {
051
052 private final ExpressionTypingFacade expressionTypingFacade;
053 private final ExpressionTypingComponents expressionTypingComponents;
054
055 @NotNull private final AnnotationChecker annotationChecker;
056 @NotNull private final StatementFilter statementFilter;
057
058 public ExpressionTypingServices(
059 @NotNull ExpressionTypingComponents components,
060 @NotNull AnnotationChecker annotationChecker,
061 @NotNull StatementFilter statementFilter,
062 @NotNull ExpressionTypingVisitorDispatcher.ForDeclarations facade
063 ) {
064 this.expressionTypingComponents = components;
065 this.annotationChecker = annotationChecker;
066 this.statementFilter = statementFilter;
067 this.expressionTypingFacade = facade;
068 }
069
070 @NotNull public StatementFilter getStatementFilter() {
071 return statementFilter;
072 }
073
074 @NotNull
075 public KotlinType safeGetType(
076 @NotNull LexicalScope scope,
077 @NotNull KtExpression expression,
078 @NotNull KotlinType expectedType,
079 @NotNull DataFlowInfo dataFlowInfo,
080 @NotNull BindingTrace trace
081 ) {
082 KotlinType type = getType(scope, expression, expectedType, dataFlowInfo, trace);
083
084 return type != null ? type : ErrorUtils.createErrorType("Type for " + expression.getText());
085 }
086
087 @NotNull
088 public KotlinTypeInfo getTypeInfo(
089 @NotNull LexicalScope scope,
090 @NotNull KtExpression expression,
091 @NotNull KotlinType expectedType,
092 @NotNull DataFlowInfo dataFlowInfo,
093 @NotNull BindingTrace trace,
094 boolean isStatement
095 ) {
096 return getTypeInfo(scope, expression, expectedType, dataFlowInfo, trace, isStatement, expression, ContextDependency.INDEPENDENT);
097 }
098
099 @NotNull
100 public KotlinTypeInfo getTypeInfo(
101 @NotNull LexicalScope scope,
102 @NotNull final KtExpression expression,
103 @NotNull KotlinType expectedType,
104 @NotNull DataFlowInfo dataFlowInfo,
105 @NotNull BindingTrace trace,
106 boolean isStatement,
107 @NotNull final KtExpression contextExpression,
108 @NotNull ContextDependency contextDependency
109 ) {
110 ExpressionTypingContext context = ExpressionTypingContext.newContext(
111 trace, scope, dataFlowInfo, expectedType, contextDependency
112 );
113 if (contextExpression != expression) {
114 context = context.replaceExpressionContextProvider(new Function1<KtExpression, KtExpression>() {
115 @Override
116 public KtExpression invoke(KtExpression arg) {
117 return arg == expression ? contextExpression : null;
118 }
119 });
120 }
121 return expressionTypingFacade.getTypeInfo(expression, context, isStatement);
122 }
123
124 @NotNull
125 public KotlinTypeInfo getTypeInfo(@NotNull KtExpression expression, @NotNull ResolutionContext resolutionContext) {
126 return expressionTypingFacade.getTypeInfo(expression, ExpressionTypingContext.newContext(resolutionContext));
127 }
128
129 @Nullable
130 public KotlinType getType(
131 @NotNull LexicalScope scope,
132 @NotNull KtExpression expression,
133 @NotNull KotlinType expectedType,
134 @NotNull DataFlowInfo dataFlowInfo,
135 @NotNull BindingTrace trace
136 ) {
137 return getTypeInfo(scope, expression, expectedType, dataFlowInfo, trace, false).getType();
138 }
139
140 /////////////////////////////////////////////////////////
141
142 public void checkFunctionReturnType(
143 @NotNull LexicalScope functionInnerScope,
144 @NotNull KtDeclarationWithBody function,
145 @NotNull FunctionDescriptor functionDescriptor,
146 @NotNull DataFlowInfo dataFlowInfo,
147 @Nullable KotlinType expectedReturnType,
148 BindingTrace trace
149 ) {
150 if (expectedReturnType == null) {
151 expectedReturnType = functionDescriptor.getReturnType();
152 if (!function.hasBlockBody() && !function.hasDeclaredReturnType()) {
153 expectedReturnType = NO_EXPECTED_TYPE;
154 }
155 }
156 checkFunctionReturnType(function, ExpressionTypingContext.newContext(
157 trace,
158 functionInnerScope, dataFlowInfo, expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE
159 ));
160 }
161
162 /*package*/ void checkFunctionReturnType(KtDeclarationWithBody function, ExpressionTypingContext context) {
163 KtExpression bodyExpression = function.getBodyExpression();
164 if (bodyExpression == null) return;
165
166 boolean blockBody = function.hasBlockBody();
167 ExpressionTypingContext newContext =
168 blockBody
169 ? context.replaceExpectedType(NO_EXPECTED_TYPE)
170 : context;
171
172 expressionTypingFacade.getTypeInfo(bodyExpression, newContext, blockBody);
173 }
174
175 @NotNull
176 public KotlinTypeInfo getBlockReturnedType(KtBlockExpression expression, ExpressionTypingContext context, boolean isStatement) {
177 return getBlockReturnedType(expression, isStatement ? CoercionStrategy.COERCION_TO_UNIT : CoercionStrategy.NO_COERCION, context);
178 }
179
180 @NotNull
181 public KotlinTypeInfo getBlockReturnedType(
182 @NotNull KtBlockExpression expression,
183 @NotNull CoercionStrategy coercionStrategyForLastExpression,
184 @NotNull ExpressionTypingContext context
185 ) {
186 List<KtExpression> block = StatementFilterKt.filterStatements(statementFilter, expression);
187
188 DeclarationDescriptor containingDescriptor = context.scope.getOwnerDescriptor();
189 LexicalWritableScope scope = new LexicalWritableScope(context.scope, containingDescriptor, false, null,
190 new TraceBasedLocalRedeclarationChecker(context.trace), LexicalScopeKind.CODE_BLOCK);
191
192 KotlinTypeInfo r;
193 if (block.isEmpty()) {
194 r = expressionTypingComponents.dataFlowAnalyzer
195 .createCheckedTypeInfo(expressionTypingComponents.builtIns.getUnitType(), context, expression);
196 }
197 else {
198 r = getBlockReturnedTypeWithWritableScope(scope, block, coercionStrategyForLastExpression,
199 context.replaceStatementFilter(statementFilter));
200 }
201 scope.freeze();
202
203 if (containingDescriptor instanceof ScriptDescriptor) {
204 context.trace.record(BindingContext.SCRIPT_SCOPE, (ScriptDescriptor) containingDescriptor, scope);
205 }
206
207 return r;
208 }
209
210 @NotNull
211 public KotlinType getBodyExpressionType(
212 @NotNull BindingTrace trace,
213 @NotNull LexicalScope outerScope,
214 @NotNull DataFlowInfo dataFlowInfo,
215 @NotNull KtDeclarationWithBody function,
216 @NotNull FunctionDescriptor functionDescriptor
217 ) {
218 KtExpression bodyExpression = function.getBodyExpression();
219 assert bodyExpression != null;
220 LexicalScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace);
221
222 ExpressionTypingContext context = ExpressionTypingContext.newContext(
223 trace, functionInnerScope, dataFlowInfo, NO_EXPECTED_TYPE
224 );
225 KotlinTypeInfo typeInfo = expressionTypingFacade.getTypeInfo(bodyExpression, context, function.hasBlockBody());
226
227 KotlinType type = typeInfo.getType();
228 if (type != null) {
229 return type;
230 }
231 else {
232 return ErrorUtils.createErrorType("Error function type");
233 }
234 }
235
236 /**
237 * Visits block statements propagating data flow information from the first to the last.
238 * Determines block returned type and data flow information at the end of the block AND
239 * at the nearest jump point from the block beginning.
240 */
241 /*package*/ KotlinTypeInfo getBlockReturnedTypeWithWritableScope(
242 @NotNull LexicalWritableScope scope,
243 @NotNull List<? extends KtElement> block,
244 @NotNull CoercionStrategy coercionStrategyForLastExpression,
245 @NotNull ExpressionTypingContext context
246 ) {
247 if (block.isEmpty()) {
248 return TypeInfoFactoryKt.createTypeInfo(expressionTypingComponents.builtIns.getUnitType(), context);
249 }
250
251 ExpressionTypingInternals blockLevelVisitor = new ExpressionTypingVisitorDispatcher.ForBlock(
252 expressionTypingComponents, annotationChecker, scope);
253 ExpressionTypingContext newContext = context.replaceScope(scope).replaceExpectedType(NO_EXPECTED_TYPE);
254
255 KotlinTypeInfo result = TypeInfoFactoryKt.noTypeInfo(context);
256 // Jump point data flow info
257 DataFlowInfo beforeJumpInfo = newContext.dataFlowInfo;
258 boolean jumpOutPossible = false;
259 for (Iterator<? extends KtElement> iterator = block.iterator(); iterator.hasNext(); ) {
260 KtElement statement = iterator.next();
261 if (!(statement instanceof KtExpression)) {
262 continue;
263 }
264 KtExpression statementExpression = (KtExpression) statement;
265 if (!iterator.hasNext()) {
266 result = getTypeOfLastExpressionInBlock(
267 statementExpression, newContext.replaceExpectedType(context.expectedType), coercionStrategyForLastExpression,
268 blockLevelVisitor);
269 if (result.getType() != null && statementExpression.getParent() instanceof KtBlockExpression) {
270 DataFlowValue lastExpressionValue = DataFlowValueFactory.createDataFlowValue(
271 statementExpression, result.getType(), context);
272 DataFlowValue blockExpressionValue = DataFlowValueFactory.createDataFlowValue(
273 (KtBlockExpression) statementExpression.getParent(), result.getType(), context);
274 result = result.replaceDataFlowInfo(result.getDataFlowInfo().assign(blockExpressionValue, lastExpressionValue));
275 }
276 }
277 else {
278 result = blockLevelVisitor
279 .getTypeInfo(statementExpression, newContext.replaceContextDependency(ContextDependency.INDEPENDENT), true);
280 }
281
282 DataFlowInfo newDataFlowInfo = result.getDataFlowInfo();
283 // If jump is not possible, we take new data flow info before jump
284 if (!jumpOutPossible) {
285 beforeJumpInfo = result.getJumpFlowInfo();
286 jumpOutPossible = result.getJumpOutPossible();
287 }
288 if (newDataFlowInfo != context.dataFlowInfo) {
289 newContext = newContext.replaceDataFlowInfo(newDataFlowInfo);
290 // We take current data flow info if jump there is not possible
291 }
292 blockLevelVisitor = new ExpressionTypingVisitorDispatcher.ForBlock(expressionTypingComponents, annotationChecker, scope);
293 }
294 return result.replaceJumpOutPossible(jumpOutPossible).replaceJumpFlowInfo(beforeJumpInfo);
295 }
296
297 private KotlinTypeInfo getTypeOfLastExpressionInBlock(
298 @NotNull KtExpression statementExpression,
299 @NotNull ExpressionTypingContext context,
300 @NotNull CoercionStrategy coercionStrategyForLastExpression,
301 @NotNull ExpressionTypingInternals blockLevelVisitor
302 ) {
303 if (context.expectedType != NO_EXPECTED_TYPE) {
304 KotlinType expectedType;
305 if (context.expectedType == UNIT_EXPECTED_TYPE ||//the first check is necessary to avoid invocation 'isUnit(UNIT_EXPECTED_TYPE)'
306 (coercionStrategyForLastExpression == COERCION_TO_UNIT && KotlinBuiltIns.isUnit(context.expectedType))) {
307 expectedType = UNIT_EXPECTED_TYPE;
308 }
309 else {
310 expectedType = context.expectedType;
311 }
312
313 return blockLevelVisitor.getTypeInfo(statementExpression, context.replaceExpectedType(expectedType), true);
314 }
315 KotlinTypeInfo result = blockLevelVisitor.getTypeInfo(statementExpression, context, true);
316 if (coercionStrategyForLastExpression == COERCION_TO_UNIT) {
317 boolean mightBeUnit = false;
318 if (statementExpression instanceof KtDeclaration) {
319 if (!(statementExpression instanceof KtNamedFunction) || statementExpression.getName() != null) {
320 mightBeUnit = true;
321 }
322 }
323 if (statementExpression instanceof KtBinaryExpression) {
324 KtBinaryExpression binaryExpression = (KtBinaryExpression) statementExpression;
325 IElementType operationType = binaryExpression.getOperationToken();
326 //noinspection SuspiciousMethodCalls
327 if (operationType == KtTokens.EQ || OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
328 mightBeUnit = true;
329 }
330 }
331 if (mightBeUnit) {
332 // ExpressionTypingVisitorForStatements should return only null or Unit for declarations and assignments,
333 // but (for correct assignment / initialization analysis) data flow info must be preserved
334 assert result.getType() == null || KotlinBuiltIns.isUnit(result.getType());
335 result = result.replaceType(expressionTypingComponents.builtIns.getUnitType());
336 }
337 }
338 return result;
339 }
340
341 }