1212/// line arguments.
1313library ;
1414
15- import 'dart:io' show Platform, exitCode, stderr, stdout;
15+ import 'dart:io' show exitCode, stderr, stdout;
1616
1717import 'package:analyzer/dart/element/element.dart' ;
1818import 'package:analyzer/file_system/file_system.dart' ;
@@ -26,8 +26,7 @@ import 'package:dartdoc/src/logging.dart';
2626import 'package:dartdoc/src/model/model.dart' ;
2727import 'package:dartdoc/src/package_meta.dart' ;
2828import 'package:dartdoc/src/source_linker.dart' ;
29- import 'package:dartdoc/src/tool_definition.dart' ;
30- import 'package:dartdoc/src/tool_runner.dart' ;
29+ import 'package:dartdoc/src/tool_configuration.dart' ;
3130import 'package:dartdoc/src/warnings.dart' ;
3231import 'package:path/path.dart' as p show Context, canonicalize;
3332import 'package:yaml/yaml.dart' ;
@@ -152,130 +151,6 @@ class CategoryConfiguration {
152151 }
153152}
154153
155- /// A configuration class that can interpret [ToolDefinition] s from a YAML map.
156- class ToolConfiguration {
157- final Map <String , ToolDefinition > tools;
158-
159- final ResourceProvider resourceProvider;
160-
161- late ToolRunner runner = ToolRunner (this );
162-
163- ToolConfiguration ._(this .tools, this .resourceProvider);
164-
165- static ToolConfiguration empty (ResourceProvider resourceProvider) {
166- return ToolConfiguration ._(const {}, resourceProvider);
167- }
168-
169- // TODO(jcollins-g): consider caching these.
170- static ToolConfiguration fromYamlMap (YamlMap yamlMap,
171- String canonicalYamlPath, ResourceProvider resourceProvider) {
172- var newToolDefinitions = < String , ToolDefinition > {};
173- var pathContext = resourceProvider.pathContext;
174- for (var MapEntry (: key, value: toolMap) in yamlMap.entries) {
175- var name = key.toString ();
176- if (toolMap is ! Map ) {
177- throw DartdocOptionError (
178- 'Tools must be defined as a map of tool names to definitions. Tool '
179- '$name is not a map.' );
180- }
181-
182- var description = toolMap['description' ].toString ();
183-
184- List <String >? findCommand ([String prefix = '' ]) {
185- // If the command key is given, then it applies to all platforms.
186- var commandFromKey = toolMap.containsKey ('${prefix }command' )
187- ? '${prefix }command'
188- : '$prefix ${Platform .operatingSystem }' ;
189- if (! toolMap.containsKey (commandFromKey)) {
190- return null ;
191- }
192- var commandFrom = toolMap[commandFromKey] as YamlNode ;
193- List <String > command;
194- if (commandFrom.value is String ) {
195- command = [commandFrom.toString ()];
196- } else if (commandFrom is YamlList ) {
197- command = commandFrom.map ((node) => node.toString ()).toList ();
198- } else {
199- throw DartdocOptionError (
200- 'Tool commands must be a path to an executable, or a list of '
201- 'strings that starts with a path to an executable. The tool '
202- "'$name ' has a '$commandFromKey ' entry that is a "
203- '${commandFrom .runtimeType }' );
204- }
205- if (command.isEmpty || command[0 ].isEmpty) {
206- throw DartdocOptionError (
207- 'Tool commands must not be empty. Tool $name command entry '
208- '"$commandFromKey " must contain at least one path.' );
209- }
210- return command;
211- }
212-
213- var command = findCommand ();
214- if (command == null ) {
215- throw DartdocOptionError (
216- 'At least one of "command" or "${Platform .operatingSystem }" must '
217- 'be defined for the tool $name .' );
218- }
219- var setupCommand = findCommand ('setup_' );
220-
221- var rawCompileArgs = toolMap[compileArgsTagName];
222- var compileArgs = switch (rawCompileArgs) {
223- null => const < String > [],
224- String () => [toolMap[compileArgsTagName].toString ()],
225- YamlList () =>
226- rawCompileArgs.map ((node) => node.toString ()).toList (growable: false ),
227- _ => throw DartdocOptionError (
228- 'Tool compile arguments must be a list of strings. The tool '
229- "'$name ' has a '$compileArgsTagName ' entry that is a "
230- '${rawCompileArgs .runtimeType }' ,
231- ),
232- };
233-
234- /// Validates [executable] and returns whether it is a Dart script.
235- bool isDartScript (String executable) {
236- var executableFile = resourceProvider.getFile (executable);
237- if (resourceProvider.isNotFound (executableFile)) {
238- throw DartdocOptionError ('Command executables must exist. '
239- 'The file "$executable " does not exist for tool $name .' );
240- }
241-
242- var isDartCommand = ToolDefinition .isDartExecutable (executable);
243- // Dart scripts don't need to be executable, because they'll be
244- // executed with the Dart binary.
245- if (! isDartCommand && ! resourceProvider.isExecutable (executableFile)) {
246- throw DartdocOptionError ('Non-Dart commands must be '
247- 'executable. The file "$executable " for tool $name does not have '
248- 'execute permission.' );
249- }
250- return isDartCommand;
251- }
252-
253- var executableRelativePath = command.removeAt (0 );
254- var executable = pathContext.canonicalize (
255- pathContext.join (canonicalYamlPath, executableRelativePath));
256- var isDartSetupScript = isDartScript (executable);
257- if (setupCommand != null ) {
258- var setupExecutableRelativePath = setupCommand.removeAt (0 );
259- var setupExecutable = pathContext.canonicalize (
260- pathContext.join (canonicalYamlPath, setupExecutableRelativePath));
261- // Setup commands aren't snapshotted, since they're only run once.
262- setupCommand = [
263- if (isDartSetupScript) Platform .resolvedExecutable,
264- setupExecutable,
265- ...setupCommand,
266- ];
267- }
268- newToolDefinitions[name] = ToolDefinition .fromCommand (
269- [executable, ...command],
270- setupCommand ?? const [],
271- description,
272- resourceProvider,
273- compileArgs: compileArgs);
274- }
275- return ToolConfiguration ._(newToolDefinitions, resourceProvider);
276- }
277- }
278-
279154/// A container class to keep track of where our yaml data came from.
280155class _YamlFileData {
281156 /// The map from the yaml file.
0 commit comments