Stop using getReadType() in nnbd_migration.
The packages 'analyzer' and 'nnbd_migration' tightly depend on each
other via MigrationResolutionHooks. I will publish analyzer 0.40.4
shortly after this CL lands.
Change-Id: I6f5e51f88e0020a1674ffb251712658e896170e7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164900
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
diff --git a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
index 59d39ff..6fd621d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
@@ -67,6 +67,8 @@
_resolver.setReadElement(left, readElement);
}
_resolver.setWriteElement(left, writeElement);
+ _resolver.migrationResolutionHooks
+ ?.setCompoundAssignmentExpressionTypes(node);
_resolver.setAssignmentBackwardCompatibility(
assignment: node,
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 c5a5ea2..dbc01c0 100644
--- a/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
@@ -62,6 +62,8 @@
var operand = node.operand;
_resolver.setReadElement(operand, readElement);
_resolver.setWriteElement(operand, writeElement);
+ _resolver.migrationResolutionHooks
+ ?.setCompoundAssignmentExpressionTypes(node);
_resolver.setAssignmentBackwardCompatibility(
assignment: node,
@@ -82,8 +84,8 @@
///
/// TODO(scheglov) this is duplicate
void _checkForInvalidAssignmentIncDec(
- AstNode node, Expression operand, DartType type) {
- var operandWriteType = _getWriteType(operand);
+ PostfixExpression node, Expression operand, DartType type) {
+ var operandWriteType = node.writeType;
if (!_typeSystem.isAssignableTo2(type, operandWriteType)) {
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.INVALID_ASSIGNMENT,
@@ -129,16 +131,6 @@
}
}
- DartType _getWriteType(Expression node) {
- if (node is SimpleIdentifier) {
- var element = node.staticElement;
- if (element is PromotableElement) {
- return element.type;
- }
- }
- return node.staticType;
- }
-
void _resolve1(PostfixExpression node, DartType receiverType) {
Expression operand = node.operand;
diff --git a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
index d16861a..c3c161a 100644
--- a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
@@ -65,6 +65,8 @@
var operand = node.operand;
_resolver.setReadElement(operand, readElement);
_resolver.setWriteElement(operand, writeElement);
+ _resolver.migrationResolutionHooks
+ ?.setCompoundAssignmentExpressionTypes(node);
_resolver.setAssignmentBackwardCompatibility(
assignment: node,
diff --git a/pkg/analyzer/lib/src/generated/migration.dart b/pkg/analyzer/lib/src/generated/migration.dart
index 8ea9925..93d82cc 100644
--- a/pkg/analyzer/lib/src/generated/migration.dart
+++ b/pkg/analyzer/lib/src/generated/migration.dart
@@ -31,6 +31,10 @@
DartType modifyInferredParameterType(
ParameterElement parameter, DartType type);
+ /// Called after the resolver has determined the read and write types
+ /// of the assignment expression.
+ void setCompoundAssignmentExpressionTypes(CompoundAssignmentExpression node);
+
/// Called when the resolver starts or stops making use of a [FlowAnalysis]
/// instance.
void setFlowAnalysis(
diff --git a/pkg/nnbd_migration/lib/src/fix_builder.dart b/pkg/nnbd_migration/lib/src/fix_builder.dart
index ff2d412..9e5e486 100644
--- a/pkg/nnbd_migration/lib/src/fix_builder.dart
+++ b/pkg/nnbd_migration/lib/src/fix_builder.dart
@@ -26,7 +26,6 @@
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:analyzer/src/task/strong/checker.dart';
import 'package:nnbd_migration/fix_reason_target.dart';
import 'package:nnbd_migration/instrumentation.dart';
import 'package:nnbd_migration/nnbd_migration.dart';
@@ -471,20 +470,18 @@
_wrapExceptions(node, () => type, () {
var parent = node.parent;
if (parent is AssignmentExpression) {
- return (_assignmentLikeExpressionHandlers[parent] ??=
- _AssignmentExpressionHandler(parent))
- .modifySubexpressionType(this, node, type);
+ if (parent.leftHandSide == node) {
+ return type;
+ }
+ return _assignmentLikeExpressionHandlers[parent]
+ .modifyAssignmentRhs(this, node, type);
} else if (parent is PrefixExpression) {
if (_isIncrementOrDecrementOperator(parent.operator.type)) {
- return (_assignmentLikeExpressionHandlers[parent] ??=
- _PrefixExpressionHandler(parent))
- .modifySubexpressionType(this, node, type);
+ return type;
}
} else if (parent is PostfixExpression) {
if (_isIncrementOrDecrementOperator(parent.operator.type)) {
- return (_assignmentLikeExpressionHandlers[parent] ??=
- _PostfixExpressionHandler(parent))
- .modifySubexpressionType(this, node, type);
+ return type;
}
}
return _modifyRValueType(node, type);
@@ -503,6 +500,30 @@
}
@override
+ void setCompoundAssignmentExpressionTypes(CompoundAssignmentExpression node) {
+ assert(_assignmentLikeExpressionHandlers[node] == null);
+ if (node is AssignmentExpression) {
+ var handler = _AssignmentExpressionHandler(node);
+ _assignmentLikeExpressionHandlers[node] = handler;
+ handler.handleLValueType(this, node.readType, node.writeType);
+ } else if (node is PrefixExpression) {
+ assert(_isIncrementOrDecrementOperator(node.operator.type));
+ var handler = _PrefixExpressionHandler(node);
+ _assignmentLikeExpressionHandlers[node] = handler;
+ handler.handleLValueType(this, node.readType, node.writeType);
+ handler.handleAssignmentRhs(this, _fixBuilder.typeProvider.intType);
+ } else if (node is PostfixExpression) {
+ assert(_isIncrementOrDecrementOperator(node.operator.type));
+ var handler = _PostfixExpressionHandler(node);
+ _assignmentLikeExpressionHandlers[node] = handler;
+ handler.handleLValueType(this, node.readType, node.writeType);
+ handler.handleAssignmentRhs(this, _fixBuilder.typeProvider.intType);
+ } else {
+ throw StateError('(${node.runtimeType}) $node');
+ }
+ }
+
+ @override
void setFlowAnalysis(
FlowAnalysis<AstNode, Statement, Expression, PromotableElement, DartType>
flowAnalysis) {
@@ -765,37 +786,21 @@
/// [writeType], and [rhsContextType]. Also verifies that for compound
/// assignments, the [readType] is non-nullable, and that for null-aware
/// assignments, the [readType] is nullable.
- void handleLValueType(
- MigrationResolutionHooksImpl hooks, DartType resolvedType) {
- assert(resolvedType.nullabilitySuffix != NullabilitySuffix.star);
- // Provisionally store the resolved type as the type of the target, so that
- // getReadType can fall back on it if necessary.
- var target = this.target;
- target.staticType = resolvedType;
- // The type passed in by the resolver for the LHS of an assignment is the
- // "write type".
- var writeType = resolvedType;
- if (target is SimpleIdentifier) {
- var element = target.staticElement;
- if (element is PromotableElement) {
- // However, if the LHS is a reference to a local variable that has
- // been promoted, the resolver passes in the promoted type. We
- // want to use the variable element's type, so that we consider it
- // ok to assign a value to the variable that un-does the
- // promotion. See https://github.com/dart-lang/sdk/issues/41411.
- writeType = element.type;
- }
- }
- assert(writeType.nullabilitySuffix != NullabilitySuffix.star);
- this.writeType = writeType;
+ void handleLValueType(MigrationResolutionHooksImpl hooks,
+ DartType readTypeToSet, DartType writeTypeToSet) {
+ assert(writeTypeToSet.nullabilitySuffix != NullabilitySuffix.star);
+ writeType = writeTypeToSet;
+ // TODO(scheglov) Remove this after the analyzer breaking change that
+ // will top setting types for LHS.
+ target.staticType = writeTypeToSet;
var fixBuilder = hooks._fixBuilder;
if (combinerType == TokenType.EQ) {
- rhsContextType = writeType;
+ rhsContextType = writeTypeToSet;
} else {
- readType = getReadType(target);
+ readType = readTypeToSet;
assert(readType.nullabilitySuffix != NullabilitySuffix.star);
if (combinerType == TokenType.QUESTION_QUESTION_EQ) {
- rhsContextType = writeType;
+ rhsContextType = writeTypeToSet;
if (fixBuilder._typeSystem.isNonNullable(readType)) {
(fixBuilder._getChange(node) as NodeChangeForAssignment)
.isWeakNullAware = true;
@@ -810,26 +815,13 @@
}
}
- /// Called after visiting the LHS or the RHS of the assignment.
- DartType modifySubexpressionType(MigrationResolutionHooksImpl hooks,
+ /// Called after visiting the RHS of the assignment.
+ DartType modifyAssignmentRhs(MigrationResolutionHooksImpl hooks,
Expression subexpression, DartType type) {
- if (identical(subexpression, target)) {
- handleLValueType(hooks, type);
- if (node is! AssignmentExpression) {
- // Must be a pre or post increment/decrement, so the "RHS" is implicitly
- // the integer 1.
- handleAssignmentRhs(hooks, hooks._fixBuilder.typeProvider.intType);
- }
- return type;
- } else {
- var node = this.node;
- assert(node is AssignmentExpression &&
- identical(subexpression, node.rightHandSide));
- type =
- hooks._modifyRValueType(subexpression, type, context: rhsContextType);
- handleAssignmentRhs(hooks, type);
- return type;
- }
+ type =
+ hooks._modifyRValueType(subexpression, type, context: rhsContextType);
+ handleAssignmentRhs(hooks, type);
+ return type;
}
}
diff --git a/pkg/nnbd_migration/pubspec.yaml b/pkg/nnbd_migration/pubspec.yaml
index 0ee45b0..ac8b395 100644
--- a/pkg/nnbd_migration/pubspec.yaml
+++ b/pkg/nnbd_migration/pubspec.yaml
@@ -6,7 +6,7 @@
sdk: '>=2.6.0 <3.0.0'
dependencies:
_fe_analyzer_shared: ^4.0.0
- analyzer: ^0.40.1
+ analyzer: ^0.40.4
analyzer_plugin: ^0.2.4
args: ^1.4.4
charcode: ^1.1.2
diff --git a/pkg/nnbd_migration/test/fix_builder_test.dart b/pkg/nnbd_migration/test/fix_builder_test.dart
index 010f005..4e3e6e9 100644
--- a/pkg/nnbd_migration/test/fix_builder_test.dart
+++ b/pkg/nnbd_migration/test/fix_builder_test.dart
@@ -3,13 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/error/hint_codes.dart';
import 'package:analyzer/src/generated/element_type_provider.dart';
-import 'package:analyzer/src/task/strong/checker.dart';
import 'package:nnbd_migration/fix_reason_target.dart';
import 'package:nnbd_migration/nnbd_migration.dart';
import 'package:nnbd_migration/src/edit_plan.dart';
@@ -3364,10 +3362,8 @@
identical(ElementTypeProvider.current, const ElementTypeProvider()));
ElementTypeProvider.current = fixBuilder.migrationResolutionHooks;
var assignment = node.thisOrAncestorOfType<AssignmentExpression>();
- var isReadWrite = assignment.operator.type != TokenType.EQ;
- var readType =
- isReadWrite ? getReadType(node) ?? typeProvider.dynamicType : null;
- var writeType = node.staticType;
+ var readType = assignment.readType;
+ var writeType = assignment.writeType;
return AssignmentTargetInfo(readType, writeType);
} finally {
ElementTypeProvider.current = const ElementTypeProvider();