@@ -9,6 +9,7 @@ import 'package:analyzer/src/analysis_options/analysis_options_file.dart';
99import  'package:analyzer/src/generated/source.dart'  show  SourceFactory;
1010import  'package:analyzer/src/util/file_paths.dart'  as  file_paths;
1111import  'package:analyzer/src/util/yaml.dart' ;
12+ import  'package:path/path.dart'  as  path;
1213import  'package:source_span/source_span.dart' ;
1314import  'package:yaml/yaml.dart' ;
1415
@@ -59,15 +60,19 @@ class AnalysisOptionsProvider {
5960  /// Returns an empty options map if the file does not exist or cannot be 
6061  /// parsed. 
6162   YamlMap  getOptionsFromFile (File  file) {
62-     return  getOptionsFromSource (FileSource (file));
63+     return  getOptionsFromSource (FileSource (file), file.provider.pathContext );
6364  }
6465
6566  /// Provides the options found in [source] . 
6667  /// 
6768  /// Recursively merges options referenced by any `include`  directives and 
6869  /// removes any `include`  directives from the resulting options map. Returns 
6970  /// an empty options map if the file does not exist or cannot be parsed. 
70-    YamlMap  getOptionsFromSource (Source  source, {Set <Source >?  handled}) {
71+    YamlMap  getOptionsFromSource (
72+     Source  source,
73+     path.Context  pathContext, {
74+     Set <Source >?  handled,
75+   }) {
7176    handled ?? =  {};
7277    try  {
7378      var  options =  getOptionsFromString (_readAnalysisOptions (source));
@@ -85,16 +90,23 @@ class AnalysisOptionsProvider {
8590              .toList (),
8691        _ =>  < String > [],
8792      };
88-       var  includeOptions =  includes.fold (YamlMap (), (options , path) {
89-         var  includeUri  =  _sourceFactory.resolveUri (source, path);
90-         if  (includeUri  ==  null  ||  ! handled! .add (includeUri )) {
93+       var  includeOptions =  includes.fold (YamlMap (), (currentOptions , path) {
94+         var  includeSource  =  _sourceFactory.resolveUri (source, path);
95+         if  (includeSource  ==  null  ||  ! handled! .add (includeSource )) {
9196          // Return the existing options, unchanged. 
92-           return  options ;
97+           return  currentOptions ;
9398        }
94-         return  merge (
95-           options,
96-           getOptionsFromSource (includeUri, handled:  handled),
99+         var  includedOptions =  getOptionsFromSource (
100+           includeSource,
101+           pathContext,
102+           handled:  handled,
97103        );
104+         includedOptions =  _rewriteRelativePaths (
105+           includedOptions,
106+           pathContext.dirname (includeSource.fullName),
107+           pathContext,
108+         );
109+         return  merge (currentOptions, includedOptions);
98110      });
99111      options =  merge (includeOptions, options);
100112      return  options;
@@ -147,6 +159,39 @@ class AnalysisOptionsProvider {
147159      return  null ;
148160    }
149161  }
162+ 
163+   /// Walks [options]  with semantic knowledge about where paths may appear in an 
164+   /// analysis options file, rewriting relative paths (relative to [directory] ) 
165+   /// as absolute paths. 
166+   /// 
167+   /// Namely: paths to plugins which are specified by path. 
168+    // TODO(srawlins): I think 'exclude' paths should be made absolute too; I 
169+   // believe there is an existing bug about 'include'd 'exclude' paths. 
170+   YamlMap  _rewriteRelativePaths (
171+     YamlMap  options,
172+     String  directory,
173+     path.Context  pathContext,
174+   ) {
175+     var  pluginsSection =  options.valueAt ('plugins' );
176+     if  (pluginsSection is !  YamlMap ) return  options;
177+     var  plugins =  < String , Object > {};
178+     pluginsSection.nodes.forEach ((key, value) {
179+       if  (key is  YamlScalar  &&  value is  YamlMap ) {
180+         var  pathValue =  value.valueAt ('path' )? .value;
181+         if  (pathValue is  String ) {
182+           if  (pathContext.isRelative (pathValue)) {
183+             // We need to store the absolute path, before this value is used in 
184+             // a synthetic pub package. 
185+             pathValue =  pathContext.join (directory, pathValue);
186+             pathValue =  pathContext.normalize (pathValue);
187+           }
188+ 
189+           plugins[key.value as  String ] =  {'path' :  pathValue};
190+         }
191+       }
192+     });
193+     return  merge (options, YamlMap .wrap ({'plugins' :  plugins}));
194+   }
150195}
151196
152197/// Thrown on options format exceptions. 
0 commit comments