@@ -6,7 +6,7 @@ use base_db::CrateId;
6
6
use either:: Either ;
7
7
use hir_expand:: {
8
8
name:: { AsName , Name } ,
9
- InFile ,
9
+ HirFileId , InFile ,
10
10
} ;
11
11
use la_arena:: { Arena , ArenaMap } ;
12
12
use syntax:: ast:: { self , HasName , HasVisibility } ;
@@ -17,13 +17,15 @@ use crate::{
17
17
builtin_type:: { BuiltinInt , BuiltinUint } ,
18
18
db:: DefDatabase ,
19
19
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 ,
21
22
src:: HasChildSource ,
22
23
src:: HasSource ,
23
24
trace:: Trace ,
24
25
type_ref:: TypeRef ,
25
26
visibility:: RawVisibility ,
26
- EnumId , LocalEnumVariantId , LocalFieldId , Lookup , ModuleId , StructId , UnionId , VariantId ,
27
+ EnumId , LocalEnumVariantId , LocalFieldId , LocalModuleId , Lookup , ModuleId , StructId , UnionId ,
28
+ VariantId ,
27
29
} ;
28
30
use cfg:: CfgOptions ;
29
31
@@ -143,43 +145,87 @@ fn parse_repr_tt(tt: &Subtree) -> Option<ReprData> {
143
145
144
146
impl StructData {
145
147
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 ] > ) {
146
155
let loc = id. lookup ( db) ;
147
156
let krate = loc. container . krate ;
148
157
let item_tree = loc. id . item_tree ( db) ;
149
158
let repr = repr_from_value ( db, krate, & item_tree, ModItem :: from ( loc. id . value ) . into ( ) ) ;
150
159
let cfg_options = db. crate_graph ( ) [ loc. container . krate ] . cfg_options . clone ( ) ;
151
160
152
161
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
+ )
160
181
}
161
182
162
183
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 ] > ) {
163
191
let loc = id. lookup ( db) ;
164
192
let krate = loc. container . krate ;
165
193
let item_tree = loc. id . item_tree ( db) ;
166
194
let repr = repr_from_value ( db, krate, & item_tree, ModItem :: from ( loc. id . value ) . into ( ) ) ;
167
195
let cfg_options = db. crate_graph ( ) [ loc. container . krate ] . cfg_options . clone ( ) ;
168
196
169
197
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
+ )
178
217
}
179
218
}
180
219
181
220
impl EnumData {
182
221
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 ] > ) {
183
229
let loc = e. lookup ( db) ;
184
230
let krate = loc. container . krate ;
185
231
let item_tree = loc. id . item_tree ( db) ;
@@ -188,31 +234,46 @@ impl EnumData {
188
234
189
235
let enum_ = & item_tree[ loc. id . value ] ;
190
236
let mut variants = Arena :: new ( ) ;
237
+ let mut diagnostics = Vec :: new ( ) ;
191
238
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 (
195
243
db,
196
244
krate,
245
+ loc. id . file_id ( ) ,
246
+ loc. container . local_id ,
197
247
& item_tree,
198
248
& cfg_options,
199
249
& var. fields ,
200
250
Some ( enum_. visibility ) ,
201
251
) ;
252
+ diagnostics. extend ( field_diagnostics) ;
202
253
203
254
variants. alloc ( EnumVariantData {
204
255
name : var. name . clone ( ) ,
205
256
variant_data : Arc :: new ( var_data) ,
206
257
} ) ;
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
+ ) )
207
265
}
208
266
}
209
267
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
+ )
216
277
}
217
278
218
279
pub fn variant ( & self , name : & Name ) -> Option < LocalEnumVariantId > {
@@ -384,31 +445,64 @@ fn lower_struct(
384
445
fn lower_fields (
385
446
db : & dyn DefDatabase ,
386
447
krate : CrateId ,
448
+ current_file_id : HirFileId ,
449
+ container : LocalModuleId ,
387
450
item_tree : & ItemTree ,
388
451
cfg_options : & CfgOptions ,
389
452
fields : & Fields ,
390
453
override_visibility : Option < RawVisibilityId > ,
391
- ) -> VariantData {
454
+ ) -> ( VariantData , Vec < DefDiagnostic > ) {
455
+ let mut diagnostics = Vec :: new ( ) ;
392
456
match fields {
393
457
Fields :: Record ( flds) => {
394
458
let mut arena = Arena :: new ( ) ;
395
459
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
+ ) )
398
477
}
399
478
}
400
- VariantData :: Record ( arena)
479
+ ( VariantData :: Record ( arena) , diagnostics )
401
480
}
402
481
Fields :: Tuple ( flds) => {
403
482
let mut arena = Arena :: new ( ) ;
404
483
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
+ ) )
407
501
}
408
502
}
409
- VariantData :: Tuple ( arena)
503
+ ( VariantData :: Tuple ( arena) , diagnostics )
410
504
}
411
- Fields :: Unit => VariantData :: Unit ,
505
+ Fields :: Unit => ( VariantData :: Unit , diagnostics ) ,
412
506
}
413
507
}
414
508
0 commit comments