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