From cb35597b291ae8e67888c2c8e4a68aee1bc64f19 Mon Sep 17 00:00:00 2001 From: pq Date: Fri, 4 Jan 2019 05:28:43 -0800 Subject: [PATCH 1/3] scoring wip --- pubspec.yaml | 5 ++ tool/crawl.dart | 49 ++++++++++++++ tool/scorecard.dart | 159 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 213 insertions(+) create mode 100644 tool/crawl.dart create mode 100644 tool/scorecard.dart diff --git a/pubspec.yaml b/pubspec.yaml index 360808b7a..fafe52eac 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -20,6 +20,11 @@ dependencies: dev_dependencies: cli_util: ^0.1.2 dart_style: ^1.1.0 + github: + git: + # todo(pq): update when 4.0.1 is released (https://github.com/DirectMyFile/github.dart/issues/128) + url: git://github.com/DirectMyFile/github.dart.git + ref: 0a04ae19e06f95b8afe018d666eea96585869492 grinder: ^0.8.0 markdown: ^2.0.0 matcher: ^0.12.0 diff --git a/tool/crawl.dart b/tool/crawl.dart new file mode 100644 index 000000000..38fec3424 --- /dev/null +++ b/tool/crawl.dart @@ -0,0 +1,49 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analyzer/src/lint/config.dart'; +import 'package:http/http.dart' as http; + +const _flutterOptionsUrl = + 'https://raw.githubusercontent.com/flutter/flutter/master/packages/flutter/lib/analysis_options_user.yaml'; + +const _flutterRepoOptionsUrl = +'https://raw.githubusercontent.com/flutter/flutter/master/analysis_options.yaml'; + +const _pedanticOptionsUrl = + 'https://raw.githubusercontent.com/dart-lang/pedantic/master/lib/analysis_options.yaml'; +const _stagehandOptionsUrl = + 'https://raw.githubusercontent.com/dart-lang/stagehand/master/templates/analysis_options.yaml'; + +List _flutterRules; +List _flutterRepoRules; +List _pedanticRules; +List _stagehandRules; + +Future> get flutterRules async => + _flutterRules ??= await _fetchRules(_flutterOptionsUrl); + +Future> get flutterRepoRules async => + _flutterRepoRules ??= await _fetchRules(_flutterRepoOptionsUrl); + +Future> get pedanticRules async => + _pedanticRules ??= await _fetchRules(_pedanticOptionsUrl); + +Future> get stagehandRules async => + _stagehandRules ??= await _fetchRules(_stagehandOptionsUrl); + +Future _fetchConfig(String url) async { + var client = new http.Client(); + var req = await client.get(url); + return processAnalysisOptionsFile(req.body); +} + +Future> _fetchRules(String optionsUrl) async { + var config = await _fetchConfig(optionsUrl); + var rules = []; + for (var ruleConfig in config.ruleConfigs) { + rules.add(ruleConfig.name); + } + return rules; +} diff --git a/tool/scorecard.dart b/tool/scorecard.dart new file mode 100644 index 000000000..adde46a89 --- /dev/null +++ b/tool/scorecard.dart @@ -0,0 +1,159 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:analyzer/src/lint/registry.dart'; +import 'package:github/server.dart'; +import 'package:http/http.dart' as http; +import 'package:linter/src/analyzer.dart'; +import 'package:linter/src/rules.dart'; + +import 'crawl.dart'; + +const bulb = '💡'; +const checkMark = '✅'; + +Iterable _registeredLints; + +Iterable get registeredLints { + if (_registeredLints == null) { + registerLintRules(); + _registeredLints = Registry.ruleRegistry; + } + return _registeredLints; +} + +main() async { + var scorecard = await ScoreCard.calculate(); + + //printAll(scorecard); + printMarkdownTable(scorecard); +} + +void printAll(ScoreCard scorecard) { + print('-- ALL -----------------------------------------'); + scorecard.forEach(print); +} + +void printMarkdownTable(ScoreCard scorecard) { + print( + '| name | fix | flutter user | flutter repo | pedantic | stagehand | status | bug refs |'); + print('| :--- | :---: | :---:| :---: | :---: | :---: | :---: | :--- |'); + scorecard.forEach((lint) { + var sb = StringBuffer('| `${lint.name}` |'); + sb.write('${lint.hasFix ? " $bulb" : ""} |'); + sb.write('${lint.ruleSets.contains('flutter') ? " $checkMark" : ""} |'); + sb.write( + '${lint.ruleSets.contains('flutter_repo') ? " $checkMark" : ""} |'); + sb.write('${lint.ruleSets.contains('pedantic') ? " $checkMark" : ""} |'); + sb.write('${lint.ruleSets.contains('stagehand') ? " $checkMark" : ""} |'); + sb.write('${lint.maturity != 'stable' ? ' **${lint.maturity}** ' : ""} |'); + sb.write(' ${lint.bugReferences.join(", ")} |'); + print(sb.toString()); + }); +} + +class ScoreCard { + int get lintCount => registeredLints.length; + + List scores = []; + + void add(LintScore score) { + scores.add(score); + } + + void forEach(void f(LintScore element)) { + scores.forEach(f); + } + + static Future> _getLintsWithFixes() async { + var client = http.Client(); + var req = await client.get( + 'https://raw.githubusercontent.com/dart-lang/sdk/master/pkg/analysis_server/lib/src/services/correction/fix_internal.dart'); + var lintsWithFixes = []; + for (var word in req.body.split(RegExp('\\s+'))) { + if (word.startsWith('LintNames.')) { + var lintName = word.substring(10); + if (lintName.endsWith(')')) { + lintName = lintName.substring(0, lintName.length - 1); + } + lintsWithFixes.add(lintName); + } + } + return lintsWithFixes; + } + + static Future> _getIssues() async { + var github = createGitHubClient(); + var slug = RepositorySlug('dart-lang', 'linter'); + return github.issues.listByRepo(slug).toList(); + } + + static Future calculate() async { + var lintsWithFixes = await _getLintsWithFixes(); + var flutterRuleset = await flutterRules; + var flutterRepoRuleset = await flutterRepoRules; + var pedanticRuleset = await pedanticRules; + var stagehandRuleset = await stagehandRules; + + var issues = await _getIssues(); + var bugs = issues.where(_isBug).toList(); + + var scorecard = ScoreCard(); + for (var lint in registeredLints) { + var ruleSets = []; + if (flutterRuleset.contains(lint.name)) { + ruleSets.add('flutter'); + } + if (flutterRepoRuleset.contains(lint.name)) { + ruleSets.add('flutter_repo'); + } + if (pedanticRuleset.contains(lint.name)) { + ruleSets.add('pedantic'); + } + if (stagehandRuleset.contains(lint.name)) { + ruleSets.add('stagehand'); + } + var bugReferences = []; + for (var bug in bugs) { + if (bug.title.contains(lint.name)) { + bugReferences.add('#${bug.number.toString()}'); + } + } + + scorecard.add(LintScore( + name: lint.name, + hasFix: lintsWithFixes.contains(lint.name), + maturity: lint.maturity.name, + ruleSets: ruleSets, + bugReferences: bugReferences)); + } + + return scorecard; + } +} + +bool _isBug(Issue issue) => issue.labels.map((l) => l.name).contains('bug'); + +class LintScore { + String name; + bool hasFix; + String maturity; + + List ruleSets; + List bugReferences; + + LintScore( + {this.name, + this.hasFix, + this.maturity, + this.ruleSets, + this.bugReferences}); + + String get _ruleSets => ruleSets.isNotEmpty ? ' ${ruleSets.toString()}' : ''; + + @override + String toString() => '$name$_ruleSets${hasFix ? " 💡" : ""}'; +} From 3f3de13cc49d3b09f58befd2b5d6f0b11b57e66c Mon Sep 17 00:00:00 2001 From: pq Date: Fri, 4 Jan 2019 05:34:50 -0800 Subject: [PATCH 2/3] date adjust --- tool/crawl.dart | 2 +- tool/scorecard.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tool/crawl.dart b/tool/crawl.dart index 38fec3424..8b22d4e34 100644 --- a/tool/crawl.dart +++ b/tool/crawl.dart @@ -1,4 +1,4 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. diff --git a/tool/scorecard.dart b/tool/scorecard.dart index adde46a89..160efdfdf 100644 --- a/tool/scorecard.dart +++ b/tool/scorecard.dart @@ -1,4 +1,4 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. From ec544296f72f9ddec435daff29f9a29c22da9043 Mon Sep 17 00:00:00 2001 From: pq Date: Fri, 4 Jan 2019 05:38:57 -0800 Subject: [PATCH 3/3] fmt --- tool/crawl.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tool/crawl.dart b/tool/crawl.dart index 8b22d4e34..4c2aebd45 100644 --- a/tool/crawl.dart +++ b/tool/crawl.dart @@ -7,10 +7,8 @@ import 'package:http/http.dart' as http; const _flutterOptionsUrl = 'https://raw.githubusercontent.com/flutter/flutter/master/packages/flutter/lib/analysis_options_user.yaml'; - const _flutterRepoOptionsUrl = -'https://raw.githubusercontent.com/flutter/flutter/master/analysis_options.yaml'; - + 'https://raw.githubusercontent.com/flutter/flutter/master/analysis_options.yaml'; const _pedanticOptionsUrl = 'https://raw.githubusercontent.com/dart-lang/pedantic/master/lib/analysis_options.yaml'; const _stagehandOptionsUrl =