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

feat: add ignored-types option to avoid-late-keyword #1146

Merged
merged 4 commits into from
Jan 12, 2023
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* fix: handle try and switch statements for [`use-setstate-synchronously`](https://dartcodemetrics.dev/docs/rules/flutter/use-setstate-synchronously)
* chore: restrict `analyzer` version to `>=5.1.0 <5.4.0`.
* feat: add `allow-initialized` option to [`avoid-late-keyword`](https://dartcodemetrics.dev/docs/rules/common/avoid-late-keyword).
* feat: add `ignored-types` option to [`avoid-late-keyword`](https://dartcodemetrics.dev/docs/rules/common/avoid-late-keyword).

## 5.4.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ class AvoidLateKeywordRule extends CommonRule {
static const _warning = "Avoid using 'late' keyword.";

final bool _allowInitialized;
final Iterable<String> _ignoredTypes;

AvoidLateKeywordRule([Map<String, Object> config = const {}])
: _allowInitialized = _ConfigParser.parseAllowInitialized(config),
_ignoredTypes = _ConfigParser.parseIgnoredTypes(config),
super(
id: ruleId,
severity: readSeverity(config, Severity.warning),
Expand All @@ -32,7 +34,7 @@ class AvoidLateKeywordRule extends CommonRule {

@override
Iterable<Issue> check(InternalResolvedUnitResult source) {
final visitor = _Visitor(_allowInitialized);
final visitor = _Visitor(_allowInitialized, _ignoredTypes);

source.unit.visitChildren(visitor);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@ part of 'avoid_late_keyword_rule.dart';

class _ConfigParser {
static const _allowInitializedConfig = 'allow-initialized';
static const _ignoredTypesConfig = 'ignored-types';

static bool parseAllowInitialized(Map<String, Object> config) =>
config[_allowInitializedConfig] as bool? ?? false;

static Iterable<String> parseIgnoredTypes(Map<String, Object> config) =>
config.containsKey(_ignoredTypesConfig) &&
config[_ignoredTypesConfig] is Iterable
? List<String>.from(config[_ignoredTypesConfig] as Iterable)
: <String>['AnimationController'];
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ part of 'avoid_late_keyword_rule.dart';

class _Visitor extends RecursiveAstVisitor<void> {
final bool allowInitialized;
final Iterable<String> ignoredTypes;

final _declarations = <AstNode>[];

Iterable<AstNode> get declarations => _declarations;

// ignore: avoid_positional_boolean_parameters
_Visitor(this.allowInitialized);
_Visitor(this.allowInitialized, this.ignoredTypes);

@override
void visitVariableDeclaration(VariableDeclaration node) {
Expand All @@ -17,9 +18,17 @@ class _Visitor extends RecursiveAstVisitor<void> {
if (node.isLate && node.parent != null) {
final parent = node.parent;

if (!(allowInitialized && node.initializer != null)) {
if (!_allowsInitialized(node) && !_hasIgnoredType(node)) {
_declarations.add(parent ?? node);
}
}
}

bool _allowsInitialized(VariableDeclaration node) =>
allowInitialized && node.initializer != null;

bool _hasIgnoredType(VariableDeclaration node) => ignoredTypes.contains(
// ignore: deprecated_member_use
node.declaredElement2?.type.getDisplayString(withNullability: false),
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ void main() {
startColumns: [3, 3, 5, 5, 1, 1],
locationTexts: [
"late final field = 'string'",
'late String uninitializedField',
'late int uninitializedField',
"late final variable = 'string'",
'late String uninitializedVariable',
"late final topLevelVariable = 'string'",
Expand All @@ -46,7 +46,7 @@ void main() {
);
});

test('reports about found issues with config', () async {
test('reports about found issues with allow initialized config', () async {
final unit = await RuleTestHelper.resolveFromFile(_examplePath);
final issues =
AvoidLateKeywordRule({'allow-initialized': true}).check(unit);
Expand All @@ -56,7 +56,7 @@ void main() {
startLines: [8, 17, 23],
startColumns: [3, 5, 1],
locationTexts: [
'late String uninitializedField',
'late int uninitializedField',
'late String uninitializedVariable',
'late String topLevelUninitializedVariable',
],
Expand All @@ -67,5 +67,24 @@ void main() {
],
);
});

test('reports about found issues with ignored types config', () async {
final unit = await RuleTestHelper.resolveFromFile(_examplePath);
final issues = AvoidLateKeywordRule({
'ignored-types': ['String'],
}).check(unit);

RuleTestHelper.verifyIssues(
issues: issues,
startLines: [8],
startColumns: [3],
locationTexts: [
'late int uninitializedField',
],
messages: [
"Avoid using 'late' keyword.",
],
);
});
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class Test {

String? nullableField;

late String uninitializedField; // LINT
late int uninitializedField; // LINT

void method() {
late final variable = 'string'; // LINT
Expand Down