Skip to content

Commit a1d6dc7

Browse files
authored
Added tool support for running snapshotted Dart scripts. (#1820)
Since tools are run so often, it makes sense to use snapshots to run them, so this makes it so that Dartdoc creates a snapshot automatically of a tool the first time it is run, and then uses that snapshot from then on. See the README.md for the new instructions, but basically, it creates a snapshot in a tempdir the first time the tool is run, using the first time arguments as training arguments for the compiler. The second time and beyond, it is run using the snapshot. This results in about a 20-100x speedup in startup time for the tool invocations. If you'd rather build and use your own snapshots, it does recognize the .snapshot suffix, and will just use that one instead of generating its own. In addition, I added the ability to run a "setup" command before the first time a tool runs. This would allow generation of script code, or fetching one-time information needed for the tool to run. I also added some more tests for things that weren't broken, but also weren't tested, and converted the tool_runner test to get its information from parsing a YAML block instead of setting up the map programmatically (more code coverage that way, and I can test the snapshotted executables that way).
1 parent 19fb1a9 commit a1d6dc7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1154
-152
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.24.2-dev
2+
* Added support for automatic snapshotting of external tools (i.e. for {@tool}
3+
directives) written in Dart.
4+
15
## 0.24.1
26
* Added more metadata (element name, project name, etc.) to external tool invocations.
37
(#1801)

README.md

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -259,11 +259,15 @@ dartdoc:
259259
tools:
260260
drill:
261261
command: ["bin/drill.dart"]
262+
setup_command: ["bin/setup.dart"]
262263
description: "Puts holes in things."
263264
echo:
264265
macos: ['/bin/sh', '-c', 'echo']
266+
setup_macos: ['/bin/sh', '-c', 'setup.sh']
265267
linux: ['/bin/sh', '-c', 'echo']
268+
setup_linux: ['/bin/sh', '-c', 'setup.sh']
266269
windows: ['C:\\Windows\\System32\\cmd.exe', '/c', 'echo']
270+
setup_windows: ['/bin/sh', '-c', 'setup.sh']
267271
description: 'Works on everything'
268272
```
269273

@@ -272,16 +276,32 @@ that are common among all executions. If the first element of this list is a
272276
filename that ends in `.dart`, then the dart executable will automatically be
273277
used to invoke that script. The `command` defined will be run on all platforms.
274278

275-
The `macos`, `linux`, and `windows` tags are used to describe the commands to
276-
be run on each of those platforms.
279+
If the `command` is a Dart script, then the first time it is run, a snapshot
280+
will be created using the input and first-time arguments as training arguments,
281+
and will be run from the snapshot from then on. Note that the `Platform.script`
282+
property will point to the snapshot location during the snapshot runs. You can
283+
obtain the original `.dart` script location in a tool by looking at the
284+
`TOOL_COMMAND` environment variable.
285+
286+
The `setup_command` tag is used to describe a command executable, and any
287+
options, for a command that is run once before running a tool for the first
288+
time. If the first element of this list is a filename that ends in `.dart`, then
289+
the dart executable will automatically be used to invoke that script. The
290+
`setup_command` defined will be run on all platforms. If the setup command is a
291+
Dart script, then it will be run with the Dart executable, but will not be
292+
snapshotted, as it will only be run once.
293+
294+
The `macos`, `linux`, and `windows` tags are used to describe the commands to be
295+
run on each of those platforms, and the `setup_macos`, `setup_linux`, and
296+
`setup_windows` tags define setup commands for their respective platforms.
277297

278298
The `description` is just a short description of the tool for use as help text.
279299

280300
Only tools which are configured in the `dartdoc_options.yaml` file are able to
281301
be invoked.
282302

283-
To use the tools in comment documentation, use the `{@tool <name> [<options> ...] [$INPUT]}`
284-
directive to invoke the tool:
303+
To use the tools in comment documentation, use the `{@tool <name> [<options>
304+
...] [$INPUT]}` directive to invoke the tool:
285305

286306
```dart
287307
/// {@tool drill --flag --option="value" $INPUT}
@@ -301,6 +321,27 @@ the equivalent of having the following comment in the code:
301321
/// # `This is the text that will be sent to the tool as input.`
302322
```
303323

324+
#### Tool Environment Variables
325+
326+
Tools have a number of environment variables available to them. They will be
327+
interpolated into any arguments given to the tool as `$ENV_VAR` or `$(ENV_VAR)`,
328+
as well as available in the process environment.
329+
330+
- `SOURCE_LINE`: The source line number in the original source code.
331+
- `SOURCE_COLUMN`: The source column in the original source code.
332+
- `SOURCE_PATH`: The relative path from the package root to the original source file.
333+
- `PACKAGE_PATH`: The path to the package root.
334+
- `PACKAGE_NAME`: The name of the package.
335+
- `LIBRARY_NAME`: The name of the library, if any.
336+
- `ELEMENT_NAME`: The name of the element that this doc is attached to.
337+
- `TOOL_COMMAND`: The path to the original `.dart` script or command executable.
338+
- `DART_SNAPSHOT_CACHE`: The path to the directory containing the snapshot files
339+
of the tools. This directory will be removed before Dartdoc exits.
340+
- `DART_SETUP_COMMAND`: The path to the setup command script, if any.
341+
- `INVOCATION_INDEX`: An index for how many times a tool directive has been
342+
invoked on the current dartdoc block. Allows multiple tool invocations on the
343+
same block to be differentiated.
344+
304345
### Injecting HTML
305346

306347
It happens rarely, but sometimes what you really need is to inject some raw HTML

bin/dartdoc.dart

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -71,23 +71,28 @@ void main(List<String> arguments) async {
7171
Dartdoc dartdoc = await Dartdoc.withDefaultGenerators(config);
7272

7373
dartdoc.onCheckProgress.listen(logProgress);
74-
await Chain.capture(() async {
75-
await runZoned(() async {
76-
DartdocResults results = await dartdoc.generateDocs();
77-
logInfo('Success! Docs generated into ${results.outDir.absolute.path}');
78-
},
79-
zoneSpecification: new ZoneSpecification(
80-
print: (Zone self, ZoneDelegate parent, Zone zone, String line) =>
81-
logPrint(line)));
82-
}, onError: (e, Chain chain) {
83-
if (e is DartdocFailure) {
84-
stderr.writeln('\nGeneration failed: ${e}.');
85-
exit(1);
86-
} else {
87-
stderr.writeln('\nGeneration failed: ${e}\n${chain.terse}');
88-
exit(255);
89-
}
90-
});
74+
try {
75+
await Chain.capture(() async {
76+
await runZoned(() async {
77+
DartdocResults results = await dartdoc.generateDocs();
78+
logInfo('Success! Docs generated into ${results.outDir.absolute.path}');
79+
},
80+
zoneSpecification: new ZoneSpecification(
81+
print: (Zone self, ZoneDelegate parent, Zone zone, String line) =>
82+
logPrint(line)));
83+
}, onError: (e, Chain chain) {
84+
if (e is DartdocFailure) {
85+
stderr.writeln('\nGeneration failed: ${e}.');
86+
exit(1);
87+
} else {
88+
stderr.writeln('\nGeneration failed: ${e}\n${chain.terse}');
89+
exit(255);
90+
}
91+
});
92+
} finally {
93+
// Clear out any cached tool snapshots.
94+
SnapshotCache.instance.dispose();
95+
}
9196
}
9297

9398
/// Print help if we are passed the help option.

lib/dartdoc.dart

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,12 @@ class Dartdoc extends PackageBuilder {
181181
"dartdoc could not find any libraries to document. Run `pub get` and try again.");
182182
}
183183

184-
if (dartdocResults.packageGraph.packageWarningCounter.errorCount > 0) {
185-
throw new DartdocFailure("dartdoc encountered errors while processing");
184+
final int errorCount =
185+
dartdocResults.packageGraph.packageWarningCounter.errorCount;
186+
if (errorCount > 0) {
187+
dartdocResults.packageGraph.flushWarnings();
188+
throw new DartdocFailure(
189+
"dartdoc encountered $errorCount} errors while processing.");
186190
}
187191

188192
return dartdocResults;

0 commit comments

Comments
 (0)