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

Commit d57cc84

Browse files
fzyzcjyincendialdkrutskikh
authored
feat: create tag-name; create ban-name; revert analyzer version (#722)
* add doc * add empty ban_name_rule * add tests * config parser * implement rule (without visitor) * try to implement visitor * fix bugs * enhance tests * fix wrong ruleid * change severity * rephrase * changelog * add more tests * scaffold for tag-name * add tests * partial impl * more implementations * pass tests * enhance tests and still pass tests * format code * update changelog * revert bumping analyzer, otherwise flutter stable version cannot work * fix linter issue * regsiter TagNameRule * add stripPrefix, stripPostfix * explain limitation Co-authored-by: Dmitry Zhifarsky <dimannich2380@gmail.com> Co-authored-by: Dmitry Krutskikh <dmitry.krutskikh@gmail.com>
1 parent ed7d85b commit d57cc84

File tree

21 files changed

+543
-8
lines changed

21 files changed

+543
-8
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
# JetBrains IDEs
44
.idea/
5+
*.iml
56

67
# Files and directories created by pub
78
.dart_tool/

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
## Unreleased
44

55
* **Breaking Change:** cli arguments `--fatal-unused` and `--fatal-warnings` activate by default.
6+
* feat: add static code diagnostics `avoid-collection-methods-with-unrelated-types`, `ban-name`, `tag-name`.
67
* fix: added parameter constant check in `avoid-border-all`.
7-
* chore: restrict `analyzer` version to `>=3.3.0 <3.4.0`.
8+
* chore: restrict `analyzer` version to `>=2.8.0 <3.3.0`.
89
* chore: restrict `analyzer_plugin` version to `>=0.9.0 <0.10.0`.
910
* chore: set min `mocktail` version to `^0.3.0`.
10-
* feat: add static code diagnostic `avoid-collection-methods-with-unrelated-types`
1111

1212
## 4.11.0
1313

lib/src/analyzers/lint_analyzer/rules/rules_factory.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import 'rules_list/avoid_unnecessary_type_casts/avoid_unnecessary_type_casts_rul
1818
import 'rules_list/avoid_unrelated_type_assertions/avoid_unrelated_type_assertions_rule.dart';
1919
import 'rules_list/avoid_unused_parameters/avoid_unused_parameters_rule.dart';
2020
import 'rules_list/avoid_wrapping_in_padding/avoid_wrapping_in_padding_rule.dart';
21+
import 'rules_list/ban_name/ban_name_rule.dart';
2122
import 'rules_list/binary_expression_operand_order/binary_expression_operand_order_rule.dart';
2223
import 'rules_list/component_annotation_arguments_ordering/component_annotation_arguments_ordering_rule.dart';
2324
import 'rules_list/double_literal_format/double_literal_format_rule.dart';
@@ -45,6 +46,7 @@ import 'rules_list/prefer_on_push_cd_strategy/prefer_on_push_cd_strategy_rule.da
4546
import 'rules_list/prefer_single_widget_per_file/prefer_single_widget_per_file_rule.dart';
4647
import 'rules_list/prefer_trailing_comma/prefer_trailing_comma_rule.dart';
4748
import 'rules_list/provide_correct_intl_args/provide_correct_intl_args_rule.dart';
49+
import 'rules_list/tag_name/tag_name_rule.dart';
4850

4951
final _implementedRules = <String, Rule Function(Map<String, Object>)>{
5052
AlwaysRemoveListenerRule.ruleId: (config) => AlwaysRemoveListenerRule(config),
@@ -80,6 +82,7 @@ final _implementedRules = <String, Rule Function(Map<String, Object>)>{
8082
AvoidUnusedParametersRule(config),
8183
AvoidWrappingInPaddingRule.ruleId: (config) =>
8284
AvoidWrappingInPaddingRule(config),
85+
BanNameRule.ruleId: (config) => BanNameRule(config),
8386
BinaryExpressionOperandOrderRule.ruleId: (config) =>
8487
BinaryExpressionOperandOrderRule(config),
8588
ComponentAnnotationArgumentsOrderingRule.ruleId: (config) =>
@@ -119,6 +122,7 @@ final _implementedRules = <String, Rule Function(Map<String, Object>)>{
119122
PreferTrailingCommaRule.ruleId: (config) => PreferTrailingCommaRule(config),
120123
ProvideCorrectIntlArgsRule.ruleId: (config) =>
121124
ProvideCorrectIntlArgsRule(config),
125+
TagNameRule.ruleId: (config) => TagNameRule(config),
122126
};
123127

124128
Iterable<Rule> get allRules =>

lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_returning_widgets/visitor.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class _Visitor extends RecursiveAstVisitor<void> {
3636

3737
@override
3838
void visitClassDeclaration(ClassDeclaration node) {
39-
final classType = node.extendsClause?.superclass.type;
39+
final classType = node.extendsClause?.superclass2.type;
4040
if (!isWidgetOrSubclass(classType) && !isWidgetStateOrSubclass(classType)) {
4141
return;
4242
}

lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_setstate/visitor.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class _Visitor extends RecursiveAstVisitor<void> {
1414
void visitClassDeclaration(ClassDeclaration node) {
1515
super.visitClassDeclaration(node);
1616

17-
final type = node.extendsClause?.superclass.type;
17+
final type = node.extendsClause?.superclass2.type;
1818
if (type == null || !isWidgetStateOrSubclass(type)) {
1919
return;
2020
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// ignore_for_file: public_member_api_docs
2+
3+
import 'package:analyzer/dart/ast/ast.dart';
4+
import 'package:analyzer/dart/ast/visitor.dart';
5+
6+
import '../../../../../utils/node_utils.dart';
7+
import '../../../lint_utils.dart';
8+
import '../../../models/internal_resolved_unit_result.dart';
9+
import '../../../models/issue.dart';
10+
import '../../../models/severity.dart';
11+
import '../../models/common_rule.dart';
12+
import '../../rule_utils.dart';
13+
14+
part 'visitor.dart';
15+
part 'utils/config_parser.dart';
16+
17+
class BanNameRule extends CommonRule {
18+
static const String ruleId = 'ban-name';
19+
20+
final List<_BanNameConfigEntry> _entries;
21+
22+
BanNameRule([Map<String, Object> config = const {}])
23+
: _entries = _ConfigParser._parseEntryConfig(config),
24+
super(
25+
id: ruleId,
26+
severity: readSeverity(config, Severity.style),
27+
excludes: readExcludes(config),
28+
);
29+
30+
@override
31+
Iterable<Issue> check(InternalResolvedUnitResult source) {
32+
final visitor = _Visitor(_entries);
33+
34+
source.unit.visitChildren(visitor);
35+
36+
return visitor.nodes
37+
.map(
38+
(node) => createIssue(
39+
rule: this,
40+
location: nodeLocation(node: node.node, source: source),
41+
message: node.message,
42+
),
43+
)
44+
.toList(growable: false);
45+
}
46+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
part of '../ban_name_rule.dart';
2+
3+
const _entriesLabel = 'entries';
4+
const _identLabel = 'ident';
5+
const _descriptionLabel = 'description';
6+
7+
/// Parser for rule configuration.
8+
class _ConfigParser {
9+
static List<_BanNameConfigEntry> _parseEntryConfig(
10+
Map<String, Object> config,
11+
) =>
12+
(config[_entriesLabel] as Iterable<Object?>? ?? []).map((entry) {
13+
final entryMap = entry as Map<Object?, Object?>;
14+
15+
return _BanNameConfigEntry(
16+
ident: entryMap[_identLabel] as String,
17+
description: entryMap[_descriptionLabel] as String,
18+
);
19+
}).toList();
20+
}
21+
22+
class _BanNameConfigEntry {
23+
final String ident;
24+
final String description;
25+
26+
_BanNameConfigEntry({required this.ident, required this.description});
27+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
part of 'ban_name_rule.dart';
2+
3+
class _Visitor extends RecursiveAstVisitor<void> {
4+
final Map<String, _BanNameConfigEntry> _entryMap;
5+
6+
final _nodes = <_NodeWithMessage>[];
7+
8+
Iterable<_NodeWithMessage> get nodes => _nodes;
9+
10+
_Visitor(List<_BanNameConfigEntry> entries)
11+
: _entryMap = Map.fromEntries(entries.map((e) => MapEntry(e.ident, e)));
12+
13+
@override
14+
void visitSimpleIdentifier(SimpleIdentifier node) {
15+
super.visitSimpleIdentifier(node);
16+
_visitIdent(node, node);
17+
}
18+
19+
@override
20+
void visitPrefixedIdentifier(PrefixedIdentifier node) {
21+
super.visitPrefixedIdentifier(node);
22+
_visitIdent(node, node.identifier);
23+
_visitIdent(node, node.prefix);
24+
}
25+
26+
@override
27+
void visitLibraryIdentifier(LibraryIdentifier node) {
28+
super.visitLibraryIdentifier(node);
29+
for (final component in node.components) {
30+
_visitIdent(node, component);
31+
}
32+
}
33+
34+
void _visitIdent(Expression node, SimpleIdentifier ident) {
35+
final name = ident.name;
36+
if (_entryMap.containsKey(name)) {
37+
_nodes.add(_NodeWithMessage(
38+
node,
39+
'${_entryMap[name]!.description} ($name is banned)',
40+
));
41+
}
42+
}
43+
}
44+
45+
class _NodeWithMessage {
46+
final Expression node;
47+
final String message;
48+
49+
_NodeWithMessage(this.node, this.message);
50+
}

lib/src/analyzers/lint_analyzer/rules/rules_list/prefer_extracting_callbacks/visitor.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class _Visitor extends SimpleAstVisitor<void> {
1111

1212
@override
1313
void visitClassDeclaration(ClassDeclaration node) {
14-
final classType = node.extendsClause?.superclass.type;
14+
final classType = node.extendsClause?.superclass2.type;
1515
if (!isWidgetOrSubclass(classType) && !isWidgetStateOrSubclass(classType)) {
1616
return;
1717
}

lib/src/analyzers/lint_analyzer/rules/rules_list/prefer_single_widget_per_file/visitor.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class _Visitor extends SimpleAstVisitor<void> {
1515
void visitClassDeclaration(ClassDeclaration node) {
1616
super.visitClassDeclaration(node);
1717

18-
final classType = node.extendsClause?.superclass.type;
18+
final classType = node.extendsClause?.superclass2.type;
1919
if (isWidgetOrSubclass(classType) &&
2020
(!_ignorePrivateWidgets || !Identifier.isPrivateName(node.name.name))) {
2121
_nodes.add(node);

0 commit comments

Comments
 (0)