Skip to content

Commit 4a14687

Browse files
authored
Reactivate coverage tracking for dartdoc via coveralls (#1869)
* First try at enabling coveralls again for dartdoc * dartfmt * syntax error in travis.sh * add quotes * Fix coverage runner * coveralls installation problem fix? * coveralls is named coveralls * Use relative package paths and otherwise fix up the format run * Set up DART_VERSION correctly * Work around dart-lang/coverage#239 * Don't try to run coverage on sdk-analyzer passes * Add workarounds for bugs * Drop almost everything from travis config to try to speed this up * use packages flag instead of package-root * Revert test code / travis changes * dartfmt * fix merge problem: flutter goes first
1 parent de0e4c1 commit 4a14687

9 files changed

+367
-22
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
.settings/
99
build/
1010
doc/
11+
lcov.info
1112
packages
1213
pub.dartlang.org/
1314
testing/test_package/doc

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# dartdoc
22

33
[![Build Status](https://travis-ci.org/dart-lang/dartdoc.svg?branch=master)](https://travis-ci.org/dart-lang/dartdoc)
4+
[![Coverage Status](https://coveralls.io/repos/github/dart-lang/dartdoc/badge.svg?branch=master)](https://coveralls.io/github/dart-lang/dartdoc?branch=master)
5+
46

57
Use `dartdoc` to generate HTML documentaton for your Dart package.
68

bin/dartdoc.dart

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Future<List<DartdocOption>> createDartdocProgramOptions() async {
3838

3939
/// Analyzes Dart files and generates a representation of included libraries,
4040
/// classes, and members. Uses the current directory to look for libraries.
41-
void main(List<String> arguments) async {
41+
Future<void> main(List<String> arguments) async {
4242
DartdocOptionSet optionSet =
4343
await DartdocOptionSet.fromOptionGenerators('dartdoc', [
4444
createDartdocOptions,
@@ -52,17 +52,27 @@ void main(List<String> arguments) async {
5252
} on FormatException catch (e) {
5353
stderr.writeln(' fatal error: ${e.message}');
5454
stderr.writeln('');
55-
_printUsageAndExit(optionSet.argParser, exitCode: 64);
55+
_printUsage(optionSet.argParser);
56+
// Do not use exit() as this bypasses --pause-isolates-on-exit
57+
// TODO(jcollins-g): use exit once dart-lang/sdk#31747 is fixed.
58+
exitCode = 64;
59+
return;
5660
} on DartdocOptionError catch (e) {
5761
stderr.writeln(' fatal error: ${e.message}');
5862
stderr.writeln('');
59-
_printUsageAndExit(optionSet.argParser, exitCode: 64);
63+
_printUsage(optionSet.argParser);
64+
exitCode = 64;
65+
return;
6066
}
6167
if (optionSet['help'].valueAt(Directory.current)) {
62-
_printHelpAndExit(optionSet.argParser);
68+
_printHelp(optionSet.argParser);
69+
exitCode = 0;
70+
return;
6371
}
6472
if (optionSet['version'].valueAt(Directory.current)) {
65-
_printVersionAndExit(optionSet.argParser);
73+
_printVersion(optionSet.argParser);
74+
exitCode = 0;
75+
return;
6676
}
6777

6878
DartdocProgramOptionContext config =
@@ -88,34 +98,37 @@ void main(List<String> arguments) async {
8898
}, onError: (e, Chain chain) {
8999
if (e is DartdocFailure) {
90100
stderr.writeln('\nGeneration failed: ${e}.');
91-
exit(1);
101+
exitCode = 1;
102+
return;
92103
} else {
93104
stderr.writeln('\nGeneration failed: ${e}\n${chain.terse}');
94-
exit(255);
105+
exitCode = 255;
106+
return;
95107
}
96108
}, when: config.asyncStackTraces);
97109
} finally {
98110
// Clear out any cached tool snapshots and temporary directories.
111+
// ignore: unawaited_futures
99112
SnapshotCache.instance.dispose();
113+
// ignore: unawaited_futures
100114
ToolTempFileTracker.instance.dispose();
101115
}
116+
exitCode = 0;
117+
return;
102118
}
103119

104120
/// Print help if we are passed the help option.
105-
void _printHelpAndExit(ArgParser parser, {int exitCode: 0}) {
121+
void _printHelp(ArgParser parser) {
106122
print('Generate HTML documentation for Dart libraries.\n');
107-
_printUsageAndExit(parser, exitCode: exitCode);
108123
}
109124

110125
/// Print usage information on invalid command lines.
111-
void _printUsageAndExit(ArgParser parser, {int exitCode: 0}) {
126+
void _printUsage(ArgParser parser) {
112127
print('Usage: dartdoc [OPTIONS]\n');
113128
print(parser.usage);
114-
exit(exitCode);
115129
}
116130

117131
/// Print version information.
118-
void _printVersionAndExit(ArgParser parser) {
132+
void _printVersion(ArgParser parser) {
119133
print('dartdoc version: ${dartdocVersion}');
120-
exit(exitCode);
121134
}

lib/src/io_utils.dart

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'dart:async';
99
import 'dart:convert';
1010
import 'dart:io';
1111

12+
import 'package:dartdoc/src/tuple.dart';
1213
import 'package:path/path.dart' as pathLib;
1314

1415
/// Return a resolved path including the home directory in place of tilde
@@ -116,6 +117,88 @@ class MultiFutureTracker<T> {
116117
Future<void> wait() async => await _waitUntil(0);
117118
}
118119

120+
/// Keeps track of coverage data automatically for any processes run by this
121+
/// [CoverageSubprocessLauncher]. Requires that these be dart processes.
122+
class CoverageSubprocessLauncher extends SubprocessLauncher {
123+
CoverageSubprocessLauncher(String context, [Map<String, String> environment])
124+
: super(context, environment);
125+
126+
static int nextObservatoryPort = 9292;
127+
128+
/// Set this to true to enable coverage runs.
129+
static bool coverageEnabled = false;
130+
131+
/// A list of all coverage results picked up by all launchers.
132+
static List<Tuple2<String, Future<Iterable<Map>>>> coverageResults = [];
133+
134+
static Directory _tempDir;
135+
static Directory get tempDir =>
136+
_tempDir ??= Directory.systemTemp.createTempSync('dartdoc_coverage_data');
137+
138+
int _observatoryPort;
139+
// TODO(jcollins-g): use ephemeral ports
140+
int get observatoryPort => _observatoryPort ??= nextObservatoryPort++;
141+
142+
String _outCoverageFilename;
143+
String get outCoverageFilename => _outCoverageFilename ??=
144+
pathLib.join(tempDir.path, 'dart-cov-0-${observatoryPort}.json');
145+
146+
/// Call once all coverage runs have been generated by calling runStreamed
147+
/// on all [CoverageSubprocessLaunchers].
148+
static Future<void> generateCoverageToFile(File outputFile) async {
149+
if (!coverageEnabled) return Future.value(null);
150+
var currentCoverageResults = coverageResults;
151+
coverageResults = [];
152+
var launcher = SubprocessLauncher('format_coverage');
153+
154+
/// Wait for all coverage runs to finish.
155+
await Future.wait(currentCoverageResults.map((t) => t.item2));
156+
157+
return launcher.runStreamed(Platform.executable, [
158+
'tool/format_coverage.dart', // TODO(jcollins-g): use pub after dart-lang/coverage#240 is landed
159+
'--lcov',
160+
'-v',
161+
'-b', '.',
162+
'--packages=.packages',
163+
'--sdk-root=${pathLib.canonicalize(pathLib.join(pathLib.dirname(Platform.executable), '..'))}',
164+
'--out=${pathLib.canonicalize(outputFile.path)}',
165+
'--report-on=bin,lib',
166+
'-i', tempDir.path,
167+
]);
168+
}
169+
170+
@override
171+
Future<Iterable<Map>> runStreamed(String executable, List<String> arguments,
172+
{String workingDirectory}) {
173+
assert(executable == Platform.executable,
174+
'Must use dart executable for tracking coverage');
175+
176+
if (coverageEnabled) {
177+
arguments = [
178+
'--enable-vm-service=${observatoryPort}',
179+
'--pause-isolates-on-exit'
180+
]..addAll(arguments);
181+
}
182+
183+
Future<Iterable<Map>> results = super
184+
.runStreamed(executable, arguments, workingDirectory: workingDirectory);
185+
186+
if (coverageEnabled) {
187+
coverageResults.add(new Tuple2(
188+
outCoverageFilename,
189+
super.runStreamed('pub', [
190+
'run',
191+
'coverage:collect_coverage',
192+
'--wait-paused',
193+
'--resume-isolates',
194+
'--port=${observatoryPort}',
195+
'--out=${outCoverageFilename}',
196+
])));
197+
}
198+
return results;
199+
}
200+
}
201+
119202
class SubprocessLauncher {
120203
final String context;
121204
final Map<String, String> environment;

pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ dev_dependencies:
3434
build: ^1.0.1
3535
build_runner: ^1.0.0
3636
build_version: ^1.0.0
37+
coverage: any
3738
dhttpd: ^3.0.0
3839
glob: ^1.1.5
3940
grinder: ^0.8.2

0 commit comments

Comments
 (0)