Merge pull request dart-lang/markdown#106 from dart-lang/better_tools
Better tools
diff --git a/pkgs/markdown/lib/src/block_parser.dart b/pkgs/markdown/lib/src/block_parser.dart
index 6e1cf9f..bc53d03 100644
--- a/pkgs/markdown/lib/src/block_parser.dart
+++ b/pkgs/markdown/lib/src/block_parser.dart
@@ -598,7 +598,7 @@
}
endItem();
- var itemNodes = <Node>[];
+ var itemNodes = <Element>[];
var anyEmptyLines = removeTrailingEmptyLines(items);
var anyEmptyLinesBetweenBlocks = false;
diff --git a/pkgs/markdown/tool/common_mark_stats.dart b/pkgs/markdown/tool/common_mark_stats.dart
index 2bcb4c3..9d54293 100644
--- a/pkgs/markdown/tool/common_mark_stats.dart
+++ b/pkgs/markdown/tool/common_mark_stats.dart
@@ -1,11 +1,10 @@
-library markdown.tool.common_mark_stats;
-
+import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:io';
import 'dart:mirrors';
-import 'package:args/args.dart' show ArgParser;
+import 'package:args/args.dart';
import 'package:collection/collection.dart';
import 'package:html/dom.dart' as dom;
import 'package:html/parser.dart' show parseFragment;
@@ -16,23 +15,52 @@
// Locate the "test" directory. Use mirrors so that this works with the test
// package, which loads this suite into an isolate.
-String get _currentDir => p.dirname(currentMirrorSystem()
- .findLibrary(#markdown.tool.common_mark_stats)
- .uri
- .path);
+String get _currentDir => p
+ .dirname((reflect(main) as ClosureMirror).function.location.sourceUri.path);
-void main(List<String> args) {
+main(List<String> args) async {
final parser = new ArgParser()
- ..addOption('section', help: 'Restrict tests to one section')
- ..addFlag('raw', defaultsTo: false, help: 'raw JSON format')
- ..addFlag('verbose', defaultsTo: false, help: 'verbose output');
- var options = parser.parse(args);
+ ..addOption('section',
+ help: 'Restrict tests to one section, provided after the option.')
+ ..addFlag('raw',
+ defaultsTo: false, help: 'raw JSON format', negatable: false)
+ ..addFlag('update-files',
+ defaultsTo: false,
+ help: 'Update stats files in $_currentDir',
+ negatable: false)
+ ..addFlag('verbose',
+ defaultsTo: false, help: 'verbose output', negatable: false)
+ ..addFlag('help', defaultsTo: false, negatable: false);
- var specifiedSection = options['section'];
- var raw = options['raw'];
- var verbose = options['verbose'];
+ ArgResults options;
- var sections = loadCommonMarkSections();
+ try {
+ options = parser.parse(args);
+ } on FormatException catch (e) {
+ stderr.writeln(e);
+ print(parser.usage);
+ exitCode = 64;
+ return;
+ }
+
+ if (options['help']) {
+ print(parser.usage);
+ return;
+ }
+
+ var specifiedSection = options['section'] as String;
+ var raw = options['raw'] as bool;
+ var verbose = options['verbose'] as bool;
+ var updateFiles = options['update-files'] as bool;
+
+ if (updateFiles && (raw || verbose || (specifiedSection != null))) {
+ stderr.writeln('The `update-files` flag must be used by itself');
+ print(parser.usage);
+ exitCode = 64; // unix standard improper usage
+ return;
+ }
+
+ var sections = _loadCommonMarkSections();
var scores = new SplayTreeMap<String, SplayTreeMap<int, bool>>(
compareAsciiLowerCaseNatural);
@@ -71,17 +99,12 @@
}
});
- if (raw) {
- var encoder = const JsonEncoder.withIndent(' ', _convert);
- try {
- print(encoder.convert(scores));
- } on JsonUnsupportedObjectError catch (e) {
- print(e.cause);
- print(e.unsupportedObject.runtimeType);
- rethrow;
- }
- } else {
- _printFriendly(scores);
+ if (raw || updateFiles) {
+ _printRaw(scores, updateFiles);
+ }
+
+ if (!raw || updateFiles) {
+ _printFriendly(scores, updateFiles);
}
}
@@ -97,12 +120,47 @@
return obj;
}
-void _printFriendly(SplayTreeMap<String, SplayTreeMap<int, bool>> scores) {
+Future _printRaw(scores, bool updateFiles) async {
+ IOSink sink;
+ if (updateFiles) {
+ var path = p.join(_currentDir, 'common_mark_stats.json');
+ print('Updating $path');
+ var file = new File(path);
+ sink = file.openWrite();
+ } else {
+ sink = stdout;
+ }
+
+ var encoder = const JsonEncoder.withIndent(' ', _convert);
+ try {
+ sink.writeln(encoder.convert(scores));
+ } on JsonUnsupportedObjectError catch (e) {
+ stderr.writeln(e.cause);
+ stderr.writeln(e.unsupportedObject.runtimeType);
+ rethrow;
+ }
+
+ await sink.flush();
+ await sink.close();
+}
+
+Future _printFriendly(SplayTreeMap<String, SplayTreeMap<int, bool>> scores,
+ bool updateFiles) async {
const countWidth = 4;
var totalValid = 0;
var totalExamples = 0;
+ IOSink sink;
+ if (updateFiles) {
+ var path = p.join(_currentDir, 'common_mark_stats.txt');
+ print('Updating $path');
+ var file = new File(path);
+ sink = file.openWrite();
+ } else {
+ sink = stdout;
+ }
+
scores.forEach((section, map) {
var total = map.values.length;
totalExamples += total;
@@ -113,16 +171,19 @@
var pct = (100 * sectionValidCount / total).toStringAsFixed(1).padLeft(5);
- print('${sectionValidCount.toString().padLeft(countWidth)} '
+ sink.writeln('${sectionValidCount.toString().padLeft(countWidth)} '
'of ${total.toString().padLeft(countWidth)} '
'– ${pct}% $section');
});
var pct = (100 * totalValid / totalExamples).toStringAsFixed(1).padLeft(5);
- print('${totalValid.toString().padLeft(countWidth)} '
+ sink.writeln('${totalValid.toString().padLeft(countWidth)} '
'of ${totalExamples.toString().padLeft(countWidth)} '
'– ${pct}% TOTAL');
+
+ await sink.flush();
+ await sink.close();
}
/// Compare two DOM trees for equality.
@@ -178,7 +239,7 @@
return true;
}
-Map<String, List<CommonMarkTestCase>> loadCommonMarkSections() {
+Map<String, List<CommonMarkTestCase>> _loadCommonMarkSections() {
var testFile = new File(p.join(_currentDir, _commonMarkTests));
var testsJson = testFile.readAsStringSync();
diff --git a/pkgs/markdown/tool/common_mark_stats.json b/pkgs/markdown/tool/common_mark_stats.json
index 7f783f3..c07aa12 100644
--- a/pkgs/markdown/tool/common_mark_stats.json
+++ b/pkgs/markdown/tool/common_mark_stats.json
@@ -64,12 +64,12 @@
"189": true,
"190": true,
"191": true,
- "192": false,
- "193": false,
- "194": false,
+ "192": true,
+ "193": true,
+ "194": true,
"195": true,
"196": true,
- "197": true,
+ "197": false,
"198": false,
"199": true,
"200": true,
@@ -79,11 +79,11 @@
"204": true,
"205": true,
"206": true,
- "207": false,
+ "207": true,
"208": true,
- "209": true,
- "210": false,
- "211": false,
+ "209": false,
+ "210": true,
+ "211": true,
"212": true
},
"Code spans": {
@@ -517,7 +517,7 @@
"239": false,
"240": false,
"241": false,
- "242": true,
+ "242": false,
"243": false,
"244": false,
"245": true,
@@ -525,9 +525,9 @@
"247": true,
"248": true,
"249": true,
- "250": false,
- "251": false,
- "252": false,
+ "250": true,
+ "251": true,
+ "252": true,
"253": false,
"254": true,
"255": false,
@@ -548,10 +548,10 @@
"268": false,
"269": false,
"270": false,
- "271": false,
+ "271": true,
"272": false,
"273": false,
- "274": false,
+ "274": true,
"275": false,
"276": false,
"277": false,
@@ -610,16 +610,16 @@
"57": true,
"58": true,
"59": true,
- "60": false,
+ "60": true,
"61": false,
- "62": false,
+ "62": true,
"63": false,
"64": true,
"65": true,
- "66": false,
- "67": false,
+ "66": true,
+ "67": true,
"68": false,
- "69": false,
+ "69": true,
"70": true,
"71": true,
"72": true,
@@ -647,7 +647,7 @@
"616": true
},
"Thematic breaks": {
- "11": false,
+ "11": true,
"12": true,
"13": true,
"14": true,