Skip to content

Commit 8e9ed19

Browse files
authored
Revert "Revert "Refactor html generator into frontend and backend (#2115)" (#2120)" (#2121)
This reverts commit 0cbefb9.
1 parent 57c7032 commit 8e9ed19

10 files changed

+777
-633
lines changed

lib/dartdoc.dart

Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
4997
class 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
}

lib/src/empty_generator.dart

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'dart:async';
44

55
import 'package:dartdoc/src/dartdoc_options.dart';
66
import 'package:dartdoc/src/generator.dart';
7+
import 'package:dartdoc/src/logging.dart';
78
import 'package:dartdoc/src/model/model.dart';
89
import 'package:dartdoc/src/model_utils.dart';
910
import 'package:dartdoc/src/warnings.dart';
@@ -13,34 +14,23 @@ import 'package:dartdoc/src/warnings.dart';
1314
/// it were.
1415
class EmptyGenerator extends Generator {
1516
@override
16-
Future generate(PackageGraph _packageGraph, String outputDirectoryPath) {
17-
_onFileCreated.add(_packageGraph.defaultPackage.documentationAsHtml);
17+
Future generate(PackageGraph _packageGraph, FileWriter writer) {
18+
logProgress(_packageGraph.defaultPackage.documentationAsHtml);
1819
for (var package in Set.from([_packageGraph.defaultPackage])
1920
..addAll(_packageGraph.localPackages)) {
2021
for (var category in filterNonDocumented(package.categories)) {
21-
_onFileCreated.add(category.documentationAsHtml);
22+
logProgress(category.documentationAsHtml);
2223
}
2324

2425
for (Library lib in filterNonDocumented(package.libraries)) {
2526
filterNonDocumented(lib.allModelElements)
26-
.forEach((m) => _onFileCreated.add(m.documentationAsHtml));
27+
.forEach((m) => logProgress(m.documentationAsHtml));
2728
}
2829
}
2930
return null;
3031
}
31-
32-
final StreamController<void> _onFileCreated = StreamController(sync: true);
33-
34-
@override
35-
36-
/// Implementation fires on each model element processed rather than
37-
/// file creation.
38-
Stream<void> get onFileCreated => _onFileCreated.stream;
39-
40-
@override
41-
final Map<String, Warnable> writtenFiles = {};
4232
}
4333

44-
Future<List<Generator>> initEmptyGenerators(DartdocOptionContext config) async {
45-
return [EmptyGenerator()];
34+
Future<Generator> initEmptyGenerator(DartdocOptionContext config) async {
35+
return EmptyGenerator();
4636
}

lib/src/generator.dart

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,23 @@ import 'package:dartdoc/src/package_meta.dart';
1515
import 'package:dartdoc/src/warnings.dart';
1616
import 'package:path/path.dart' as path;
1717

18+
abstract class FileWriter {
19+
/// All filenames written by this generator.
20+
Set<String> get writtenFiles;
21+
22+
/// Write [content] to a file at [filePath].
23+
void write(String filePath, Object content,
24+
{bool allowOverwrite, Warnable element});
25+
}
26+
1827
/// An abstract class that defines a generator that generates documentation for
1928
/// a given package.
2029
///
2130
/// Generators can generate documentation in different formats: html, json etc.
2231
abstract class Generator {
23-
/// Generate the documentation for the given package in the specified
24-
/// directory. Completes the returned future when done.
25-
Future generate(PackageGraph packageGraph, String outputDirectoryPath);
26-
27-
/// Fires when a file is created.
28-
Stream<void> get onFileCreated;
29-
30-
/// Fetches all filenames written by this generator.
31-
Map<String, Warnable> get writtenFiles;
32+
/// Generate the documentation for the given package using the specified
33+
/// writer. Completes the returned future when done.
34+
Future generate(PackageGraph packageGraph, FileWriter writer);
3235
}
3336

3437
/// Dartdoc options related to generators generally.

0 commit comments

Comments
 (0)