Skip to content

Commit 65426d6

Browse files
committed
Merge branch 'master' into grind-support-flutter-packages
2 parents 9c8f496 + 7befb36 commit 65426d6

13 files changed

+779
-637
lines changed

analysis_options.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
include: package:pedantic/analysis_options.1.8.0.yaml
22

33
analyzer:
4+
errors:
5+
unused_import: warning
6+
unused_shown_name: warning
47
exclude:
58
- 'doc/**'
69
- 'lib/src/third_party/pkg/**'

bin/dartdoc.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import 'dart:io';
99

1010
import 'package:args/args.dart';
1111
import 'package:dartdoc/dartdoc.dart';
12-
import 'package:dartdoc/src/html/html_generator.dart';
1312
import 'package:dartdoc/src/logging.dart';
1413
import 'package:dartdoc/src/tool_runner.dart';
1514
import 'package:stack_trace/stack_trace.dart';

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 & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,43 +4,32 @@ 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';
9-
import 'package:dartdoc/src/warnings.dart';
1010

1111
/// A generator that does not generate files, but does traverse the [PackageGraph]
1212
/// and access [ModelElement.documentationAsHtml] for every element as though
1313
/// it were.
1414
class EmptyGenerator extends Generator {
1515
@override
16-
Future generate(PackageGraph _packageGraph, String outputDirectoryPath) {
17-
_onFileCreated.add(_packageGraph.defaultPackage.documentationAsHtml);
16+
Future generate(PackageGraph _packageGraph, FileWriter writer) {
17+
logProgress(_packageGraph.defaultPackage.documentationAsHtml);
1818
for (var package in Set.from([_packageGraph.defaultPackage])
1919
..addAll(_packageGraph.localPackages)) {
2020
for (var category in filterNonDocumented(package.categories)) {
21-
_onFileCreated.add(category.documentationAsHtml);
21+
logProgress(category.documentationAsHtml);
2222
}
2323

2424
for (Library lib in filterNonDocumented(package.libraries)) {
2525
filterNonDocumented(lib.allModelElements)
26-
.forEach((m) => _onFileCreated.add(m.documentationAsHtml));
26+
.forEach((m) => logProgress(m.documentationAsHtml));
2727
}
2828
}
2929
return null;
3030
}
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 = {};
4231
}
4332

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

lib/src/generator.dart

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
/// A library containing an abstract documentation generator.
66
library dartdoc.generator;
77

8-
import 'dart:async' show Stream, Future;
8+
import 'dart:async' show Future;
99
import 'dart:io' show Directory;
1010
import 'dart:isolate';
1111

@@ -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)