Skip to content

Commit 774fec3

Browse files
srawlinsCommit Queue
authored andcommitted
analyzer: elementUsageFrontierDetectors: Consider super constructor parameters corresponding to super-parameters
The primary effect this has is to report super-parameters whose corresponding super-constructor parameters are `@deprecated`. Also `@experimental`. Let's say we have a deprecated constructor parameter, and code which calls that constructor as a super-constructor (implicitly or explicitly). If the code has no deprecation warnings, it should be safe to remove the deprecated constructor. This is not the case without this additional safeguard. Change-Id: Iacec920d680dfb5d6ccbe19d3f3f54e24a240a9f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/453441 Commit-Queue: Samuel Rawlins <[email protected]> Reviewed-by: Paul Berry <[email protected]>
1 parent 5c2fec9 commit 774fec3

File tree

3 files changed

+118
-3
lines changed

3 files changed

+118
-3
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -317,9 +317,6 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
317317
v.pushElement(element);
318318
}
319319

320-
// TODO(srawlins): Use _elementUsageFrontierDetectors to detect
321-
// super-parameters corresponding to `@Deprecated` or `@experimental`
322-
// parameters.
323320
// TODO(srawlins): Use _elementUsageFrontierDetectors to detect
324321
// `@Deprecated` or `@experimental` parameters in a redirecting factory
325322
// constructor.
@@ -880,6 +877,9 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
880877

881878
@override
882879
void visitSuperFormalParameter(SuperFormalParameter node) {
880+
for (var v in _elementUsageFrontierDetectors) {
881+
v.superFormalParameter(node);
882+
}
883883
_checkFinalParameter(node, node.keyword);
884884
super.visitSuperFormalParameter(node);
885885
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,10 @@ class ElementUsageDetector<TagInfo extends Object> {
223223
_invocationArguments(node.element, node.argumentList);
224224
}
225225

226+
void superFormalParameter(SuperFormalParameter node) {
227+
checkUsage(node.declaredFragment!.element.superConstructorParameter, node);
228+
}
229+
226230
void _invocationArguments(Element? element, ArgumentList arguments) {
227231
element = element?.baseElement;
228232
if (element is ExecutableElement) {

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

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,6 +1654,117 @@ void f(A a) {
16541654
);
16551655
}
16561656

1657+
test_parameterInSuper_explicitInvocation() async {
1658+
newFile('$workspaceRootPath/aaa/lib/a.dart', r'''
1659+
class A {
1660+
A([@deprecated int? p]);
1661+
}
1662+
''');
1663+
1664+
await assertErrorsInCode(
1665+
r'''
1666+
import 'package:aaa/a.dart';
1667+
1668+
class B extends A {
1669+
B() : super(7);
1670+
}
1671+
''',
1672+
[error(HintCode.deprecatedMemberUse, 64, 1)],
1673+
);
1674+
}
1675+
1676+
test_parameterInSuper_explicitInvocation_namedParameter() async {
1677+
newFile('$workspaceRootPath/aaa/lib/a.dart', r'''
1678+
class A {
1679+
A({@deprecated int? p});
1680+
}
1681+
''');
1682+
1683+
await assertErrorsInCode(
1684+
r'''
1685+
import 'package:aaa/a.dart';
1686+
1687+
class B extends A {
1688+
B() : super(p: 7);
1689+
}
1690+
''',
1691+
[error(HintCode.deprecatedMemberUse, 64, 1)],
1692+
);
1693+
}
1694+
1695+
test_parameterInSuper_implicitArgument() async {
1696+
newFile('$workspaceRootPath/aaa/lib/a.dart', r'''
1697+
class A {
1698+
A([@deprecated int? p]);
1699+
}
1700+
''');
1701+
1702+
await assertErrorsInCode(
1703+
r'''
1704+
import 'package:aaa/a.dart';
1705+
1706+
class B extends A {
1707+
B([super.p]);
1708+
}
1709+
''',
1710+
[error(HintCode.deprecatedMemberUse, 55, 7)],
1711+
);
1712+
}
1713+
1714+
test_parameterInSuper_implicitArgument_alsoDeprecated() async {
1715+
newFile('$workspaceRootPath/aaa/lib/a.dart', r'''
1716+
class A {
1717+
A([@deprecated int? p]);
1718+
}
1719+
''');
1720+
1721+
await assertNoErrorsInCode(r'''
1722+
import 'package:aaa/a.dart';
1723+
1724+
class B extends A {
1725+
B([@deprecated super.p]);
1726+
}
1727+
''');
1728+
}
1729+
1730+
test_parameterInSuper_implicitArgument_explicitInvocation() async {
1731+
newFile('$workspaceRootPath/aaa/lib/a.dart', r'''
1732+
class A {
1733+
A.named([@deprecated int? p]);
1734+
}
1735+
''');
1736+
1737+
await assertErrorsInCode(
1738+
r'''
1739+
import 'package:aaa/a.dart';
1740+
1741+
class B extends A {
1742+
B([super.p]) : super.named();
1743+
}
1744+
''',
1745+
[error(HintCode.deprecatedMemberUse, 55, 7)],
1746+
);
1747+
}
1748+
1749+
test_parameterInSuper_implicitInvocation_namedParameter() async {
1750+
newFile('$workspaceRootPath/aaa/lib/a.dart', r'''
1751+
class A {
1752+
A({@deprecated int? p});
1753+
}
1754+
''');
1755+
1756+
await assertErrorsInCode(
1757+
r'''
1758+
import 'package:aaa/a.dart';
1759+
1760+
class B extends A {
1761+
B({super.p});
1762+
}
1763+
''',
1764+
[error(HintCode.deprecatedMemberUse, 55, 7)],
1765+
);
1766+
}
1767+
16571768
test_postfixExpression_deprecatedGetter() async {
16581769
await assertErrorsInCode2(
16591770
externalCode: r'''

0 commit comments

Comments
 (0)