Skip to content

Commit 5a1f899

Browse files
authored
new tweak: drop lint (#315)
1 parent 50dd246 commit 5a1f899

File tree

3 files changed

+220
-0
lines changed

3 files changed

+220
-0
lines changed

pkgs/blast_repo/lib/src/top_level.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import 'package:git/git.dart';
1111
import 'repo_tweak.dart';
1212
import 'tweaks/auto_publish_tweak.dart';
1313
import 'tweaks/dependabot_tweak.dart';
14+
import 'tweaks/drop_lint_tweak.dart';
1415
import 'tweaks/github_action_tweak.dart';
1516
import 'tweaks/mono_repo_tweak.dart';
1617
import 'tweaks/no_reponse_tweak.dart';
@@ -19,6 +20,7 @@ import 'utils.dart';
1920
final allTweaks = Set<RepoTweak>.unmodifiable([
2021
AutoPublishTweak(),
2122
DependabotTweak(),
23+
DropLintTweak(),
2224
GitHubActionTweak(),
2325
MonoRepoTweak(),
2426
NoResponseTweak(),
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:async';
6+
import 'dart:io';
7+
8+
import 'package:collection/collection.dart';
9+
import 'package:path/path.dart' as p;
10+
import 'package:yaml/yaml.dart';
11+
import 'package:yaml_edit/yaml_edit.dart';
12+
13+
import '../repo_tweak.dart';
14+
15+
final _instance = DropLintTweak._();
16+
17+
class DropLintTweak extends RepoTweak {
18+
factory DropLintTweak() => _instance;
19+
20+
DropLintTweak._()
21+
: super(
22+
id: 'drop-lint',
23+
description: 'Drop deprecated lints from analysis_options.yaml',
24+
);
25+
26+
@override
27+
bool shouldRunByDefault(Directory checkout, String repoSlug) => true;
28+
29+
@override
30+
FutureOr<FixResult> fix(Directory checkout, String repoSlug) async {
31+
final analysisOptionsFile =
32+
File(p.join(checkout.path, 'analysis_options.yaml'));
33+
34+
if (!analysisOptionsFile.existsSync()) {
35+
return FixResult.noFixesMade;
36+
}
37+
38+
final yamlSource = loadYaml(
39+
analysisOptionsFile.readAsStringSync(),
40+
sourceUrl: analysisOptionsFile.uri,
41+
);
42+
43+
if (yamlSource is YamlMap) {
44+
final linterNode = yamlSource['linter'];
45+
if (linterNode is YamlMap) {
46+
final rules = linterNode['rules'];
47+
48+
if (rules is YamlList) {
49+
final fixes = <String>{};
50+
final badIndexes = rules
51+
.mapIndexed((index, value) {
52+
if (_deprecatedLints.contains(value)) {
53+
fixes.add('Removed "$value".');
54+
return index;
55+
}
56+
return -1;
57+
})
58+
.where((e) => e >= 0)
59+
.toList();
60+
61+
final editor = YamlEditor(analysisOptionsFile.readAsStringSync());
62+
for (var index in badIndexes.reversed) {
63+
editor.remove(['linter', 'rules', index]);
64+
}
65+
66+
analysisOptionsFile.writeAsStringSync(editor.toString(),
67+
mode: FileMode.writeOnly);
68+
69+
return FixResult(fixes: fixes.toList()..sort());
70+
}
71+
72+
if (rules == null) {
73+
return FixResult(fixes: []);
74+
}
75+
76+
throw UnimplementedError('not sure what to do with $rules');
77+
}
78+
}
79+
80+
return FixResult(fixes: []);
81+
}
82+
}
83+
84+
final _deprecatedLints = {
85+
'avoid_null_checks_in_equality_operators',
86+
'package_api_docs',
87+
'unsafe_html',
88+
};
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:blast_repo/src/tweaks/drop_lint_tweak.dart';
6+
import 'package:test/test.dart';
7+
import 'package:test_descriptor/test_descriptor.dart' as d;
8+
9+
void main() {
10+
late DropLintTweak tweak;
11+
12+
setUp(() async {
13+
tweak = DropLintTweak();
14+
});
15+
16+
test('removes the dead items', () async {
17+
await d.dir('foo', [
18+
d.file('analysis_options.yaml', r'''
19+
analyzer:
20+
language:
21+
strict-inference: true
22+
strict-raw-types: true
23+
24+
linter:
25+
rules:
26+
- avoid_classes_with_only_static_members
27+
- avoid_null_checks_in_equality_operators
28+
- no_runtimeType_toString
29+
- package_api_docs
30+
- prefer_const_declarations
31+
- unsafe_html
32+
- use_if_null_to_convert_nulls_to_bools
33+
''')
34+
]).create();
35+
final dir = d.dir('foo').io;
36+
37+
var results = await tweak.fix(dir, 'my_org/my_repo');
38+
expect(results.fixes, hasLength(3));
39+
40+
await d.dir('foo', [
41+
d.file('analysis_options.yaml', r'''
42+
analyzer:
43+
language:
44+
strict-inference: true
45+
strict-raw-types: true
46+
47+
linter:
48+
rules:
49+
- avoid_classes_with_only_static_members
50+
- no_runtimeType_toString
51+
- prefer_const_declarations
52+
- use_if_null_to_convert_nulls_to_bools
53+
''')
54+
]).validate();
55+
});
56+
57+
test('handles no linter section', () async {
58+
await d.dir('foo', [
59+
d.file('analysis_options.yaml', r'''
60+
analyzer:
61+
language:
62+
strict-inference: true
63+
strict-raw-types: true
64+
''')
65+
]).create();
66+
final dir = d.dir('foo').io;
67+
68+
var results = await tweak.fix(dir, 'my_org/my_repo');
69+
expect(results.fixes, isEmpty);
70+
71+
await d.dir('foo', [
72+
d.file('analysis_options.yaml', r'''
73+
analyzer:
74+
language:
75+
strict-inference: true
76+
strict-raw-types: true
77+
''')
78+
]).validate();
79+
});
80+
81+
test('handles no analysis options file', () async {
82+
await d.dir('foo', []).create();
83+
final dir = d.dir('foo').io;
84+
85+
var results = await tweak.fix(dir, 'my_org/my_repo');
86+
expect(results.fixes, isEmpty);
87+
});
88+
89+
test('handles no bad lints', () async {
90+
await d.dir('foo', [
91+
d.file('analysis_options.yaml', r'''
92+
analyzer:
93+
language:
94+
strict-inference: true
95+
strict-raw-types: true
96+
97+
linter:
98+
rules:
99+
- avoid_classes_with_only_static_members
100+
- no_runtimeType_toString
101+
- prefer_const_declarations
102+
- use_if_null_to_convert_nulls_to_bools
103+
''')
104+
]).create();
105+
final dir = d.dir('foo').io;
106+
107+
var results = await tweak.fix(dir, 'my_org/my_repo');
108+
expect(results.fixes, isEmpty);
109+
110+
await d.dir('foo', [
111+
d.file('analysis_options.yaml', r'''
112+
analyzer:
113+
language:
114+
strict-inference: true
115+
strict-raw-types: true
116+
117+
linter:
118+
rules:
119+
- avoid_classes_with_only_static_members
120+
- no_runtimeType_toString
121+
- prefer_const_declarations
122+
- use_if_null_to_convert_nulls_to_bools
123+
''')
124+
]).validate();
125+
});
126+
127+
test('handles rules as map', skip: 'not implemented yet!', () async {
128+
print('TODO!');
129+
});
130+
}

0 commit comments

Comments
 (0)