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>
This commit is contained in:
Konstantin Shcheglov 2020-09-29 17:18:25 +00:00
parent e8683d25ed
commit 8de1bc0a07
7 changed files with 62 additions and 74 deletions

View file

@ -67,6 +67,8 @@ class AssignmentExpressionResolver {
_resolver.setReadElement(left, readElement);
}
_resolver.setWriteElement(left, writeElement);
_resolver.migrationResolutionHooks
?.setCompoundAssignmentExpressionTypes(node);
_resolver.setAssignmentBackwardCompatibility(
assignment: node,

View file

@ -62,6 +62,8 @@ class PostfixExpressionResolver {
var operand = node.operand;
_resolver.setReadElement(operand, readElement);
_resolver.setWriteElement(operand, writeElement);
_resolver.migrationResolutionHooks
?.setCompoundAssignmentExpressionTypes(node);
_resolver.setAssignmentBackwardCompatibility(
assignment: node,
@ -82,8 +84,8 @@ class PostfixExpressionResolver {
///
/// 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 @@ class PostfixExpressionResolver {
}
}
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;

View file

@ -65,6 +65,8 @@ class PrefixExpressionResolver {
var operand = node.operand;
_resolver.setReadElement(operand, readElement);
_resolver.setWriteElement(operand, writeElement);
_resolver.migrationResolutionHooks
?.setCompoundAssignmentExpressionTypes(node);
_resolver.setAssignmentBackwardCompatibility(
assignment: node,

View file

@ -31,6 +31,10 @@ abstract class MigrationResolutionHooks
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(

View file

@ -26,7 +26,6 @@ import 'package:analyzer/src/generated/migration.dart';
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 @@ class MigrationResolutionHooksImpl
_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);
@ -502,6 +499,30 @@ class MigrationResolutionHooksImpl
return type;
}
@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>
@ -765,37 +786,21 @@ abstract class _AssignmentLikeExpressionHandler {
/// [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 @@ abstract class _AssignmentLikeExpressionHandler {
}
}
/// 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;
}
}

View file

@ -6,7 +6,7 @@ environment:
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

View file

@ -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 @@ void _f(bool/*?*/ x, bool/*?*/ y) {
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();