Skip to content

Commit 169b1a2

Browse files
srawlinsCommit Queue
authored andcommitted
linter: Tidy up extension utilities
* Simplify `ClassElementExtension.hasImmutableAnnotation`, `DartTypeExtension.extendsClass`, `.implementsAnyInterface`, and `.implementsInterface`. * Make private `hasSubclassInDefiningCompilationUnit` * Move `ClassMemberListExtension.getMethod` to the one lint rule that uses it; this does not seem like a general purpose extension. * Delete unused `InterfaceElementExtension`. * Tidy doc comments along the way. Change-Id: I70ba98202d45ccbc439334e4d92ea3490d68e455 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/444160 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Samuel Rawlins <[email protected]>
1 parent 66b1378 commit 169b1a2

File tree

2 files changed

+39
-55
lines changed

2 files changed

+39
-55
lines changed

pkg/linter/lib/src/extensions.dart

Lines changed: 33 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import 'package:analyzer/dart/constant/value.dart';
88
import 'package:analyzer/dart/element/element.dart';
99
import 'package:analyzer/dart/element/type.dart';
1010
import 'package:analyzer/file_system/physical_file_system.dart';
11-
import 'package:analyzer/src/dart/ast/ast.dart' // ignore: implementation_imports
12-
show FunctionDeclarationImpl;
1311
import 'package:analyzer/src/dart/element/element.dart'; // ignore: implementation_imports
1412
import 'package:analyzer/src/dart/element/type.dart' // ignore: implementation_imports
1513
show InvalidTypeImpl;
@@ -47,7 +45,7 @@ extension AstNodeExtension on AstNode {
4745
EnumDeclaration() => self.augmentKeyword != null,
4846
ExtensionTypeDeclaration() => self.augmentKeyword != null,
4947
FieldDeclaration() => self.augmentKeyword != null,
50-
FunctionDeclarationImpl() => self.augmentKeyword != null,
48+
FunctionDeclaration() => self.augmentKeyword != null,
5149
FunctionExpression() => self.parent?.isAugmentation ?? false,
5250
MethodDeclaration() => self.augmentKeyword != null,
5351
MixinDeclaration() => self.augmentKeyword != null,
@@ -131,7 +129,7 @@ extension AstNodeNullableExtension on AstNode? {
131129
}
132130

133131
extension BlockExtension on Block {
134-
/// Returns the last statement of this block, or `null` if this is empty.
132+
/// The last statement of this block, or `null` if this is empty.
135133
///
136134
/// If the last immediate statement of this block is a [Block], recurses into
137135
/// it to find the last statement.
@@ -148,20 +146,14 @@ extension BlockExtension on Block {
148146
}
149147

150148
extension ClassElementExtension on ClassElement {
151-
bool get hasImmutableAnnotation {
152-
var inheritedAndSelfElements = <InterfaceElement>[
153-
...allSupertypes.map((t) => t.element),
154-
this,
155-
];
156-
157-
return inheritedAndSelfElements.any((e) => e.metadata.hasImmutable);
158-
159-
// TODO(pq): update when implemented or replace w/ a better has{*} call
160-
// https://github.com/dart-lang/linter/issues/4939
161-
//return inheritedAndSelfElements.any((e) => e.augmented.metadata.any((e) => e.isImmutable));
162-
}
163-
164-
bool get hasSubclassInDefiningCompilationUnit {
149+
/// Whether this [ClassElement], or one of its supertypes, is annotated with
150+
/// `@Immutable`.
151+
bool get hasImmutableAnnotation => [
152+
...allSupertypes.map((t) => t.element),
153+
this,
154+
].any((e) => e.metadata.hasImmutable);
155+
156+
bool get _hasSubclassInDefiningCompilationUnit {
165157
for (var cls in library.classes) {
166158
InterfaceType? classType = cls.thisType;
167159
do {
@@ -232,22 +224,17 @@ extension ClassElementExtension on ClassElement {
232224
}
233225

234226
// And no subclasses in the defining library.
235-
if (hasSubclassInDefiningCompilationUnit) return null;
227+
if (_hasSubclassInDefiningCompilationUnit) return null;
236228

237229
return EnumLikeClassDescription(enumConstants);
238230
}
239231

240232
bool isEnumLikeClass() => asEnumLikeClass() != null;
241233
}
242234

243-
extension ClassMemberListExtension on List<ClassMember> {
244-
MethodDeclaration? getMethod(String name) => whereType<MethodDeclaration>()
245-
.firstWhereOrNull((node) => node.name.lexeme == name);
246-
}
247-
248235
extension ConstructorElementExtension on ConstructorElement {
249-
/// Returns whether `this` is the same element as the [className] constructor
250-
/// named [constructorName] declared in [uri].
236+
/// Whether this [ConstructorElement] is the same constructor as the
237+
/// [className] constructor named [constructorName] declared in [uri].
251238
bool isSameAs({
252239
required String uri,
253240
required String className,
@@ -259,43 +246,41 @@ extension ConstructorElementExtension on ConstructorElement {
259246
}
260247

261248
extension DartTypeExtension on DartType? {
249+
/// Whether this [DartType] extends [className], declared in [library].
262250
bool extendsClass(String? className, String library) {
263251
var self = this;
264-
if (self is InterfaceType) {
265-
return _extendsClass(self, <InterfaceElement>{}, className, library);
266-
}
267-
return false;
252+
return self is InterfaceType &&
253+
_extendsClass(self, <InterfaceElement>{}, className, library);
268254
}
269255

256+
/// Whether this [DartType] implements any of [definitions].
270257
bool implementsAnyInterface(Iterable<InterfaceTypeDefinition> definitions) {
271-
bool isAnyInterface(InterfaceType i) =>
272-
definitions.any((d) => i.isSameAs(d.name, d.library));
273-
274258
var typeToCheck = this;
275259
if (typeToCheck is TypeParameterType) {
276260
typeToCheck = typeToCheck.typeForInterfaceCheck;
277261
}
278-
if (typeToCheck is InterfaceType) {
279-
return isAnyInterface(typeToCheck) ||
280-
!typeToCheck.element.isSynthetic &&
281-
typeToCheck.element.allSupertypes.any(isAnyInterface);
282-
} else {
283-
return false;
284-
}
262+
if (typeToCheck is! InterfaceType) return false;
263+
264+
bool isAnyInterface(InterfaceType i) =>
265+
definitions.any((d) => i.isSameAs(d.name, d.library));
266+
267+
return isAnyInterface(typeToCheck) ||
268+
!typeToCheck.element.isSynthetic &&
269+
typeToCheck.element.allSupertypes.any(isAnyInterface);
285270
}
286271

272+
/// Whether this [DartType] implements [interface], declared in [library].
287273
bool implementsInterface(String interface, String library) {
288274
var self = this;
289-
if (self is! InterfaceType) {
290-
return false;
291-
}
292-
bool predicate(InterfaceType i) => i.isSameAs(interface, library);
293-
var element = self.element;
294-
return predicate(self) ||
295-
!element.isSynthetic && element.allSupertypes.any(predicate);
275+
if (self is! InterfaceType) return false;
276+
if (self.isSameAs(interface, library)) return true;
277+
if (self.element.isSynthetic) return false;
278+
return self.element.allSupertypes.any(
279+
(i) => i.isSameAs(interface, library),
280+
);
296281
}
297282

298-
/// Returns whether `this` is the same element as [interface], declared in
283+
/// Whether this [DartType] is the same element as [interface], declared in
299284
/// [library].
300285
bool isSameAs(String? interface, String? library) {
301286
var self = this;
@@ -537,13 +522,6 @@ extension InstanceElementExtension on InstanceElement {
537522
metadata.annotations.any((a) => a.isReflectiveTest);
538523
}
539524

540-
extension InterfaceElementExtension on InterfaceElement {
541-
/// Whether this element has the exact [name] and defined in the file with
542-
/// the given [uri].
543-
bool isExactly(String name, Uri uri) =>
544-
this.name == name && enclosingElement.uri == uri;
545-
}
546-
547525
extension InterfaceTypeExtension on InterfaceType {
548526
/// Returns the collection of all interfaces that this type implements,
549527
/// including itself.

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'package:analyzer/dart/ast/visitor.dart';
99
import 'package:analyzer/dart/element/element.dart';
1010
import 'package:analyzer/dart/element/type.dart';
1111
import 'package:analyzer/error/error.dart';
12+
import 'package:collection/collection.dart';
1213

1314
import '../analyzer.dart';
1415
import '../extensions.dart';
@@ -134,3 +135,8 @@ class _Visitor extends SimpleAstVisitor<void> {
134135
return classElement.getInheritedMember(Name(null, name)) != null;
135136
}
136137
}
138+
139+
extension on List<ClassMember> {
140+
MethodDeclaration? getMethod(String name) => whereType<MethodDeclaration>()
141+
.firstWhereOrNull((node) => node.name.lexeme == name);
142+
}

0 commit comments

Comments
 (0)