Skip to content

Commit

Permalink
analyzer 5.0.0 prep (#3643)
Browse files Browse the repository at this point in the history
  • Loading branch information
pq authored Sep 1, 2022
1 parent 201fd3b commit b6714c5
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 111 deletions.
206 changes: 103 additions & 103 deletions lib/src/extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,6 @@ import 'package:collection/collection.dart';

import 'util/dart_type_utilities.dart';

extension ElementExtension on Element {
Element get canonicalElement {
var self = this;
if (self is PropertyAccessorElement) {
var variable = self.variable;
if (variable is FieldMember) {
// A field element defined in a parameterized type where the values of
// the type parameters are known.
//
// This concept should be invisible when comparing FieldElements, but a
// bug in the analyzer causes FieldElements to not evaluate as
// equivalent to equivalent FieldMembers. See
// https://github.com/dart-lang/sdk/issues/35343.
return variable.declaration;
} else {
return variable;
}
} else {
return self;
}
}
}

class EnumLikeClassDescription {
final Map<DartObject, Set<FieldElement>> _enumConstants;
EnumLikeClassDescription(this._enumConstants);
Expand All @@ -42,6 +19,53 @@ class EnumLikeClassDescription {
Map<DartObject, Set<FieldElement>> get enumConstants => {..._enumConstants};
}

extension AstNodeExtension on AstNode {
Iterable<AstNode> get childNodes => childEntities.whereType<AstNode>();

/// Builds the list resulting from traversing the node in DFS and does not
/// include the node itself.
///
/// It excludes the nodes for which the [excludeCriteria] returns true. If
/// [excludeCriteria] is not provided, all nodes are included.
Iterable<AstNode> traverseNodesInDFS({AstNodePredicate? excludeCriteria}) {
var nodes = <AstNode>{};
var nodesToVisit = List.of(childNodes);
if (excludeCriteria == null) {
while (nodesToVisit.isNotEmpty) {
var node = nodesToVisit.removeAt(0);
nodes.add(node);
nodesToVisit.insertAll(0, node.childNodes);
}
} else {
while (nodesToVisit.isNotEmpty) {
var node = nodesToVisit.removeAt(0);
if (excludeCriteria(node)) continue;
nodes.add(node);
nodesToVisit.insertAll(0, node.childNodes);
}
}

return nodes;
}
}

extension BlockExtension on Block {
/// Returns the last statement of this block, or `null` if this is empty.
///
/// If the last immediate statement of this block is a [Block], recurses into
/// it to find the last statement.
Statement? get lastStatement {
if (statements.isEmpty) {
return null;
}
var lastStatement = statements.last;
if (lastStatement is Block) {
return lastStatement.lastStatement;
}
return lastStatement;
}
}

extension ClassElementExtension on ClassElement {
/// Returns an [EnumLikeClassDescription] for this if the latter is a valid
/// "enum-like" class.
Expand Down Expand Up @@ -120,12 +144,17 @@ extension ClassElementExtension on ClassElement {
return false;
}

bool get isEnumLikeClass => asEnumLikeClass != null;

/// Returns whether this class is exactly [otherName] declared in
/// [otherLibrary].
bool isClass(String otherName, String otherLibrary) =>
name == otherName && library.name == otherLibrary;
}

bool get isEnumLikeClass => asEnumLikeClass != null;
extension ClassMemberListExtension on List<ClassMember> {
MethodDeclaration? getMethod(String name) => whereType<MethodDeclaration>()
.firstWhereOrNull((node) => node.name2.lexeme == name);
}

extension ConstructorElementExtension on ConstructorElement {
Expand All @@ -141,80 +170,6 @@ extension ConstructorElementExtension on ConstructorElement {
name == constructorName;
}

extension InterfaceElementExtension on InterfaceElement {
/// Returns whether this element is exactly [otherName] declared in
/// [otherLibrary].
bool isClass(String otherName, String otherLibrary) =>
name == otherName && library.name == otherLibrary;
}

extension NullableAstNodeExtension on AstNode? {
Element? get canonicalElement {
var self = this;
if (self is Expression) {
var node = self.unParenthesized;
if (node is Identifier) {
return node.staticElement?.canonicalElement;
} else if (node is PropertyAccess) {
return node.propertyName.staticElement?.canonicalElement;
}
}
return null;
}
}

extension AstNodeExtension on AstNode {
/// Builds the list resulting from traversing the node in DFS and does not
/// include the node itself.
///
/// It excludes the nodes for which the [excludeCriteria] returns true. If
/// [excludeCriteria] is not provided, all nodes are included.
Iterable<AstNode> traverseNodesInDFS({AstNodePredicate? excludeCriteria}) {
var nodes = <AstNode>{};
var nodesToVisit = List.of(childNodes);
if (excludeCriteria == null) {
while (nodesToVisit.isNotEmpty) {
var node = nodesToVisit.removeAt(0);
nodes.add(node);
nodesToVisit.insertAll(0, node.childNodes);
}
} else {
while (nodesToVisit.isNotEmpty) {
var node = nodesToVisit.removeAt(0);
if (excludeCriteria(node)) continue;
nodes.add(node);
nodesToVisit.insertAll(0, node.childNodes);
}
}

return nodes;
}

Iterable<AstNode> get childNodes => childEntities.whereType<AstNode>();
}

extension BlockExtension on Block {
/// Returns the last statement of this block, or `null` if this is empty.
///
/// If the last immediate statement of this block is a [Block], recurses into
/// it to find the last statement.
Statement? get lastStatement {
if (statements.isEmpty) {
return null;
}
var lastStatement = statements.last;
if (lastStatement is Block) {
return lastStatement.lastStatement;
}
return lastStatement;
}
}

extension ClassMemberListExtension on List<ClassMember> {
MethodDeclaration? getMethod(String name) => whereType<MethodDeclaration>()
.firstWhereOrNull((node) => node.name2.lexeme == name);
}

extension DartTypeExtension on DartType? {
bool extendsClass(String? className, String library) {
var self = this;
Expand Down Expand Up @@ -269,10 +224,40 @@ extension DartTypeExtension on DartType? {
_extendsClass(type.superclass, seenElements, className, library));
}

extension ElementExtension on Element {
Element get canonicalElement {
var self = this;
if (self is PropertyAccessorElement) {
var variable = self.variable;
if (variable is FieldMember) {
// A field element defined in a parameterized type where the values of
// the type parameters are known.
//
// This concept should be invisible when comparing FieldElements, but a
// bug in the analyzer causes FieldElements to not evaluate as
// equivalent to equivalent FieldMembers. See
// https://github.com/dart-lang/sdk/issues/35343.
return variable.declaration;
} else {
return variable;
}
} else {
return self;
}
}
}

extension ExpressionExtension on Expression? {
bool get isNullLiteral => this?.unParenthesized is NullLiteral;
}

extension InterfaceElementExtension on InterfaceElement {
/// Returns whether this element is exactly [otherName] declared in
/// [otherLibrary].
bool isClass(String otherName, String otherLibrary) =>
name == otherName && library.name == otherLibrary;
}

extension InterfaceTypeExtension on InterfaceType {
/// Returns the collection of all interfaces that this type implements,
/// including itself.
Expand Down Expand Up @@ -336,7 +321,7 @@ extension MethodDeclarationExtension on MethodDeclaration {
return null;
}
var parent = declaredElement.enclosingElement3;
if (parent is ClassElement) {
if (parent is InterfaceElement) {
return parent.lookUpGetter(name2.lexeme, declaredElement.library);
}
if (parent is ExtensionElement) {
Expand All @@ -351,7 +336,7 @@ extension MethodDeclarationExtension on MethodDeclaration {
return null;
}
var parent = declaredElement.enclosingElement3;
if (parent is ClassElement) {
if (parent is InterfaceElement) {
return parent.lookUpInheritedConcreteGetter(
name2.lexeme, declaredElement.library);
}
Expand All @@ -363,7 +348,7 @@ extension MethodDeclarationExtension on MethodDeclaration {
var declaredElement = declaredElement2;
if (declaredElement != null) {
var parent = declaredElement.enclosingElement3;
if (parent is ClassElement) {
if (parent is InterfaceElement) {
return parent.lookUpInheritedConcreteMethod(
name2.lexeme, declaredElement.library);
}
Expand All @@ -376,7 +361,7 @@ extension MethodDeclarationExtension on MethodDeclaration {
var declaredElement = declaredElement2;
if (declaredElement != null) {
var parent = declaredElement.enclosingElement3;
if (parent is ClassElement) {
if (parent is InterfaceElement) {
return parent.lookUpInheritedConcreteSetter(
name2.lexeme, declaredElement.library);
}
Expand All @@ -389,11 +374,26 @@ extension MethodDeclarationExtension on MethodDeclaration {
var declaredElement = declaredElement2;
if (declaredElement != null) {
var parent = declaredElement.enclosingElement3;
if (parent is ClassElement) {
if (parent is InterfaceElement) {
return parent.lookUpInheritedMethod(
name2.lexeme, declaredElement.library);
}
}
return null;
}
}

extension NullableAstNodeExtension on AstNode? {
Element? get canonicalElement {
var self = this;
if (self is Expression) {
var node = self.unParenthesized;
if (node is Identifier) {
return node.staticElement?.canonicalElement;
} else if (node is PropertyAccess) {
return node.propertyName.staticElement?.canonicalElement;
}
}
return null;
}
}
2 changes: 1 addition & 1 deletion lib/src/rules/annotate_overrides.dart
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class _Visitor extends SimpleAstVisitor<void> {
}

Element? getOverriddenMember(Element member) {
var classElement = member.thisOrAncestorOfType<ClassElement>();
var classElement = member.thisOrAncestorOfType<InterfaceElement>();
if (classElement == null) {
return null;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/src/rules/avoid_renaming_method_parameters.dart
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class _Visitor extends SimpleAstVisitor<void> {
}
var parentElement = parentNode.declaredElement2;
// Note: there are no override semantics with extension methods.
if (parentElement is! ClassElement) {
if (parentElement is! InterfaceElement) {
return;
}

Expand Down
8 changes: 4 additions & 4 deletions lib/src/rules/public_member_api_docs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -161,18 +161,18 @@ class _Visitor extends SimpleAstVisitor {
return null;
}

var classElement = member.thisOrAncestorOfType<ClassElement>();
if (classElement == null) {
var interfaceElement = member.thisOrAncestorOfType<InterfaceElement>();
if (interfaceElement == null) {
return null;
}
var name = member.name;
if (name == null) {
return null;
}

var libraryUri = classElement.library.source.uri;
var libraryUri = interfaceElement.library.source.uri;
return context.inheritanceManager.getInherited(
classElement.thisType,
interfaceElement.thisType,
Name(libraryUri, name),
);
}
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ environment:
sdk: '>=2.17.0 <3.0.0'

dependencies:
analyzer: ^4.6.0
analyzer: ^4.7.0
args: ^2.1.0
collection: ^1.15.0
http: ^0.13.0
Expand Down
1 change: 0 additions & 1 deletion test/rules/constant_identifier_names_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ const R = (x: 1);
]);
}

@FailingTest(issue: 'https://github.com/dart-lang/linter/issues/3630')
test_recordTypeDeclarations_ok() async {
await assertNoDiagnostics(r'''
const r = (x: 1);
Expand Down
19 changes: 19 additions & 0 deletions test/rules/public_member_api_docs_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,23 @@ extension E on Object {
lint('public_member_api_docs', 31, 1),
]);
}

test_mixin_method() async {
await assertDiagnostics(r'''
/// A mixin M.
mixin M {
String m() => '';
}''', [
lint('public_member_api_docs', 34, 1),
]);
}

test_mixin_overridingMethod_OK() async {
await assertNoDiagnostics(r'''
/// A mixin M.
mixin M {
@override
String toString() => '';
}''');
}
}

0 comments on commit b6714c5

Please sign in to comment.