@@ -20,6 +20,7 @@ import 'package:dartdoc/src/generator/markdown_generator.dart';
20
20
import 'package:dartdoc/src/logging.dart' ;
21
21
import 'package:dartdoc/src/model/model.dart' ;
22
22
import 'package:dartdoc/src/package_meta.dart' ;
23
+ import 'package:dartdoc/src/tool_runner.dart' ;
23
24
import 'package:dartdoc/src/tuple.dart' ;
24
25
import 'package:dartdoc/src/utils.dart' ;
25
26
import 'package:dartdoc/src/version.dart' ;
@@ -94,36 +95,53 @@ class DartdocFileWriter implements FileWriter {
94
95
95
96
/// Generates Dart documentation for all public Dart libraries in the given
96
97
/// directory.
97
- class Dartdoc extends PackageBuilder {
98
+ class Dartdoc {
98
99
final Generator generator;
100
+ final PackageBuilder packageBuilder;
101
+ final DartdocOptionContext config;
99
102
final Set <String > writtenFiles = {};
100
103
Directory outputDir;
101
104
102
105
// Fires when the self checks make progress.
103
106
final StreamController <String > _onCheckProgress =
104
107
StreamController (sync : true );
105
108
106
- Dartdoc ._(DartdocOptionContext config, this .generator) : super (config ) {
109
+ Dartdoc ._(this . config, this .generator, this .packageBuilder ) {
107
110
outputDir = Directory (config.output)..createSync (recursive: true );
108
111
}
109
112
110
113
/// An asynchronous factory method that builds Dartdoc's file writers
111
114
/// and returns a Dartdoc object with them.
112
115
@Deprecated ('Prefer fromContext() instead' )
113
116
static Future <Dartdoc > withDefaultGenerators (
114
- DartdocGeneratorOptionContext config) async {
115
- return Dartdoc ._(config, await initHtmlGenerator (config));
117
+ DartdocGeneratorOptionContext config,
118
+ PackageBuilder packageBuilder,
119
+ ) async {
120
+ return Dartdoc ._(
121
+ config,
122
+ await initHtmlGenerator (config),
123
+ packageBuilder,
124
+ );
116
125
}
117
126
118
127
/// Asynchronous factory method that builds Dartdoc with an empty generator.
119
- static Future <Dartdoc > withEmptyGenerator (DartdocOptionContext config) async {
120
- return Dartdoc ._(config, await initEmptyGenerator (config));
128
+ static Future <Dartdoc > withEmptyGenerator (
129
+ DartdocOptionContext config,
130
+ PackageBuilder packageBuilder,
131
+ ) async {
132
+ return Dartdoc ._(
133
+ config,
134
+ await initEmptyGenerator (config),
135
+ packageBuilder,
136
+ );
121
137
}
122
138
123
139
/// Asynchronous factory method that builds Dartdoc with a generator
124
140
/// determined by the given context.
125
141
static Future <Dartdoc > fromContext (
126
- DartdocGeneratorOptionContext context) async {
142
+ DartdocGeneratorOptionContext context,
143
+ PackageBuilder packageBuilder,
144
+ ) async {
127
145
Generator generator;
128
146
switch (context.format) {
129
147
case 'html' :
@@ -135,7 +153,11 @@ class Dartdoc extends PackageBuilder {
135
153
default :
136
154
throw DartdocFailure ('Unsupported output format: ${context .format }' );
137
155
}
138
- return Dartdoc ._(context, generator);
156
+ return Dartdoc ._(
157
+ context,
158
+ generator,
159
+ packageBuilder,
160
+ );
139
161
}
140
162
141
163
Stream <String > get onCheckProgress => _onCheckProgress.stream;
@@ -150,7 +172,7 @@ class Dartdoc extends PackageBuilder {
150
172
Future <DartdocResults > generateDocsBase () async {
151
173
var _stopwatch = Stopwatch ()..start ();
152
174
double seconds;
153
- packageGraph = await buildPackageGraph ();
175
+ packageGraph = await packageBuilder. buildPackageGraph ();
154
176
seconds = _stopwatch.elapsedMilliseconds / 1000.0 ;
155
177
var libs = packageGraph.libraries.length;
156
178
logInfo ("Initialized dartdoc with ${libs } librar${libs == 1 ? 'y' : 'ies' } "
@@ -188,22 +210,31 @@ class Dartdoc extends PackageBuilder {
188
210
}
189
211
190
212
Future <DartdocResults > generateDocs () async {
191
- logInfo ('Documenting ${config .topLevelPackageMeta }...' );
213
+ try {
214
+ logInfo ('Documenting ${config .topLevelPackageMeta }...' );
192
215
193
- var dartdocResults = await generateDocsBase ();
194
- if (dartdocResults.packageGraph.localPublicLibraries.isEmpty) {
195
- throw DartdocFailure ('dartdoc could not find any libraries to document' );
196
- }
216
+ var dartdocResults = await generateDocsBase ();
217
+ if (dartdocResults.packageGraph.localPublicLibraries.isEmpty) {
218
+ throw DartdocFailure (
219
+ 'dartdoc could not find any libraries to document' );
220
+ }
197
221
198
- final errorCount =
199
- dartdocResults.packageGraph.packageWarningCounter.errorCount;
200
- if (errorCount > 0 ) {
201
- throw DartdocFailure (
202
- 'dartdoc encountered $errorCount errors while processing.' );
222
+ final errorCount =
223
+ dartdocResults.packageGraph.packageWarningCounter.errorCount;
224
+ if (errorCount > 0 ) {
225
+ throw DartdocFailure (
226
+ 'dartdoc encountered $errorCount errors while processing.' );
227
+ }
228
+ logInfo (
229
+ 'Success! Docs generated into ${dartdocResults .outDir .absolute .path }' );
230
+ return dartdocResults;
231
+ } finally {
232
+ // Clear out any cached tool snapshots and temporary directories.
233
+ // ignore: unawaited_futures
234
+ SnapshotCache .instance.dispose ();
235
+ // ignore: unawaited_futures
236
+ ToolTempFileTracker .instance.dispose ();
203
237
}
204
- logInfo (
205
- 'Success! Docs generated into ${dartdocResults .outDir .absolute .path }' );
206
- return dartdocResults;
207
238
}
208
239
209
240
/// Warn on file paths.
@@ -429,6 +460,37 @@ class Dartdoc extends PackageBuilder {
429
460
_doOrphanCheck (packageGraph, origin, visited);
430
461
_doSearchIndexCheck (packageGraph, origin, visited);
431
462
}
463
+
464
+ /// Runs [generateDocs] function and properly handles the errors.
465
+ void executeGuarded () {
466
+ onCheckProgress.listen (logProgress);
467
+ // This function should *never* await `runZonedGuarded` because the errors
468
+ // thrown in generateDocs are uncaught. We want this because uncaught errors
469
+ // cause IDE debugger to automatically stop at the exception.
470
+ //
471
+ // If you await the zone, the code that comes after the await is not
472
+ // executed if the zone dies due to uncaught error. To avoid this confusion,
473
+ // never await `runZonedGuarded` and never change the return value of
474
+ // [executeGuarded].
475
+ runZonedGuarded (
476
+ generateDocs,
477
+ (e, chain) {
478
+ if (e is DartdocFailure ) {
479
+ stderr.writeln ('\n dartdoc failed: ${e }.' );
480
+ if (config.verboseWarnings) {
481
+ stderr.writeln (chain);
482
+ }
483
+ exitCode = 1 ;
484
+ } else {
485
+ stderr.writeln ('\n dartdoc failed: ${e }\n ${chain }' );
486
+ exitCode = 255 ;
487
+ }
488
+ },
489
+ zoneSpecification: ZoneSpecification (
490
+ print: (_, __, ___, String line) => logPrint (line),
491
+ ),
492
+ );
493
+ }
432
494
}
433
495
434
496
/// This class is returned if dartdoc fails in an expected way (for instance, if
0 commit comments