Skip to content

Commit 01a3bc4

Browse files
srawlinsCommit Queue
authored and
Commit Queue
committed
analyzer: allow casting to Function
Fixes #56939 This allows users to cast to Function as a way to avoid `avoid_dynamic_calls`, similar to casting to `dynamic`. Change-Id: I2b447f6f07845e94b5f2e1a41fea855bf89e2113 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/415261 Commit-Queue: Samuel Rawlins <[email protected]> Reviewed-by: Konstantin Shcheglov <[email protected]>
1 parent 1c1e94d commit 01a3bc4

File tree

2 files changed

+37
-25
lines changed

2 files changed

+37
-25
lines changed

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

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
134134

135135
@override
136136
void visitAsExpression(AsExpression node) {
137-
if (isUnnecessaryCast(node, _typeSystem)) {
137+
if (_isUnnecessaryCast(node, _typeSystem)) {
138138
_errorReporter.atNode(
139139
node,
140140
WarningCode.UNNECESSARY_CAST,
@@ -1509,30 +1509,34 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
15091509
return _workspacePackage.contains(library.firstFragment.source);
15101510
}
15111511

1512+
static String _formalParameterNameOrEmpty(FormalParameter node) {
1513+
return node.name?.lexeme ?? '';
1514+
}
1515+
1516+
static bool _hasNonVirtualAnnotation(ExecutableElement2 element) {
1517+
if (element is PropertyAccessorElement2 && element.isSynthetic) {
1518+
var variable = element.variable3;
1519+
if (variable != null && variable.metadata2.hasNonVirtual) {
1520+
return true;
1521+
}
1522+
}
1523+
return element.metadata2.hasNonVirtual;
1524+
}
1525+
15121526
/// Checks for the passed as expression for the [WarningCode.UNNECESSARY_CAST]
15131527
/// hint code.
15141528
///
15151529
/// Returns `true` if and only if an unnecessary cast hint should be generated
15161530
/// on [node]. See [WarningCode.UNNECESSARY_CAST].
1517-
static bool isUnnecessaryCast(AsExpression node, TypeSystemImpl typeSystem) {
1531+
static bool _isUnnecessaryCast(AsExpression node, TypeSystemImpl typeSystem) {
15181532
var leftType = node.expression.typeOrThrow;
15191533
var rightType = node.type.typeOrThrow;
15201534

1521-
// `dynamicValue as SomeType` is a valid use case.
1522-
if (leftType is DynamicType) {
1523-
return false;
1524-
}
1525-
15261535
// `cannotResolve is SomeType` is already reported.
15271536
if (leftType is InvalidType) {
15281537
return false;
15291538
}
15301539

1531-
// `x as dynamic` is a valid use case.
1532-
if (rightType is DynamicType) {
1533-
return false;
1534-
}
1535-
15361540
// `x as Unresolved` is already reported as an error.
15371541
if (rightType is InvalidType) {
15381542
return false;
@@ -1543,21 +1547,21 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
15431547
return false;
15441548
}
15451549

1546-
return true;
1547-
}
1548-
1549-
static String _formalParameterNameOrEmpty(FormalParameter node) {
1550-
return node.name?.lexeme ?? '';
1551-
}
1550+
// `x as dynamic` is a valid use case. The explicit cast is a recommended
1551+
// way to dynamically call a `Function` when the `avoid_dynamic_calls` lint
1552+
// rule is enabled.
1553+
if (rightType is DynamicType) {
1554+
return false;
1555+
}
15521556

1553-
static bool _hasNonVirtualAnnotation(ExecutableElement2 element) {
1554-
if (element is PropertyAccessorElement2 && element.isSynthetic) {
1555-
var variable = element.variable3;
1556-
if (variable != null && variable.metadata2.hasNonVirtual) {
1557-
return true;
1558-
}
1557+
// `x as Function` is a valid use case. The explicit cast is a recommended
1558+
// way to dynamically call a `Function` when the `avoid_dynamic_calls` lint
1559+
// rule is enabled.
1560+
if (rightType.isDartCoreFunction) {
1561+
return false;
15591562
}
1560-
return element.metadata2.hasNonVirtual;
1563+
1564+
return true;
15611565
}
15621566
}
15631567

pkg/analyzer/test/src/diagnostics/unnecessary_cast_test.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,14 @@ void f() {
163163
''');
164164
}
165165

166+
test_type_function() async {
167+
await assertNoErrorsInCode(r'''
168+
void f(Function f) {
169+
f as Function;
170+
}
171+
''');
172+
}
173+
166174
test_type_supertype() async {
167175
await assertNoErrorsInCode(r'''
168176
void f(int a) {

0 commit comments

Comments
 (0)