Skip to content

Commit 54abf5e

Browse files
srawlinsCommit Queue
authored and
Commit Queue
committed
analyzer: do not report dead_code on initializer empty body
Fixed #54283 Change-Id: I08063de016e3fe91e795fb10155a6cc34e1cf2fa Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/363680 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Samuel Rawlins <[email protected]>
1 parent 553df4b commit 54abf5e

File tree

2 files changed

+267
-140
lines changed

2 files changed

+267
-140
lines changed

pkg/analyzer/lib/src/error/dead_code_verifier.dart

+105-87
Original file line numberDiff line numberDiff line change
@@ -177,101 +177,119 @@ class NullSafetyDeadCodeVerifier {
177177
/// the current dead code interval.
178178
void flowEnd(AstNode node) {
179179
var firstDeadNode = _firstDeadNode;
180-
if (firstDeadNode != null) {
181-
if (!_containsFirstDeadNode(node)) {
182-
return;
183-
}
180+
if (firstDeadNode == null) {
181+
return;
182+
}
184183

185-
if (node is SwitchMember && node == firstDeadNode) {
186-
_errorReporter.atToken(
187-
node.keyword,
188-
WarningCode.DEAD_CODE,
189-
);
190-
_firstDeadNode = null;
191-
return;
192-
}
184+
if (!_containsFirstDeadNode(node)) {
185+
return;
186+
}
193187

194-
var parent = firstDeadNode.parent;
195-
if (parent is Assertion && identical(firstDeadNode, parent.message)) {
196-
// Don't report "dead code" for the message part of an assert statement,
197-
// because this causes nuisance warnings for redundant `!= null`
198-
// asserts.
199-
} else {
200-
var offset = firstDeadNode.offset;
201-
// We know that [node] is the first dead node, or contains it.
202-
// So, technically the code interval ends at the end of [node].
203-
// But we trim it to the last statement for presentation purposes.
204-
if (node != firstDeadNode) {
205-
if (node is FunctionDeclaration) {
206-
node = node.functionExpression.body;
207-
}
208-
if (node is FunctionExpression) {
209-
node = node.body;
210-
}
211-
if (node is MethodDeclaration) {
212-
node = node.body;
213-
}
214-
if (node is BlockFunctionBody) {
215-
node = node.block;
216-
}
217-
if (node is Block && node.statements.isNotEmpty) {
218-
node = node.statements.last;
219-
}
220-
if (node is SwitchMember && node.statements.isNotEmpty) {
221-
node = node.statements.last;
222-
}
223-
} else if (parent is BinaryExpression && node == parent.rightOperand) {
224-
offset = parent.operator.offset;
188+
if (node is SwitchMember && node == firstDeadNode) {
189+
_errorReporter.atToken(
190+
node.keyword,
191+
WarningCode.DEAD_CODE,
192+
);
193+
_firstDeadNode = null;
194+
return;
195+
}
196+
197+
var parent = firstDeadNode.parent;
198+
if (parent is Assertion && identical(firstDeadNode, parent.message)) {
199+
// Don't report "dead code" for the message part of an assert statement,
200+
// because this causes nuisance warnings for redundant `!= null`
201+
// asserts.
202+
} else if (parent is ConstructorDeclaration &&
203+
firstDeadNode is EmptyFunctionBody) {
204+
// Don't report "dead code" for an unreachable, but syntacically required,
205+
// semicolon that follows one or more constructor initializers.
206+
} else if (parent is ConstructorDeclaration &&
207+
firstDeadNode is BlockFunctionBody &&
208+
firstDeadNode.block.statements.isEmpty) {
209+
// Don't report "dead code" for an unreachable, but empty block body that
210+
// follows one or more constructor initializers.
211+
} else {
212+
var offset = firstDeadNode.offset;
213+
// We know that [node] is the first dead node, or contains it.
214+
// So, technically the code interval ends at the end of [node].
215+
// But we trim it to the last statement for presentation purposes.
216+
if (node != firstDeadNode) {
217+
if (node is FunctionDeclaration) {
218+
node = node.functionExpression.body;
225219
}
226-
if (parent is DoStatement) {
227-
var doOffset = parent.doKeyword.offset;
228-
var doEnd = parent.doKeyword.end;
229-
var whileOffset = parent.whileKeyword.offset;
230-
var whileEnd = parent.semicolon.end;
231-
var body = parent.body;
232-
if (body is Block) {
233-
doEnd = body.leftBracket.end;
234-
whileOffset = body.rightBracket.offset;
235-
}
236-
_errorReporter.atOffset(
237-
offset: doOffset,
238-
length: doEnd - doOffset,
239-
errorCode: WarningCode.DEAD_CODE,
240-
);
241-
_errorReporter.atOffset(
242-
offset: whileOffset,
243-
length: whileEnd - whileOffset,
244-
errorCode: WarningCode.DEAD_CODE,
245-
);
246-
offset = parent.semicolon.next!.offset;
247-
if (parent.hasBreakStatement) {
248-
offset = node.end;
249-
}
250-
} else if (parent is ForParts) {
251-
node = parent.updaters.last;
252-
} else if (parent is ForStatement) {
253-
_reportForUpdaters(parent);
254-
} else if (parent is Block) {
255-
var grandParent = parent.parent;
256-
if (grandParent is ForStatement) {
257-
_reportForUpdaters(grandParent);
258-
}
259-
} else if (parent is LogicalOrPattern && node == parent.rightOperand) {
260-
offset = parent.operator.offset;
220+
if (node is FunctionExpression) {
221+
node = node.body;
261222
}
262-
263-
var length = node.end - offset;
264-
if (length > 0) {
265-
_errorReporter.atOffset(
266-
offset: offset,
267-
length: length,
268-
errorCode: WarningCode.DEAD_CODE,
269-
);
223+
if (node is MethodDeclaration) {
224+
node = node.body;
225+
}
226+
if (node is BlockFunctionBody) {
227+
node = node.block;
228+
}
229+
if (node is Block && node.statements.isNotEmpty) {
230+
node = node.statements.last;
270231
}
232+
if (node is SwitchMember && node.statements.isNotEmpty) {
233+
node = node.statements.last;
234+
}
235+
} else if (parent is BinaryExpression && node == parent.rightOperand) {
236+
offset = parent.operator.offset;
237+
}
238+
if (parent is ConstructorInitializer) {
239+
_errorReporter.atOffset(
240+
offset: parent.offset,
241+
length: parent.end - parent.offset,
242+
errorCode: WarningCode.DEAD_CODE,
243+
);
244+
offset = node.end;
245+
} else if (parent is DoStatement) {
246+
var doOffset = parent.doKeyword.offset;
247+
var doEnd = parent.doKeyword.end;
248+
var whileOffset = parent.whileKeyword.offset;
249+
var whileEnd = parent.semicolon.end;
250+
var body = parent.body;
251+
if (body is Block) {
252+
doEnd = body.leftBracket.end;
253+
whileOffset = body.rightBracket.offset;
254+
}
255+
_errorReporter.atOffset(
256+
offset: doOffset,
257+
length: doEnd - doOffset,
258+
errorCode: WarningCode.DEAD_CODE,
259+
);
260+
_errorReporter.atOffset(
261+
offset: whileOffset,
262+
length: whileEnd - whileOffset,
263+
errorCode: WarningCode.DEAD_CODE,
264+
);
265+
offset = parent.semicolon.next!.offset;
266+
if (parent.hasBreakStatement) {
267+
offset = node.end;
268+
}
269+
} else if (parent is ForParts) {
270+
node = parent.updaters.last;
271+
} else if (parent is ForStatement) {
272+
_reportForUpdaters(parent);
273+
} else if (parent is Block) {
274+
var grandParent = parent.parent;
275+
if (grandParent is ForStatement) {
276+
_reportForUpdaters(grandParent);
277+
}
278+
} else if (parent is LogicalOrPattern && node == parent.rightOperand) {
279+
offset = parent.operator.offset;
271280
}
272281

273-
_firstDeadNode = null;
282+
var length = node.end - offset;
283+
if (length > 0) {
284+
_errorReporter.atOffset(
285+
offset: offset,
286+
length: length,
287+
errorCode: WarningCode.DEAD_CODE,
288+
);
289+
}
274290
}
291+
292+
_firstDeadNode = null;
275293
}
276294

277295
void tryStatementEnter(TryStatement node) {

0 commit comments

Comments
 (0)