Skip to content
This repository was archived by the owner on Nov 20, 2024. It is now read-only.

Commit 59cefe3

Browse files
authored
Merge pull request #1351 from dart-lang/sinc_sdk
Calculate “since” dart sdk mapping
2 parents 531a0a9 + 9162ab0 commit 59cefe3

File tree

6 files changed

+291
-25
lines changed

6 files changed

+291
-25
lines changed

pubspec.yaml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,10 @@ dependencies:
2020
dev_dependencies:
2121
cli_util: ^0.1.2
2222
dart_style: ^1.1.0
23-
github:
24-
git:
25-
# todo(pq): update when 4.0.1 is released (https://github.com/DirectMyFile/github.dart/issues/128)
26-
url: git://github.com/DirectMyFile/github.dart.git
27-
ref: 0a04ae19e06f95b8afe018d666eea96585869492
23+
github: ^4.0.1
2824
grinder: ^0.8.0
2925
markdown: ^2.0.0
3026
matcher: ^0.12.0
3127
path: ^1.2.0
28+
pub_semver: ^1.4.2
3229
test: ^1.0.0

tool/crawl.dart

Lines changed: 86 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ import 'dart:io';
66

77
import 'package:analyzer/src/lint/config.dart';
88
import 'package:analyzer/src/lint/registry.dart';
9+
import 'package:github/server.dart';
910
import 'package:http/http.dart' as http;
1011
import 'package:linter/src/analyzer.dart';
1112
import 'package:linter/src/rules.dart';
13+
import 'package:pub_semver/pub_semver.dart';
1214
import 'package:yaml/yaml.dart';
1315

1416
const _allPathSuffix = '/example/all.yaml';
@@ -48,6 +50,33 @@ Future<List<String>> get stagehandRules async =>
4850
Future<int> get latestMinor async =>
4951
_latestMinor ??= await _readLatestMinorVersion();
5052

53+
List<String> _sdkTags;
54+
55+
Future<List<String>> get sdkTags async => _sdkTags ??= await _fetchSdkTags();
56+
57+
/// We don't care about SDKs previous to this bottom.
58+
final Version bottomDartSdk = new Version(2, 0, 0);
59+
60+
Future<List<String>> _fetchSdkTags() {
61+
var github = createGitHubClient();
62+
var slug = RepositorySlug('dart-lang', 'sdk');
63+
64+
return github.repositories.listTags(slug).map((t) => t.name).where((t) {
65+
// Filter on numeric release tags.
66+
if (!t.startsWith(new RegExp(r'\d+'))) {
67+
return false;
68+
}
69+
70+
// Filter on bottom.
71+
try {
72+
var version = Version.parse(t);
73+
return version.compareTo(bottomDartSdk) >= 0;
74+
} on FormatException {
75+
return false;
76+
}
77+
}).toList();
78+
}
79+
5180
Iterable<LintRule> _registeredLints;
5281

5382
Iterable<LintRule> get registeredLints {
@@ -58,10 +87,27 @@ Iterable<LintRule> get registeredLints {
5887
return _registeredLints;
5988
}
6089

61-
Future<String> findSinceLinter(LintRule lint) async {
90+
Future<String> findSinceDartSdk(String linterVersion) async =>
91+
await dartSdkForLinter(linterVersion);
92+
93+
Future<String> dartSdkForLinter(String version) async {
94+
var sdkVersions = <String>[];
95+
var sdks = await sdkTags;
96+
for (var sdk in sdks) {
97+
var linterVersion = await linterForDartSdk(sdk);
98+
if (linterVersion == version) {
99+
sdkVersions.add(sdk);
100+
}
101+
}
102+
103+
sdkVersions.sort();
104+
return sdkVersions.isNotEmpty ? sdkVersions.first : null;
105+
}
106+
107+
Future<String> findSinceLinter(String lint) async {
62108
// History recorded in `all.yaml` starts in minor 31.
63109
var rules_31 = await rulesForVersion(31);
64-
if (rules_31.contains(lint.name)) {
110+
if (rules_31.contains(lint)) {
65111
var version = await _crawlForVersion(lint);
66112
if (version != null) {
67113
return version;
@@ -72,7 +118,7 @@ Future<String> findSinceLinter(LintRule lint) async {
72118
for (var minor = 31; minor <= latest; ++minor) {
73119
var rules = await rulesForVersion(minor);
74120
if (rules != null) {
75-
if (rules.contains(lint.name)) {
121+
if (rules.contains(lint)) {
76122
return '0.1.$minor';
77123
}
78124
}
@@ -87,12 +133,12 @@ Future<int> _readLatestMinorVersion() async {
87133
return int.parse(pubspec['version'].split('.').last);
88134
}
89135

90-
Future<String> _crawlForVersion(LintRule lint) async {
136+
Future<String> _crawlForVersion(String lint) async {
91137
var client = new http.Client();
92138
for (int minor = 1; minor < 31; ++minor) {
93139
var version = '0.1.$minor';
94-
var req = await client
95-
.get('$_rulePathPrefix/$version/lib/src/rules/${lint.name}.dart');
140+
var req =
141+
await client.get('$_rulePathPrefix/$version/lib/src/rules/$lint.dart');
96142
if (req.statusCode == 200) {
97143
return version;
98144
}
@@ -109,6 +155,36 @@ Future<List<String>> rulesForVersion(int minor) async {
109155
return null;
110156
}
111157

158+
Map<String, String> _dartSdkToLinterMap = <String, String>{};
159+
160+
Future<String> linterForDartSdk(String sdk) async =>
161+
_dartSdkToLinterMap[sdk] ??= await _fetchLinterForVersion(sdk);
162+
163+
Future<String> _fetchLinterForVersion(String version) async {
164+
var deps = await _fetchDEPSforVersion(version);
165+
if (deps != null) {
166+
for (var line in deps.split('\n')) {
167+
if (line.trim().startsWith('"lint')) {
168+
// "linter_tag": "0.1.59",
169+
var split = line.trim().split('"linter_tag":');
170+
if (split.length == 2) {
171+
// "0.1.59",
172+
return split[1].split('"')[1];
173+
}
174+
}
175+
}
176+
}
177+
return null;
178+
}
179+
180+
Future<String> _fetchDEPSforVersion(String version) async {
181+
var client = new http.Client();
182+
//https://raw.githubusercontent.com/dart-lang/sdk/2.1.0-dev.1.0/DEPS
183+
var req = await client
184+
.get('https://raw.githubusercontent.com/dart-lang/sdk/$version/DEPS');
185+
return req.body;
186+
}
187+
112188
Future<LintConfig> _fetchConfig(String url) async {
113189
var client = new http.Client();
114190
var req = await client.get(url);
@@ -117,6 +193,10 @@ Future<LintConfig> _fetchConfig(String url) async {
117193

118194
Future<List<String>> _fetchRules(String optionsUrl) async {
119195
var config = await _fetchConfig(optionsUrl);
196+
if (config == null) {
197+
print('no config found for: $optionsUrl (SKIPPED)');
198+
return <String>[];
199+
}
120200
var rules = <String>[];
121201
for (var ruleConfig in config.ruleConfigs) {
122202
rules.add(ruleConfig.name);

tool/scorecard.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,13 @@ void printAll(ScoreCard scorecard) {
4040

4141
void printMarkdownTable(ScoreCard scorecard) {
4242
print(
43-
'| name | since | fix | flutter user | flutter repo | pedantic | stagehand | status | bug refs |');
43+
'| name | linter | dart sdk | fix | flutter user | flutter repo | pedantic | stagehand | status | bug refs |');
4444
print(
45-
'| :--- | :--- | :---: | :---:| :---: | :---: | :---: | :---: | :--- |');
45+
'| :--- | :--- | :--- | :---: | :---:| :---: | :---: | :---: | :---: | :--- |');
4646
scorecard.forEach((lint) {
4747
var sb = StringBuffer('| `${lint.name}` |');
4848
sb.write(' ${lint.since.sinceLinter} |');
49+
sb.write(' ${lint.since.sinceDartSdk} |');
4950
sb.write('${lint.hasFix ? " $bulb" : ""} |');
5051
sb.write('${lint.ruleSets.contains('flutter') ? " $checkMark" : ""} |');
5152
sb.write(

tool/since.dart

Lines changed: 97 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,28 @@
44

55
import 'dart:io';
66

7+
import 'package:pub_semver/pub_semver.dart';
78
import 'package:yaml/yaml.dart';
89

910
import 'crawl.dart';
1011

1112
main() async {
12-
// Uncomment to (re)generate since.yaml contents.
13+
// Uncomment to (re)generate since/linter.yaml contents.
1314
// for (var lint in registeredLints) {
1415
// var since = await findSinceLinter(lint);
1516
// if (since != null) {
1617
// print('${lint.name}: $since');
1718
// }
19+
// }
20+
21+
// Uncomment to (re)generate since/dart_sdk.yaml contents.
22+
// var tags = await sdkTags;
23+
// for (var tag in sdkTags)) {
24+
// var version = await fetchLinterForVersion(tag);
25+
// if (version.startsWith('@')) {
26+
// version = version.substring(1);
27+
// }
28+
// print('$tag: $version');
1829
// }
1930

2031
await sinceMap.then((m) => m.entries.forEach(print));
@@ -26,22 +37,96 @@ Future<Map<String, SinceInfo>> get sinceMap async =>
2637
_sinceMap ??= await _getSinceInfo();
2738

2839
Future<Map<String, SinceInfo>> _getSinceInfo() async {
29-
var cache = await new File('tool/since.yaml').readAsString();
30-
YamlMap yaml = loadYamlNode(cache);
31-
Map<String, SinceInfo> sinceMap = <String, SinceInfo>{};
32-
for (var lint in registeredLints) {
33-
var linterVersion = yaml[lint.name];
34-
sinceMap[lint.name] =
35-
new SinceInfo(linterVersion ?? await findSinceLinter(lint));
40+
var linterCache = await new File('tool/since/linter.yaml').readAsString();
41+
YamlMap linterVersionCache = loadYamlNode(linterCache);
42+
43+
var sinceMap = <String, SinceInfo>{};
44+
for (var lint in registeredLints.map((l) => l.name)) {
45+
var linterVersion = linterVersionCache[lint];
46+
sinceMap[lint] = new SinceInfo(
47+
sinceLinter: linterVersion ?? await findSinceLinter(lint),
48+
sinceDartSdk: await _sinceSdkForLinter(linterVersion));
3649
}
3750
return sinceMap;
3851
}
3952

53+
Map<String, String> _dartSdkMap;
54+
55+
Future<Map<String, String>> get dartSdkMap async {
56+
if (_dartSdkMap == null) {
57+
var dartSdkCache =
58+
await new File('tool/since/dart_sdk.yaml').readAsString();
59+
YamlMap yamlMap = loadYamlNode(dartSdkCache);
60+
_dartSdkMap =
61+
yamlMap.map((k, v) => new MapEntry(k.toString(), v.toString()));
62+
63+
var sdks = await sdkTags;
64+
for (var sdk in sdks) {
65+
if (!_dartSdkMap.containsKey(sdk)) {
66+
var linterVersion = await linterForDartSdk(sdk);
67+
_dartSdkMap[sdk] = linterVersion;
68+
print('fetched...');
69+
print('$sdk : $linterVersion');
70+
print('(consider caching in tool/dart_sdk.yaml)');
71+
}
72+
}
73+
}
74+
return _dartSdkMap;
75+
}
76+
77+
Version earliestLinterInDart2 = Version.parse('0.1.58');
78+
79+
Future<String> _sinceSdkForLinter(String linterVersionString) async {
80+
if (linterVersionString == null) {
81+
return null;
82+
}
83+
84+
var linterVersion = Version.parse(linterVersionString);
85+
if (linterVersion.compareTo(earliestLinterInDart2) < 0) {
86+
return bottomDartSdk.toString();
87+
}
88+
89+
var sdkVersions = <String>[];
90+
var sdkCache = await dartSdkMap;
91+
for (var sdkEntry in sdkCache.entries) {
92+
if (Version.parse(sdkEntry.value) == linterVersion) {
93+
sdkVersions.add(sdkEntry.key);
94+
}
95+
}
96+
if (sdkVersions.isEmpty) {
97+
var nextLinter = await _nextLinterVersion(linterVersion);
98+
return _sinceSdkForLinter(nextLinter);
99+
}
100+
101+
sdkVersions.sort();
102+
return sdkVersions.first;
103+
}
104+
105+
Future<String> _nextLinterVersion(Version linterVersion) async {
106+
for (String version in await linterVersions) {
107+
if (Version.parse(version).compareTo(linterVersion) > 0) {
108+
return version;
109+
}
110+
}
111+
return null;
112+
}
113+
114+
List<String> _linterVersions;
115+
Future<List<String>> get linterVersions async {
116+
if (_linterVersions == null) {
117+
_linterVersions = <String>[];
118+
for (var minor = 0; minor <= await latestMinor; ++minor) {
119+
_linterVersions.add('0.1.$minor');
120+
}
121+
}
122+
return _linterVersions;
123+
}
124+
40125
class SinceInfo {
41-
// todo (pq): add sinceSdk
42-
String sinceLinter;
43-
SinceInfo(this.sinceLinter);
126+
final String sinceLinter;
127+
final String sinceDartSdk;
128+
SinceInfo({this.sinceLinter, this.sinceDartSdk});
44129

45130
@override
46-
String toString() => 'linter: $sinceLinter';
131+
String toString() => 'linter: $sinceLinter | sdk: $sinceDartSdk';
47132
}

0 commit comments

Comments
 (0)