Skip to content

Commit 17fe19d

Browse files
pqCommit Queue
authored and
Commit Queue
committed
augmentation support for use_key_in_widget_constructors
Fixes: https://github.com/dart-lang/linter/issues/4936 Change-Id: Ib002878a1f7bf59db684f957d36eaf4e1a5b97bf Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/362843 Commit-Queue: Phil Quitslund <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent d3d3efb commit 17fe19d

File tree

4 files changed

+113
-8
lines changed

4 files changed

+113
-8
lines changed

pkg/linter/lib/src/extensions.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ extension BlockExtension on Block {
126126
}
127127

128128
extension ClassElementExtension on ClassElement {
129+
/// Get all constructors, including merged augmentations.
130+
List<ConstructorElement> get allConstructors => augmented.constructors;
131+
129132
/// Get all fields, including merged augmentations.
130133
List<FieldElement> get allFields => augmented.fields;
131134

pkg/linter/lib/src/rules/use_key_in_widget_constructors.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,16 @@ class _Visitor extends SimpleAstVisitor<void> {
6868
if (classElement != null &&
6969
classElement.isPublic &&
7070
hasWidgetAsAscendant(classElement) &&
71-
classElement.constructors.where((e) => !e.isSynthetic).isEmpty) {
71+
classElement.allConstructors.where((e) => !e.isSynthetic).isEmpty) {
7272
rule.reportLintForToken(node.name);
7373
}
7474
super.visitClassDeclaration(node);
7575
}
7676

7777
@override
7878
void visitConstructorDeclaration(ConstructorDeclaration node) {
79+
if (node.isAugmentation) return;
80+
7981
var constructorElement = node.declaredElement;
8082
if (constructorElement == null) {
8183
return;

pkg/linter/lib/src/util/flutter_utils.dart

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,16 @@ class _Flutter {
8585

8686
bool hasWidgetAsAscendant(InterfaceElement? element,
8787
[Set<InterfaceElement>? alreadySeen]) {
88+
if (element == null) return false;
89+
90+
if (isExactly(element, _nameWidget, _uriFramework)) return true;
91+
8892
alreadySeen ??= {};
89-
if (element == null || !alreadySeen.add(element)) {
90-
return false;
91-
}
92-
if (isExactly(element, _nameWidget, _uriFramework)) {
93-
return true;
94-
}
95-
return hasWidgetAsAscendant(element.supertype?.element, alreadySeen);
93+
if (!alreadySeen.add(element)) return false;
94+
95+
var type =
96+
element.isAugmentation ? element.augmented.thisType : element.supertype;
97+
return hasWidgetAsAscendant(type?.element, alreadySeen);
9698
}
9799

98100
bool isBuildContext(DartType? type, {bool skipNullable = false}) {

pkg/linter/test/rules/use_key_in_widget_constructors_test.dart

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,30 @@ class UseKeyInWidgetConstructorsTest extends LintRuleTest {
2020
@override
2121
String get lintRule => 'use_key_in_widget_constructors';
2222

23+
test_augmentedConstructor_noKey() async {
24+
newFile('$testPackageLibPath/a.dart', r'''
25+
import augment 'test.dart';
26+
import 'package:flutter/widgets.dart';
27+
28+
class W extends StatelessWidget {
29+
W();
30+
31+
@override
32+
Widget build(BuildContext context) => Container();
33+
}
34+
''');
35+
36+
await assertNoDiagnostics(r'''
37+
augment library 'a.dart';
38+
39+
import 'package:flutter/widgets.dart';
40+
41+
augment class W {
42+
augment const W();
43+
}
44+
''');
45+
}
46+
2347
test_constNamedConstructor_missingKey() async {
2448
await assertDiagnostics(r'''
2549
import 'package:flutter/widgets.dart';
@@ -32,6 +56,57 @@ abstract class MyWidget extends StatelessWidget {
3256
]);
3357
}
3458

59+
test_constructorInAugmentedClass() async {
60+
newFile('$testPackageLibPath/a.dart', r'''
61+
import augment 'test.dart';
62+
import 'package:flutter/widgets.dart';
63+
64+
class W extends StatelessWidget {
65+
@override
66+
Widget build(BuildContext context) => Container();
67+
}
68+
''');
69+
70+
await assertDiagnostics(r'''
71+
augment library 'a.dart';
72+
73+
import 'package:flutter/foundation.dart';
74+
import 'package:flutter/widgets.dart';
75+
76+
augment class W { }
77+
78+
augment class W {
79+
const W({Key? key});
80+
}
81+
''', [
82+
lint(156, 1),
83+
]);
84+
}
85+
86+
test_constructorInAugmentedClass_noKeyParam() async {
87+
newFile('$testPackageLibPath/a.dart', r'''
88+
import augment 'test.dart';
89+
import 'package:flutter/widgets.dart';
90+
91+
class W extends StatelessWidget {
92+
@override
93+
Widget build(BuildContext context) => Container();
94+
}
95+
''');
96+
97+
await assertDiagnostics(r'''
98+
augment library 'a.dart';
99+
100+
import 'package:flutter/widgets.dart';
101+
102+
augment class W {
103+
const W();
104+
}
105+
''', [
106+
lint(93, 1),
107+
]);
108+
}
109+
35110
test_constUnnamedConstructor_missingKey() async {
36111
await assertDiagnostics(r'''
37112
import 'package:flutter/widgets.dart';
@@ -57,6 +132,29 @@ class MyWidget extends StatelessWidget {
57132
''');
58133
}
59134

135+
test_keyUse_inAugmentedConstructor() async {
136+
newFile('$testPackageLibPath/a.dart', r'''
137+
augment library 'test.dart';
138+
139+
import 'package:flutter/foundation.dart';
140+
import 'package:flutter/widgets.dart';
141+
142+
augment class W {
143+
const W({Key? key}) : super(key: key);
144+
}
145+
''');
146+
147+
await assertNoDiagnostics(r'''
148+
import augment 'a.dart';
149+
import 'package:flutter/widgets.dart';
150+
151+
class W extends StatelessWidget {
152+
@override
153+
Widget build(BuildContext context) => Container();
154+
}
155+
''');
156+
}
157+
60158
test_missingConstructor() async {
61159
await assertDiagnostics(r'''
62160
import 'package:flutter/widgets.dart';

0 commit comments

Comments
 (0)