Skip to content
This repository was archived by the owner on Jul 16, 2023. It is now read-only.

fix: remove recursive traversal for ban-name #1090

Merged
merged 2 commits into from
Dec 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## Unreleased

* fix: remove recursive traversal for [`ban-name`](https://dartcodemetrics.dev/docs/rules/common/ban-name) rule.

## 5.1.0

* feat: add static code diagnostic [`arguments-ordering`](https://dartcodemetrics.dev/docs/rules/common/arguments-ordering).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,33 @@ class BanNameRule extends CommonRule {

source.unit.visitChildren(visitor);

return visitor.nodes
.map(
(node) => createIssue(
rule: this,
location: nodeLocation(node: node.node, source: source),
message: node.message,
),
)
.toList(growable: false);
final filteredNodeList = visitor.nodes.where((node) {
if (node.endNode != null) {
final inlineNode = source.content
.substring(
node.node.offset,
node.endNode!.end,
)
.replaceAll('\n', '');

if (!inlineNode.contains(node.fullName)) {
return false;
}
}

return true;
});

return filteredNodeList.map(
(node) => createIssue(
rule: this,
location: nodeLocation(
node: node.node,
source: source,
endNode: node.endNode,
),
message: node.message,
),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,96 +3,88 @@ part of 'ban_name_rule.dart';
class _Visitor extends GeneralizingAstVisitor<void> {
final Map<String, _BanNameConfigEntry> _entryMap;

final _nodeBreadcrumb = <String, AstNode>{};
final _nodes = <_NodeInfo>[];

Iterable<_NodeInfo> get nodes => _nodes;

final _visitedNodes = <AstNode>{};

_Visitor(List<_BanNameConfigEntry> entries)
: _entryMap = Map.fromEntries(entries.map((e) => MapEntry(e.ident, e)));

@override
void visitSimpleIdentifier(SimpleIdentifier node) {
_visitIdent(node, node);
_visitIdent(node, node.name);
}

@override
void visitPrefixedIdentifier(PrefixedIdentifier node) {
_visitIdent(node, node.identifier);
_visitIdent(node, node.prefix);
_visitIdent(node, node.identifier.name);
_visitIdent(node, node.prefix.name);
}

@override
void visitLibraryIdentifier(LibraryIdentifier node) {
for (final component in node.components) {
_visitIdent(node, component);
_visitIdent(node, component.name);
}
}

@override
void visitDeclaration(Declaration node) {
final name = node.declaredElement?.displayName;
if (name != null) {
_checkBannedName(node, name);
_visitIdent(node, name);
}

super.visitDeclaration(node);
}

void _visitIdent(AstNode node, SimpleIdentifier name) {
_checkBannedName(name, name.name);

if (node is PrefixedIdentifier) {
_checkBannedName(node, node.name);
void _visitIdent(AstNode node, String name) {
final prevNode =
_nodeBreadcrumb.isNotEmpty ? _nodeBreadcrumb.values.last : null;
if (node.offset - 1 == prevNode?.end) {
_nodeBreadcrumb.addAll({name: node});
} else {
_nodeBreadcrumb.clear();
}

_traverseParents(name.parent);
}

void _traverseParents(AstNode? node) {
if (node is MethodInvocation) {
_checkBannedName(
node,
'${node.realTarget}.${node.methodName}',
);
_traverseParents(node.parent);
if (_nodeBreadcrumb.isEmpty) {
_nodeBreadcrumb.addAll({name: node});
}

if (node is PropertyAccess) {
_checkBannedName(
if (_entryMap.containsKey(name)) {
_nodes.add(_NodeInfo(
node,
'${node.realTarget}.${node.propertyName}',
);
_traverseParents(node.realTarget);
}
fullName: name,
message: '${_entryMap[name]!.description} ($name is banned)',
));

if (node is ConstructorName) {
_traverseParents(node.parent);
return;
}

if (node is InstanceCreationExpression) {
_checkBannedName(node, node.constructorName.toString());
}
}

void _checkBannedName(AstNode node, String name) {
if (_entryMap.containsKey(name) && !_visitedNodes.contains(node)) {
_visitedNodes.add(node);
final breadcrumbString = _nodeBreadcrumb.keys.join('.');
if (_entryMap.containsKey(breadcrumbString)) {
_nodes.add(_NodeInfo(
node,
message: '${_entryMap[name]!.description} ($name is banned)',
_nodeBreadcrumb.values.first,
fullName: breadcrumbString,
message:
'${_entryMap[breadcrumbString]!.description} ($breadcrumbString is banned)',
endNode: _nodeBreadcrumb.values.last,
));
}
}
}

class _NodeInfo {
final AstNode node;
final String fullName;
final String message;
final AstNode? endNode;

_NodeInfo(
this.node, {
required this.fullName,
required this.message,
this.endNode,
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ void main() {
' late var strangeName; // LINT\n'
'}',
'strangeName',
'StrangeClass.someMethod()',
'DateTime.now()',
'DateTime.now()',
'DateTime.now()',
'DateTime.now()',
'StrangeClass.someMethod',
'DateTime.now',
'DateTime.now',
'DateTime.now',
'DateTime.now',
],
messages: [
'Please use myShowDialog (showDialog is banned)',
Expand Down