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.types.expressions;
018
019 import com.google.common.collect.Sets;
020 import com.intellij.psi.tree.IElementType;
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.VariableDescriptor;
027 import org.jetbrains.kotlin.diagnostics.Errors;
028 import org.jetbrains.kotlin.lexer.KtTokens;
029 import org.jetbrains.kotlin.name.Name;
030 import org.jetbrains.kotlin.psi.*;
031 import org.jetbrains.kotlin.resolve.DescriptorUtils;
032 import org.jetbrains.kotlin.resolve.TemporaryBindingTrace;
033 import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache;
034 import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
035 import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
036 import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl;
037 import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil;
038 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
039 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
040 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
041 import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope;
042 import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
043 import org.jetbrains.kotlin.types.KotlinType;
044 import org.jetbrains.kotlin.types.TypeUtils;
045 import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
046 import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
047
048 import java.util.Collection;
049
050 import static org.jetbrains.kotlin.diagnostics.Errors.*;
051 import static org.jetbrains.kotlin.psi.KtPsiUtil.deparenthesize;
052 import static org.jetbrains.kotlin.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET;
053 import static org.jetbrains.kotlin.resolve.BindingContext.VARIABLE_REASSIGNMENT;
054 import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT;
055 import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
056 import static org.jetbrains.kotlin.types.TypeUtils.noExpectedType;
057
058 @SuppressWarnings("SuspiciousMethodCalls")
059 public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisitor {
060 private final LexicalWritableScope scope;
061 private final BasicExpressionTypingVisitor basic;
062 private final ControlStructureTypingVisitor controlStructures;
063 private final PatternMatchingTypingVisitor patterns;
064 private final FunctionsTypingVisitor functions;
065
066 public ExpressionTypingVisitorForStatements(
067 @NotNull ExpressionTypingInternals facade,
068 @NotNull LexicalWritableScope scope,
069 @NotNull BasicExpressionTypingVisitor basic,
070 @NotNull ControlStructureTypingVisitor controlStructures,
071 @NotNull PatternMatchingTypingVisitor patterns,
072 @NotNull FunctionsTypingVisitor functions
073 ) {
074 super(facade);
075 this.scope = scope;
076 this.basic = basic;
077 this.controlStructures = controlStructures;
078 this.patterns = patterns;
079 this.functions = functions;
080 }
081
082 @Nullable
083 private KotlinType checkAssignmentType(
084 @Nullable KotlinType assignmentType,
085 @NotNull KtBinaryExpression expression,
086 @NotNull ExpressionTypingContext context
087 ) {
088 if (assignmentType != null && !KotlinBuiltIns.isUnit(assignmentType) && !noExpectedType(context.expectedType) &&
089 !context.expectedType.isError() && TypeUtils.equalTypes(context.expectedType, assignmentType)) {
090 context.trace.report(Errors.ASSIGNMENT_TYPE_MISMATCH.on(expression, context.expectedType));
091 return null;
092 }
093 return components.dataFlowAnalyzer.checkStatementType(expression, context);
094 }
095
096 @Override
097 public KotlinTypeInfo visitObjectDeclaration(@NotNull KtObjectDeclaration declaration, ExpressionTypingContext context) {
098 components.localClassifierAnalyzer.processClassOrObject(
099 scope, context.replaceScope(scope).replaceContextDependency(INDEPENDENT),
100 scope.getOwnerDescriptor(),
101 declaration);
102 return TypeInfoFactoryKt.createTypeInfo(components.dataFlowAnalyzer.checkStatementType(declaration, context), context);
103 }
104
105 @Override
106 public KotlinTypeInfo visitProperty(@NotNull KtProperty property, ExpressionTypingContext typingContext) {
107 ExpressionTypingContext context = typingContext.replaceContextDependency(INDEPENDENT).replaceScope(scope);
108 KtTypeReference receiverTypeRef = property.getReceiverTypeReference();
109 if (receiverTypeRef != null) {
110 context.trace.report(LOCAL_EXTENSION_PROPERTY.on(receiverTypeRef));
111 }
112
113 KtPropertyAccessor getter = property.getGetter();
114 if (getter != null) {
115 context.trace.report(LOCAL_VARIABLE_WITH_GETTER.on(getter));
116 }
117
118 KtPropertyAccessor setter = property.getSetter();
119 if (setter != null) {
120 context.trace.report(LOCAL_VARIABLE_WITH_SETTER.on(setter));
121 }
122
123 KtExpression delegateExpression = property.getDelegateExpression();
124 if (delegateExpression != null) {
125 components.expressionTypingServices.getTypeInfo(delegateExpression, context);
126 context.trace.report(LOCAL_VARIABLE_WITH_DELEGATE.on(property.getDelegate()));
127 }
128
129 VariableDescriptor propertyDescriptor = components.descriptorResolver.
130 resolveLocalVariableDescriptor(scope, property, context.dataFlowInfo, context.trace);
131 KtExpression initializer = property.getInitializer();
132 KotlinTypeInfo typeInfo;
133 if (initializer != null) {
134 KotlinType outType = propertyDescriptor.getType();
135 typeInfo = facade.getTypeInfo(initializer, context.replaceExpectedType(outType));
136 DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
137 KotlinType type = typeInfo.getType();
138 // At this moment we do not take initializer value into account if type is given for a property
139 // We can comment first part of this condition to take them into account, like here: var s: String? = "xyz"
140 // In this case s will be not-nullable until it is changed
141 if (property.getTypeReference() == null && type != null) {
142 DataFlowValue variableDataFlowValue = DataFlowValueFactory.createDataFlowValueForProperty(
143 property, propertyDescriptor, context.trace.getBindingContext(),
144 DescriptorUtils.getContainingModuleOrNull(scope.getOwnerDescriptor()));
145 DataFlowValue initializerDataFlowValue = DataFlowValueFactory.createDataFlowValue(initializer, type, context);
146 // We cannot say here anything new about initializerDataFlowValue
147 // except it has the same value as variableDataFlowValue
148 typeInfo = typeInfo.replaceDataFlowInfo(dataFlowInfo.assign(variableDataFlowValue, initializerDataFlowValue));
149 }
150 }
151 else {
152 typeInfo = TypeInfoFactoryKt.noTypeInfo(context);
153 }
154
155 ExpressionTypingUtils.checkVariableShadowing(context.scope, context.trace, propertyDescriptor);
156
157 scope.addVariableDescriptor(propertyDescriptor);
158 components.modifiersChecker.withTrace(context.trace).checkModifiersForLocalDeclaration(property, propertyDescriptor);
159 components.identifierChecker.checkDeclaration(property, context.trace);
160 return typeInfo.replaceType(components.dataFlowAnalyzer.checkStatementType(property, context));
161 }
162
163 @Override
164 public KotlinTypeInfo visitMultiDeclaration(@NotNull KtMultiDeclaration multiDeclaration, ExpressionTypingContext context) {
165 components.annotationResolver.resolveAnnotationsWithArguments(scope, multiDeclaration.getModifierList(), context.trace);
166
167 KtExpression initializer = multiDeclaration.getInitializer();
168 if (initializer == null) {
169 context.trace.report(INITIALIZER_REQUIRED_FOR_MULTIDECLARATION.on(multiDeclaration));
170 return TypeInfoFactoryKt.noTypeInfo(context);
171 }
172 ExpressionReceiver expressionReceiver = ExpressionTypingUtils.getExpressionReceiver(
173 facade, initializer, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT));
174 KotlinTypeInfo typeInfo = facade.getTypeInfo(initializer, context);
175 if (expressionReceiver == null) {
176 return TypeInfoFactoryKt.noTypeInfo(context);
177 }
178 components.multiDeclarationResolver.defineLocalVariablesFromMultiDeclaration(scope, multiDeclaration, expressionReceiver, initializer, context);
179 components.modifiersChecker.withTrace(context.trace).checkModifiersForMultiDeclaration(multiDeclaration);
180 components.identifierChecker.checkDeclaration(multiDeclaration, context.trace);
181 return typeInfo.replaceType(components.dataFlowAnalyzer.checkStatementType(multiDeclaration, context));
182 }
183
184 @Override
185 public KotlinTypeInfo visitNamedFunction(@NotNull KtNamedFunction function, ExpressionTypingContext context) {
186 return functions.visitNamedFunction(function, context, true, scope);
187 }
188
189 @Override
190 public KotlinTypeInfo visitClass(@NotNull KtClass klass, ExpressionTypingContext context) {
191 components.localClassifierAnalyzer.processClassOrObject(
192 scope, context.replaceScope(scope).replaceContextDependency(INDEPENDENT),
193 scope.getOwnerDescriptor(),
194 klass);
195 return TypeInfoFactoryKt.createTypeInfo(components.dataFlowAnalyzer.checkStatementType(klass, context), context);
196 }
197
198 @Override
199 public KotlinTypeInfo visitTypedef(@NotNull KtTypedef typedef, ExpressionTypingContext context) {
200 context.trace.report(UNSUPPORTED.on(typedef, "Typedefs are not supported"));
201 return super.visitTypedef(typedef, context);
202 }
203
204 @Override
205 public KotlinTypeInfo visitDeclaration(@NotNull KtDeclaration dcl, ExpressionTypingContext context) {
206 return TypeInfoFactoryKt.createTypeInfo(components.dataFlowAnalyzer.checkStatementType(dcl, context), context);
207 }
208
209 @Override
210 public KotlinTypeInfo visitBinaryExpression(@NotNull KtBinaryExpression expression, ExpressionTypingContext context) {
211 KtSimpleNameExpression operationSign = expression.getOperationReference();
212 IElementType operationType = operationSign.getReferencedNameElementType();
213 KotlinTypeInfo result;
214 if (operationType == KtTokens.EQ) {
215 result = visitAssignment(expression, context);
216 }
217 else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
218 result = visitAssignmentOperation(expression, context);
219 }
220 else {
221 return facade.getTypeInfo(expression, context);
222 }
223 return components.dataFlowAnalyzer.checkType(result, expression, context);
224 }
225
226 @NotNull
227 protected KotlinTypeInfo visitAssignmentOperation(KtBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
228 //There is a temporary binding trace for an opportunity to resolve set method for array if needed (the initial trace should be used there)
229 TemporaryTraceAndCache temporary = TemporaryTraceAndCache.create(
230 contextWithExpectedType, "trace to resolve array set method for binary expression", expression);
231 ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE)
232 .replaceTraceAndCache(temporary).replaceContextDependency(INDEPENDENT);
233
234 KtSimpleNameExpression operationSign = expression.getOperationReference();
235 IElementType operationType = operationSign.getReferencedNameElementType();
236 KtExpression leftOperand = expression.getLeft();
237 KotlinTypeInfo leftInfo = ExpressionTypingUtils.getTypeInfoOrNullType(leftOperand, context, facade);
238 KotlinType leftType = leftInfo.getType();
239
240 KtExpression right = expression.getRight();
241 KtExpression left = leftOperand == null ? null : deparenthesize(leftOperand);
242 if (right == null || left == null) {
243 temporary.commit();
244 return leftInfo.clearType();
245 }
246
247 if (leftType == null) {
248 KotlinTypeInfo rightInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(leftInfo.getDataFlowInfo()));
249 context.trace.report(UNRESOLVED_REFERENCE.on(operationSign, operationSign));
250 temporary.commit();
251 return rightInfo.clearType();
252 }
253 ExpressionReceiver receiver = new ExpressionReceiver(left, leftType);
254
255 // We check that defined only one of '+=' and '+' operations, and call it (in the case '+' we then also assign)
256 // Check for '+='
257 Name name = OperatorConventions.ASSIGNMENT_OPERATIONS.get(operationType);
258 TemporaryTraceAndCache temporaryForAssignmentOperation = TemporaryTraceAndCache.create(
259 context, "trace to check assignment operation like '+=' for", expression);
260 OverloadResolutionResults<FunctionDescriptor> assignmentOperationDescriptors =
261 components.callResolver.resolveBinaryCall(
262 context.replaceTraceAndCache(temporaryForAssignmentOperation).replaceScope(scope),
263 receiver, expression, name
264 );
265 KotlinType assignmentOperationType = OverloadResolutionResultsUtil.getResultingType(assignmentOperationDescriptors,
266 context.contextDependency);
267
268 OverloadResolutionResults<FunctionDescriptor> binaryOperationDescriptors;
269 KotlinType binaryOperationType;
270 TemporaryTraceAndCache temporaryForBinaryOperation = TemporaryTraceAndCache.create(
271 context, "trace to check binary operation like '+' for", expression);
272 TemporaryBindingTrace ignoreReportsTrace = TemporaryBindingTrace.create(context.trace, "Trace for checking assignability");
273 boolean lhsAssignable = basic.checkLValue(ignoreReportsTrace, context, left, right);
274 if (assignmentOperationType == null || lhsAssignable) {
275 // Check for '+'
276 Name counterpartName = OperatorConventions.BINARY_OPERATION_NAMES.get(OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(operationType));
277 binaryOperationDescriptors = components.callResolver.resolveBinaryCall(
278 context.replaceTraceAndCache(temporaryForBinaryOperation).replaceScope(scope),
279 receiver, expression, counterpartName
280 );
281 binaryOperationType = OverloadResolutionResultsUtil.getResultingType(binaryOperationDescriptors, context.contextDependency);
282 }
283 else {
284 binaryOperationDescriptors = OverloadResolutionResultsImpl.nameNotFound();
285 binaryOperationType = null;
286 }
287
288 KotlinType type = assignmentOperationType != null ? assignmentOperationType : binaryOperationType;
289 KotlinTypeInfo rightInfo = leftInfo;
290 if (assignmentOperationDescriptors.isSuccess() && binaryOperationDescriptors.isSuccess()) {
291 // Both 'plus()' and 'plusAssign()' available => ambiguity
292 OverloadResolutionResults<FunctionDescriptor> ambiguityResolutionResults = OverloadResolutionResultsUtil.ambiguity(assignmentOperationDescriptors, binaryOperationDescriptors);
293 context.trace.report(ASSIGN_OPERATOR_AMBIGUITY.on(operationSign, ambiguityResolutionResults.getResultingCalls()));
294 Collection<DeclarationDescriptor> descriptors = Sets.newHashSet();
295 for (ResolvedCall<?> resolvedCall : ambiguityResolutionResults.getResultingCalls()) {
296 descriptors.add(resolvedCall.getResultingDescriptor());
297 }
298 rightInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(leftInfo.getDataFlowInfo()));
299 context.trace.record(AMBIGUOUS_REFERENCE_TARGET, operationSign, descriptors);
300 }
301 else if (assignmentOperationType != null && (assignmentOperationDescriptors.isSuccess() || !binaryOperationDescriptors.isSuccess())) {
302 // There's 'plusAssign()', so we do a.plusAssign(b)
303 temporaryForAssignmentOperation.commit();
304 if (!KotlinTypeChecker.DEFAULT.equalTypes(components.builtIns.getUnitType(), assignmentOperationType)) {
305 context.trace.report(ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT.on(operationSign, assignmentOperationDescriptors.getResultingDescriptor(), operationSign));
306 }
307 }
308 else {
309 // There's only 'plus()', so we try 'a = a + b'
310 temporaryForBinaryOperation.commit();
311 context.trace.record(VARIABLE_REASSIGNMENT, expression);
312 if (left instanceof KtArrayAccessExpression) {
313 ExpressionTypingContext contextForResolve = context.replaceScope(scope).replaceBindingTrace(TemporaryBindingTrace.create(
314 context.trace, "trace to resolve array set method for assignment", expression));
315 basic.resolveArrayAccessSetMethod((KtArrayAccessExpression) left, right, contextForResolve, context.trace);
316 }
317 rightInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(leftInfo.getDataFlowInfo()));
318 components.dataFlowAnalyzer.checkType(binaryOperationType, expression, context.replaceExpectedType(leftType).replaceDataFlowInfo(rightInfo.getDataFlowInfo()));
319 basic.checkLValue(context.trace, context, leftOperand, right);
320 }
321 temporary.commit();
322 return rightInfo.replaceType(checkAssignmentType(type, expression, contextWithExpectedType));
323 }
324
325 @NotNull
326 protected KotlinTypeInfo visitAssignment(KtBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
327 final ExpressionTypingContext context =
328 contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceScope(scope).replaceContextDependency(INDEPENDENT);
329 KtExpression leftOperand = expression.getLeft();
330 if (leftOperand instanceof KtAnnotatedExpression) {
331 // We will lose all annotations during deparenthesizing, so we have to resolve them right now
332 components.annotationResolver.resolveAnnotationsWithArguments(
333 scope, ((KtAnnotatedExpression) leftOperand).getAnnotationEntries(), context.trace
334 );
335 }
336 KtExpression left = deparenthesize(leftOperand);
337 KtExpression right = expression.getRight();
338 if (left instanceof KtArrayAccessExpression) {
339 KtArrayAccessExpression arrayAccessExpression = (KtArrayAccessExpression) left;
340 if (right == null) return TypeInfoFactoryKt.noTypeInfo(context);
341 KotlinTypeInfo typeInfo = basic.resolveArrayAccessSetMethod(arrayAccessExpression, right, context, context.trace);
342 basic.checkLValue(context.trace, context, arrayAccessExpression, right);
343 return typeInfo.replaceType(checkAssignmentType(typeInfo.getType(), expression, contextWithExpectedType));
344 }
345 KotlinTypeInfo leftInfo = ExpressionTypingUtils.getTypeInfoOrNullType(left, context, facade);
346 KotlinType leftType = leftInfo.getType();
347 DataFlowInfo dataFlowInfo = leftInfo.getDataFlowInfo();
348 KotlinTypeInfo resultInfo;
349 if (right != null) {
350 resultInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo).replaceExpectedType(leftType));
351 dataFlowInfo = resultInfo.getDataFlowInfo();
352 KotlinType rightType = resultInfo.getType();
353 if (left != null && leftType != null && rightType != null) {
354 DataFlowValue leftValue = DataFlowValueFactory.createDataFlowValue(left, leftType, context);
355 DataFlowValue rightValue = DataFlowValueFactory.createDataFlowValue(right, rightType, context);
356 // We cannot say here anything new about rightValue except it has the same value as leftValue
357 resultInfo = resultInfo.replaceDataFlowInfo(dataFlowInfo.assign(leftValue, rightValue));
358 }
359 }
360 else {
361 resultInfo = leftInfo;
362 }
363 if (leftType != null && leftOperand != null) { //if leftType == null, some other error has been generated
364 basic.checkLValue(context.trace, context, leftOperand, right);
365 }
366 return resultInfo.replaceType(components.dataFlowAnalyzer.checkStatementType(expression, contextWithExpectedType));
367 }
368
369
370 @Override
371 public KotlinTypeInfo visitExpression(@NotNull KtExpression expression, ExpressionTypingContext context) {
372 return facade.getTypeInfo(expression, context);
373 }
374
375 @Override
376 public KotlinTypeInfo visitKtElement(@NotNull KtElement element, ExpressionTypingContext context) {
377 context.trace.report(UNSUPPORTED.on(element, "in a block"));
378 return TypeInfoFactoryKt.noTypeInfo(context);
379 }
380
381 @Override
382 public KotlinTypeInfo visitWhileExpression(@NotNull KtWhileExpression expression, ExpressionTypingContext context) {
383 return controlStructures.visitWhileExpression(expression, context, true);
384 }
385
386 @Override
387 public KotlinTypeInfo visitDoWhileExpression(@NotNull KtDoWhileExpression expression, ExpressionTypingContext context) {
388 return controlStructures.visitDoWhileExpression(expression, context, true);
389 }
390
391 @Override
392 public KotlinTypeInfo visitForExpression(@NotNull KtForExpression expression, ExpressionTypingContext context) {
393 return controlStructures.visitForExpression(expression, context, true);
394 }
395
396 @Override
397 public KotlinTypeInfo visitAnnotatedExpression(
398 @NotNull KtAnnotatedExpression expression, ExpressionTypingContext data
399 ) {
400 return basic.visitAnnotatedExpression(expression, data, true);
401 }
402
403 @Override
404 public KotlinTypeInfo visitIfExpression(@NotNull KtIfExpression expression, ExpressionTypingContext context) {
405 return controlStructures.visitIfExpression(expression, context, true);
406 }
407
408 @Override
409 public KotlinTypeInfo visitWhenExpression(@NotNull KtWhenExpression expression, ExpressionTypingContext context) {
410 return patterns.visitWhenExpression(expression, context, true);
411 }
412
413 @Override
414 public KotlinTypeInfo visitBlockExpression(@NotNull KtBlockExpression expression, ExpressionTypingContext context) {
415 return components.expressionTypingServices.getBlockReturnedType(expression, context, true);
416 }
417
418 @Override
419 public KotlinTypeInfo visitLabeledExpression(@NotNull KtLabeledExpression expression, ExpressionTypingContext context) {
420 return basic.visitLabeledExpression(expression, context, true);
421 }
422 }