Skip to content

Commit b854176

Browse files
author
Dart CI
committed
Version 2.10.0-33.0.dev
Merge commit '87027c97a12a9926c2af8770a3d2a5cebc1767f3' into 'dev'
2 parents 1253afe + 87027c9 commit b854176

6 files changed

Lines changed: 757 additions & 475 deletions

File tree

pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart

Lines changed: 86 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import 'package:analyzer/src/dart/resolver/resolution_result.dart';
1818
import 'package:analyzer/src/dart/resolver/type_property_resolver.dart';
1919
import 'package:analyzer/src/error/codes.dart';
2020
import 'package:analyzer/src/error/nullable_dereference_verifier.dart';
21+
import 'package:analyzer/src/generated/migration.dart';
2122
import 'package:analyzer/src/generated/resolver.dart';
2223
import 'package:analyzer/src/task/strong/checker.dart';
2324
import 'package:meta/meta.dart';
@@ -46,6 +47,10 @@ class AssignmentExpressionResolver {
4647

4748
bool get _isNonNullableByDefault => _typeSystem.isNonNullableByDefault;
4849

50+
MigrationResolutionHooks get _migrationResolutionHooks {
51+
return _resolver.migrationResolutionHooks;
52+
}
53+
4954
NullableDereferenceVerifier get _nullableDereferenceVerifier =>
5055
_resolver.nullableDereferenceVerifier;
5156

@@ -57,10 +62,22 @@ class AssignmentExpressionResolver {
5762
var left = node.leftHandSide;
5863
var right = node.rightHandSide;
5964

65+
// Case `id = e`.
66+
// Consider an assignment of the form `id = e`, where `id` is an identifier.
67+
if (left is SimpleIdentifier) {
68+
var leftLookup = _resolver.nameScope.lookup2(left.name);
69+
// When the lexical lookup yields a local variable `v`.
70+
var leftGetter = leftLookup.getter;
71+
if (leftGetter is VariableElement) {
72+
_resolve_SimpleIdentifier_LocalVariable(node, left, leftGetter, right);
73+
return;
74+
}
75+
}
76+
6077
left?.accept(_resolver);
6178
left = node.leftHandSide;
6279

63-
var leftLocalVariable = _flowAnalysis?.assignmentExpression(node);
80+
_flowAnalysis?.assignmentExpression(node);
6481

6582
TokenType operator = node.operator.type;
6683
if (operator == TokenType.EQ ||
@@ -76,12 +93,7 @@ class AssignmentExpressionResolver {
7693
_resolve1(node);
7794
_resolve2(node);
7895

79-
_flowAnalysis?.assignmentExpression_afterRight(
80-
node,
81-
leftLocalVariable,
82-
operator == TokenType.QUESTION_QUESTION_EQ
83-
? node.rightHandSide.staticType
84-
: node.staticType);
96+
_flowAnalysis?.assignmentExpression_afterRight(node);
8597
}
8698

8799
/// Set the static type of [node] to be the least upper bound of the static
@@ -180,6 +192,32 @@ class AssignmentExpressionResolver {
180192
return type;
181193
}
182194

195+
/// Record that the static type of the given node is the given type.
196+
///
197+
/// @param expression the node whose type is to be recorded
198+
/// @param type the static type of the node
199+
///
200+
/// TODO(scheglov) this is duplication
201+
void _recordStaticType(Expression expression, DartType type) {
202+
if (_resolver.migrationResolutionHooks != null) {
203+
// TODO(scheglov) type cannot be null
204+
type = _migrationResolutionHooks.modifyExpressionType(
205+
expression,
206+
type ?? DynamicTypeImpl.instance,
207+
);
208+
}
209+
210+
// TODO(scheglov) type cannot be null
211+
if (type == null) {
212+
expression.staticType = DynamicTypeImpl.instance;
213+
} else {
214+
expression.staticType = type;
215+
if (_typeSystem.isBottom(type)) {
216+
_flowAnalysis?.flow?.handleExit();
217+
}
218+
}
219+
}
220+
183221
void _resolve1(AssignmentExpressionImpl node) {
184222
Token operator = node.operator;
185223
TokenType operatorType = operator.type;
@@ -290,6 +328,47 @@ class AssignmentExpressionResolver {
290328
_resolver.nullShortingTermination(node);
291329
}
292330

331+
void _resolve_SimpleIdentifier_LocalVariable(
332+
AssignmentExpressionImpl node,
333+
SimpleIdentifier left,
334+
VariableElement leftElement,
335+
Expression right,
336+
) {
337+
left.staticElement = leftElement;
338+
339+
var leftType = _resolver.localVariableTypeProvider.getType(left);
340+
// TODO(scheglov) Set the type only when `operator != TokenType.EQ`.
341+
_recordStaticType(left, leftType);
342+
343+
var operator = node.operator.type;
344+
if (operator != TokenType.EQ) {
345+
_resolver.checkReadOfNotAssignedLocalVariable(left);
346+
}
347+
348+
if (operator == TokenType.EQ ||
349+
operator == TokenType.QUESTION_QUESTION_EQ) {
350+
InferenceContext.setType(right, leftType);
351+
}
352+
353+
var flow = _flowAnalysis?.flow;
354+
if (flow != null && operator == TokenType.QUESTION_QUESTION_EQ) {
355+
flow.ifNullExpression_rightBegin(left);
356+
}
357+
358+
right?.accept(_resolver);
359+
right = node.rightHandSide;
360+
361+
_resolve1(node);
362+
_resolve2(node);
363+
364+
if (flow != null) {
365+
flow.write(leftElement, node.staticType);
366+
if (node.operator.type == TokenType.QUESTION_QUESTION_EQ) {
367+
flow.ifNullExpression_end();
368+
}
369+
}
370+
}
371+
293372
/// If the given [type] is a type parameter, resolve it to the type that
294373
/// should be used when looking up members. Otherwise, return the original
295374
/// type.

pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -77,30 +77,16 @@ class FlowAnalysisHelper {
7777
flow.asExpression_end(expression, typeAnnotation.type);
7878
}
7979

80-
VariableElement assignmentExpression(AssignmentExpression node) {
80+
void assignmentExpression(AssignmentExpression node) {
8181
if (flow == null) return null;
8282

8383
if (node.operator.type == TokenType.QUESTION_QUESTION_EQ) {
8484
flow.ifNullExpression_rightBegin(node.leftHandSide);
8585
}
86-
87-
var left = node.leftHandSide;
88-
89-
if (left is SimpleIdentifier) {
90-
var element = left.staticElement;
91-
if (element is VariableElement) {
92-
return element;
93-
}
94-
}
95-
96-
return null;
9786
}
9887

99-
void assignmentExpression_afterRight(AssignmentExpression node,
100-
VariableElement localElement, DartType writtenType) {
101-
if (localElement != null) {
102-
flow.write(localElement, writtenType);
103-
}
88+
void assignmentExpression_afterRight(AssignmentExpression node) {
89+
if (flow == null) return null;
10490

10591
if (node.operator.type == TokenType.QUESTION_QUESTION_EQ) {
10692
flow.ifNullExpression_end();

pkg/analyzer/lib/src/generated/resolver.dart

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ class ResolverVisitor extends ScopedVisitor {
153153

154154
final MigratableAstInfoProvider _migratableAstInfoProvider;
155155

156+
final MigrationResolutionHooks migrationResolutionHooks;
157+
156158
/// Helper for checking expression that should have the `bool` type.
157159
BoolExpressionVerifier boolExpressionVerifier;
158160

@@ -290,6 +292,7 @@ class ResolverVisitor extends ScopedVisitor {
290292
this._migratableAstInfoProvider,
291293
MigrationResolutionHooks migrationResolutionHooks)
292294
: _featureSet = featureSet,
295+
migrationResolutionHooks = migrationResolutionHooks,
293296
super(definingLibrary, source, typeProvider, errorListener,
294297
nameScope: nameScope) {
295298
_promoteManager = TypePromotionManager(typeSystem);
@@ -429,6 +432,26 @@ class ResolverVisitor extends ScopedVisitor {
429432
}
430433
}
431434

435+
void checkReadOfNotAssignedLocalVariable(SimpleIdentifier node) {
436+
if (_flowAnalysis != null) {
437+
if (_flowAnalysis.isPotentiallyNonNullableLocalReadBeforeWrite(node)) {
438+
errorReporter.reportErrorForNode(
439+
CompileTimeErrorCode
440+
.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE,
441+
node,
442+
[node.name],
443+
);
444+
}
445+
if (_flowAnalysis.isReadOfDefinitelyUnassignedLateLocal(node)) {
446+
errorReporter.reportErrorForNode(
447+
CompileTimeErrorCode.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE,
448+
node,
449+
[node.name],
450+
);
451+
}
452+
}
453+
}
454+
432455
void checkUnreachableNode(AstNode node) {
433456
nullSafetyDeadCodeVerifier.visitNode(node);
434457
}
@@ -1533,23 +1556,7 @@ class ResolverVisitor extends ScopedVisitor {
15331556
return;
15341557
}
15351558

1536-
if (_flowAnalysis != null) {
1537-
if (_flowAnalysis.isPotentiallyNonNullableLocalReadBeforeWrite(node)) {
1538-
errorReporter.reportErrorForNode(
1539-
CompileTimeErrorCode
1540-
.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE,
1541-
node,
1542-
[node.name],
1543-
);
1544-
}
1545-
if (_flowAnalysis.isReadOfDefinitelyUnassignedLateLocal(node)) {
1546-
errorReporter.reportErrorForNode(
1547-
CompileTimeErrorCode.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE,
1548-
node,
1549-
[node.name],
1550-
);
1551-
}
1552-
}
1559+
checkReadOfNotAssignedLocalVariable(node);
15531560

15541561
super.visitSimpleIdentifier(node);
15551562
}

pkg/analyzer/lib/src/generated/static_type_analyzer.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,20 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<void> {
102102
///
103103
/// @param expression the node whose type is to be recorded
104104
/// @param type the static type of the node
105+
///
106+
/// TODO(scheglov) this is duplication
105107
void recordStaticType(Expression expression, DartType type) {
106108
if (_migrationResolutionHooks != null) {
109+
// TODO(scheglov) type cannot be null
107110
type = _migrationResolutionHooks.modifyExpressionType(
108-
expression, type ?? _dynamicType);
111+
expression,
112+
type ?? DynamicTypeImpl.instance,
113+
);
109114
}
110115

116+
// TODO(scheglov) type cannot be null
111117
if (type == null) {
112-
expression.staticType = _dynamicType;
118+
expression.staticType = DynamicTypeImpl.instance;
113119
} else {
114120
expression.staticType = type;
115121
if (_typeSystem.isBottom(type)) {

0 commit comments

Comments
 (0)