@@ -24,10 +24,10 @@ import 'package:dartdoc/dartdoc.dart';
2424import 'package:dartdoc/src/experiment_options.dart' ;
2525import 'package:dartdoc/src/io_utils.dart' ;
2626import 'package:dartdoc/src/source_linker.dart' ;
27+ import 'package:dartdoc/src/tool_definition.dart' ;
2728import 'package:dartdoc/src/tool_runner.dart' ;
28- import 'package:dartdoc/src/tuple.dart' ;
2929import 'package:dartdoc/src/warnings.dart' ;
30- import 'package:path/path.dart' as p show Context, canonicalize, extension ;
30+ import 'package:path/path.dart' as p show Context, canonicalize;
3131import 'package:yaml/yaml.dart' ;
3232
3333/// Constants to help with type checking, because T is int and so forth
@@ -39,7 +39,7 @@ const int _kIntVal = 0;
3939const double _kDoubleVal = 0.0 ;
4040const bool _kBoolVal = true ;
4141
42- const String _kCompileArgsTagName = 'compile_args' ;
42+ const String compileArgsTagName = 'compile_args' ;
4343
4444int get _usageLineLength => stdout.hasTerminal ? stdout.terminalColumns : null ;
4545
@@ -114,219 +114,6 @@ class CategoryConfiguration {
114114 }
115115}
116116
117- /// Defines the attributes of a tool in the options file, corresponding to
118- /// the 'tools' keyword in the options file, and populated by the
119- /// [ToolConfiguration] class.
120- class ToolDefinition {
121- /// A list containing the command and options to be run for this tool. The
122- /// first argument in the command is the tool executable, and will have its
123- /// path evaluated relative to the `dartdoc_options.yaml` location. Must not
124- /// be an empty list, or be null.
125- final List <String > command;
126-
127- /// A list containing the command and options to setup phase for this tool.
128- /// The first argument in the command is the tool executable, and will have
129- /// its path evaluated relative to the `dartdoc_options.yaml` location. May
130- /// be null or empty, in which case it will be ignored at setup time.
131- final List <String > setupCommand;
132-
133- /// A description of the defined tool. Must not be null.
134- final String description;
135-
136- /// If set, then the setup command has been run once for this tool definition.
137- bool setupComplete = false ;
138-
139- /// Returns true if the given executable path has an extension recognized as a
140- /// Dart extension (e.g. '.dart' or '.snapshot').
141- static bool isDartExecutable (String executable) {
142- var extension = p.extension (executable);
143- return extension == '.dart' || extension == '.snapshot' ;
144- }
145-
146- /// Creates a ToolDefinition or subclass that is appropriate for the command
147- /// given.
148- factory ToolDefinition .fromCommand (
149- List <String > command,
150- List <String > setupCommand,
151- String description,
152- ResourceProvider resourceProvider,
153- {List <String > compileArgs}) {
154- assert (command != null );
155- assert (command.isNotEmpty);
156- assert (description != null );
157- if (isDartExecutable (command[0 ])) {
158- return DartToolDefinition (
159- command, setupCommand, description, resourceProvider,
160- compileArgs: compileArgs ?? const []);
161- } else {
162- if (compileArgs != null && compileArgs.isNotEmpty) {
163- throw DartdocOptionError (
164- 'Compile arguments may only be specified for Dart tools, but '
165- '$_kCompileArgsTagName of $compileArgs were specified for '
166- '$command .' );
167- }
168- return ToolDefinition (command, setupCommand, description);
169- }
170- }
171-
172- ToolDefinition (this .command, this .setupCommand, this .description)
173- : assert (command != null ),
174- assert (command.isNotEmpty),
175- assert (description != null );
176-
177- @override
178- String toString () {
179- final commandString =
180- '${this is DartToolDefinition ? '(Dart) ' : '' }"${command .join (' ' )}"' ;
181- if (setupCommand == null ) {
182- return '$runtimeType : $commandString ($description )' ;
183- } else {
184- return '$runtimeType : $commandString , with setup command '
185- '"${setupCommand .join (' ' )}" ($description )' ;
186- }
187- }
188- }
189-
190- /// Manages the creation of a single snapshot file in a context where multiple
191- /// async functions could be trying to use and/or create it.
192- ///
193- /// To use:
194- ///
195- /// var s = new Snapshot(...);
196- ///
197- /// if (s.needsSnapshot) {
198- /// // create s.snapshotFile, then call:
199- /// s.snapshotCompleted();
200- /// } else {
201- /// await snapshotValid();
202- /// // use existing s.snapshotFile;
203- /// }
204- ///
205- class Snapshot {
206- File _snapshotFile;
207-
208- // TODO(srawlins): Deprecate this public getter; change private field to just
209- // be the absolute path.
210- File get snapshotFile => _snapshotFile;
211- final Completer <void > _snapshotCompleter = Completer ();
212-
213- Snapshot (Folder snapshotCache, String toolPath, int serial,
214- ResourceProvider resourceProvider) {
215- if (toolPath.endsWith ('.snapshot' )) {
216- _needsSnapshot = false ;
217- _snapshotFile = resourceProvider.getFile (toolPath);
218- snapshotCompleted ();
219- } else {
220- _snapshotFile = resourceProvider.getFile (resourceProvider.pathContext
221- .join (resourceProvider.pathContext.absolute (snapshotCache.path),
222- 'snapshot_$serial ' ));
223- }
224- }
225-
226- bool _needsSnapshot = true ;
227-
228- /// Will return true precisely once, unless [snapshotFile] was already a
229- /// snapshot. In that case, will always return false.
230- bool get needsSnapshot {
231- if (_needsSnapshot == true ) {
232- _needsSnapshot = false ;
233- return true ;
234- }
235- return _needsSnapshot;
236- }
237-
238- Future <void > snapshotValid () => _snapshotCompleter.future;
239-
240- void snapshotCompleted () => _snapshotCompleter.complete ();
241- }
242-
243- /// A singleton that keeps track of cached snapshot files. The [dispose]
244- /// function must be called before process exit to clean up snapshots in the
245- /// cache.
246- class SnapshotCache {
247- static SnapshotCache _instance;
248-
249- // TODO(srawlins): Make this final.
250- Folder snapshotCache;
251- final ResourceProvider _resourceProvider;
252- final Map <String , Snapshot > snapshots = {};
253- int _serial = 0 ;
254-
255- SnapshotCache ._(this ._resourceProvider)
256- : snapshotCache =
257- _resourceProvider.createSystemTemp ('dartdoc_snapshot_cache_' );
258-
259- static SnapshotCache get instance => _instance;
260-
261- static SnapshotCache createInstance (ResourceProvider resourceProvider) =>
262- _instance ?? = SnapshotCache ._(resourceProvider);
263-
264- Snapshot getSnapshot (String toolPath) {
265- if (snapshots.containsKey (toolPath)) {
266- return snapshots[toolPath];
267- }
268- snapshots[toolPath] =
269- Snapshot (snapshotCache, toolPath, _serial, _resourceProvider);
270- _serial++ ;
271- return snapshots[toolPath];
272- }
273-
274- void dispose () {
275- _instance = null ;
276- if (snapshotCache != null && snapshotCache.exists) {
277- return snapshotCache.delete ();
278- }
279- return null ;
280- }
281- }
282-
283- /// A special kind of tool definition for Dart commands.
284- class DartToolDefinition extends ToolDefinition {
285- final ResourceProvider _resourceProvider;
286-
287- /// A list of arguments to add to the snapshot compilation arguments.
288- final List <String > compileArgs;
289-
290- /// Takes a list of args to modify, and returns the name of the executable
291- /// to run. If no snapshot file existed, then create one and modify the args
292- /// so that if they are executed with dart, will result in the snapshot being
293- /// built.
294- Future <Tuple2 <String , Function ()>> modifyArgsToCreateSnapshotIfNeeded (
295- List <String > args) async {
296- assert (args[0 ] == command.first);
297- // Set up flags to create a new snapshot, if needed, and use the first run
298- // as the training run.
299- SnapshotCache .createInstance (_resourceProvider);
300- var snapshot = SnapshotCache .instance.getSnapshot (command.first);
301- var snapshotFile = snapshot.snapshotFile;
302- var needsSnapshot = snapshot.needsSnapshot;
303- if (needsSnapshot) {
304- args.insertAll (0 , [
305- // TODO(jcollins-g): remove ignore and verbosity resets once
306- // https://dart-review.googlesource.com/c/sdk/+/181421 is safely
307- // in the rearview mirror in dev/Flutter.
308- '--ignore-unrecognized-flags' ,
309- '--verbosity=error' ,
310- '--snapshot=${_resourceProvider .pathContext .absolute (snapshotFile .path )}' ,
311- '--snapshot_kind=app-jit' ,
312- ...compileArgs,
313- ]);
314- } else {
315- await snapshot.snapshotValid ();
316- // replace the first argument with the path to the snapshot.
317- args[0 ] = _resourceProvider.pathContext.absolute (snapshotFile.path);
318- }
319- return Tuple2 (_resourceProvider.resolvedExecutable,
320- needsSnapshot ? snapshot.snapshotCompleted : null );
321- }
322-
323- DartToolDefinition (List <String > command, List <String > setupCommand,
324- String description, this ._resourceProvider,
325- {this .compileArgs = const []})
326- : assert (compileArgs != null ),
327- super (command, setupCommand, description);
328- }
329-
330117/// A configuration class that can interpret [ToolDefinition] s from a YAML map.
331118class ToolConfiguration {
332119 final Map <String , ToolDefinition > tools;
@@ -396,17 +183,17 @@ class ToolConfiguration {
396183
397184 List <String > findArgs () {
398185 List <String > args;
399- if (toolMap.containsKey (_kCompileArgsTagName )) {
400- var compileArgs = toolMap[_kCompileArgsTagName ];
186+ if (toolMap.containsKey (compileArgsTagName )) {
187+ var compileArgs = toolMap[compileArgsTagName ];
401188 if (compileArgs is String ) {
402- args = [toolMap[_kCompileArgsTagName ].toString ()];
189+ args = [toolMap[compileArgsTagName ].toString ()];
403190 } else if (compileArgs is YamlList ) {
404191 args =
405192 compileArgs.map <String >((node) => node.toString ()).toList ();
406193 } else {
407194 throw DartdocOptionError (
408195 'Tool compile arguments must be a list of strings. The tool '
409- '$name has a $_kCompileArgsTagName entry that is a '
196+ '$name has a $compileArgsTagName entry that is a '
410197 '${compileArgs .runtimeType }' );
411198 }
412199 }
0 commit comments