@@ -223,7 +223,7 @@ final class AnalysisOptionsBuilder {
223223    }
224224
225225    var  configurations =  < PluginConfiguration > [];
226-     String ?  dependencyOverrides;
226+     Map < String ,  PluginSource > ?  dependencyOverrides;
227227
228228    plugins.nodes.forEach ((nameNode, pluginNode) {
229229      if  (nameNode is !  YamlScalar ) {
@@ -233,63 +233,26 @@ final class AnalysisOptionsBuilder {
233233      var  pluginName =  nameNode.toString ();
234234      if  (pluginName ==  'dependency_overrides' ) {
235235        // This is a magic key; not the name of a plugin. 
236-         var  indent =  pluginNode.span.start.column;
237-         dependencyOverrides =  ' '  *  indent +  pluginNode.span.text;
238-       }
239- 
240-       // If the plugin name just maps to a String, then that is the version 
241-       // constraint; use it and move on. 
242-       if  (pluginNode case  YamlScalar (: String  value)) {
243-         configurations.add (
244-           PluginConfiguration (
245-             name:  pluginName,
246-             source:  VersionedPluginSource (constraint:  value),
247-           ),
248-         );
249-         return ;
250-       }
236+         if  (pluginNode is !  YamlMap ) return ;
237+         pluginNode.nodes.forEach ((nameNode, dependencyOverride) {
238+           if  (nameNode is !  YamlScalar ) {
239+             return ;
240+           }
241+           var  source =  _getSource (dependencyOverride, resourceProvider);
242+           if  (source ==  null ) return ;
243+           (dependencyOverrides ?? =  {})[nameNode.toString ()] =  source;
244+         });
251245
252-       if  (pluginNode is !  YamlMap ) {
253246        return ;
254247      }
255248
256-       // Grab either the source value from 'version', 'git', or 'path'. In the 
257-       // erroneous case that multiple are specified, just take the first. A 
258-       // warning should be reported by `OptionsFileValidator`. 
259-       // TODO(srawlins): In adition to 'version' and 'path', try 'git'. 
260- 
261-       PluginSource ?  source;
262-       var  versionSource =  pluginNode.valueAt (AnalysisOptionsFile .version);
263-       if  (versionSource case  YamlScalar (: String  value)) {
264-         // TODO(srawlins): Handle the 'hosted' key. 
265-         source =  VersionedPluginSource (constraint:  value);
266-       } else  {
267-         var  pathSource =  pluginNode.valueAt (AnalysisOptionsFile .path);
268-         if  (pathSource case  YamlScalar (value:  String  pathValue)) {
269-           var  file =  this .file;
270-           assert (
271-             file !=  null ,
272-             "AnalysisOptionsImpl must be initialized with a non-null 'file' if " 
273-             'plugins are specified with path constraints.' ,
274-           );
275-           if  (file !=  null  && 
276-               resourceProvider !=  null  && 
277-               resourceProvider.pathContext.isRelative (pathValue)) {
278-             // We need to store the absolute path, before this value is used in 
279-             // a synthetic pub package. 
280-             pathValue =  resourceProvider.pathContext.join (
281-               file.parent.path,
282-               pathValue,
283-             );
284-             pathValue =  resourceProvider.pathContext.normalize (pathValue);
285-           }
286-           source =  PathPluginSource (path:  pathValue);
287-         }
288-       }
249+       var  source =  _getSource (pluginNode, resourceProvider);
250+       if  (source ==  null ) return ;
289251
290-       if  (source ==  null ) {
291-         // Either the source data is malformed, or neither 'version' nor 'git' 
292-         // was provided. A warning should be reported by OptionsFileValidator. 
252+       if  (pluginNode is !  YamlMap ) {
253+         configurations.add (
254+           PluginConfiguration (name:  pluginName, source:  source),
255+         );
293256        return ;
294257      }
295258
@@ -348,6 +311,53 @@ final class AnalysisOptionsBuilder {
348311      stringValues.map ((name) =>  name.toUpperCase ()),
349312    );
350313  }
314+ 
315+   PluginSource ?  _getSource (
316+     YamlNode  pluginNode,
317+     ResourceProvider ?  resourceProvider,
318+   ) {
319+     // If it just maps to a String, then that is the version constraint. 
320+     if  (pluginNode case  YamlScalar (: String  value)) {
321+       return  VersionedPluginSource (constraint:  value);
322+     }
323+ 
324+     if  (pluginNode is !  YamlMap ) {
325+       return  null ;
326+     }
327+ 
328+     // Grab either the source value from 'version', 'git', or 'path'. In the 
329+     // erroneous case that multiple are specified, just take the first. A 
330+     // warning should be reported by `OptionsFileValidator`. 
331+     // TODO(srawlins): In adition to 'version' and 'path', try 'git'. 
332+ 
333+     var  versionSource =  pluginNode.valueAt (AnalysisOptionsFile .version);
334+     if  (versionSource case  YamlScalar (: String  value)) {
335+       // TODO(srawlins): Handle the 'hosted' key. 
336+       return  VersionedPluginSource (constraint:  value);
337+     }
338+     var  pathSource =  pluginNode.valueAt (AnalysisOptionsFile .path);
339+     if  (pathSource case  YamlScalar (value:  String  pathValue)) {
340+       var  file =  this .file;
341+       assert (
342+         file !=  null ,
343+         "AnalysisOptionsImpl must be initialized with a non-null 'file' if " 
344+         'plugins are specified with path constraints.' ,
345+       );
346+       if  (file !=  null  && 
347+           resourceProvider !=  null  && 
348+           resourceProvider.pathContext.isRelative (pathValue)) {
349+         // We need to store the absolute path, before this value is used in 
350+         // a synthetic pub package. 
351+         pathValue =  resourceProvider.pathContext.join (
352+           file.parent.path,
353+           pathValue,
354+         );
355+         pathValue =  resourceProvider.pathContext.normalize (pathValue);
356+       }
357+       return  PathPluginSource (path:  pathValue);
358+     }
359+     return  null ;
360+   }
351361}
352362
353363/// A set of analysis options used to control the behavior of an analysis 
@@ -622,7 +632,24 @@ class AnalysisOptionsImpl implements AnalysisOptions {
622632          buffer.addInt (diagnosticConfig.severity.index);
623633        }
624634        if  (pluginsOptions.dependencyOverrides case  var  dependencyOverrides? ) {
625-           buffer.addString (dependencyOverrides);
635+           for  (var  pluginDependencyOverrideEntry
636+               in  dependencyOverrides.entries.sortedBy ((entry) =>  entry.key)) {
637+             buffer.addString (pluginDependencyOverrideEntry.key);
638+             switch  (pluginDependencyOverrideEntry.value) {
639+               case  GitPluginSource  source: 
640+                 buffer.addString (source._url);
641+                 if  (source._path case  var  path? ) {
642+                   buffer.addString (path);
643+                 }
644+                 if  (source._ref case  var  ref? ) {
645+                   buffer.addString (ref);
646+                 }
647+               case  PathPluginSource  source: 
648+                 buffer.addString (source._path);
649+               case  VersionedPluginSource  source: 
650+                 buffer.addString (source._constraint);
651+             }
652+           }
626653        }
627654      }
628655
@@ -759,7 +786,7 @@ final class PluginsOptions {
759786   final  List <PluginConfiguration > configurations;
760787
761788  /// The dependency overrides, if specified. 
762-    final  String ?  dependencyOverrides;
789+    final  Map < String ,  PluginSource > ?  dependencyOverrides;
763790
764791  PluginsOptions ({
765792    required  this .configurations,
0 commit comments