@@ -6,7 +6,7 @@ use base_db::CrateId;
66use either:: Either ;
77use hir_expand:: {
88 name:: { AsName , Name } ,
9- InFile ,
9+ HirFileId , InFile ,
1010} ;
1111use la_arena:: { Arena , ArenaMap } ;
1212use syntax:: ast:: { self , HasName , HasVisibility } ;
@@ -17,13 +17,15 @@ use crate::{
1717 builtin_type:: { BuiltinInt , BuiltinUint } ,
1818 db:: DefDatabase ,
1919 intern:: Interned ,
20- item_tree:: { AttrOwner , Field , Fields , ItemTree , ModItem , RawVisibilityId } ,
20+ item_tree:: { AttrOwner , Field , FieldAstId , Fields , ItemTree , ModItem , RawVisibilityId } ,
21+ nameres:: diagnostics:: DefDiagnostic ,
2122 src:: HasChildSource ,
2223 src:: HasSource ,
2324 trace:: Trace ,
2425 type_ref:: TypeRef ,
2526 visibility:: RawVisibility ,
26- EnumId , LocalEnumVariantId , LocalFieldId , Lookup , ModuleId , StructId , UnionId , VariantId ,
27+ EnumId , LocalEnumVariantId , LocalFieldId , LocalModuleId , Lookup , ModuleId , StructId , UnionId ,
28+ VariantId ,
2729} ;
2830use cfg:: CfgOptions ;
2931
@@ -143,43 +145,87 @@ fn parse_repr_tt(tt: &Subtree) -> Option<ReprData> {
143145
144146impl StructData {
145147 pub ( crate ) fn struct_data_query ( db : & dyn DefDatabase , id : StructId ) -> Arc < StructData > {
148+ db. struct_data_with_diagnostics ( id) . 0
149+ }
150+
151+ pub ( crate ) fn struct_data_with_diagnostics_query (
152+ db : & dyn DefDatabase ,
153+ id : StructId ,
154+ ) -> ( Arc < StructData > , Arc < [ DefDiagnostic ] > ) {
146155 let loc = id. lookup ( db) ;
147156 let krate = loc. container . krate ;
148157 let item_tree = loc. id . item_tree ( db) ;
149158 let repr = repr_from_value ( db, krate, & item_tree, ModItem :: from ( loc. id . value ) . into ( ) ) ;
150159 let cfg_options = db. crate_graph ( ) [ loc. container . krate ] . cfg_options . clone ( ) ;
151160
152161 let strukt = & item_tree[ loc. id . value ] ;
153- let variant_data = lower_fields ( db, krate, & item_tree, & cfg_options, & strukt. fields , None ) ;
154- Arc :: new ( StructData {
155- name : strukt. name . clone ( ) ,
156- variant_data : Arc :: new ( variant_data) ,
157- repr,
158- visibility : item_tree[ strukt. visibility ] . clone ( ) ,
159- } )
162+ let ( variant_data, diagnostics) = lower_fields (
163+ db,
164+ krate,
165+ loc. id . file_id ( ) ,
166+ loc. container . local_id ,
167+ & item_tree,
168+ & cfg_options,
169+ & strukt. fields ,
170+ None ,
171+ ) ;
172+ (
173+ Arc :: new ( StructData {
174+ name : strukt. name . clone ( ) ,
175+ variant_data : Arc :: new ( variant_data) ,
176+ repr,
177+ visibility : item_tree[ strukt. visibility ] . clone ( ) ,
178+ } ) ,
179+ diagnostics. into ( ) ,
180+ )
160181 }
161182
162183 pub ( crate ) fn union_data_query ( db : & dyn DefDatabase , id : UnionId ) -> Arc < StructData > {
184+ db. union_data_with_diagnostics ( id) . 0
185+ }
186+
187+ pub ( crate ) fn union_data_with_diagnostics_query (
188+ db : & dyn DefDatabase ,
189+ id : UnionId ,
190+ ) -> ( Arc < StructData > , Arc < [ DefDiagnostic ] > ) {
163191 let loc = id. lookup ( db) ;
164192 let krate = loc. container . krate ;
165193 let item_tree = loc. id . item_tree ( db) ;
166194 let repr = repr_from_value ( db, krate, & item_tree, ModItem :: from ( loc. id . value ) . into ( ) ) ;
167195 let cfg_options = db. crate_graph ( ) [ loc. container . krate ] . cfg_options . clone ( ) ;
168196
169197 let union = & item_tree[ loc. id . value ] ;
170- let variant_data = lower_fields ( db, krate, & item_tree, & cfg_options, & union. fields , None ) ;
171-
172- Arc :: new ( StructData {
173- name : union. name . clone ( ) ,
174- variant_data : Arc :: new ( variant_data) ,
175- repr,
176- visibility : item_tree[ union. visibility ] . clone ( ) ,
177- } )
198+ let ( variant_data, diagnostics) = lower_fields (
199+ db,
200+ krate,
201+ loc. id . file_id ( ) ,
202+ loc. container . local_id ,
203+ & item_tree,
204+ & cfg_options,
205+ & union. fields ,
206+ None ,
207+ ) ;
208+ (
209+ Arc :: new ( StructData {
210+ name : union. name . clone ( ) ,
211+ variant_data : Arc :: new ( variant_data) ,
212+ repr,
213+ visibility : item_tree[ union. visibility ] . clone ( ) ,
214+ } ) ,
215+ diagnostics. into ( ) ,
216+ )
178217 }
179218}
180219
181220impl EnumData {
182221 pub ( crate ) fn enum_data_query ( db : & dyn DefDatabase , e : EnumId ) -> Arc < EnumData > {
222+ db. enum_data_with_diagnostics ( e) . 0
223+ }
224+
225+ pub ( crate ) fn enum_data_with_diagnostics_query (
226+ db : & dyn DefDatabase ,
227+ e : EnumId ,
228+ ) -> ( Arc < EnumData > , Arc < [ DefDiagnostic ] > ) {
183229 let loc = e. lookup ( db) ;
184230 let krate = loc. container . krate ;
185231 let item_tree = loc. id . item_tree ( db) ;
@@ -188,31 +234,46 @@ impl EnumData {
188234
189235 let enum_ = & item_tree[ loc. id . value ] ;
190236 let mut variants = Arena :: new ( ) ;
237+ let mut diagnostics = Vec :: new ( ) ;
191238 for tree_id in enum_. variants . clone ( ) {
192- if item_tree. attrs ( db, krate, tree_id. into ( ) ) . is_cfg_enabled ( & cfg_options) {
193- let var = & item_tree[ tree_id] ;
194- let var_data = lower_fields (
239+ let attrs = item_tree. attrs ( db, krate, tree_id. into ( ) ) ;
240+ let var = & item_tree[ tree_id] ;
241+ if attrs. is_cfg_enabled ( & cfg_options) {
242+ let ( var_data, field_diagnostics) = lower_fields (
195243 db,
196244 krate,
245+ loc. id . file_id ( ) ,
246+ loc. container . local_id ,
197247 & item_tree,
198248 & cfg_options,
199249 & var. fields ,
200250 Some ( enum_. visibility ) ,
201251 ) ;
252+ diagnostics. extend ( field_diagnostics) ;
202253
203254 variants. alloc ( EnumVariantData {
204255 name : var. name . clone ( ) ,
205256 variant_data : Arc :: new ( var_data) ,
206257 } ) ;
258+ } else {
259+ diagnostics. push ( DefDiagnostic :: unconfigured_code (
260+ loc. container . local_id ,
261+ InFile :: new ( loc. id . file_id ( ) , var. ast_id . upcast ( ) ) ,
262+ attrs. cfg ( ) . unwrap ( ) ,
263+ cfg_options. clone ( ) ,
264+ ) )
207265 }
208266 }
209267
210- Arc :: new ( EnumData {
211- name : enum_. name . clone ( ) ,
212- variants,
213- repr,
214- visibility : item_tree[ enum_. visibility ] . clone ( ) ,
215- } )
268+ (
269+ Arc :: new ( EnumData {
270+ name : enum_. name . clone ( ) ,
271+ variants,
272+ repr,
273+ visibility : item_tree[ enum_. visibility ] . clone ( ) ,
274+ } ) ,
275+ diagnostics. into ( ) ,
276+ )
216277 }
217278
218279 pub fn variant ( & self , name : & Name ) -> Option < LocalEnumVariantId > {
@@ -384,31 +445,64 @@ fn lower_struct(
384445fn lower_fields (
385446 db : & dyn DefDatabase ,
386447 krate : CrateId ,
448+ current_file_id : HirFileId ,
449+ container : LocalModuleId ,
387450 item_tree : & ItemTree ,
388451 cfg_options : & CfgOptions ,
389452 fields : & Fields ,
390453 override_visibility : Option < RawVisibilityId > ,
391- ) -> VariantData {
454+ ) -> ( VariantData , Vec < DefDiagnostic > ) {
455+ let mut diagnostics = Vec :: new ( ) ;
392456 match fields {
393457 Fields :: Record ( flds) => {
394458 let mut arena = Arena :: new ( ) ;
395459 for field_id in flds. clone ( ) {
396- if item_tree. attrs ( db, krate, field_id. into ( ) ) . is_cfg_enabled ( cfg_options) {
397- arena. alloc ( lower_field ( item_tree, & item_tree[ field_id] , override_visibility) ) ;
460+ let attrs = item_tree. attrs ( db, krate, field_id. into ( ) ) ;
461+ let field = & item_tree[ field_id] ;
462+ if attrs. is_cfg_enabled ( cfg_options) {
463+ arena. alloc ( lower_field ( item_tree, field, override_visibility) ) ;
464+ } else {
465+ diagnostics. push ( DefDiagnostic :: unconfigured_code (
466+ container,
467+ InFile :: new (
468+ current_file_id,
469+ match field. ast_id {
470+ FieldAstId :: Record ( it) => it. upcast ( ) ,
471+ FieldAstId :: Tuple ( it) => it. upcast ( ) ,
472+ } ,
473+ ) ,
474+ attrs. cfg ( ) . unwrap ( ) ,
475+ cfg_options. clone ( ) ,
476+ ) )
398477 }
399478 }
400- VariantData :: Record ( arena)
479+ ( VariantData :: Record ( arena) , diagnostics )
401480 }
402481 Fields :: Tuple ( flds) => {
403482 let mut arena = Arena :: new ( ) ;
404483 for field_id in flds. clone ( ) {
405- if item_tree. attrs ( db, krate, field_id. into ( ) ) . is_cfg_enabled ( cfg_options) {
406- arena. alloc ( lower_field ( item_tree, & item_tree[ field_id] , override_visibility) ) ;
484+ let attrs = item_tree. attrs ( db, krate, field_id. into ( ) ) ;
485+ let field = & item_tree[ field_id] ;
486+ if attrs. is_cfg_enabled ( cfg_options) {
487+ arena. alloc ( lower_field ( item_tree, field, override_visibility) ) ;
488+ } else {
489+ diagnostics. push ( DefDiagnostic :: unconfigured_code (
490+ container,
491+ InFile :: new (
492+ current_file_id,
493+ match field. ast_id {
494+ FieldAstId :: Record ( it) => it. upcast ( ) ,
495+ FieldAstId :: Tuple ( it) => it. upcast ( ) ,
496+ } ,
497+ ) ,
498+ attrs. cfg ( ) . unwrap ( ) ,
499+ cfg_options. clone ( ) ,
500+ ) )
407501 }
408502 }
409- VariantData :: Tuple ( arena)
503+ ( VariantData :: Tuple ( arena) , diagnostics )
410504 }
411- Fields :: Unit => VariantData :: Unit ,
505+ Fields :: Unit => ( VariantData :: Unit , diagnostics ) ,
412506 }
413507}
414508
0 commit comments