@@ -77,7 +77,7 @@ public class ScriptBodyResolver {
|
||||
DataFlowInfo.EMPTY,
|
||||
NO_EXPECTED_TYPE,
|
||||
false);
|
||||
JetType returnType = expressionTypingServices.getBlockReturnedType(scope, declaration.getBlockExpression(), CoercionStrategy.NO_COERCION, context, trace);
|
||||
JetType returnType = expressionTypingServices.getBlockReturnedType(scope, declaration.getBlockExpression(), CoercionStrategy.NO_COERCION, context, trace).getType();
|
||||
if (returnType == null) {
|
||||
returnType = ErrorUtils.createErrorType("getBlockReturnedType returned null");
|
||||
}
|
||||
|
||||
+2
-2
@@ -109,7 +109,7 @@ public class DataFlowInfo {
|
||||
|
||||
boolean changed = false;
|
||||
changed |= putNullability(builder, a, nullabilityOfA.refine(nullabilityOfB));
|
||||
changed |= putNullability(builder, b, nullabilityOfA.refine(nullabilityOfA));
|
||||
changed |= putNullability(builder, b, nullabilityOfB.refine(nullabilityOfA));
|
||||
return changed ? new DataFlowInfo(ImmutableMap.copyOf(builder), typeInfo) : this;
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ public class DataFlowInfo {
|
||||
|
||||
ListMultimap<DataFlowValue, JetType> newTypeInfo = Multimaps.newListMultimap(Maps.<DataFlowValue, Collection<JetType>>newHashMap(), CommonSuppliers.<JetType>getArrayListSupplier());
|
||||
|
||||
Set<DataFlowValue> keys = newTypeInfo.keySet();
|
||||
Set<DataFlowValue> keys = typeInfo.keySet();
|
||||
keys.retainAll(other.typeInfo.keySet());
|
||||
|
||||
for (DataFlowValue key : keys) {
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2010-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||
|
||||
/**
|
||||
* @author udalov
|
||||
*/
|
||||
public class JetTypeInfo {
|
||||
|
||||
@NotNull
|
||||
public static JetTypeInfo create(@Nullable JetType type, @NotNull DataFlowInfo dataFlowInfo) {
|
||||
return new JetTypeInfo(type, dataFlowInfo);
|
||||
}
|
||||
|
||||
private final JetType type;
|
||||
private final DataFlowInfo dataFlowInfo;
|
||||
|
||||
private JetTypeInfo(@Nullable JetType type, @NotNull DataFlowInfo dataFlowInfo) {
|
||||
this.type = type;
|
||||
this.dataFlowInfo = dataFlowInfo;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JetType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DataFlowInfo getDataFlowInfo() {
|
||||
return dataFlowInfo;
|
||||
}
|
||||
}
|
||||
+77
-71
@@ -69,12 +69,12 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitSimpleNameExpression(JetSimpleNameExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitSimpleNameExpression(JetSimpleNameExpression expression, ExpressionTypingContext context) {
|
||||
// TODO : other members
|
||||
// TODO : type substitutions???
|
||||
JetType type = DataFlowUtils.checkType(getSelectorReturnType(NO_RECEIVER, null, expression, context), expression, context);
|
||||
ExpressionTypingUtils.checkWrappingInRef(expression, context);
|
||||
return type; // TODO : Extensions to this
|
||||
return JetTypeInfo.create(type, context.dataFlowInfo); // TODO : Extensions to this
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -137,20 +137,21 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context) {
|
||||
return visitParenthesizedExpression(expression, context, false);
|
||||
}
|
||||
|
||||
public JetType visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context, boolean isStatement) {
|
||||
public JetTypeInfo visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context, boolean isStatement) {
|
||||
JetExpression innerExpression = expression.getExpression();
|
||||
if (innerExpression == null) {
|
||||
return null;
|
||||
return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
}
|
||||
return DataFlowUtils.checkType(facade.getType(innerExpression, context.replaceScope(context.scope), isStatement), expression, context);
|
||||
JetTypeInfo typeInfo = facade.getTypeInfo(innerExpression, context.replaceScope(context.scope), isStatement);
|
||||
return DataFlowUtils.checkType(typeInfo.getType(), expression, context, typeInfo.getDataFlowInfo());
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitConstantExpression(JetConstantExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitConstantExpression(JetConstantExpression expression, ExpressionTypingContext context) {
|
||||
ASTNode node = expression.getNode();
|
||||
IElementType elementType = node.getElementType();
|
||||
String text = node.getText();
|
||||
@@ -179,16 +180,16 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (value instanceof ErrorValue) {
|
||||
ErrorValue errorValue = (ErrorValue) value;
|
||||
context.trace.report(ERROR_COMPILE_TIME_VALUE.on(node.getPsi(), errorValue.getMessage()));
|
||||
return getDefaultType(elementType);
|
||||
return JetTypeInfo.create(getDefaultType(elementType), context.dataFlowInfo);
|
||||
}
|
||||
else {
|
||||
context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, value);
|
||||
return DataFlowUtils.checkType(value.getType(standardLibrary), expression, context);
|
||||
return DataFlowUtils.checkType(value.getType(standardLibrary), expression, context, context.dataFlowInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression, ExpressionTypingContext context) {
|
||||
JetTypeReference right = expression.getRight();
|
||||
JetType result = null;
|
||||
if (right != null) {
|
||||
@@ -212,14 +213,14 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
result = operationType == JetTokens.AS_SAFE ? TypeUtils.makeNullable(targetType) : targetType;
|
||||
}
|
||||
else {
|
||||
facade.getType(expression.getLeft(), context.replaceExpectedType(NO_EXPECTED_TYPE));
|
||||
facade.getTypeInfo(expression.getLeft(), context.replaceExpectedType(NO_EXPECTED_TYPE));
|
||||
}
|
||||
return DataFlowUtils.checkType(result, expression, context);
|
||||
return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
private boolean checkBinaryWithTypeRHS(JetBinaryExpressionWithTypeRHS expression, ExpressionTypingContext context, @NotNull JetType targetType) {
|
||||
|
||||
JetType actualType = facade.getType(expression.getLeft(), context);
|
||||
JetType actualType = facade.getTypeInfo(expression.getLeft(), context).getType();
|
||||
if (actualType == null) return false;
|
||||
|
||||
JetSimpleNameExpression operationSign = expression.getOperationSign();
|
||||
@@ -345,7 +346,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitTupleExpression(JetTupleExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitTupleExpression(JetTupleExpression expression, ExpressionTypingContext context) {
|
||||
List<JetExpression> entries = expression.getEntries();
|
||||
List<JetType> types = new ArrayList<JetType>();
|
||||
for (JetExpression entry : entries) {
|
||||
@@ -354,11 +355,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (context.expectedType != NO_EXPECTED_TYPE && JetStandardClasses.isTupleType(context.expectedType)) {
|
||||
List<JetType> enrichedTypes = checkArgumentTypes(types, entries, context.expectedType.getArguments(), context);
|
||||
if (enrichedTypes != types) {
|
||||
return JetStandardClasses.getTupleType(enrichedTypes);
|
||||
return JetTypeInfo.create(JetStandardClasses.getTupleType(enrichedTypes), context.dataFlowInfo);
|
||||
}
|
||||
}
|
||||
// TODO : labels
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getTupleType(types), expression, context);
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getTupleType(types), expression, context, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -374,7 +375,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitThisExpression(JetThisExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitThisExpression(JetThisExpression expression, ExpressionTypingContext context) {
|
||||
JetType result = null;
|
||||
ReceiverDescriptor thisReceiver = resolveToReceiver(expression, context, false);
|
||||
|
||||
@@ -387,19 +388,19 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getInstanceReference(), result);
|
||||
}
|
||||
}
|
||||
return DataFlowUtils.checkType(result, expression, context);
|
||||
return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitSuperExpression(JetSuperExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitSuperExpression(JetSuperExpression expression, ExpressionTypingContext context) {
|
||||
if (!context.namespacesAllowed) {
|
||||
context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(expression, expression.getText()));
|
||||
return null;
|
||||
return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
}
|
||||
JetType result = null;
|
||||
|
||||
ReceiverDescriptor thisReceiver = resolveToReceiver(expression, context, true);
|
||||
if (thisReceiver == null) return null;
|
||||
if (thisReceiver == null) return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
|
||||
if (!thisReceiver.exists()) {
|
||||
context.trace.report(SUPER_NOT_AVAILABLE.on(expression));
|
||||
@@ -476,7 +477,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
}
|
||||
}
|
||||
return DataFlowUtils.checkType(result, expression, context);
|
||||
return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Nullable // No class receivers
|
||||
@@ -509,30 +510,31 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context) {
|
||||
return visitBlockExpression(expression, context, false);
|
||||
}
|
||||
|
||||
public JetType visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context, boolean isStatement) {
|
||||
public JetTypeInfo visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context, boolean isStatement) {
|
||||
return context.expressionTypingServices.getBlockReturnedType(context.scope, expression, isStatement
|
||||
? CoercionStrategy.COERCION_TO_UNIT
|
||||
: CoercionStrategy.NO_COERCION, context, context.trace);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitHashQualifiedExpression(JetHashQualifiedExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitHashQualifiedExpression(JetHashQualifiedExpression expression, ExpressionTypingContext context) {
|
||||
context.trace.report(UNSUPPORTED.on(expression, getClass().getCanonicalName()));
|
||||
return null;
|
||||
return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitQualifiedExpression(JetQualifiedExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitQualifiedExpression(JetQualifiedExpression expression, ExpressionTypingContext context) {
|
||||
// TODO : functions as values
|
||||
JetExpression selectorExpression = expression.getSelectorExpression();
|
||||
JetExpression receiverExpression = expression.getReceiverExpression();
|
||||
ExpressionTypingContext contextWithNoExpectedType = context.replaceExpectedType(NO_EXPECTED_TYPE);
|
||||
JetType receiverType = facade.getType(receiverExpression, contextWithNoExpectedType.replaceNamespacesAllowed(true));
|
||||
if (selectorExpression == null) return null;
|
||||
JetTypeInfo receiverTypeInfo = facade.getTypeInfo(receiverExpression, contextWithNoExpectedType.replaceNamespacesAllowed(true));
|
||||
JetType receiverType = receiverTypeInfo.getType();
|
||||
if (selectorExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
if (receiverType == null) receiverType = ErrorUtils.createErrorType("Type for " + expression.getText());
|
||||
|
||||
if (selectorExpression instanceof JetSimpleNameExpression) {
|
||||
@@ -555,7 +557,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (result != null) {
|
||||
context.trace.record(BindingContext.EXPRESSION_TYPE, selectorExpression, result);
|
||||
}
|
||||
return DataFlowUtils.checkType(result, expression, context);
|
||||
return DataFlowUtils.checkType(result, expression, context, receiverTypeInfo.getDataFlowInfo());
|
||||
}
|
||||
|
||||
private void propagateConstantValues(JetQualifiedExpression expression, ExpressionTypingContext context, JetSimpleNameExpression selectorExpression) {
|
||||
@@ -740,19 +742,19 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitCallExpression(JetCallExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitCallExpression(JetCallExpression expression, ExpressionTypingContext context) {
|
||||
JetType expressionType = getCallExpressionType(expression, NO_RECEIVER, null, context);
|
||||
return DataFlowUtils.checkType(expressionType, expression, context);
|
||||
return DataFlowUtils.checkType(expressionType, expression, context, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context) {
|
||||
return visitUnaryExpression(expression, context, false);
|
||||
}
|
||||
|
||||
public JetType visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context, boolean isStatement) {
|
||||
public JetTypeInfo visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context, boolean isStatement) {
|
||||
JetExpression baseExpression = expression.getBaseExpression();
|
||||
if (baseExpression == null) return null;
|
||||
if (baseExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
|
||||
JetSimpleNameExpression operationSign = expression.getOperationReference();
|
||||
|
||||
@@ -762,32 +764,34 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
referencedName = referencedName == null ? " <?>" : referencedName;
|
||||
context.labelResolver.enterLabeledElement(new LabelName(referencedName.substring(1)), baseExpression);
|
||||
// TODO : Some processing for the label?
|
||||
JetType type = facade.getType(baseExpression, context, isStatement);
|
||||
JetTypeInfo typeInfo = facade.getTypeInfo(baseExpression, context, isStatement);
|
||||
context.labelResolver.exitLabeledElement(baseExpression);
|
||||
return DataFlowUtils.checkType(type, expression, context);
|
||||
return DataFlowUtils.checkType(typeInfo.getType(), expression, context, typeInfo.getDataFlowInfo());
|
||||
}
|
||||
|
||||
IElementType operationType = operationSign.getReferencedNameElementType();
|
||||
|
||||
// Type check the base expression
|
||||
JetType type = facade.getType(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE));
|
||||
JetTypeInfo typeInfo = facade.getTypeInfo(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE));
|
||||
JetType type = typeInfo.getType();
|
||||
if (type == null) {
|
||||
return null;
|
||||
return typeInfo;
|
||||
}
|
||||
DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
|
||||
|
||||
// Special case for expr!!
|
||||
if (operationType == JetTokens.EXCLEXCL) {
|
||||
if (isKnownToBeNotNull(baseExpression, context)) {
|
||||
context.trace.report(UNNECESSARY_NOT_NULL_ASSERTION.on(operationSign, type));
|
||||
}
|
||||
return DataFlowUtils.checkType(TypeUtils.makeNotNullable(type), expression, context);
|
||||
return DataFlowUtils.checkType(TypeUtils.makeNotNullable(type), expression, context, dataFlowInfo);
|
||||
}
|
||||
|
||||
// Conventions for unary operations
|
||||
Name name = OperatorConventions.UNARY_OPERATION_NAMES.get(operationType);
|
||||
if (name == null) {
|
||||
context.trace.report(UNSUPPORTED.on(operationSign, "visitUnaryExpression"));
|
||||
return null;
|
||||
return JetTypeInfo.create(null, dataFlowInfo);
|
||||
}
|
||||
|
||||
// a[i]++/-- takes special treatment because it is actually let j = i, arr = a in arr.set(j, a.get(j).inc())
|
||||
@@ -808,7 +812,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
name);
|
||||
|
||||
if (!resolutionResults.isSuccess()) {
|
||||
return null;
|
||||
return JetTypeInfo.create(null, dataFlowInfo);
|
||||
}
|
||||
|
||||
// Computing the return type
|
||||
@@ -836,7 +840,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
else {
|
||||
result = returnType;
|
||||
}
|
||||
return DataFlowUtils.checkType(result, expression, context);
|
||||
return DataFlowUtils.checkType(result, expression, context, dataFlowInfo);
|
||||
}
|
||||
|
||||
private boolean isKnownToBeNotNull(JetExpression expression, ExpressionTypingContext context) {
|
||||
@@ -871,13 +875,13 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitIdeTemplateExpression(JetIdeTemplateExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitIdeTemplateExpression(JetIdeTemplateExpression expression, ExpressionTypingContext context) {
|
||||
context.trace.report(UNRESOLVED_IDE_TEMPLATE.on(expression, ObjectUtils.notNull(expression.getText(), "<no name>")));
|
||||
return null;
|
||||
return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitBinaryExpression(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
||||
public JetTypeInfo visitBinaryExpression(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
|
||||
JetSimpleNameExpression operationSign = expression.getOperationReference();
|
||||
|
||||
@@ -951,13 +955,13 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
else if (OperatorConventions.IN_OPERATIONS.contains(operationType)) {
|
||||
if (right == null) {
|
||||
result = ErrorUtils.createErrorType("No right argument"); // TODO
|
||||
return null;
|
||||
return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
}
|
||||
checkInExpression(expression, expression.getOperationReference(), expression.getLeft(), expression.getRight(), context);
|
||||
result = booleanType;
|
||||
}
|
||||
else if (operationType == JetTokens.ANDAND || operationType == JetTokens.OROR) {
|
||||
JetType leftType = facade.getType(left, context.replaceScope(context.scope));
|
||||
JetType leftType = facade.getTypeInfo(left, context.replaceScope(context.scope)).getType();
|
||||
WritableScopeImpl leftScope = newWritableScopeImpl(context, "Left scope of && or ||");
|
||||
DataFlowInfo flowInfoLeft = DataFlowUtils.extractDataFlowInfoFromCondition(left, operationType == JetTokens.ANDAND, leftScope, context); // TODO: This gets computed twice: here and in extractDataFlowInfoFromCondition() for the whole condition
|
||||
WritableScopeImpl rightScope = operationType == JetTokens.ANDAND
|
||||
@@ -965,7 +969,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
: newWritableScopeImpl(context, "Right scope of && or ||");
|
||||
JetType rightType = right == null
|
||||
? null
|
||||
: facade.getType(right, context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope));
|
||||
: facade.getTypeInfo(right, context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope)).getType();
|
||||
if (leftType != null && !isBoolean(leftType)) {
|
||||
context.trace.report(TYPE_MISMATCH.on(left, booleanType, leftType));
|
||||
}
|
||||
@@ -975,17 +979,19 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
result = booleanType;
|
||||
}
|
||||
else if (operationType == JetTokens.ELVIS) {
|
||||
JetType leftType = facade.getType(left, context.replaceScope(context.scope));
|
||||
JetType leftType = facade.getTypeInfo(left, context.replaceScope(context.scope)).getType();
|
||||
JetType rightType = right == null
|
||||
? null
|
||||
: facade.getType(right, contextWithExpectedType.replaceScope(context.scope));
|
||||
: facade.getTypeInfo(right, contextWithExpectedType.replaceScope(context.scope)).getType();
|
||||
if (leftType != null) {
|
||||
if (!leftType.isNullable()) {
|
||||
context.trace.report(USELESS_ELVIS.on(left, leftType));
|
||||
}
|
||||
if (rightType != null) {
|
||||
DataFlowUtils.checkType(TypeUtils.makeNullableAsSpecified(leftType, rightType.isNullable()), left, contextWithExpectedType);
|
||||
return TypeUtils.makeNullableAsSpecified(CommonSupertypes.commonSupertype(Arrays.asList(leftType, rightType)), rightType.isNullable());
|
||||
return JetTypeInfo.create(TypeUtils.makeNullableAsSpecified(
|
||||
CommonSupertypes.commonSupertype(Arrays.asList(leftType, rightType)), rightType.isNullable()),
|
||||
context.dataFlowInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -993,7 +999,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
context.trace.report(UNSUPPORTED.on(operationSign, "Unknown operation"));
|
||||
}
|
||||
}
|
||||
return DataFlowUtils.checkType(result, expression, contextWithExpectedType);
|
||||
return DataFlowUtils.checkType(result, expression, contextWithExpectedType, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
public boolean checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @Nullable JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context) {
|
||||
@@ -1014,9 +1020,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
JetExpression right = expression.getRight();
|
||||
|
||||
// TODO : duplicated effort for == and !=
|
||||
JetType leftType = facade.getType(left, context.replaceScope(context.scope));
|
||||
JetType leftType = facade.getTypeInfo(left, context.replaceScope(context.scope)).getType();
|
||||
if (leftType != null && right != null) {
|
||||
JetType rightType = facade.getType(right, context.replaceScope(context.scope));
|
||||
JetType rightType = facade.getTypeInfo(right, context.replaceScope(context.scope)).getType();
|
||||
|
||||
if (rightType != null) {
|
||||
if (TypeUtils.isIntersectionEmpty(leftType, rightType)) {
|
||||
@@ -1049,10 +1055,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitArrayAccessExpression(JetArrayAccessExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitArrayAccessExpression(JetArrayAccessExpression expression, ExpressionTypingContext context) {
|
||||
JetType type = resolveArrayAccessGetMethod(expression, context.replaceExpectedType(NO_EXPECTED_TYPE));
|
||||
DataFlowUtils.checkType(type, expression, context);
|
||||
return type;
|
||||
return JetTypeInfo.create(type, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -1072,23 +1078,23 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitDeclaration(JetDeclaration dcl, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitDeclaration(JetDeclaration dcl, ExpressionTypingContext context) {
|
||||
context.trace.report(DECLARATION_IN_ILLEGAL_CONTEXT.on(dcl));
|
||||
return null;
|
||||
return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitRootNamespaceExpression(JetRootNamespaceExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitRootNamespaceExpression(JetRootNamespaceExpression expression, ExpressionTypingContext context) {
|
||||
if (context.namespacesAllowed) {
|
||||
return DataFlowUtils.checkType(JetModuleUtil.getRootNamespaceType(expression), expression, context);
|
||||
return DataFlowUtils.checkType(JetModuleUtil.getRootNamespaceType(expression), expression, context, context.dataFlowInfo);
|
||||
}
|
||||
context.trace.report(NAMESPACE_IS_NOT_AN_EXPRESSION.on(expression));
|
||||
return null;
|
||||
return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public JetType visitStringTemplateExpression(JetStringTemplateExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
||||
public JetTypeInfo visitStringTemplateExpression(JetStringTemplateExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
||||
final ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
final CompileTimeConstant<?>[] value = new CompileTimeConstant<?>[1];
|
||||
@@ -1099,7 +1105,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
public void visitStringTemplateEntryWithExpression(JetStringTemplateEntryWithExpression entry) {
|
||||
JetExpression entryExpression = entry.getExpression();
|
||||
if (entryExpression != null) {
|
||||
facade.getType(entryExpression, context);
|
||||
facade.getTypeInfo(entryExpression, context);
|
||||
}
|
||||
value[0] = CompileTimeConstantResolver.OUT_OF_RANGE;
|
||||
}
|
||||
@@ -1127,22 +1133,22 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (value[0] != CompileTimeConstantResolver.OUT_OF_RANGE) {
|
||||
context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new StringValue(builder.toString()));
|
||||
}
|
||||
return DataFlowUtils.checkType(JetStandardLibrary.getInstance().getStringType(), expression, contextWithExpectedType);
|
||||
return DataFlowUtils.checkType(JetStandardLibrary.getInstance().getStringType(), expression, contextWithExpectedType, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitAnnotatedExpression(JetAnnotatedExpression expression, ExpressionTypingContext data) {
|
||||
public JetTypeInfo visitAnnotatedExpression(JetAnnotatedExpression expression, ExpressionTypingContext data) {
|
||||
JetExpression baseExpression = expression.getBaseExpression();
|
||||
if (baseExpression == null) {
|
||||
return null;
|
||||
return JetTypeInfo.create(null, data.dataFlowInfo);
|
||||
}
|
||||
return facade.getType(baseExpression, data);
|
||||
return facade.getTypeInfo(baseExpression, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitJetElement(JetElement element, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitJetElement(JetElement element, ExpressionTypingContext context) {
|
||||
context.trace.report(UNSUPPORTED.on(element, getClass().getCanonicalName()));
|
||||
return null;
|
||||
return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -1161,7 +1167,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
@NotNull ExpressionTypingContext context,
|
||||
@NotNull BindingTrace traceForResolveResult,
|
||||
boolean isGet) {
|
||||
JetType arrayType = facade.getType(arrayAccessExpression.getArrayExpression(), context);
|
||||
JetType arrayType = facade.getTypeInfo(arrayAccessExpression.getArrayExpression(), context).getType();
|
||||
if (arrayType == null) return null;
|
||||
|
||||
ExpressionReceiver receiver = new ExpressionReceiver(arrayAccessExpression.getArrayExpression(), arrayType);
|
||||
|
||||
+7
-7
@@ -50,12 +50,12 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitObjectLiteralExpression(final JetObjectLiteralExpression expression, final ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitObjectLiteralExpression(final JetObjectLiteralExpression expression, final ExpressionTypingContext context) {
|
||||
DelegatingBindingTrace delegatingBindingTrace = context.trace.get(TRACE_DELTAS_CACHE, expression.getObjectDeclaration());
|
||||
if (delegatingBindingTrace != null) {
|
||||
delegatingBindingTrace.addAllMyDataTo(context.trace);
|
||||
JetType type = context.trace.get(EXPRESSION_TYPE, expression);
|
||||
return DataFlowUtils.checkType(type, expression, context);
|
||||
return DataFlowUtils.checkType(type, expression, context, context.dataFlowInfo);
|
||||
}
|
||||
final JetType[] result = new JetType[1];
|
||||
final TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace);
|
||||
@@ -87,11 +87,11 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor {
|
||||
temporaryTrace.addAllMyDataTo(cloneDelta);
|
||||
context.trace.record(TRACE_DELTAS_CACHE, expression.getObjectDeclaration(), cloneDelta);
|
||||
temporaryTrace.commit();
|
||||
return DataFlowUtils.checkType(result[0], expression, context);
|
||||
return DataFlowUtils.checkType(result[0], expression, context, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, ExpressionTypingContext context) {
|
||||
JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
|
||||
JetBlockExpression bodyExpression = functionLiteral.getBodyExpression();
|
||||
if (bodyExpression == null) return null;
|
||||
@@ -123,7 +123,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor {
|
||||
returnType = JetStandardClasses.getReturnTypeFromFunctionType(expectedType);
|
||||
}
|
||||
returnType = context.expressionTypingServices.getBlockReturnedType(functionInnerScope, bodyExpression, CoercionStrategy.COERCION_TO_UNIT,
|
||||
context.replaceExpectedType(returnType).replaceBindingTrace(temporaryTrace), temporaryTrace);
|
||||
context.replaceExpectedType(returnType).replaceBindingTrace(temporaryTrace), temporaryTrace).getType();
|
||||
}
|
||||
temporaryTrace.commit(new Predicate<WritableSlice>() {
|
||||
@Override
|
||||
@@ -140,11 +140,11 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor {
|
||||
JetType expectedReturnType = JetStandardClasses.getReturnTypeFromFunctionType(expectedType);
|
||||
if (JetStandardClasses.isUnit(expectedReturnType)) {
|
||||
functionDescriptor.setReturnType(JetStandardClasses.getUnitType());
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getFunctionType(Collections.<AnnotationDescriptor>emptyList(), receiver, parameterTypes, JetStandardClasses.getUnitType()), expression, context);
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getFunctionType(Collections.<AnnotationDescriptor>emptyList(), receiver, parameterTypes, JetStandardClasses.getUnitType()), expression, context, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
}
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getFunctionType(Collections.<AnnotationDescriptor>emptyList(), receiver, parameterTypes, safeReturnType), expression, context);
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getFunctionType(Collections.<AnnotationDescriptor>emptyList(), receiver, parameterTypes, safeReturnType), expression, context, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
private SimpleFunctionDescriptorImpl createFunctionDescriptor(JetFunctionLiteralExpression expression, ExpressionTypingContext context, boolean functionTypeExpected) {
|
||||
|
||||
+74
-58
@@ -65,7 +65,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
|
||||
private void checkCondition(@NotNull JetScope scope, @Nullable JetExpression condition, ExpressionTypingContext context) {
|
||||
if (condition != null) {
|
||||
JetType conditionType = facade.getType(condition, context.replaceScope(scope));
|
||||
JetType conditionType = facade.getTypeInfo(condition, context.replaceScope(scope)).getType();
|
||||
|
||||
if (conditionType != null && !isBoolean(conditionType)) {
|
||||
context.trace.report(TYPE_MISMATCH_IN_CONDITION.on(condition, conditionType));
|
||||
@@ -77,11 +77,11 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
|
||||
|
||||
@Override
|
||||
public JetType visitIfExpression(JetIfExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitIfExpression(JetIfExpression expression, ExpressionTypingContext context) {
|
||||
return visitIfExpression(expression, context, false);
|
||||
}
|
||||
|
||||
public JetType visitIfExpression(JetIfExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||
public JetTypeInfo visitIfExpression(JetIfExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
||||
JetExpression condition = expression.getCondition();
|
||||
checkCondition(context.scope, condition, context);
|
||||
@@ -96,55 +96,63 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
|
||||
if (elseBranch == null) {
|
||||
if (thenBranch != null) {
|
||||
JetType type = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(thenScope, Collections.singletonList(thenBranch), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(thenInfo), context.trace);
|
||||
JetTypeInfo typeInfo = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(thenScope, Collections.singletonList(thenBranch), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(thenInfo), context.trace);
|
||||
JetType type = typeInfo.getType();
|
||||
DataFlowInfo dataFlowInfo;
|
||||
if (type != null && JetStandardClasses.isNothing(type)) {
|
||||
facade.setResultingDataFlowInfo(elseInfo);
|
||||
dataFlowInfo = elseInfo;
|
||||
} else {
|
||||
dataFlowInfo = typeInfo.getDataFlowInfo().or(elseInfo);
|
||||
}
|
||||
return DataFlowUtils.checkImplicitCast(DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType), expression, contextWithExpectedType, isStatement);
|
||||
return DataFlowUtils.checkImplicitCast(DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType), expression, contextWithExpectedType, isStatement, dataFlowInfo);
|
||||
}
|
||||
return null;
|
||||
return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
}
|
||||
if (thenBranch == null) {
|
||||
JetType type = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(elseScope, Collections.singletonList(elseBranch), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(elseInfo), context.trace);
|
||||
JetTypeInfo typeInfo = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(elseScope, Collections.singletonList(elseBranch), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(elseInfo), context.trace);
|
||||
JetType type = typeInfo.getType();
|
||||
DataFlowInfo dataFlowInfo;
|
||||
if (type != null && JetStandardClasses.isNothing(type)) {
|
||||
facade.setResultingDataFlowInfo(thenInfo);
|
||||
dataFlowInfo = thenInfo;
|
||||
} else {
|
||||
dataFlowInfo = typeInfo.getDataFlowInfo().or(thenInfo);
|
||||
}
|
||||
return DataFlowUtils.checkImplicitCast(DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType), expression, contextWithExpectedType, isStatement);
|
||||
return DataFlowUtils.checkImplicitCast(DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType), expression, contextWithExpectedType, isStatement, dataFlowInfo);
|
||||
}
|
||||
CoercionStrategy coercionStrategy = isStatement ? CoercionStrategy.COERCION_TO_UNIT : CoercionStrategy.NO_COERCION;
|
||||
JetType thenType = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(thenScope, Collections.singletonList(thenBranch), coercionStrategy, contextWithExpectedType.replaceDataFlowInfo(thenInfo), context.trace);
|
||||
JetType elseType = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(elseScope, Collections.singletonList(elseBranch), coercionStrategy, contextWithExpectedType.replaceDataFlowInfo(elseInfo), context.trace);
|
||||
|
||||
JetType result;
|
||||
if (thenType == null) {
|
||||
result = elseType;
|
||||
}
|
||||
else if (elseType == null) {
|
||||
result = thenType;
|
||||
}
|
||||
else {
|
||||
result = CommonSupertypes.commonSupertype(Arrays.asList(thenType, elseType));
|
||||
}
|
||||
JetTypeInfo thenTypeInfo = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(thenScope, Collections.singletonList(thenBranch), coercionStrategy, contextWithExpectedType.replaceDataFlowInfo(thenInfo), context.trace);
|
||||
JetTypeInfo elseTypeInfo = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(elseScope, Collections.singletonList(elseBranch), coercionStrategy, contextWithExpectedType.replaceDataFlowInfo(elseInfo), context.trace);
|
||||
JetType thenType = thenTypeInfo.getType();
|
||||
JetType elseType = elseTypeInfo.getType();
|
||||
DataFlowInfo thenDataFlowInfo = thenTypeInfo.getDataFlowInfo();
|
||||
DataFlowInfo elseDataFlowInfo = elseTypeInfo.getDataFlowInfo();
|
||||
|
||||
boolean jumpInThen = thenType != null && JetStandardClasses.isNothing(thenType);
|
||||
boolean jumpInElse = elseType != null && JetStandardClasses.isNothing(elseType);
|
||||
|
||||
if (jumpInThen && !jumpInElse) {
|
||||
facade.setResultingDataFlowInfo(elseInfo);
|
||||
JetTypeInfo result;
|
||||
if (thenType == null && elseType == null) {
|
||||
result = JetTypeInfo.create(null, thenDataFlowInfo.or(elseDataFlowInfo));
|
||||
}
|
||||
else if (jumpInElse && !jumpInThen) {
|
||||
facade.setResultingDataFlowInfo(thenInfo);
|
||||
else if (thenType == null || (jumpInThen && !jumpInElse)) {
|
||||
result = elseTypeInfo;
|
||||
}
|
||||
if (result == null) return null;
|
||||
return DataFlowUtils.checkImplicitCast(result, expression, contextWithExpectedType, isStatement);
|
||||
}
|
||||
else if (elseType == null || (jumpInElse && !jumpInThen)) {
|
||||
result = thenTypeInfo;
|
||||
}
|
||||
else {
|
||||
result = JetTypeInfo.create(CommonSupertypes.commonSupertype(Arrays.asList(thenType, elseType)), thenDataFlowInfo.or(elseDataFlowInfo));
|
||||
}
|
||||
|
||||
return DataFlowUtils.checkImplicitCast(result.getType(), expression, contextWithExpectedType, isStatement, result.getDataFlowInfo());
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext context) {
|
||||
return visitWhileExpression(expression, context, false);
|
||||
}
|
||||
|
||||
public JetType visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||
public JetTypeInfo visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||
if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade);
|
||||
|
||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
||||
@@ -156,10 +164,14 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
DataFlowInfo conditionInfo = condition == null ? context.dataFlowInfo : DataFlowUtils.extractDataFlowInfoFromCondition(condition, true, scopeToExtend, context);
|
||||
context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(scopeToExtend, Collections.singletonList(body), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(conditionInfo), context.trace);
|
||||
}
|
||||
DataFlowInfo dataFlowInfo;
|
||||
if (!containsBreak(expression, context)) {
|
||||
facade.setResultingDataFlowInfo(DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, null, context));
|
||||
dataFlowInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, null, context);
|
||||
}
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType);
|
||||
else {
|
||||
dataFlowInfo = context.dataFlowInfo;
|
||||
}
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType, dataFlowInfo);
|
||||
}
|
||||
|
||||
private boolean containsBreak(final JetLoopExpression loopExpression, final ExpressionTypingContext context) {
|
||||
@@ -187,10 +199,10 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext context) {
|
||||
return visitDoWhileExpression(expression, context, false);
|
||||
}
|
||||
public JetType visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||
public JetTypeInfo visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||
if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade);
|
||||
|
||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
||||
@@ -205,7 +217,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
context.trace.record(BindingContext.BLOCK, function);
|
||||
}
|
||||
else {
|
||||
facade.getType(body, context.replaceScope(context.scope));
|
||||
facade.getTypeInfo(body, context.replaceScope(context.scope));
|
||||
}
|
||||
}
|
||||
else if (body != null) {
|
||||
@@ -222,18 +234,22 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
JetExpression condition = expression.getCondition();
|
||||
checkCondition(conditionScope, condition, context);
|
||||
DataFlowInfo dataFlowInfo;
|
||||
if (!containsBreak(expression, context)) {
|
||||
facade.setResultingDataFlowInfo(DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, null, context));
|
||||
dataFlowInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, null, context);
|
||||
}
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType);
|
||||
else {
|
||||
dataFlowInfo = context.dataFlowInfo;
|
||||
}
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType, dataFlowInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitForExpression(JetForExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitForExpression(JetForExpression expression, ExpressionTypingContext context) {
|
||||
return visitForExpression(expression, context, false);
|
||||
}
|
||||
|
||||
public JetType visitForExpression(JetForExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||
public JetTypeInfo visitForExpression(JetForExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||
if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade);
|
||||
|
||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
||||
@@ -286,7 +302,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(loopScope, Collections.singletonList(body), CoercionStrategy.NO_COERCION, context, context.trace);
|
||||
}
|
||||
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType);
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -403,7 +419,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitTryExpression(JetTryExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitTryExpression(JetTryExpression expression, ExpressionTypingContext context) {
|
||||
JetExpression tryBlock = expression.getTryBlock();
|
||||
List<JetCatchClause> catchClauses = expression.getCatchClauses();
|
||||
JetFinallySection finallyBlock = expression.getFinallyBlock();
|
||||
@@ -419,7 +435,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (catchBody != null) {
|
||||
WritableScope catchScope = newWritableScopeImpl(context, "Catch scope");
|
||||
catchScope.addVariableDescriptor(variableDescriptor);
|
||||
JetType type = facade.getType(catchBody, context.replaceScope(catchScope));
|
||||
JetType type = facade.getTypeInfo(catchBody, context.replaceScope(catchScope)).getType();
|
||||
if (type != null) {
|
||||
types.add(type);
|
||||
}
|
||||
@@ -427,32 +443,32 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
}
|
||||
if (finallyBlock != null) {
|
||||
facade.getType(finallyBlock.getFinalExpression(), context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE));
|
||||
facade.getTypeInfo(finallyBlock.getFinalExpression(), context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE));
|
||||
}
|
||||
JetType type = facade.getType(tryBlock, context);
|
||||
JetType type = facade.getTypeInfo(tryBlock, context).getType();
|
||||
if (type != null) {
|
||||
types.add(type);
|
||||
}
|
||||
if (types.isEmpty()) {
|
||||
return null;
|
||||
return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
}
|
||||
else {
|
||||
return CommonSupertypes.commonSupertype(types);
|
||||
return JetTypeInfo.create(CommonSupertypes.commonSupertype(types), context.dataFlowInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitThrowExpression(JetThrowExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitThrowExpression(JetThrowExpression expression, ExpressionTypingContext context) {
|
||||
JetExpression thrownExpression = expression.getThrownExpression();
|
||||
if (thrownExpression != null) {
|
||||
JetType throwableType = JetStandardLibrary.getInstance().getThrowable().getDefaultType();
|
||||
facade.getType(thrownExpression, context.replaceExpectedType(throwableType).replaceScope(context.scope));
|
||||
facade.getTypeInfo(thrownExpression, context.replaceExpectedType(throwableType).replaceScope(context.scope));
|
||||
}
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context);
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitReturnExpression(JetReturnExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitReturnExpression(JetReturnExpression expression, ExpressionTypingContext context) {
|
||||
JetElement element = context.labelResolver.resolveLabel(expression, context);
|
||||
|
||||
JetExpression returnedExpression = expression.getReturnedExpression();
|
||||
@@ -501,25 +517,25 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
}
|
||||
if (returnedExpression != null) {
|
||||
facade.getType(returnedExpression, context.replaceExpectedType(expectedType).replaceScope(context.scope));
|
||||
facade.getTypeInfo(returnedExpression, context.replaceExpectedType(expectedType).replaceScope(context.scope));
|
||||
}
|
||||
else {
|
||||
if (expectedType != TypeUtils.NO_EXPECTED_TYPE && expectedType != null && !JetStandardClasses.isUnit(expectedType)) {
|
||||
context.trace.report(RETURN_TYPE_MISMATCH.on(expression, expectedType));
|
||||
}
|
||||
}
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context);
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitBreakExpression(JetBreakExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitBreakExpression(JetBreakExpression expression, ExpressionTypingContext context) {
|
||||
context.labelResolver.resolveLabel(expression, context);
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context);
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitContinueExpression(JetContinueExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitContinueExpression(JetContinueExpression expression, ExpressionTypingContext context) {
|
||||
context.labelResolver.resolveLabel(expression, context);
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context);
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context, context.dataFlowInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||
import org.jetbrains.jet.lang.types.JetTypeInfo;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||
@@ -151,6 +152,11 @@ public class DataFlowUtils {
|
||||
return context.dataFlowInfo.and(result.get());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JetTypeInfo checkType(@Nullable JetType expressionType, @NotNull JetExpression expression, @NotNull ExpressionTypingContext context, @NotNull DataFlowInfo dataFlowInfo) {
|
||||
return JetTypeInfo.create(checkType(expressionType, expression, context), dataFlowInfo);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static JetType checkType(@Nullable JetType expressionType, @NotNull JetExpression expression, @NotNull ExpressionTypingContext context) {
|
||||
if (expressionType == null || context.expectedType == null || context.expectedType == TypeUtils.NO_EXPECTED_TYPE ||
|
||||
@@ -174,6 +180,11 @@ public class DataFlowUtils {
|
||||
return expressionType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JetTypeInfo checkStatementType(@NotNull JetExpression expression, @NotNull ExpressionTypingContext context, @NotNull DataFlowInfo dataFlowInfo) {
|
||||
return JetTypeInfo.create(checkStatementType(expression, context), dataFlowInfo);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static JetType checkStatementType(@NotNull JetExpression expression, @NotNull ExpressionTypingContext context) {
|
||||
if (context.expectedType != TypeUtils.NO_EXPECTED_TYPE && !JetStandardClasses.isUnit(context.expectedType)) {
|
||||
@@ -183,6 +194,11 @@ public class DataFlowUtils {
|
||||
return JetStandardClasses.getUnitType();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JetTypeInfo checkImplicitCast(@Nullable JetType expressionType, @NotNull JetExpression expression, @NotNull ExpressionTypingContext context, boolean isStatement, DataFlowInfo dataFlowInfo) {
|
||||
return JetTypeInfo.create(checkImplicitCast(expressionType, expression, context, isStatement), dataFlowInfo);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static JetType checkImplicitCast(@Nullable JetType expressionType, @NotNull JetExpression expression, @NotNull ExpressionTypingContext context, boolean isStatement) {
|
||||
if (expressionType != null && context.expectedType == TypeUtils.NO_EXPECTED_TYPE && !isStatement &&
|
||||
@@ -193,10 +209,10 @@ public class DataFlowUtils {
|
||||
return expressionType;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static JetType illegalStatementType(@NotNull JetExpression expression, @NotNull ExpressionTypingContext context, @NotNull ExpressionTypingInternals facade) {
|
||||
@NotNull
|
||||
public static JetTypeInfo illegalStatementType(@NotNull JetExpression expression, @NotNull ExpressionTypingContext context, @NotNull ExpressionTypingInternals facade) {
|
||||
facade.checkStatementType(expression, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE));
|
||||
context.trace.report(EXPRESSION_EXPECTED.on(expression, expression));
|
||||
return null;
|
||||
return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -19,18 +19,18 @@ package org.jetbrains.jet.lang.types.expressions;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeInfo;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public interface ExpressionTypingFacade {
|
||||
@NotNull
|
||||
JetType safeGetType(@NotNull JetExpression expression, ExpressionTypingContext context);
|
||||
JetTypeInfo safeGetTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context);
|
||||
|
||||
@Nullable
|
||||
JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context);
|
||||
@NotNull
|
||||
JetTypeInfo getTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context);
|
||||
|
||||
@Nullable
|
||||
JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context, boolean isStatement);
|
||||
@NotNull
|
||||
JetTypeInfo getTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context, boolean isStatement);
|
||||
}
|
||||
|
||||
-5
@@ -31,11 +31,6 @@ import org.jetbrains.jet.lang.types.JetType;
|
||||
*/
|
||||
/*package*/ interface ExpressionTypingInternals extends ExpressionTypingFacade {
|
||||
|
||||
void setResultingDataFlowInfo(@NotNull DataFlowInfo dataFlowInfo);
|
||||
|
||||
@Nullable
|
||||
DataFlowInfo getResultingDataFlowInfo();
|
||||
|
||||
@Nullable
|
||||
JetType getSelectorReturnType(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression selectorExpression, @NotNull ExpressionTypingContext context);
|
||||
|
||||
|
||||
+20
-22
@@ -37,6 +37,7 @@ import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
|
||||
import org.jetbrains.jet.lang.types.CommonSupertypes;
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeInfo;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
@@ -119,13 +120,13 @@ public class ExpressionTypingServices {
|
||||
ExpressionTypingContext context = ExpressionTypingContext.newContext(
|
||||
this, trace, scope, dataFlowInfo, expectedType, false
|
||||
);
|
||||
return expressionTypingFacade.getType(expression, context);
|
||||
return expressionTypingFacade.getTypeInfo(expression, context).getType();
|
||||
}
|
||||
|
||||
public JetType getTypeWithNamespaces(@NotNull final JetScope scope, @NotNull JetExpression expression, @NotNull BindingTrace trace) {
|
||||
ExpressionTypingContext context = ExpressionTypingContext.newContext(
|
||||
this, trace, scope, DataFlowInfo.EMPTY, NO_EXPECTED_TYPE, true);
|
||||
return expressionTypingFacade.getType(expression, context);
|
||||
return expressionTypingFacade.getTypeInfo(expression, context).getType();
|
||||
// return ((ExpressionTypingContext) ExpressionTyperVisitorWithNamespaces).INSTANCE.getType(expression, ExpressionTypingContext.newRootContext(semanticServices, trace, scope, DataFlowInfo.getEmpty(), TypeUtils.NO_EXPECTED_TYPE, TypeUtils.NO_EXPECTED_TYPE));
|
||||
}
|
||||
|
||||
@@ -170,12 +171,12 @@ public class ExpressionTypingServices {
|
||||
getBlockReturnedType(newContext.scope, blockExpression, CoercionStrategy.COERCION_TO_UNIT, context, trace);
|
||||
}
|
||||
else {
|
||||
expressionTypingFacade.getType(bodyExpression, newContext, !blockBody);
|
||||
expressionTypingFacade.getTypeInfo(bodyExpression, newContext, !blockBody);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JetType getBlockReturnedType(@NotNull JetScope outerScope, @NotNull JetBlockExpression expression, @NotNull CoercionStrategy coercionStrategyForLastExpression, ExpressionTypingContext context, BindingTrace trace) {
|
||||
@NotNull
|
||||
public JetTypeInfo getBlockReturnedType(@NotNull JetScope outerScope, @NotNull JetBlockExpression expression, @NotNull CoercionStrategy coercionStrategyForLastExpression, ExpressionTypingContext context, BindingTrace trace) {
|
||||
List<JetElement> block = expression.getStatements();
|
||||
|
||||
DeclarationDescriptor containingDescriptor = outerScope.getContainingDeclaration();
|
||||
@@ -190,9 +191,9 @@ public class ExpressionTypingServices {
|
||||
outerScope, containingDescriptor, new TraceBasedRedeclarationHandler(context.trace), "getBlockReturnedType");
|
||||
scope.changeLockLevel(WritableScope.LockLevel.BOTH);
|
||||
|
||||
JetType r;
|
||||
JetTypeInfo r;
|
||||
if (block.isEmpty()) {
|
||||
r = DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, context);
|
||||
r = DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, context, context.dataFlowInfo);
|
||||
}
|
||||
else {
|
||||
r = getBlockReturnedTypeWithWritableScope(scope, block, coercionStrategyForLastExpression, context, trace);
|
||||
@@ -214,7 +215,7 @@ public class ExpressionTypingServices {
|
||||
JetExpression bodyExpression = function.getBodyExpression();
|
||||
assert bodyExpression != null;
|
||||
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace);
|
||||
expressionTypingFacade.getType(bodyExpression, ExpressionTypingContext.newContext(
|
||||
expressionTypingFacade.getTypeInfo(bodyExpression, ExpressionTypingContext.newContext(
|
||||
this,
|
||||
trace, functionInnerScope, DataFlowInfo.EMPTY, NO_EXPECTED_TYPE, false), !function.hasBlockBody());
|
||||
//todo function literals
|
||||
@@ -262,15 +263,15 @@ public class ExpressionTypingServices {
|
||||
|
||||
/*package*/
|
||||
@SuppressWarnings("SuspiciousMethodCalls")
|
||||
JetType getBlockReturnedTypeWithWritableScope(@NotNull WritableScope scope, @NotNull List<? extends JetElement> block, @NotNull CoercionStrategy coercionStrategyForLastExpression, ExpressionTypingContext context, BindingTrace trace) {
|
||||
JetTypeInfo getBlockReturnedTypeWithWritableScope(@NotNull WritableScope scope, @NotNull List<? extends JetElement> block, @NotNull CoercionStrategy coercionStrategyForLastExpression, ExpressionTypingContext context, BindingTrace trace) {
|
||||
if (block.isEmpty()) {
|
||||
return JetStandardClasses.getUnitType();
|
||||
return JetTypeInfo.create(JetStandardClasses.getUnitType(), context.dataFlowInfo);
|
||||
}
|
||||
|
||||
ExpressionTypingInternals blockLevelVisitor = ExpressionTypingVisitorDispatcher.createForBlock(scope);
|
||||
ExpressionTypingContext newContext = createContext(context, trace, scope, context.dataFlowInfo, NO_EXPECTED_TYPE);
|
||||
|
||||
JetType result = null;
|
||||
JetTypeInfo result = JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
for (Iterator<? extends JetElement> iterator = block.iterator(); iterator.hasNext(); ) {
|
||||
final JetElement statement = iterator.next();
|
||||
trace.record(STATEMENT, statement);
|
||||
@@ -284,13 +285,13 @@ public class ExpressionTypingServices {
|
||||
final boolean[] mismatch = new boolean[1];
|
||||
ObservableBindingTrace errorInterceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceExpectingUnit, statementExpression, mismatch);
|
||||
newContext = createContext(newContext, errorInterceptingTrace, scope, newContext.dataFlowInfo, context.expectedType);
|
||||
result = blockLevelVisitor.getType(statementExpression, newContext, true);
|
||||
result = blockLevelVisitor.getTypeInfo(statementExpression, newContext, true);
|
||||
if (mismatch[0]) {
|
||||
TemporaryBindingTrace temporaryTraceNoExpectedType = TemporaryBindingTrace.create(trace);
|
||||
mismatch[0] = false;
|
||||
ObservableBindingTrace interceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceNoExpectedType, statementExpression, mismatch);
|
||||
newContext = createContext(newContext, interceptingTrace, scope, newContext.dataFlowInfo, NO_EXPECTED_TYPE);
|
||||
result = blockLevelVisitor.getType(statementExpression, newContext, true);
|
||||
result = blockLevelVisitor.getTypeInfo(statementExpression, newContext, true);
|
||||
if (mismatch[0]) {
|
||||
temporaryTraceExpectingUnit.commit();
|
||||
}
|
||||
@@ -304,11 +305,11 @@ public class ExpressionTypingServices {
|
||||
}
|
||||
else {
|
||||
newContext = createContext(newContext, trace, scope, newContext.dataFlowInfo, context.expectedType);
|
||||
result = blockLevelVisitor.getType(statementExpression, newContext, true);
|
||||
result = blockLevelVisitor.getTypeInfo(statementExpression, newContext, true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = blockLevelVisitor.getType(statementExpression, newContext, true);
|
||||
result = blockLevelVisitor.getTypeInfo(statementExpression, newContext, true);
|
||||
if (coercionStrategyForLastExpression == CoercionStrategy.COERCION_TO_UNIT) {
|
||||
boolean mightBeUnit = false;
|
||||
if (statementExpression instanceof JetDeclaration) {
|
||||
@@ -323,20 +324,17 @@ public class ExpressionTypingServices {
|
||||
}
|
||||
if (mightBeUnit) {
|
||||
// ExpressionTypingVisitorForStatements should return only null or Unit for declarations and assignments
|
||||
assert result == null || JetStandardClasses.isUnit(result);
|
||||
result = JetStandardClasses.getUnitType();
|
||||
assert result.getType() == null || JetStandardClasses.isUnit(result.getType());
|
||||
result = JetTypeInfo.create(JetStandardClasses.getUnitType(), newContext.dataFlowInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = blockLevelVisitor.getType(statementExpression, newContext, true);
|
||||
result = blockLevelVisitor.getTypeInfo(statementExpression, newContext, true);
|
||||
}
|
||||
|
||||
DataFlowInfo newDataFlowInfo = blockLevelVisitor.getResultingDataFlowInfo();
|
||||
if (newDataFlowInfo == null) {
|
||||
newDataFlowInfo = context.dataFlowInfo;
|
||||
}
|
||||
DataFlowInfo newDataFlowInfo = result.getDataFlowInfo();
|
||||
if (newDataFlowInfo != context.dataFlowInfo) {
|
||||
newContext = createContext(newContext, trace, scope, newDataFlowInfo, NO_EXPECTED_TYPE);
|
||||
}
|
||||
|
||||
+2
-2
@@ -71,12 +71,12 @@ public class ExpressionTypingUtils {
|
||||
|
||||
@Nullable
|
||||
protected static ExpressionReceiver getExpressionReceiver(@NotNull ExpressionTypingFacade facade, @NotNull JetExpression expression, ExpressionTypingContext context) {
|
||||
return getExpressionReceiver(expression, facade.getType(expression, context));
|
||||
return getExpressionReceiver(expression, facade.getTypeInfo(expression, context).getType());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected static ExpressionReceiver safeGetExpressionReceiver(@NotNull ExpressionTypingFacade facade, @NotNull JetExpression expression, ExpressionTypingContext context) {
|
||||
return new ExpressionReceiver(expression, facade.safeGetType(expression, context));
|
||||
return new ExpressionReceiver(expression, facade.safeGetTypeInfo(expression, context).getType());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+2
-2
@@ -18,12 +18,12 @@ package org.jetbrains.jet.lang.types.expressions;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.JetVisitor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeInfo;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
/*package*/ abstract class ExpressionTypingVisitor extends JetVisitor<JetType, ExpressionTypingContext> {
|
||||
/*package*/ abstract class ExpressionTypingVisitor extends JetVisitor<JetTypeInfo, ExpressionTypingContext> {
|
||||
|
||||
protected final ExpressionTypingInternals facade;
|
||||
|
||||
|
||||
+43
-52
@@ -27,6 +27,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.DeferredType;
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeInfo;
|
||||
import org.jetbrains.jet.util.lazy.ReenteringLazyValueComputationException;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM;
|
||||
@@ -34,10 +35,10 @@ import static org.jetbrains.jet.lang.diagnostics.Errors.TYPECHECKER_HAS_RUN_INTO
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetType, ExpressionTypingContext> implements ExpressionTypingInternals {
|
||||
public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetTypeInfo, ExpressionTypingContext> implements ExpressionTypingInternals {
|
||||
|
||||
@Override
|
||||
public JetType visitIdeTemplateExpression(JetIdeTemplateExpression expression, ExpressionTypingContext data) {
|
||||
public JetTypeInfo visitIdeTemplateExpression(JetIdeTemplateExpression expression, ExpressionTypingContext data) {
|
||||
return basic.visitIdeTemplateExpression(expression, data);
|
||||
}
|
||||
|
||||
@@ -56,7 +57,6 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetType, Expre
|
||||
private final ClosureExpressionsTypingVisitor closures = new ClosureExpressionsTypingVisitor(this);
|
||||
private final ControlStructureTypingVisitor controlStructures = new ControlStructureTypingVisitor(this);
|
||||
private final PatternMatchingTypingVisitor patterns = new PatternMatchingTypingVisitor(this);
|
||||
protected DataFlowInfo resultDataFlowInfo;
|
||||
|
||||
private ExpressionTypingVisitorDispatcher(WritableScope writableScope) {
|
||||
this.basic = new BasicExpressionTypingVisitor(this);
|
||||
@@ -68,12 +68,6 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetType, Expre
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public DataFlowInfo getResultingDataFlowInfo() {
|
||||
return resultDataFlowInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType getSelectorReturnType(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression selectorExpression, @NotNull ExpressionTypingContext context) {
|
||||
return basic.getSelectorReturnType(receiver, callOperationNode, selectorExpression, context);
|
||||
@@ -85,33 +79,28 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetType, Expre
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResultingDataFlowInfo(@NotNull DataFlowInfo dataFlowInfo) {
|
||||
this.resultDataFlowInfo = dataFlowInfo;
|
||||
@NotNull
|
||||
public final JetTypeInfo safeGetTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context) {
|
||||
JetTypeInfo typeInfo = getTypeInfo(expression, context);
|
||||
if (typeInfo.getType() != null) {
|
||||
return typeInfo;
|
||||
}
|
||||
return JetTypeInfo.create(ErrorUtils.createErrorType("Type for " + expression.getText()), context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public final JetType safeGetType(@NotNull JetExpression expression, ExpressionTypingContext context) {
|
||||
JetType type = getType(expression, context);
|
||||
if (type != null) {
|
||||
return type;
|
||||
}
|
||||
return ErrorUtils.createErrorType("Type for " + expression.getText());
|
||||
public final JetTypeInfo getTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context) {
|
||||
return getTypeInfo(expression, context, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public final JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context) {
|
||||
return getType(expression, context, this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public final JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context, boolean isStatement) {
|
||||
if (!isStatement) return getType(expression, context);
|
||||
@NotNull
|
||||
public final JetTypeInfo getTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context, boolean isStatement) {
|
||||
if (!isStatement) return getTypeInfo(expression, context);
|
||||
if (statements != null) {
|
||||
return getType(expression, context, statements);
|
||||
return getTypeInfo(expression, context, statements);
|
||||
}
|
||||
return getType(expression, context, createStatementVisitor(context));
|
||||
return getTypeInfo(expression, context, createStatementVisitor(context));
|
||||
}
|
||||
|
||||
private ExpressionTypingVisitorForStatements createStatementVisitor(ExpressionTypingContext context) {
|
||||
@@ -123,30 +112,32 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetType, Expre
|
||||
expression.accept(createStatementVisitor(context), context);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context, JetVisitor<JetType, ExpressionTypingContext> visitor) {
|
||||
@NotNull
|
||||
private JetTypeInfo getTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context, JetVisitor<JetTypeInfo, ExpressionTypingContext> visitor) {
|
||||
if (context.trace.get(BindingContext.PROCESSED, expression)) {
|
||||
return context.trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression);
|
||||
return JetTypeInfo.create(context.trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression),
|
||||
context.dataFlowInfo);
|
||||
}
|
||||
JetType result;
|
||||
JetTypeInfo result;
|
||||
try {
|
||||
result = expression.accept(visitor, context);
|
||||
// Some recursive definitions (object expressions) must put their types in the cache manually:
|
||||
if (context.trace.get(BindingContext.PROCESSED, expression)) {
|
||||
return context.trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression);
|
||||
return JetTypeInfo.create(context.trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression),
|
||||
result.getDataFlowInfo());
|
||||
}
|
||||
|
||||
if (result instanceof DeferredType) {
|
||||
result = ((DeferredType) result).getActualType();
|
||||
if (result.getType() instanceof DeferredType) {
|
||||
result = JetTypeInfo.create(((DeferredType) result.getType()).getActualType(), context.dataFlowInfo);
|
||||
}
|
||||
if (result != null) {
|
||||
context.trace.record(BindingContext.EXPRESSION_TYPE, expression, result);
|
||||
if (result.getType() != null) {
|
||||
context.trace.record(BindingContext.EXPRESSION_TYPE, expression, result.getType());
|
||||
}
|
||||
|
||||
}
|
||||
catch (ReenteringLazyValueComputationException e) {
|
||||
context.trace.report(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM.on(expression));
|
||||
result = null;
|
||||
result = JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
if (!context.trace.get(BindingContext.PROCESSED, expression) && !(expression instanceof JetReferenceExpression)) {
|
||||
@@ -159,78 +150,78 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetType, Expre
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public JetType visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, ExpressionTypingContext data) {
|
||||
public JetTypeInfo visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, ExpressionTypingContext data) {
|
||||
return expression.accept(closures, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitObjectLiteralExpression(JetObjectLiteralExpression expression, ExpressionTypingContext data) {
|
||||
public JetTypeInfo visitObjectLiteralExpression(JetObjectLiteralExpression expression, ExpressionTypingContext data) {
|
||||
return expression.accept(closures, data);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public JetType visitThrowExpression(JetThrowExpression expression, ExpressionTypingContext data) {
|
||||
public JetTypeInfo visitThrowExpression(JetThrowExpression expression, ExpressionTypingContext data) {
|
||||
return expression.accept(controlStructures, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitReturnExpression(JetReturnExpression expression, ExpressionTypingContext data) {
|
||||
public JetTypeInfo visitReturnExpression(JetReturnExpression expression, ExpressionTypingContext data) {
|
||||
return expression.accept(controlStructures, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitContinueExpression(JetContinueExpression expression, ExpressionTypingContext data) {
|
||||
public JetTypeInfo visitContinueExpression(JetContinueExpression expression, ExpressionTypingContext data) {
|
||||
return expression.accept(controlStructures, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitIfExpression(JetIfExpression expression, ExpressionTypingContext data) {
|
||||
public JetTypeInfo visitIfExpression(JetIfExpression expression, ExpressionTypingContext data) {
|
||||
return expression.accept(controlStructures, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitTryExpression(JetTryExpression expression, ExpressionTypingContext data) {
|
||||
public JetTypeInfo visitTryExpression(JetTryExpression expression, ExpressionTypingContext data) {
|
||||
return expression.accept(controlStructures, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitForExpression(JetForExpression expression, ExpressionTypingContext data) {
|
||||
public JetTypeInfo visitForExpression(JetForExpression expression, ExpressionTypingContext data) {
|
||||
return expression.accept(controlStructures, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext data) {
|
||||
public JetTypeInfo visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext data) {
|
||||
return expression.accept(controlStructures, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext data) {
|
||||
public JetTypeInfo visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext data) {
|
||||
return expression.accept(controlStructures, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitBreakExpression(JetBreakExpression expression, ExpressionTypingContext data) {
|
||||
public JetTypeInfo visitBreakExpression(JetBreakExpression expression, ExpressionTypingContext data) {
|
||||
return expression.accept(controlStructures, data);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public JetType visitIsExpression(JetIsExpression expression, ExpressionTypingContext data) {
|
||||
public JetTypeInfo visitIsExpression(JetIsExpression expression, ExpressionTypingContext data) {
|
||||
return expression.accept(patterns, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitWhenExpression(JetWhenExpression expression, ExpressionTypingContext data) {
|
||||
public JetTypeInfo visitWhenExpression(JetWhenExpression expression, ExpressionTypingContext data) {
|
||||
return expression.accept(patterns, data);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public JetType visitJetElement(JetElement element, ExpressionTypingContext data) {
|
||||
public JetTypeInfo visitJetElement(JetElement element, ExpressionTypingContext data) {
|
||||
return element.accept(basic, data);
|
||||
}
|
||||
}
|
||||
|
||||
+35
-34
@@ -33,6 +33,7 @@ import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.jet.lang.types.JetTypeInfo;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||
@@ -78,7 +79,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitObjectDeclaration(JetObjectDeclaration declaration, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitObjectDeclaration(JetObjectDeclaration declaration, ExpressionTypingContext context) {
|
||||
TopDownAnalyzer.processClassOrObject(context.expressionTypingServices.getProject(), context.trace, scope,
|
||||
scope.getContainingDeclaration(), declaration);
|
||||
ClassDescriptor classDescriptor = context.trace.getBindingContext().get(BindingContext.CLASS, declaration);
|
||||
@@ -87,11 +88,11 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
.resolveObjectDeclaration(scope.getContainingDeclaration(), declaration, classDescriptor, context.trace);
|
||||
scope.addVariableDescriptor(variableDescriptor);
|
||||
}
|
||||
return DataFlowUtils.checkStatementType(declaration, context);
|
||||
return DataFlowUtils.checkStatementType(declaration, context, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitProperty(JetProperty property, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitProperty(JetProperty property, ExpressionTypingContext context) {
|
||||
JetTypeReference receiverTypeRef = property.getReceiverTypeRef();
|
||||
if (receiverTypeRef != null) {
|
||||
context.trace.report(LOCAL_EXTENSION_PROPERTY.on(receiverTypeRef));
|
||||
@@ -111,7 +112,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
JetExpression initializer = property.getInitializer();
|
||||
if (property.getPropertyTypeRef() != null && initializer != null) {
|
||||
JetType outType = propertyDescriptor.getType();
|
||||
JetType initializerType = facade.getType(initializer, context.replaceExpectedType(outType).replaceScope(scope));
|
||||
JetType initializerType = facade.getTypeInfo(initializer, context.replaceExpectedType(outType).replaceScope(scope)).getType();
|
||||
}
|
||||
|
||||
{
|
||||
@@ -123,41 +124,41 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
}
|
||||
|
||||
scope.addVariableDescriptor(propertyDescriptor);
|
||||
return DataFlowUtils.checkStatementType(property, context);
|
||||
return DataFlowUtils.checkStatementType(property, context, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitNamedFunction(JetNamedFunction function, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitNamedFunction(JetNamedFunction function, ExpressionTypingContext context) {
|
||||
SimpleFunctionDescriptor functionDescriptor = context.expressionTypingServices.getDescriptorResolver().resolveFunctionDescriptor(scope.getContainingDeclaration(), scope, function, context.trace);
|
||||
scope.addFunctionDescriptor(functionDescriptor);
|
||||
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace);
|
||||
context.expressionTypingServices.checkFunctionReturnType(functionInnerScope, function, functionDescriptor, context.dataFlowInfo, null, context.trace);
|
||||
return DataFlowUtils.checkStatementType(function, context);
|
||||
return DataFlowUtils.checkStatementType(function, context, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitClass(JetClass klass, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitClass(JetClass klass, ExpressionTypingContext context) {
|
||||
TopDownAnalyzer.processClassOrObject(context.expressionTypingServices.getProject(), context.trace, scope,
|
||||
scope.getContainingDeclaration(), klass);
|
||||
ClassDescriptor classDescriptor = context.trace.getBindingContext().get(BindingContext.CLASS, klass);
|
||||
if (classDescriptor != null) {
|
||||
scope.addClassifierDescriptor(classDescriptor);
|
||||
}
|
||||
return DataFlowUtils.checkStatementType(klass, context);
|
||||
return DataFlowUtils.checkStatementType(klass, context, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitTypedef(JetTypedef typedef, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitTypedef(JetTypedef typedef, ExpressionTypingContext context) {
|
||||
return super.visitTypedef(typedef, context); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitDeclaration(JetDeclaration dcl, ExpressionTypingContext context) {
|
||||
return DataFlowUtils.checkStatementType(dcl, context);
|
||||
public JetTypeInfo visitDeclaration(JetDeclaration dcl, ExpressionTypingContext context) {
|
||||
return DataFlowUtils.checkStatementType(dcl, context, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitBinaryExpression(JetBinaryExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitBinaryExpression(JetBinaryExpression expression, ExpressionTypingContext context) {
|
||||
JetSimpleNameExpression operationSign = expression.getOperationReference();
|
||||
IElementType operationType = operationSign.getReferencedNameElementType();
|
||||
JetType result;
|
||||
@@ -168,9 +169,9 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
result = visitAssignmentOperation(expression, context);
|
||||
}
|
||||
else {
|
||||
return facade.getType(expression, context);
|
||||
return facade.getTypeInfo(expression, context);
|
||||
}
|
||||
return DataFlowUtils.checkType(result, expression, context);
|
||||
return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
protected JetType visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
||||
@@ -186,9 +187,9 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
|
||||
if (left == null) return null;
|
||||
|
||||
JetType leftType = facade.getType(left, context);
|
||||
JetType leftType = facade.getTypeInfo(left, context).getType();
|
||||
if (leftType == null) {
|
||||
facade.getType(right, context);
|
||||
facade.getTypeInfo(right, context);
|
||||
context.trace.report(UNRESOLVED_REFERENCE.on(operationSign));
|
||||
temporaryBindingTrace.commit();
|
||||
return null;
|
||||
@@ -216,7 +217,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
for (ResolvedCall<? extends FunctionDescriptor> call : ambiguityResolutionResults.getResultingCalls()) {
|
||||
descriptors.add(call.getResultingDescriptor());
|
||||
}
|
||||
facade.getType(right, context);
|
||||
facade.getTypeInfo(right, context);
|
||||
context.trace.record(AMBIGUOUS_REFERENCE_TARGET, operationSign, descriptors);
|
||||
}
|
||||
else if (assignmentOperationType != null) {
|
||||
@@ -249,9 +250,9 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
basic.checkLValue(context.trace, arrayAccessExpression);
|
||||
return checkAssignmentType(assignmentType, expression, contextWithExpectedType);
|
||||
}
|
||||
JetType leftType = facade.getType(expression.getLeft(), context.replaceScope(scope));
|
||||
JetType leftType = facade.getTypeInfo(expression.getLeft(), context.replaceScope(scope)).getType();
|
||||
if (right != null) {
|
||||
JetType rightType = facade.getType(right, context.replaceExpectedType(leftType).replaceScope(scope));
|
||||
JetType rightType = facade.getTypeInfo(right, context.replaceExpectedType(leftType).replaceScope(scope)).getType();
|
||||
}
|
||||
if (leftType != null) { //if leftType == null, some another error has been generated
|
||||
basic.checkLValue(context.trace, expression.getLeft());
|
||||
@@ -261,59 +262,59 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
|
||||
|
||||
@Override
|
||||
public JetType visitExpression(JetExpression expression, ExpressionTypingContext context) {
|
||||
return facade.getType(expression, context);
|
||||
public JetTypeInfo visitExpression(JetExpression expression, ExpressionTypingContext context) {
|
||||
return facade.getTypeInfo(expression, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitJetElement(JetElement element, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitJetElement(JetElement element, ExpressionTypingContext context) {
|
||||
context.trace.report(UNSUPPORTED.on(element, "in a block"));
|
||||
return null;
|
||||
return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext context) {
|
||||
return controlStructures.visitWhileExpression(expression, context, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext context) {
|
||||
return controlStructures.visitDoWhileExpression(expression, context, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitForExpression(JetForExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitForExpression(JetForExpression expression, ExpressionTypingContext context) {
|
||||
return controlStructures.visitForExpression(expression, context, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitIfExpression(JetIfExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitIfExpression(JetIfExpression expression, ExpressionTypingContext context) {
|
||||
return controlStructures.visitIfExpression(expression, context, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitWhenExpression(final JetWhenExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitWhenExpression(final JetWhenExpression expression, ExpressionTypingContext context) {
|
||||
return patterns.visitWhenExpression(expression, context, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context) {
|
||||
return basic.visitBlockExpression(expression, context, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context) {
|
||||
return basic.visitParenthesizedExpression(expression, context, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context) {
|
||||
return basic.visitUnaryExpression(expression, context, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitIdeTemplateExpression(JetIdeTemplateExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitIdeTemplateExpression(JetIdeTemplateExpression expression, ExpressionTypingContext context) {
|
||||
context.trace.report(UNRESOLVED_IDE_TEMPLATE.on(expression, ObjectUtils.notNull(expression.getText(), "<no name>")));
|
||||
return null;
|
||||
return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
}
|
||||
}
|
||||
|
||||
+25
-12
@@ -52,27 +52,28 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitIsExpression(JetIsExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
||||
public JetTypeInfo visitIsExpression(JetIsExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
||||
JetExpression leftHandSide = expression.getLeftHandSide();
|
||||
JetType knownType = facade.safeGetType(leftHandSide, context.replaceScope(context.scope));
|
||||
JetType knownType = facade.safeGetTypeInfo(leftHandSide, context.replaceScope(context.scope)).getType();
|
||||
JetPattern pattern = expression.getPattern();
|
||||
DataFlowInfo newDataFlowInfo = context.dataFlowInfo;
|
||||
if (pattern != null) {
|
||||
WritableScopeImpl scopeToExtend = newWritableScopeImpl(context, "Scope extended in 'is'");
|
||||
DataFlowValue dataFlowValue = DataFlowValueFactory.INSTANCE.createDataFlowValue(leftHandSide, knownType, context.trace.getBindingContext());
|
||||
DataFlowInfo newDataFlowInfo = checkPatternType(pattern, knownType, false, scopeToExtend, context, dataFlowValue);
|
||||
newDataFlowInfo = checkPatternType(pattern, knownType, false, scopeToExtend, context, dataFlowValue);
|
||||
context.patternsToDataFlowInfo.put(pattern, newDataFlowInfo);
|
||||
context.patternsToBoundVariableLists.put(pattern, scopeToExtend.getDeclaredVariables());
|
||||
}
|
||||
return DataFlowUtils.checkType(JetStandardLibrary.getInstance().getBooleanType(), expression, contextWithExpectedType);
|
||||
return DataFlowUtils.checkType(JetStandardLibrary.getInstance().getBooleanType(), expression, contextWithExpectedType, newDataFlowInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitWhenExpression(final JetWhenExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitWhenExpression(final JetWhenExpression expression, ExpressionTypingContext context) {
|
||||
return visitWhenExpression(expression, context, false);
|
||||
}
|
||||
|
||||
public JetType visitWhenExpression(final JetWhenExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||
public JetTypeInfo visitWhenExpression(final JetWhenExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
||||
// TODO :change scope according to the bound value in the when header
|
||||
final JetExpression subjectExpression = expression.getSubjectExpression();
|
||||
@@ -85,6 +86,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
// TODO : exhaustive patterns
|
||||
|
||||
Set<JetType> expressionTypes = Sets.newHashSet();
|
||||
DataFlowInfo commonDataFlowInfo = null;
|
||||
for (JetWhenEntry whenEntry : expression.getEntries()) {
|
||||
JetWhenCondition[] conditions = whenEntry.getConditions();
|
||||
DataFlowInfo newDataFlowInfo;
|
||||
@@ -122,17 +124,28 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (bodyExpression != null) {
|
||||
ExpressionTypingContext newContext = contextWithExpectedType.replaceScope(scopeToExtend).replaceDataFlowInfo(newDataFlowInfo);
|
||||
CoercionStrategy coercionStrategy = isStatement ? CoercionStrategy.COERCION_TO_UNIT : CoercionStrategy.NO_COERCION;
|
||||
JetType type = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(scopeToExtend, Collections.singletonList(bodyExpression), coercionStrategy, newContext, context.trace);
|
||||
JetTypeInfo typeInfo = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(scopeToExtend, Collections.singletonList(bodyExpression), coercionStrategy, newContext, context.trace);
|
||||
JetType type = typeInfo.getType();
|
||||
if (type != null) {
|
||||
expressionTypes.add(type);
|
||||
}
|
||||
if (commonDataFlowInfo == null) {
|
||||
commonDataFlowInfo = typeInfo.getDataFlowInfo();
|
||||
}
|
||||
else {
|
||||
commonDataFlowInfo = commonDataFlowInfo.or(typeInfo.getDataFlowInfo());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!expressionTypes.isEmpty()) {
|
||||
return DataFlowUtils.checkImplicitCast(CommonSupertypes.commonSupertype(expressionTypes), expression, contextWithExpectedType, isStatement);
|
||||
if (commonDataFlowInfo == null) {
|
||||
commonDataFlowInfo = context.dataFlowInfo;
|
||||
}
|
||||
return null;
|
||||
|
||||
if (!expressionTypes.isEmpty()) {
|
||||
return DataFlowUtils.checkImplicitCast(CommonSupertypes.commonSupertype(expressionTypes), expression, contextWithExpectedType, isStatement, commonDataFlowInfo);
|
||||
}
|
||||
return JetTypeInfo.create(null, commonDataFlowInfo);
|
||||
}
|
||||
|
||||
private DataFlowInfo checkWhenCondition(@Nullable final JetExpression subjectExpression, final boolean expectedCondition, final JetType subjectType, JetWhenCondition condition, final WritableScope scopeToExtend, final ExpressionTypingContext context, final DataFlowValue... subjectVariables) {
|
||||
@@ -145,7 +158,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (rangeExpression == null) return;
|
||||
if (expectedCondition) {
|
||||
context.trace.report(EXPECTED_CONDITION.on(condition));
|
||||
facade.getType(rangeExpression, context);
|
||||
facade.getTypeInfo(rangeExpression, context);
|
||||
return;
|
||||
}
|
||||
if (!facade.checkInExpression(condition, condition.getOperationReference(), subjectExpression, rangeExpression, context)) {
|
||||
@@ -245,7 +258,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
public void visitExpressionPattern(JetExpressionPattern pattern) {
|
||||
JetExpression expression = pattern.getExpression();
|
||||
if (expression == null) return;
|
||||
JetType type = facade.getType(expression, context.replaceScope(scopeToExtend));
|
||||
JetType type = facade.getTypeInfo(expression, context.replaceScope(scopeToExtend)).getType();
|
||||
if (conditionExpected) {
|
||||
JetType booleanType = JetStandardLibrary.getInstance().getBooleanType();
|
||||
if (type != null && !JetTypeChecker.INSTANCE.equalTypes(booleanType, type)) {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
fun bar(x: Int): Int = x + 1
|
||||
|
||||
fun foo() {
|
||||
val x: Int? = null
|
||||
|
||||
if (x != null && bar(x) == 0) bar(bar(x))
|
||||
bar(<!TYPE_MISMATCH!>x<!>)
|
||||
if (x == null || bar(x) == 0) bar(bar(<!TYPE_MISMATCH!>x<!>))
|
||||
bar(<!TYPE_MISMATCH!>x<!>)
|
||||
if (x is Int && bar(x)*bar(x) == bar(x)) bar(x)
|
||||
bar(<!TYPE_MISMATCH!>x<!>)
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fun bar(x: Int): Int = x + 1
|
||||
|
||||
fun foo() {
|
||||
val x: Int? = null
|
||||
val a = Array<Int>(3, {0})
|
||||
|
||||
if (x != null) bar(a[x]) else bar(a<!NO_GET_METHOD!>[<!TYPE_MISMATCH!>x<!>]<!>)
|
||||
bar(a[if (x == null) 0 else x])
|
||||
bar(a<!NO_GET_METHOD!>[<!TYPE_MISMATCH!>x<!>]<!>)
|
||||
|
||||
"123"<!NO_GET_METHOD!>[<!TYPE_MISMATCH!>x<!>]<!>;
|
||||
if (x != null) "123"[x];
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fun bar(x: Int): Int = x + 1
|
||||
|
||||
fun foo() {
|
||||
val x: Int? = null
|
||||
|
||||
bar(1 + (if (x == null) 0 else x))
|
||||
bar(if (x == null) <!TYPE_MISMATCH!>x<!> else x)
|
||||
if (x != null) bar(x + x/(x-x*x))
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
fun bar(x: Int) = x + 1
|
||||
|
||||
fun foo() {
|
||||
val x: Int? = null
|
||||
|
||||
if (x != null) {
|
||||
bar(x)
|
||||
if (x != null) {
|
||||
bar(x)
|
||||
if (1 < 2) bar(x)
|
||||
if (1 > 2) bar(x)
|
||||
}
|
||||
if (x == null) {
|
||||
bar(x)
|
||||
}
|
||||
if (x == null) bar(x) else bar(x)
|
||||
bar(bar(x))
|
||||
} else if (x == null) {
|
||||
bar(<!TYPE_MISMATCH!>x<!>)
|
||||
if (x != null) {
|
||||
bar(x)
|
||||
if (x == null) bar(x)
|
||||
if (x == null) bar(x) else bar(x)
|
||||
bar(bar(x) + bar(x))
|
||||
} else if (x == null) {
|
||||
bar(<!TYPE_MISMATCH!>x<!>)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
fun bar(x: Int): Int = x + 1
|
||||
|
||||
fun foo() {
|
||||
val x: Int? = null
|
||||
|
||||
do {
|
||||
bar(<!TYPE_MISMATCH!>x<!>)
|
||||
} while (x == null)
|
||||
bar(x)
|
||||
|
||||
val y: Int? = null
|
||||
do {
|
||||
bar(<!TYPE_MISMATCH!>y<!>)
|
||||
} while (y != null)
|
||||
bar(<!TYPE_MISMATCH!>y<!>)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fun bar(x: Int): Int = x + 1
|
||||
|
||||
fun foo() {
|
||||
val x: Int? = null
|
||||
|
||||
bar(x ?: 0)
|
||||
if (x != null) bar(x ?: x)
|
||||
bar(<!TYPE_MISMATCH!>x<!>)
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fun bar(x: Int) = x + 1
|
||||
|
||||
fun foo() {
|
||||
val x: Int? = null
|
||||
|
||||
bar(<!TYPE_MISMATCH!>x<!>)
|
||||
if (x != null) bar(x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>)
|
||||
if (x == null) bar(x!!)
|
||||
if (x != null) else bar(x!!)
|
||||
if (x == null) else bar(x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>)
|
||||
if (x != null) bar(x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>) else bar(x!!)
|
||||
if (x == null) bar(x!!) else bar(x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>)
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import java.util.HashMap
|
||||
|
||||
fun bar(x: Int): Int = x + 1
|
||||
|
||||
fun foo() {
|
||||
val x: Int? = null
|
||||
val a = Array<Int>(3, {0})
|
||||
|
||||
for (p in a) {
|
||||
bar(<!TYPE_MISMATCH!>x<!>)
|
||||
if (x == null) continue
|
||||
bar(x)
|
||||
for (q in a) {
|
||||
bar(x)
|
||||
if (x == null) bar(x)
|
||||
}
|
||||
}
|
||||
|
||||
for (p in a) {
|
||||
bar(<!TYPE_MISMATCH!>x<!>)
|
||||
if (x == null) break
|
||||
bar(x)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fun bar(x: Int) = x + 1
|
||||
|
||||
fun foo() {
|
||||
val x: Int? = null
|
||||
|
||||
fun baz() = bar(<!TYPE_MISMATCH!>x<!>)
|
||||
fun quux() = if (x != null) bar(x) else baz()
|
||||
fun quuux() = bar(if (x == null) 0 else x)
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
fun bar(x: Int): Int = x + 1
|
||||
|
||||
fun foo() {
|
||||
val x: Int? = null
|
||||
|
||||
bar(if (x == null) 0 else x)
|
||||
|
||||
if (x == null) {
|
||||
bar(<!TYPE_MISMATCH!>x<!>)
|
||||
return
|
||||
} else {
|
||||
bar(x)
|
||||
}
|
||||
bar(x)
|
||||
|
||||
val y: Int? = null
|
||||
if (y is Int) {
|
||||
bar(y)
|
||||
} else {
|
||||
bar(<!TYPE_MISMATCH!>y<!>)
|
||||
return
|
||||
}
|
||||
bar(y)
|
||||
|
||||
val z: Int? = null
|
||||
if (z != null) bar(z)
|
||||
bar(<!TYPE_MISMATCH!>z<!>)
|
||||
bar(z!!)
|
||||
if (z != null) bar(z<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
fun bar(x: Int): Int = x + 1
|
||||
|
||||
fun foo() {
|
||||
val x: Int? = null
|
||||
|
||||
bar(<!TYPE_MISMATCH!>x<!>)
|
||||
if (x != 2) {
|
||||
if (x == null) return
|
||||
2+<!SYNTAX!><!>
|
||||
}
|
||||
else {
|
||||
if (x == null) return
|
||||
2+<!SYNTAX!><!>
|
||||
}
|
||||
bar(x)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fun bar(x: Int): Int = x + 1
|
||||
|
||||
fun foo() {
|
||||
val x: Int? = null
|
||||
|
||||
val <!UNUSED_VARIABLE!>a<!> = object {
|
||||
fun baz() = bar(if (x == null) 0 else x)
|
||||
fun quux(): Int = if (x == null) <!TYPE_MISMATCH!>x<!> else x
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fun baz(x: Int): Int = x + 1
|
||||
|
||||
class A {
|
||||
fun bar(x: Int) = baz(x)
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
val x: Int? = null
|
||||
|
||||
A().bar(<!TYPE_MISMATCH!>x<!>)
|
||||
if (x == null) return
|
||||
A().bar(x)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fun bar(x: Int): Int = x + 1
|
||||
|
||||
fun foo(): Int {
|
||||
val x: Int? = null
|
||||
|
||||
bar(<!TYPE_MISMATCH!>x<!>)
|
||||
if (x != null) return x
|
||||
if (x == null) return if (x != null) x else <!TYPE_MISMATCH!>x<!>
|
||||
if (x == null) return x
|
||||
if (x != null) return if (x == null) x else x
|
||||
return x
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
open class Base {
|
||||
fun bar(x: Int): Int = x + 1
|
||||
}
|
||||
|
||||
class Derived : Base() {
|
||||
fun baz(x: Int): Int = x + 1
|
||||
|
||||
fun foo() {
|
||||
val x: Int? = null
|
||||
|
||||
super.bar(<!TYPE_MISMATCH!>x<!>)
|
||||
this.baz(<!TYPE_MISMATCH!>x<!>)
|
||||
if (x == null) return
|
||||
super.bar(x)
|
||||
this.baz(x)
|
||||
|
||||
val y: Int? = null
|
||||
if (y != null) super.bar(this.baz(y))
|
||||
else this.baz(super.bar(<!TYPE_MISMATCH!>y<!>))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fun bar(x: Int): RuntimeException = RuntimeException(x.toString())
|
||||
|
||||
fun foo() {
|
||||
val x: Int? = null
|
||||
|
||||
if (x == null || 1 < 2) throw bar(<!TYPE_MISMATCH!>x<!>)
|
||||
if (x == null) return
|
||||
throw bar(x)
|
||||
throw <!UNREACHABLE_CODE!>bar(x)<!>
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
fun bar(x: Int): Int = x + 1
|
||||
|
||||
fun foo() {
|
||||
val x: Int? = null
|
||||
|
||||
bar(<!TYPE_MISMATCH!>x<!>)
|
||||
if (x == null) return
|
||||
try {
|
||||
bar(x)
|
||||
}
|
||||
catch (e: Exception) {
|
||||
bar(x)
|
||||
}
|
||||
bar(x)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
fun bar(x: Int): Int = x + 1
|
||||
fun baz(b: Boolean): Boolean = !b
|
||||
|
||||
fun foo() {
|
||||
val x: Int? = null
|
||||
|
||||
bar(<!UNSAFE_CALL!>-<!>x)
|
||||
if (x != null) bar(-x)
|
||||
bar(<!UNSAFE_CALL!>-<!>x)
|
||||
|
||||
val b: Boolean? = null
|
||||
baz(<!UNSAFE_CALL!>!<!>b)
|
||||
if (b != null) baz(!b)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fun bar(x: Int): Int = x + 1
|
||||
|
||||
fun foo() {
|
||||
val x: Int? = null
|
||||
|
||||
if (x != null) {
|
||||
when (x) {
|
||||
0 -> bar(x)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
when (x) {
|
||||
0 -> { if (x == null) return }
|
||||
else -> { if (x == null) return }
|
||||
}
|
||||
bar(x)
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
fun bar(x: Int): Int = x + 1
|
||||
|
||||
fun foo() {
|
||||
val x: Int? = null
|
||||
while (x == null) {
|
||||
bar(<!TYPE_MISMATCH!>x<!>)
|
||||
}
|
||||
bar(x)
|
||||
|
||||
val y: Int? = null
|
||||
while (y != null) {
|
||||
bar(y)
|
||||
}
|
||||
bar(<!TYPE_MISMATCH!>y<!>)
|
||||
|
||||
val z: Int? = null
|
||||
while (z == null) {
|
||||
bar(<!TYPE_MISMATCH!>z<!>)
|
||||
break
|
||||
}
|
||||
bar(<!TYPE_MISMATCH!>z<!>)
|
||||
}
|
||||
Reference in New Issue
Block a user