@@ -134,82 +134,66 @@ class ToolConfiguration {
134134 for (var entry in yamlMap.entries) {
135135 var name = entry.key.toString ();
136136 var toolMap = entry.value;
137- String ? description;
138- List <String >? compileArgs;
139- List <String >? command;
140- List <String >? setupCommand;
141- if (toolMap is Map ) {
142- description = toolMap['description' ].toString ();
143- List <String >? findCommand ([String prefix = '' ]) {
144- List <String >? command;
145- // If the command key is given, then it applies to all platforms.
146- var commandFromKey = toolMap.containsKey ('${prefix }command' )
147- ? '${prefix }command'
148- : '$prefix ${Platform .operatingSystem }' ;
149- if (toolMap.containsKey (commandFromKey)) {
150- var commandFrom = toolMap[commandFromKey] as YamlNode ;
151- if (commandFrom.value is String ) {
152- command = [commandFrom.toString ()];
153- if (command[0 ].isEmpty) {
154- throw DartdocOptionError (
155- 'Tool commands must not be empty. Tool $name command entry '
156- '"$commandFromKey " must contain at least one path.' );
157- }
158- } else if (commandFrom is YamlList ) {
159- command =
160- commandFrom.map <String >((node) => node.toString ()).toList ();
161- if (command.isEmpty) {
162- throw DartdocOptionError (
163- 'Tool commands must not be empty. Tool $name command entry '
164- '"$commandFromKey " must contain at least one path.' );
165- }
166- } else {
167- throw DartdocOptionError (
168- 'Tool commands must be a path to an executable, or a list of '
169- 'strings that starts with a path to an executable. '
170- 'The tool $name has a $commandFromKey entry that is a '
171- '${commandFrom .runtimeType }' );
172- }
173- }
174- return command;
175- }
176-
177- command = findCommand ();
178- setupCommand = findCommand ('setup_' );
179-
180- List <String >? findArgs () {
181- List <String >? args;
182- if (toolMap.containsKey (compileArgsTagName)) {
183- var compileArgs = toolMap[compileArgsTagName];
184- if (compileArgs is String ) {
185- args = [toolMap[compileArgsTagName].toString ()];
186- } else if (compileArgs is YamlList ) {
187- args = compileArgs
188- .map <String >((node) => node.toString ())
189- .toList (growable: false );
190- } else {
191- throw DartdocOptionError (
192- 'Tool compile arguments must be a list of strings. The tool '
193- '$name has a $compileArgsTagName entry that is a '
194- '${compileArgs .runtimeType }' );
195- }
196- }
197- return args;
198- }
199-
200- compileArgs = findArgs ();
201- } else {
137+ if (toolMap is ! Map ) {
202138 throw DartdocOptionError (
203139 'Tools must be defined as a map of tool names to definitions. Tool '
204140 '$name is not a map.' );
205141 }
142+
143+ var description = toolMap['description' ].toString ();
144+
145+ List <String >? findCommand ([String prefix = '' ]) {
146+ // If the command key is given, then it applies to all platforms.
147+ var commandFromKey = toolMap.containsKey ('${prefix }command' )
148+ ? '${prefix }command'
149+ : '$prefix ${Platform .operatingSystem }' ;
150+ if (! toolMap.containsKey (commandFromKey)) {
151+ return null ;
152+ }
153+ var commandFrom = toolMap[commandFromKey] as YamlNode ;
154+ List <String > command;
155+ if (commandFrom.value is String ) {
156+ command = [commandFrom.toString ()];
157+ } else if (commandFrom is YamlList ) {
158+ command = commandFrom.map ((node) => node.toString ()).toList ();
159+ } else {
160+ throw DartdocOptionError (
161+ 'Tool commands must be a path to an executable, or a list of '
162+ 'strings that starts with a path to an executable. The tool '
163+ "'$name ' has a '$commandFromKey ' entry that is a "
164+ '${commandFrom .runtimeType }' );
165+ }
166+ if (command.isEmpty || command[0 ].isEmpty) {
167+ throw DartdocOptionError (
168+ 'Tool commands must not be empty. Tool $name command entry '
169+ '"$commandFromKey " must contain at least one path.' );
170+ }
171+ return command;
172+ }
173+
174+ var command = findCommand ();
206175 if (command == null ) {
207176 throw DartdocOptionError (
208177 'At least one of "command" or "${Platform .operatingSystem }" must '
209178 'be defined for the tool $name .' );
210179 }
211-
212- bool validateExecutable (String executable) {
180+ var setupCommand = findCommand ('setup_' );
181+
182+ var rawCompileArgs = toolMap[compileArgsTagName];
183+ var compileArgs = switch (rawCompileArgs) {
184+ null => const < String > [],
185+ String () => [toolMap[compileArgsTagName].toString ()],
186+ YamlList () =>
187+ rawCompileArgs.map ((node) => node.toString ()).toList (growable: false ),
188+ _ => throw DartdocOptionError (
189+ 'Tool compile arguments must be a list of strings. The tool '
190+ "'$name ' has a '$compileArgsTagName ' entry that is a "
191+ '${rawCompileArgs .runtimeType }' ,
192+ ),
193+ };
194+
195+ /// Validates [executable] and returns whether it is a Dart script.
196+ bool isDartScript (String executable) {
213197 var executableFile = resourceProvider.getFile (executable);
214198 if (resourceProvider.isNotFound (executableFile)) {
215199 throw DartdocOptionError ('Command executables must exist. '
@@ -230,24 +214,24 @@ class ToolConfiguration {
230214 var executableRelativePath = command.removeAt (0 );
231215 var executable = pathContext.canonicalize (
232216 pathContext.join (canonicalYamlPath, executableRelativePath));
233- validateExecutable (executable);
217+ var isDartSetupScript = isDartScript (executable);
234218 if (setupCommand != null ) {
235219 var setupExecutableRelativePath = setupCommand.removeAt (0 );
236220 var setupExecutable = pathContext.canonicalize (
237221 pathContext.join (canonicalYamlPath, setupExecutableRelativePath));
238- var isDartSetupCommand = validateExecutable (executable);
239222 // Setup commands aren't snapshotted, since they're only run once.
240- setupCommand = (isDartSetupCommand
241- ? [Platform .resolvedExecutable, setupExecutable]
242- : [setupExecutable]) +
243- setupCommand;
223+ setupCommand = [
224+ if (isDartSetupScript) Platform .resolvedExecutable,
225+ setupExecutable,
226+ ...setupCommand,
227+ ];
244228 }
245229 newToolDefinitions[name] = ToolDefinition .fromCommand (
246- [executable] + command,
230+ [executable, ... command] ,
247231 setupCommand ?? const [],
248232 description,
249233 resourceProvider,
250- compileArgs: compileArgs ?? const [] );
234+ compileArgs: compileArgs);
251235 }
252236 return ToolConfiguration ._(newToolDefinitions, resourceProvider);
253237 }
@@ -267,12 +251,19 @@ class _YamlFileData {
267251/// An enum to specify the multiple different kinds of data an option might
268252/// represent.
269253enum OptionKind {
270- other, // Make no assumptions about the option data; it may be of any type
271- // or semantic.
272- file, // Option data references a filename or filenames with strings.
273- dir, // Option data references a directory name or names with strings.
274- glob, // Option data references globs with strings that may cover many
275- // filenames and/or directories.
254+ /// Make no assumptions about the option data; it may be of any type or
255+ /// semantic.
256+ other,
257+
258+ /// Option data references a filename or filenames with strings.
259+ file,
260+
261+ /// Option data references a directory name or names with strings.
262+ dir,
263+
264+ /// Option data references globs with strings that may cover many filenames
265+ /// and/or directories.
266+ glob,
276267}
277268
278269/// Some DartdocOption subclasses need to keep track of where they
@@ -289,7 +280,7 @@ class _OptionValueWithContext<T> {
289280 /// If non-null, the basename of the configuration file the value came from.
290281 String ? definingFile;
291282
292- /// A [pathLib.Context] variable initialized with canonicalDirectoryPath.
283+ /// A [pathLib.Context] variable initialized with ' canonicalDirectoryPath' .
293284 p.Context pathContext;
294285
295286 /// Build a _OptionValueWithContext.
@@ -507,7 +498,6 @@ abstract class DartdocOption<T extends Object?> {
507498 dynamic valueAt (Folder dir);
508499
509500 /// Calls [valueAt] with the working directory at the start of the program.
510- // TODO(jcollins-g): use of dynamic. https://github.com/dart-lang/dartdoc/issues/2814
511501 Object ? valueAtCurrent () => valueAt (_directoryCurrent);
512502
513503 late final Folder _directoryCurrent =
@@ -539,7 +529,7 @@ abstract class DartdocOption<T extends Object?> {
539529 }
540530
541531 /// Get the immediate child of this node named [name] and its value at [dir] .
542- U getValueAs <U extends Object ? >(String name, Folder dir) =>
532+ U getValueAs <U >(String name, Folder dir) =>
543533 _children[name]? .valueAt (dir) as U ;
544534
545535 /// Apply the function [visit] to [this] and all children.
@@ -556,19 +546,16 @@ abstract class DartdocOption<T extends Object?> {
556546class DartdocOptionFileSynth <T > extends DartdocOption <T >
557547 with DartdocSyntheticOption <T >, _DartdocFileOption <T > {
558548 @override
559- final bool parentDirOverridesChild;
560- @override
561549 final T Function (DartdocSyntheticOption <T >, Folder ) _compute;
562550
563551 DartdocOptionFileSynth (
564552 String name, this ._compute, ResourceProvider resourceProvider,
565- {bool mustExist = false ,
566- String help = '' ,
567- OptionKind optionIs = OptionKind .other,
568- this .parentDirOverridesChild = false ,
569- ConvertYamlToType <T >? convertYamlToType})
570- : super (name, null , help, optionIs, mustExist, convertYamlToType,
571- resourceProvider);
553+ {String help = '' })
554+ : super (
555+ name, null , help, OptionKind .other, false , null , resourceProvider);
556+
557+ @override
558+ bool get parentDirOverridesChild => false ;
572559
573560 @override
574561 T ? valueAt (Folder dir) {
@@ -580,7 +567,7 @@ class DartdocOptionFileSynth<T> extends DartdocOption<T>
580567 }
581568
582569 @override
583- void _onMissing (
570+ Never _onMissing (
584571 _OptionValueWithContext <T > valueWithContext, String missingPath) {
585572 if (valueWithContext.definingFile != null ) {
586573 _onMissingFromFiles (valueWithContext, missingPath);
@@ -597,11 +584,7 @@ class DartdocOptionArgSynth<T> extends DartdocOption<T>
597584 @override
598585 final String ? abbr;
599586 @override
600- final bool hide;
601- @override
602587 final bool negatable;
603- @override
604- final bool splitCommas;
605588
606589 @override
607590 final T Function (DartdocSyntheticOption <T >, Folder ) _compute;
@@ -611,15 +594,19 @@ class DartdocOptionArgSynth<T> extends DartdocOption<T>
611594 {this .abbr,
612595 bool mustExist = false ,
613596 String help = '' ,
614- this .hide = false ,
615597 OptionKind optionIs = OptionKind .other,
616- this .negatable = false ,
617- this .splitCommas = false })
618- : assert (T is ! Iterable || splitCommas == true ),
598+ this .negatable = false })
599+ : assert (T is ! Iterable ),
619600 super (name, null , help, optionIs, mustExist, null , resourceProvider);
620601
621602 @override
622- void _onMissing (
603+ bool get hide => false ;
604+
605+ @override
606+ bool get splitCommas => false ;
607+
608+ @override
609+ Never _onMissing (
623610 _OptionValueWithContext <T > valueWithContext, String missingPath) {
624611 _onMissingFromArgs (valueWithContext, missingPath);
625612 }
@@ -663,11 +650,11 @@ mixin DartdocSyntheticOption<T> implements DartdocOption<T> {
663650 }
664651
665652 @override
666- void _onMissing (
653+ Never _onMissing (
667654 _OptionValueWithContext <T > valueWithContext, String missingPath) =>
668655 _onMissingFromSynthetic (valueWithContext, missingPath);
669656
670- void _onMissingFromSynthetic (
657+ Never _onMissingFromSynthetic (
671658 _OptionValueWithContext <T > valueWithContext, String missingPath) {
672659 var description = 'Synthetic configuration option $name from <internal>' ;
673660 throw DartdocFileMissing (
@@ -784,31 +771,31 @@ class DartdocOptionArgOnly<T> extends DartdocOption<T>
784771class DartdocOptionArgFile <T > extends DartdocOption <T >
785772 with _DartdocArgOption <T >, _DartdocFileOption <T > {
786773 @override
787- final String ? abbr;
788- @override
789- final bool hide;
790- @override
791774 final bool negatable;
792775 @override
793- final bool parentDirOverridesChild;
794- @override
795776 final bool splitCommas;
796777
797778 DartdocOptionArgFile (
798779 String name, T defaultsTo, ResourceProvider resourceProvider,
799- {this .abbr,
800- bool mustExist = false ,
780+ {bool mustExist = false ,
801781 String help = '' ,
802- this .hide = false ,
803782 OptionKind optionIs = OptionKind .other,
804783 this .negatable = false ,
805- this .parentDirOverridesChild = false ,
806784 this .splitCommas = false })
807785 : super (name, defaultsTo, help, optionIs, mustExist, null ,
808786 resourceProvider);
809787
810788 @override
811- void _onMissing (
789+ String ? get abbr => null ;
790+
791+ @override
792+ bool get hide => false ;
793+
794+ @override
795+ bool get parentDirOverridesChild => false ;
796+
797+ @override
798+ Never _onMissing (
812799 _OptionValueWithContext <T > valueWithContext, String missingPath) {
813800 if (valueWithContext.definingFile != null ) {
814801 _onMissingFromFiles (valueWithContext, missingPath);
@@ -858,22 +845,21 @@ mixin _DartdocFileOption<T> implements DartdocOption<T> {
858845 String get fieldName => keys.join ('.' );
859846
860847 @override
861- void _onMissing (
848+ Never _onMissing (
862849 _OptionValueWithContext <T > valueWithContext, String missingPath) =>
863850 _onMissingFromFiles (valueWithContext, missingPath);
864851
865- void _onMissingFromFiles (
852+ Never _onMissingFromFiles (
866853 _OptionValueWithContext <T > valueWithContext, String missingPath) {
867854 var dartdocYaml = resourceProvider.pathContext.join (
868855 valueWithContext.canonicalDirectoryPath, valueWithContext.definingFile);
869856 throw DartdocFileMissing ('Field $fieldName from $dartdocYaml , set to '
870857 '${valueWithContext .value }, resolves to missing path: "$missingPath "' );
871858 }
872859
873- @override
874-
875860 /// Searches for a value in configuration files relative to [dir] , and if not
876861 /// found, returns [defaultsTo] .
862+ @override
877863 T ? valueAt (Folder dir) => _valueAtFromFiles (dir) ?? defaultsTo;
878864
879865 /// The backing store for [_valueAtFromFiles] .
@@ -1064,11 +1050,11 @@ mixin _DartdocArgOption<T> implements DartdocOption<T> {
10641050 }
10651051
10661052 @override
1067- void _onMissing (
1053+ Never _onMissing (
10681054 _OptionValueWithContext <T > valueWithContext, String missingPath) =>
10691055 _onMissingFromArgs (valueWithContext, missingPath);
10701056
1071- void _onMissingFromArgs (
1057+ Never _onMissingFromArgs (
10721058 _OptionValueWithContext <T > valueWithContext, String missingPath) {
10731059 throw DartdocFileMissing (
10741060 'Argument --$argName , set to ${valueWithContext .value }, resolves to '
0 commit comments