Deprecate getReadType() and remove getExpressionType().
Change-Id: Ibc32afd7867f5b0f940affdaea97904c1afb194c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164361
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
index 489aa70..e16e7da 100644
--- a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
@@ -18,7 +18,6 @@
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/type_promotion_manager.dart';
-import 'package:analyzer/src/task/strong/checker.dart';
import 'package:meta/meta.dart';
/// Helper for resolving [BinaryExpression]s.
@@ -107,26 +106,12 @@
);
}
- /// Gets the definite type of expression, which can be used in cases where
- /// the most precise type is desired, for example computing the least upper
- /// bound.
- ///
- /// See [getExpressionType] for more information. Without strong mode, this is
- /// equivalent to [_getStaticType].
- ///
- /// TODO(scheglov) this is duplicate
- DartType _getExpressionType(Expression expr, {bool read = false}) =>
- getExpressionType(expr, _typeSystem, _typeProvider, read: read);
-
/// Return the static type of the given [expression] that is to be used for
/// type analysis.
///
/// TODO(scheglov) this is duplicate
- DartType _getStaticType(Expression expression, {bool read = false}) {
- if (expression is NullLiteral) {
- return _typeProvider.nullType;
- }
- DartType type = read ? getReadType(expression) : expression.staticType;
+ DartType _getStaticType(Expression expression) {
+ DartType type = expression.staticType;
return _resolveTypeParameter(type);
}
@@ -170,7 +155,7 @@
left.accept(_resolver);
left = node.leftOperand;
- var leftType = _getExpressionType(left, read: false);
+ var leftType = left.staticType;
var rightContextType = InferenceContext.getContext(node);
if (rightContextType == null || rightContextType.isDynamic) {
@@ -183,9 +168,7 @@
right = node.rightOperand;
flow?.ifNullExpression_end();
- // TODO(scheglov) This (and above) is absolutely wrong, and convoluted.
- // This is just the status quo, until we can make types straight.
- var rightType = _getExpressionType(right, read: false);
+ var rightType = right.staticType;
if (_isNonNullableByDefault) {
var promotedLeftType = _typeSystem.promoteToNonNull(leftType);
_analyzeLeastUpperBoundTypes(node, promotedLeftType, rightType);
diff --git a/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
index 75d46e2..30df9bf 100644
--- a/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
@@ -17,7 +17,6 @@
import 'package:analyzer/src/dart/resolver/type_property_resolver.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/task/strong/checker.dart';
import 'package:meta/meta.dart';
/// Helper for resolving [PostfixExpression]s.
@@ -228,7 +227,7 @@
operand.accept(_resolver);
operand = node.operand;
- var operandType = getReadType(operand);
+ var operandType = operand.staticType;
var type = _typeSystem.promoteToNonNull(operandType);
_inferenceHelper.recordStaticType(node, type);
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 55a6235e..9955b67 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -40,7 +40,6 @@
import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
import 'package:analyzer/src/generated/sdk.dart' show DartSdk, SdkLibrary;
import 'package:analyzer/src/generated/this_access_tracker.dart';
-import 'package:analyzer/src/task/strong/checker.dart';
import 'package:meta/meta.dart';
class EnclosingExecutableContext {
@@ -319,8 +318,7 @@
_checkForArgumentTypeNotAssignableForArgument(rhs);
}
if (operatorType == TokenType.QUESTION_QUESTION_EQ) {
- _checkForDeadNullCoalesce(
- getReadType(node.leftHandSide), node.rightHandSide);
+ _checkForDeadNullCoalesce(node.readType, node.rightHandSide);
}
_checkForAssignmentToFinal(lhs);
super.visitAssignmentExpression(node);
@@ -355,8 +353,7 @@
}
if (type == TokenType.QUESTION_QUESTION) {
- _checkForDeadNullCoalesce(
- getReadType(node.leftOperand), node.rightOperand);
+ _checkForDeadNullCoalesce(node.leftOperand.staticType, node.rightOperand);
}
_checkForUseOfVoidResult(node.leftOperand);
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index ecee766..a06752f 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -16,8 +16,6 @@
import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
import 'package:analyzer/src/generated/migration.dart';
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/task/strong/checker.dart'
- show getExpressionType, getReadType;
/// Instances of the class `StaticTypeAnalyzer` perform two type-related tasks. First, they
/// compute the static type of every expression. Second, they look for any static type errors or
@@ -344,10 +342,9 @@
/// Set the static type of [node] to be the least upper bound of the static
/// types of subexpressions [expr1] and [expr2].
void _analyzeLeastUpperBound(
- Expression node, Expression expr1, Expression expr2,
- {bool read = false}) {
- DartType staticType1 = _getExpressionType(expr1, read: read);
- DartType staticType2 = _getExpressionType(expr2, read: read);
+ Expression node, Expression expr1, Expression expr2) {
+ DartType staticType1 = expr1.staticType;
+ DartType staticType2 = expr2.staticType;
_analyzeLeastUpperBoundTypes(node, staticType1, staticType2);
}
@@ -371,20 +368,11 @@
recordStaticType(node, staticType);
}
- /// Gets the definite type of expression, which can be used in cases where
- /// the most precise type is desired, for example computing the least upper
- /// bound.
- ///
- /// See [getExpressionType] for more information. Without strong mode, this is
- /// equivalent to [_getStaticType].
- DartType _getExpressionType(Expression expr, {bool read = false}) =>
- getExpressionType(expr, _typeSystem, _typeProvider, read: read);
-
/// Return the static type of the given [expression].
DartType _getStaticType(Expression expression, {bool read = false}) {
DartType type;
if (read) {
- type = getReadType(expression);
+ type = expression.staticType;
} else {
if (expression is SimpleIdentifier && expression.inSetterContext()) {
var element = expression.staticElement;
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 4e67d44..e3049ad 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -20,22 +20,9 @@
import 'package:analyzer/src/error/codes.dart'
show CompileTimeErrorCode, StrongModeCode;
import 'package:analyzer/src/summary/idl.dart';
+import 'package:meta/meta.dart';
-/// Given an [expression] and a corresponding [typeSystem] and [typeProvider],
-/// gets the known static type of the expression.
-DartType getExpressionType(
- Expression expression, TypeSystemImpl typeSystem, TypeProvider typeProvider,
- {bool read = false}) {
- DartType type;
- if (read) {
- type = getReadType(expression);
- } else {
- type = expression.staticType;
- }
- type ??= DynamicTypeImpl.instance;
- return type;
-}
-
+@Deprecated('Use CompoundAssignmentExpression.readType')
DartType getReadType(Expression expression) {
if (expression is IndexExpression) {
var aux = expression.auxiliaryElements;
@@ -148,8 +135,8 @@
}
}
- void checkAssignment(Expression expr, DartType type) {
- checkForCast(expr, type);
+ void checkAssignment(Expression expr, DartType to) {
+ checkForCast(expr, from: expr.staticType, to: to);
}
/// Analyzer checks boolean conversions, but we need to check too, because
@@ -176,20 +163,26 @@
var exprType = element.expression.staticType;
var asIterableType = exprType.asInstanceOf(typeProvider.iterableElement);
- var elementType =
- asIterableType == null ? null : asIterableType.typeArguments[0];
- // Items in the spread will then potentially be downcast to the expected
- // type.
- _checkImplicitCast(element.expression, expectedType,
- from: elementType, forSpread: true);
+
+ if (asIterableType != null) {
+ var elementType = asIterableType.typeArguments[0];
+ // Items in the spread will then potentially be downcast to the expected
+ // type.
+ _checkImplicitCast(element.expression,
+ to: expectedType, from: elementType, forSpread: true);
+ }
}
}
- void checkForCast(Expression expr, DartType type) {
+ void checkForCast(
+ Expression expr, {
+ @required DartType from,
+ @required DartType to,
+ }) {
if (expr is ParenthesizedExpression) {
- checkForCast(expr.expression, type);
+ checkForCast(expr.expression, from: from, to: to);
} else {
- _checkImplicitCast(expr, type);
+ _checkImplicitCast(expr, from: from, to: to);
}
}
@@ -214,16 +207,18 @@
var exprType = element.expression.staticType;
var asMapType = exprType.asInstanceOf(typeProvider.mapElement);
- var elementKeyType =
- asMapType == null ? null : asMapType.typeArguments[0];
- var elementValueType =
- asMapType == null ? null : asMapType.typeArguments[1];
- // Keys and values in the spread will then potentially be downcast to
- // the expected types.
- _checkImplicitCast(element.expression, expectedKeyType,
- from: elementKeyType, forSpreadKey: true);
- _checkImplicitCast(element.expression, expectedValueType,
- from: elementValueType, forSpreadValue: true);
+ if (asMapType != null) {
+ var elementKeyType = asMapType.typeArguments[0];
+ var elementValueType = asMapType.typeArguments[1];
+ // Keys and values in the spread will then potentially be downcast to
+ // the expected types.
+ _checkImplicitCast(element.expression,
+ to: expectedKeyType, from: elementKeyType, forSpreadKey: true);
+ _checkImplicitCast(element.expression,
+ to: expectedValueType,
+ from: elementValueType,
+ forSpreadValue: true);
+ }
}
}
@@ -241,16 +236,17 @@
@override
void visitAssignmentExpression(AssignmentExpression node) {
+ var left = node.leftHandSide;
+ var right = node.rightHandSide;
Token operator = node.operator;
TokenType operatorType = operator.type;
if (operatorType == TokenType.EQ ||
operatorType == TokenType.QUESTION_QUESTION_EQ) {
- DartType staticType = _getExpressionType(node.leftHandSide);
- checkAssignment(node.rightHandSide, staticType);
+ checkForCast(right, from: right.staticType, to: node.writeType);
} else if (operatorType == TokenType.AMPERSAND_AMPERSAND_EQ ||
operatorType == TokenType.BAR_BAR_EQ) {
- checkAssignment(node.leftHandSide, typeProvider.boolType);
- checkAssignment(node.rightHandSide, typeProvider.boolType);
+ checkBoolean(left);
+ checkBoolean(right);
} else {
_checkCompoundAssignment(node);
}
@@ -457,7 +453,8 @@
@override
void visitPostfixExpression(PostfixExpression node) {
- _checkUnary(node.operand, node.operator, node.staticElement);
+ _checkUnary(node.operand, node.operator, node.staticElement,
+ readType: node.readType, writeType: node.writeType);
node.visitChildren(this);
}
@@ -466,7 +463,8 @@
if (node.operator.type == TokenType.BANG) {
checkBoolean(node.operand);
} else {
- _checkUnary(node.operand, node.operator, node.staticElement);
+ _checkUnary(node.operand, node.operator, node.staticElement,
+ readType: node.readType, writeType: node.writeType);
}
node.visitChildren(this);
}
@@ -588,7 +586,8 @@
for (VariableDeclaration variable in node.variables) {
var initializer = variable.initializer;
if (initializer != null) {
- checkForCast(initializer, type.type);
+ checkForCast(initializer,
+ from: initializer.staticType, to: type.type);
}
}
}
@@ -622,10 +621,9 @@
assert(functionType.optionalParameterTypes.isEmpty);
// Refine the return type.
- var rhsType = _getExpressionType(expr.rightHandSide);
- var lhsType = _getExpressionType(expr.leftHandSide);
+ var rhsType = expr.rightHandSide.staticType;
var returnType = rules.refineBinaryExpressionType(
- lhsType,
+ expr.readType,
op,
rhsType,
functionType.returnType,
@@ -633,7 +631,7 @@
);
// Check the argument for an implicit cast.
- _checkImplicitCast(expr.rightHandSide, paramTypes[0], from: rhsType);
+ _checkImplicitCast(expr.rightHandSide, to: paramTypes[0], from: rhsType);
// Check the return type for an implicit cast.
//
@@ -643,8 +641,8 @@
// y = /*implicit cast*/(y + 42);
// /*implicit assignment cast*/y += 42;
//
- _checkImplicitCast(expr.leftHandSide, lhsType,
- from: returnType, opAssign: true);
+ _checkImplicitCast(expr.leftHandSide,
+ to: expr.writeType, from: returnType, opAssign: true);
}
}
@@ -694,8 +692,9 @@
///
/// If [expr] does not require an implicit cast because it is not related to
/// [to] or is already a subtype of it, does nothing.
- void _checkImplicitCast(Expression expr, DartType to,
- {DartType from,
+ void _checkImplicitCast(Expression expr,
+ {@required DartType to,
+ @required DartType from,
bool opAssign = false,
bool forSpread = false,
bool forSpreadKey = false,
@@ -704,9 +703,7 @@
return;
}
- from ??= _getExpressionType(expr);
-
- if (_needsImplicitCast(expr, to, from: from) == true) {
+ if (_needsImplicitCast(expr, to: to, from: from) == true) {
_recordImplicitCast(expr, to,
from: from,
opAssign: opAssign,
@@ -730,7 +727,8 @@
if (expression != null) checkAssignment(expression, type);
}
- void _checkUnary(Expression operand, Token op, MethodElement element) {
+ void _checkUnary(Expression operand, Token op, MethodElement element,
+ {@required DartType readType, @required DartType writeType}) {
bool isIncrementAssign = op.type.isIncrementOperator;
if (op.isUserDefinableOperator || isIncrementAssign) {
if (element != null && isIncrementAssign) {
@@ -744,9 +742,8 @@
// Refine the return type.
var functionType = element.type;
var rhsType = typeProvider.intType;
- var lhsType = _getExpressionType(operand);
var returnType = rules.refineBinaryExpressionType(
- lhsType,
+ readType,
TokenType.PLUS,
rhsType,
functionType.returnType,
@@ -763,7 +760,8 @@
// y = /*implicit cast*/(y + 1);
// /*implicit assignment cast*/y++;
//
- _checkImplicitCast(operand, lhsType, from: returnType, opAssign: true);
+ _checkImplicitCast(operand,
+ to: writeType, from: returnType, opAssign: true);
}
}
}
@@ -827,9 +825,6 @@
}
}
- DartType _getExpressionType(Expression expr) =>
- getExpressionType(expr, rules, typeProvider);
-
DartType _getInstanceTypeArgument(
DartType expressionType, ClassElement instanceType) {
var asInstanceType = expressionType.asInstanceOf(instanceType);
@@ -860,9 +855,8 @@
/// downcast implicitly).
///
/// If [from] is omitted, uses the static type of [expr]
- bool _needsImplicitCast(Expression expr, DartType to, {DartType from}) {
- from ??= _getExpressionType(expr);
-
+ bool _needsImplicitCast(Expression expr,
+ {@required DartType from, @required DartType to}) {
// Void is considered Top, but may only be *explicitly* cast.
if (from.isVoid) return null;
@@ -886,8 +880,8 @@
if (to.isDartAsyncFutureOr) {
var to1 = (to as InterfaceType).typeArguments[0];
var to2 = typeProvider.futureType2(to1);
- return _needsImplicitCast(expr, to1, from: from) == true ||
- _needsImplicitCast(expr, to2, from: from) == true;
+ return _needsImplicitCast(expr, to: to1, from: from) == true ||
+ _needsImplicitCast(expr, to: to2, from: from) == true;
}
// Anything else is an illegal sideways cast.
@@ -1021,7 +1015,7 @@
var sequenceElement = awaitKeyword != null
? typeProvider.streamElement
: typeProvider.iterableElement;
- var iterableType = _getExpressionType(node.iterable);
+ var iterableType = node.iterable.staticType;
var elementType = _getInstanceTypeArgument(iterableType, sequenceElement);
// If the sequence is not an Iterable (or Stream for await for) but is a
@@ -1043,8 +1037,8 @@
if (elementType != null) {
// Insert a cast from the sequence's element type to the loop variable's
// if needed.
- _checkImplicitCast(loopVariable, loopVariableElement.type,
- from: elementType);
+ _checkImplicitCast(loopVariable,
+ to: loopVariableElement.type, from: elementType);
}
}
}
diff --git a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
index 0c06671..155270f 100644
--- a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
@@ -466,21 +466,14 @@
}
test_notLValue_postfixIncrement_compound_ifNull() async {
- await assertErrorsInCode(
- '''
+ await assertErrorsInCode('''
void f(num x, int y) {
x++ ??= y;
}
-''',
- expectedErrorsByNullability(nullable: [
- error(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 25, 3),
- error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 25, 3),
- error(StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION, 33, 1),
- ], legacy: [
- error(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 25, 3),
- error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 25, 3),
- ]),
- );
+''', [
+ error(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 25, 3),
+ error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 25, 3),
+ ]);
assertAssignment(
findNode.assignment('= y'),
@@ -557,21 +550,14 @@
}
test_notLValue_prefixIncrement_compound_ifNull() async {
- await assertErrorsInCode(
- '''
+ await assertErrorsInCode('''
void f(num x, int y) {
++x ??= y;
}
-''',
- expectedErrorsByNullability(nullable: [
- error(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 25, 3),
- error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 25, 3),
- error(StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION, 33, 1),
- ], legacy: [
- error(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 25, 3),
- error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 25, 3),
- ]),
- );
+''', [
+ error(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 25, 3),
+ error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 25, 3),
+ ]);
assertAssignment(
findNode.assignment('= y'),