@@ -42,67 +42,11 @@ class AddNullCheck extends ResolvedCorrectionProducer {
4242
4343 @override
4444 Future <void > compute (ChangeBuilder builder) async {
45- Expression ? target;
46- var coveringNode = this .coveringNode;
47- var coveringNodeParent = coveringNode? .parent;
48-
4945 if (await _isNullAware (builder, coveringNode)) {
5046 return ;
5147 }
5248
53- if (coveringNode is SimpleIdentifier ) {
54- if (coveringNodeParent is MethodInvocation ) {
55- target = coveringNodeParent.realTarget;
56- } else if (coveringNodeParent is PrefixedIdentifier ) {
57- target = coveringNodeParent.prefix;
58- } else if (coveringNodeParent is PropertyAccess ) {
59- target = coveringNodeParent.realTarget;
60- } else if (coveringNodeParent is CascadeExpression &&
61- await _isNullAware (
62- builder,
63- coveringNodeParent.cascadeSections.first,
64- )) {
65- return ;
66- } else {
67- target = coveringNode;
68- }
69- } else if (coveringNode is IndexExpression ) {
70- target = coveringNode.realTarget;
71- if (target.staticType? .nullabilitySuffix != NullabilitySuffix .question) {
72- target = coveringNode;
73- }
74- } else if (coveringNode is Expression &&
75- coveringNodeParent is FunctionExpressionInvocation ) {
76- target = coveringNode;
77- } else if (coveringNodeParent is AssignmentExpression ) {
78- target = coveringNodeParent.rightHandSide;
79- } else if (coveringNode is PostfixExpression ) {
80- target = coveringNode.operand;
81- } else if (coveringNode is PrefixExpression ) {
82- target = coveringNode.operand;
83- } else if (coveringNode is BinaryExpression ) {
84- if (coveringNode.operator .type != TokenType .QUESTION_QUESTION ) {
85- target = coveringNode.leftOperand;
86- } else {
87- var expectedType = coveringNode.correspondingParameter? .type;
88- if (expectedType == null ) return ;
89-
90- var leftType = coveringNode.leftOperand.staticType;
91- var leftAssignable =
92- leftType != null &&
93- typeSystem.isAssignableTo (
94- typeSystem.promoteToNonNull (leftType),
95- expectedType,
96- strictCasts: analysisOptions.strictCasts,
97- );
98- if (leftAssignable) {
99- target = coveringNode.rightOperand;
100- }
101- }
102- } else if (coveringNode is AsExpression ) {
103- target = coveringNode.expression;
104- }
105-
49+ var target = await _computeTarget (builder);
10650 if (target == null ) {
10751 return ;
10852 }
@@ -199,13 +143,12 @@ class AddNullCheck extends ResolvedCorrectionProducer {
199143 return ;
200144 }
201145
202- var target_final = target;
203146 var needsParentheses = target.precedence < Precedence .postfix;
204147 await builder.addDartFileEdit (file, (builder) {
205148 if (needsParentheses) {
206- builder.addSimpleInsertion (target_final .offset, '(' );
149+ builder.addSimpleInsertion (target .offset, '(' );
207150 }
208- builder.addInsertion (target_final .end, (builder) {
151+ builder.addInsertion (target .end, (builder) {
209152 if (needsParentheses) {
210153 builder.write (')' );
211154 }
@@ -214,8 +157,70 @@ class AddNullCheck extends ResolvedCorrectionProducer {
214157 });
215158 }
216159
217- /// Return `true` if the specified [node] or one of its parents `isNullAware` ,
218- /// in which case [_replaceWithNullCheck] would also be called.
160+ /// Computes the target for which we need to add a null check.
161+ Future <Expression ?> _computeTarget (ChangeBuilder builder) async {
162+ var coveringNode = this .coveringNode;
163+ var coveringNodeParent = coveringNode? .parent;
164+
165+ if (coveringNode is SimpleIdentifier ) {
166+ if (coveringNodeParent is MethodInvocation ) {
167+ return coveringNodeParent.realTarget;
168+ } else if (coveringNodeParent is PrefixedIdentifier ) {
169+ return coveringNodeParent.prefix;
170+ } else if (coveringNodeParent is PropertyAccess ) {
171+ return coveringNodeParent.realTarget;
172+ } else if (coveringNodeParent is CascadeExpression &&
173+ await _isNullAware (
174+ builder,
175+ coveringNodeParent.cascadeSections.first,
176+ )) {
177+ return null ;
178+ } else {
179+ return coveringNode;
180+ }
181+ } else if (coveringNode is IndexExpression ) {
182+ var target = coveringNode.realTarget;
183+ if (target.staticType? .nullabilitySuffix != NullabilitySuffix .question) {
184+ target = coveringNode;
185+ }
186+ return target;
187+ } else if (coveringNode is Expression &&
188+ coveringNodeParent is FunctionExpressionInvocation ) {
189+ return coveringNode;
190+ } else if (coveringNodeParent is AssignmentExpression ) {
191+ return coveringNodeParent.rightHandSide;
192+ } else if (coveringNode is PostfixExpression ) {
193+ return coveringNode.operand;
194+ } else if (coveringNode is PrefixExpression ) {
195+ return coveringNode.operand;
196+ } else if (coveringNode is BinaryExpression ) {
197+ if (coveringNode.operator .type != TokenType .QUESTION_QUESTION ) {
198+ return coveringNode.leftOperand;
199+ } else {
200+ var expectedType = coveringNode.correspondingParameter? .type;
201+ if (expectedType == null ) return null ;
202+
203+ var leftType = coveringNode.leftOperand.staticType;
204+ var leftAssignable =
205+ leftType != null &&
206+ typeSystem.isAssignableTo (
207+ typeSystem.promoteToNonNull (leftType),
208+ expectedType,
209+ strictCasts: analysisOptions.strictCasts,
210+ );
211+ if (leftAssignable) {
212+ return coveringNode.rightOperand;
213+ }
214+ }
215+ } else if (coveringNode is AsExpression ) {
216+ return coveringNode.expression;
217+ }
218+ return null ;
219+ }
220+
221+ /// Returns whether the specified [node] or, in some cases, a certain child
222+ /// node is null-aware, in which case the null-aware operator is replaced with
223+ /// a null check operator.
219224 Future <bool > _isNullAware (ChangeBuilder builder, AstNode ? node) async {
220225 if (node is PropertyAccess ) {
221226 if (node.isNullAware) {
@@ -241,7 +246,7 @@ class AddNullCheck extends ResolvedCorrectionProducer {
241246 return false ;
242247 }
243248
244- /// Replaces the null aware [token] with the null check operator.
249+ /// Replaces the null- aware [token] with the null check operator.
245250 Future <void > _replaceWithNullCheck (ChangeBuilder builder, Token token) async {
246251 fixKind = DartFixKind .REPLACE_WITH_NULL_AWARE ;
247252 var lexeme = token.lexeme;
0 commit comments