@@ -20,6 +20,7 @@ import 'package:dartdoc/src/generator/markdown_generator.dart';
2020import 'package:dartdoc/src/logging.dart' ;
2121import 'package:dartdoc/src/model/model.dart' ;
2222import 'package:dartdoc/src/package_meta.dart' ;
23+ import 'package:dartdoc/src/tool_runner.dart' ;
2324import 'package:dartdoc/src/tuple.dart' ;
2425import 'package:dartdoc/src/utils.dart' ;
2526import 'package:dartdoc/src/version.dart' ;
@@ -94,36 +95,53 @@ class DartdocFileWriter implements FileWriter {
9495
9596/// Generates Dart documentation for all public Dart libraries in the given
9697/// directory.
97- class Dartdoc extends PackageBuilder {
98+ class Dartdoc {
9899 final Generator generator;
100+ final PackageBuilder packageBuilder;
101+ final DartdocOptionContext config;
99102 final Set <String > writtenFiles = {};
100103 Directory outputDir;
101104
102105 // Fires when the self checks make progress.
103106 final StreamController <String > _onCheckProgress =
104107 StreamController (sync : true );
105108
106- Dartdoc ._(DartdocOptionContext config, this .generator) : super (config ) {
109+ Dartdoc ._(this . config, this .generator, this .packageBuilder ) {
107110 outputDir = Directory (config.output)..createSync (recursive: true );
108111 }
109112
110113 /// An asynchronous factory method that builds Dartdoc's file writers
111114 /// and returns a Dartdoc object with them.
112115 @Deprecated ('Prefer fromContext() instead' )
113116 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+ );
116125 }
117126
118127 /// 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+ );
121137 }
122138
123139 /// Asynchronous factory method that builds Dartdoc with a generator
124140 /// determined by the given context.
125141 static Future <Dartdoc > fromContext (
126- DartdocGeneratorOptionContext context) async {
142+ DartdocGeneratorOptionContext context,
143+ PackageBuilder packageBuilder,
144+ ) async {
127145 Generator generator;
128146 switch (context.format) {
129147 case 'html' :
@@ -135,7 +153,11 @@ class Dartdoc extends PackageBuilder {
135153 default :
136154 throw DartdocFailure ('Unsupported output format: ${context .format }' );
137155 }
138- return Dartdoc ._(context, generator);
156+ return Dartdoc ._(
157+ context,
158+ generator,
159+ packageBuilder,
160+ );
139161 }
140162
141163 Stream <String > get onCheckProgress => _onCheckProgress.stream;
@@ -150,7 +172,7 @@ class Dartdoc extends PackageBuilder {
150172 Future <DartdocResults > generateDocsBase () async {
151173 var _stopwatch = Stopwatch ()..start ();
152174 double seconds;
153- packageGraph = await buildPackageGraph ();
175+ packageGraph = await packageBuilder. buildPackageGraph ();
154176 seconds = _stopwatch.elapsedMilliseconds / 1000.0 ;
155177 var libs = packageGraph.libraries.length;
156178 logInfo ("Initialized dartdoc with ${libs } librar${libs == 1 ? 'y' : 'ies' } "
@@ -188,22 +210,31 @@ class Dartdoc extends PackageBuilder {
188210 }
189211
190212 Future <DartdocResults > generateDocs () async {
191- logInfo ('Documenting ${config .topLevelPackageMeta }...' );
213+ try {
214+ logInfo ('Documenting ${config .topLevelPackageMeta }...' );
192215
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+ }
197221
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 ();
203237 }
204- logInfo (
205- 'Success! Docs generated into ${dartdocResults .outDir .absolute .path }' );
206- return dartdocResults;
207238 }
208239
209240 /// Warn on file paths.
@@ -429,6 +460,37 @@ class Dartdoc extends PackageBuilder {
429460 _doOrphanCheck (packageGraph, origin, visited);
430461 _doSearchIndexCheck (packageGraph, origin, visited);
431462 }
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+ }
432494}
433495
434496/// This class is returned if dartdoc fails in an expected way (for instance, if
0 commit comments