@@ -44,40 +44,79 @@ class DartdocGeneratorOptionContext extends DartdocOptionContext
4444 : super (optionSet, dir);
4545}
4646
47+ class DartdocFileWriter implements FileWriter {
48+ final String outputDir;
49+ final Map <String , Warnable > _fileElementMap = {};
50+ @override
51+ final Set <String > writtenFiles = Set ();
52+
53+ DartdocFileWriter (this .outputDir);
54+
55+ @override
56+ void write (String filePath, Object content,
57+ {bool allowOverwrite, Warnable element}) {
58+ // Replace '/' separators with proper separators for the platform.
59+ String outFile = path.joinAll (filePath.split ('/' ));
60+
61+ allowOverwrite ?? = false ;
62+ if (! allowOverwrite) {
63+ if (_fileElementMap.containsKey (outFile)) {
64+ assert (element != null ,
65+ 'Attempted overwrite of ${outFile } without corresponding element' );
66+ Warnable originalElement = _fileElementMap[outFile];
67+ Iterable <Warnable > referredFrom =
68+ originalElement != null ? [originalElement] : null ;
69+ element? .warn (PackageWarning .duplicateFile,
70+ message: outFile, referredFrom: referredFrom);
71+ }
72+ }
73+ _fileElementMap[outFile] = element;
74+
75+ var file = File (path.join (outputDir, outFile));
76+ var parent = file.parent;
77+ if (! parent.existsSync ()) {
78+ parent.createSync (recursive: true );
79+ }
80+
81+ if (content is String ) {
82+ file.writeAsStringSync (content);
83+ } else if (content is List <int >) {
84+ file.writeAsBytesSync (content);
85+ } else {
86+ throw ArgumentError .value (
87+ content, 'content' , '`content` must be `String` or `List<int>`.' );
88+ }
89+
90+ writtenFiles.add (outFile);
91+ logProgress (outFile);
92+ }
93+ }
94+
4795/// Generates Dart documentation for all public Dart libraries in the given
4896/// directory.
4997class Dartdoc extends PackageBuilder {
50- final List < Generator > generators ;
98+ final Generator generator ;
5199 final Set <String > writtenFiles = Set ();
52100 Directory outputDir;
53101
54102 // Fires when the self checks make progress.
55103 final StreamController <String > _onCheckProgress =
56104 StreamController (sync : true );
57105
58- Dartdoc ._(DartdocOptionContext config, this .generators ) : super (config) {
106+ Dartdoc ._(DartdocOptionContext config, this .generator ) : super (config) {
59107 outputDir = Directory (config.output)..createSync (recursive: true );
60- generators.forEach ((g) => g.onFileCreated.listen (logProgress));
61108 }
62109
63110 /// An asynchronous factory method that builds Dartdoc's file writers
64111 /// and returns a Dartdoc object with them.
65112 static Future <Dartdoc > withDefaultGenerators (
66113 DartdocGeneratorOptionContext config) async {
67- List <Generator > generators = await initHtmlGenerators (config);
68- return Dartdoc ._(config, generators);
114+ return Dartdoc ._(config, await initHtmlGenerator (config));
69115 }
70116
71117 /// An asynchronous factory method that builds
72118 static Future <Dartdoc > withEmptyGenerator (DartdocOptionContext config) async {
73- List <Generator > generators = await initEmptyGenerators (config);
74- return Dartdoc ._(config, generators);
75- }
76-
77- /// Basic synchronous factory that gives a stripped down Dartdoc that won't
78- /// use generators. Useful for testing.
79- factory Dartdoc .withoutGenerators (DartdocOptionContext config) {
80- return Dartdoc ._(config, []);
119+ return Dartdoc ._(config, await initEmptyGenerator (config));
81120 }
82121
83122 Stream <String > get onCheckProgress => _onCheckProgress.stream;
@@ -94,19 +133,20 @@ class Dartdoc extends PackageBuilder {
94133 double seconds;
95134 packageGraph = await buildPackageGraph ();
96135 seconds = _stopwatch.elapsedMilliseconds / 1000.0 ;
97- logInfo (
98- "Initialized dartdoc with ${packageGraph . libraries . length } librar${packageGraph . libraries . length == 1 ? 'y' : 'ies' } "
136+ int libs = packageGraph.libraries.length;
137+ logInfo ( "Initialized dartdoc with ${libs } librar${libs == 1 ? 'y' : 'ies' } "
99138 "in ${seconds .toStringAsFixed (1 )} seconds" );
100139 _stopwatch.reset ();
101140
102- if (generators.isNotEmpty) {
141+ final generator = this .generator;
142+ if (generator != null ) {
103143 // Create the out directory.
104144 if (! outputDir.existsSync ()) outputDir.createSync (recursive: true );
105145
106- for ( var generator in generators) {
107- await generator.generate (packageGraph, outputDir.path );
108- writtenFiles. addAll (generator.writtenFiles.keys. map (path.normalize));
109- }
146+ DartdocFileWriter writer = DartdocFileWriter (outputDir.path);
147+ await generator.generate (packageGraph, writer );
148+
149+ writtenFiles. addAll (writer.writtenFiles);
110150 if (config.validateLinks && writtenFiles.isNotEmpty) {
111151 validateLinks (packageGraph, outputDir.path);
112152 }
@@ -122,8 +162,8 @@ class Dartdoc extends PackageBuilder {
122162 }
123163
124164 seconds = _stopwatch.elapsedMilliseconds / 1000.0 ;
125- logInfo (
126- "Documented ${packageGraph . localPublicLibraries . length } public librar${packageGraph . localPublicLibraries . length == 1 ? 'y' : 'ies' } "
165+ libs = packageGraph.localPublicLibraries.length;
166+ logInfo ( "Documented ${libs } public librar${libs == 1 ? 'y' : 'ies' } "
127167 "in ${seconds .toStringAsFixed (1 )} seconds" );
128168 return DartdocResults (config.topLevelPackageMeta, packageGraph, outputDir);
129169 }
0 commit comments