@@ -20,9 +20,29 @@ const Map<String, String> severityEnumNames = <String, String>{
2020  'INFO' :  'info' ,
2121};
2222
23+ /// Decoded messages from the `_fe_analyzer_shared`  package's `messages.yaml`  
24+ /// file. 
25+ final  Map <String , CfeStyleErrorCodeInfo > feAnalyzerSharedMessages = 
26+     _loadCfeStyleMessages (
27+       feAnalyzerSharedPkgPath,
28+       allowNonExistent:  true ,
29+       isShared:  true ,
30+     );
31+ 
32+ /// The path to the `fe_analyzer_shared`  package. 
33+ final  String  feAnalyzerSharedPkgPath =  normalize (
34+   join (pkg_root.packageRoot, '_fe_analyzer_shared' ),
35+ );
36+ 
37+ /// Decoded messages from the `messages.yaml`  files in the front end and 
38+ /// `_fe_analyzer_shared` . 
39+ final  Map <String , CfeStyleErrorCodeInfo > frontEndAndSharedMessages =  Map .from (
40+   frontEndMessages,
41+ )..addAll (feAnalyzerSharedMessages);
42+ 
2343/// Decoded messages from the front end's `messages.yaml`  file. 
24- final  Map <String , FrontEndErrorCodeInfo > frontEndMessages = 
25-     _loadFrontEndMessages ( );
44+ final  Map <String , CfeStyleErrorCodeInfo > frontEndMessages = 
45+     _loadCfeStyleMessages (frontEndPkgPath, isShared :   false );
2646
2747/// The path to the `front_end`  package. 
2848final  String  frontEndPkgPath =  normalize (
@@ -51,14 +71,17 @@ String convertTemplate(Map<String, int> placeholderToIndexMap, String entry) {
5171  );
5272}
5373
54- /// Decodes a YAML object (obtained from `pkg/front_end/messages.yaml` ) into a 
55- /// map from error name to [ErrorCodeInfo] . 
56- Map <String , FrontEndErrorCodeInfo > decodeCfeMessagesYaml (Object ?  yaml) {
74+ /// Decodes a YAML object (in CFE style `messages.yaml`  format) into a map from 
75+ /// error name to [ErrorCodeInfo] . 
76+ Map <String , CfeStyleErrorCodeInfo > decodeCfeStyleMessagesYaml (
77+   Object ?  yaml, {
78+   required  bool  isShared,
79+ }) {
5780  Never  problem (String  message) {
5881    throw  'Problem in pkg/front_end/messages.yaml: $message ' ;
5982  }
6083
61-   var  result =  < String , FrontEndErrorCodeInfo > {};
84+   var  result =  < String , CfeStyleErrorCodeInfo > {};
6285  if  (yaml is !  Map <Object ?, Object ?>) {
6386    problem ('root node is not a map' );
6487  }
@@ -72,22 +95,36 @@ Map<String, FrontEndErrorCodeInfo> decodeCfeMessagesYaml(Object? yaml) {
7295      problem ('value associated with error $errorName  is not a map' );
7396    }
7497    try  {
75-       result[errorName] =  FrontEndErrorCodeInfo .fromYaml (errorValue);
98+       result[errorName] =  CfeStyleErrorCodeInfo .fromYaml (
99+         errorValue,
100+         isShared:  isShared,
101+       );
76102    } catch  (e, st) {
77103      Error .throwWithStackTrace ('while processing $errorName , $e ' , st);
78104    }
79105  }
80106  return  result;
81107}
82108
83- /// Loads front end messages from the front end's `messages.yaml`  file. 
84- Map <String , FrontEndErrorCodeInfo > _loadFrontEndMessages () {
85-   var  path =  join (frontEndPkgPath, 'messages.yaml' );
109+ /// Loads messages in CFE style `messages.yaml`  format. 
110+ /// 
111+ /// If [allowNonExistent]  is `true` , and the `messages.yaml`  file does not 
112+ /// exist, an empty map is returned. This is a temporary measure to allow for an 
113+ /// easier transition when the file `pkg/_fe_analyzer_shared/messages.yaml`  is 
114+ /// created. 
115+ // TODO(paulberry): remove [allowNonExistent] once it's no longer needed. 
116+ Map <String , CfeStyleErrorCodeInfo > _loadCfeStyleMessages (
117+   String  packagePath, {
118+   bool  allowNonExistent =  false ,
119+   required  bool  isShared,
120+ }) {
121+   var  path =  join (packagePath, 'messages.yaml' );
122+   if  (allowNonExistent &&  ! File (path).existsSync ()) return  {};
86123  Object ?  messagesYaml =  loadYaml (
87124    File (path).readAsStringSync (),
88125    sourceUrl:  Uri .file (path),
89126  );
90-   return  decodeCfeMessagesYaml (messagesYaml);
127+   return  decodeCfeStyleMessagesYaml (messagesYaml, isShared :  isShared );
91128}
92129
93130/// Splits [text]  on spaces using the given [maxWidth]  (and [firstLineWidth]  if 
@@ -130,6 +167,86 @@ List<String> _splitText(
130167  return  lines;
131168}
132169
170+ /// In-memory representation of error code information obtained from a 
171+ /// `messages.yaml`  file in `pkg/front_end`  or `pkg/_fe_analyzer_shared` . 
172+ class  CfeStyleErrorCodeInfo  extends  ErrorCodeInfo  {
173+   /// The set of analyzer error codes that corresponds to this error code, if 
174+   /// any. 
175+    final  List <String > analyzerCode;
176+ 
177+   /// The index of the error in the analyzer's `fastaAnalyzerErrorCodes`  table. 
178+    final  int ?  index;
179+ 
180+   /// The name of the [CfeSeverity]  constant describing this error code's CFE 
181+   /// severity. 
182+    final  String ?  cfeSeverity;
183+ 
184+   CfeStyleErrorCodeInfo .fromYaml (YamlMap  yaml, {required  bool  isShared})
185+     :  analyzerCode =  _decodeAnalyzerCode (yaml['analyzerCode' ]),
186+       index =  _decodeIndex (yaml['index' ]),
187+       cfeSeverity =  _decodeSeverity (yaml['severity' ]),
188+       super .fromYaml (yaml) {
189+     if  (yaml['problemMessage' ] ==  null ) {
190+       throw  'Missing problemMessage' ;
191+     }
192+     if  (isShared &&  analyzerCode.length !=  1 ) {
193+       throw  StateError ('Shared messages must have exactly one analyzerCode' );
194+     }
195+   }
196+ 
197+   @override 
198+   Map <Object ?, Object ?> toYaml () =>  {
199+     if  (analyzerCode.isNotEmpty)
200+       'analyzerCode' :  _encodeAnalyzerCode (analyzerCode),
201+     if  (index !=  null ) 'index' :  index,
202+     ...super .toYaml (),
203+   };
204+ 
205+   static  List <String > _decodeAnalyzerCode (Object ?  value) {
206+     if  (value ==  null ) {
207+       return  const  [];
208+     } else  if  (value is  String ) {
209+       return  [value];
210+     } else  if  (value is  List ) {
211+       return  [for  (var  s in  value) s as  String ];
212+     } else  {
213+       throw  'Unrecognized analyzer code: $value ' ;
214+     }
215+   }
216+ 
217+   static  int ?  _decodeIndex (Object ?  value) {
218+     switch  (value) {
219+       case  null : 
220+         return  null ;
221+       case  int (): 
222+         if  (value >=  1 ) {
223+           return  value;
224+         }
225+     }
226+     throw  'Expected positive int for "index:", but found $value ' ;
227+   }
228+ 
229+   static  String ?  _decodeSeverity (Object ?  yamlEntry) {
230+     switch  (yamlEntry) {
231+       case  null : 
232+         return  null ;
233+       case  String (): 
234+         return  severityEnumNames[yamlEntry] ?? 
235+             (throw  "Unknown severity '$yamlEntry '" );
236+       default : 
237+         throw  'Bad severity type: ${yamlEntry .runtimeType }' ;
238+     }
239+   }
240+ 
241+   static  Object  _encodeAnalyzerCode (List <String > analyzerCode) {
242+     if  (analyzerCode.length ==  1 ) {
243+       return  analyzerCode.single;
244+     } else  {
245+       return  analyzerCode;
246+     }
247+   }
248+ }
249+ 
133250/// Information about how to convert the CFE's internal representation of a 
134251/// template parameter to a string. 
135252/// 
@@ -688,83 +805,6 @@ enum ErrorCodeParameterType {
688805   bool  get  isSupportedByAnalyzer =>  _analyzerName !=  null ;
689806}
690807
691- /// In-memory representation of error code information obtained from the front 
692- /// end's `messages.yaml`  file. 
693- class  FrontEndErrorCodeInfo  extends  ErrorCodeInfo  {
694-   /// The set of analyzer error codes that corresponds to this error code, if 
695-   /// any. 
696-    final  List <String > analyzerCode;
697- 
698-   /// The index of the error in the analyzer's `fastaAnalyzerErrorCodes`  table. 
699-    final  int ?  index;
700- 
701-   /// The name of the [CfeSeverity]  constant describing this error code's CFE 
702-   /// severity. 
703-    final  String ?  cfeSeverity;
704- 
705-   FrontEndErrorCodeInfo .fromYaml (YamlMap  yaml)
706-     :  analyzerCode =  _decodeAnalyzerCode (yaml['analyzerCode' ]),
707-       index =  _decodeIndex (yaml['index' ]),
708-       cfeSeverity =  _decodeSeverity (yaml['severity' ]),
709-       super .fromYaml (yaml) {
710-     if  (yaml['problemMessage' ] ==  null ) {
711-       throw  'Missing problemMessage' ;
712-     }
713-   }
714- 
715-   @override 
716-   Map <Object ?, Object ?> toYaml () =>  {
717-     if  (analyzerCode.isNotEmpty)
718-       'analyzerCode' :  _encodeAnalyzerCode (analyzerCode),
719-     if  (index !=  null ) 'index' :  index,
720-     ...super .toYaml (),
721-   };
722- 
723-   static  List <String > _decodeAnalyzerCode (Object ?  value) {
724-     if  (value ==  null ) {
725-       return  const  [];
726-     } else  if  (value is  String ) {
727-       return  [value];
728-     } else  if  (value is  List ) {
729-       return  [for  (var  s in  value) s as  String ];
730-     } else  {
731-       throw  'Unrecognized analyzer code: $value ' ;
732-     }
733-   }
734- 
735-   static  int ?  _decodeIndex (Object ?  value) {
736-     switch  (value) {
737-       case  null : 
738-         return  null ;
739-       case  int (): 
740-         if  (value >=  1 ) {
741-           return  value;
742-         }
743-     }
744-     throw  'Expected positive int for "index:", but found $value ' ;
745-   }
746- 
747-   static  String ?  _decodeSeverity (Object ?  yamlEntry) {
748-     switch  (yamlEntry) {
749-       case  null : 
750-         return  null ;
751-       case  String (): 
752-         return  severityEnumNames[yamlEntry] ?? 
753-             (throw  "Unknown severity '$yamlEntry '" );
754-       default : 
755-         throw  'Bad severity type: ${yamlEntry .runtimeType }' ;
756-     }
757-   }
758- 
759-   static  Object  _encodeAnalyzerCode (List <String > analyzerCode) {
760-     if  (analyzerCode.length ==  1 ) {
761-       return  analyzerCode.single;
762-     } else  {
763-       return  analyzerCode;
764-     }
765-   }
766- }
767- 
768808/// Representation of a single file containing generated error codes. 
769809class  GeneratedErrorCodeFile  {
770810  /// The file path (relative to the SDK's `pkg`  directory) of the generated 
0 commit comments