@@ -315,7 +315,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
315
315
Some ( _) => { }
316
316
None => {
317
317
log:: error!(
318
- "Replacement ({:?}) was generated for a function parameter which was not found: {:?}" ,
318
+ "Replacement ({:?}) was generated for a structure field which was not found: {:?}" ,
319
319
field_to_rename, struct_src
320
320
) ;
321
321
return ;
@@ -338,6 +338,131 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
338
338
339
339
fn validate_enum ( & mut self , db : & dyn HirDatabase , enum_id : EnumId ) {
340
340
let data = db. enum_data ( enum_id) ;
341
+
342
+ // 1. Check the enum name.
343
+ let enum_name = data. name . to_string ( ) ;
344
+ let enum_name_replacement = if let Some ( new_name) = to_camel_case ( & enum_name) {
345
+ let replacement = Replacement {
346
+ current_name : data. name . clone ( ) ,
347
+ suggested_text : new_name,
348
+ expected_case : CaseType :: UpperCamelCase ,
349
+ } ;
350
+ Some ( replacement)
351
+ } else {
352
+ None
353
+ } ;
354
+
355
+ // 2. Check the field names.
356
+ let mut enum_fields_replacements = Vec :: new ( ) ;
357
+
358
+ for ( _, variant) in data. variants . iter ( ) {
359
+ let variant_name = variant. name . to_string ( ) ;
360
+ if let Some ( new_name) = to_camel_case ( & variant_name) {
361
+ let replacement = Replacement {
362
+ current_name : variant. name . clone ( ) ,
363
+ suggested_text : new_name,
364
+ expected_case : CaseType :: UpperCamelCase ,
365
+ } ;
366
+ enum_fields_replacements. push ( replacement) ;
367
+ }
368
+ }
369
+
370
+ // 3. If there is at least one element to spawn a warning on, go to the source map and generate a warning.
371
+ self . create_incorrect_case_diagnostic_for_enum (
372
+ enum_id,
373
+ db,
374
+ enum_name_replacement,
375
+ enum_fields_replacements,
376
+ )
377
+ }
378
+
379
+ /// Given the information about incorrect names in the struct declaration, looks up into the source code
380
+ /// for exact locations and adds diagnostics into the sink.
381
+ fn create_incorrect_case_diagnostic_for_enum (
382
+ & mut self ,
383
+ enum_id : EnumId ,
384
+ db : & dyn HirDatabase ,
385
+ enum_name_replacement : Option < Replacement > ,
386
+ enum_variants_replacements : Vec < Replacement > ,
387
+ ) {
388
+ // XXX: only look at sources if we do have incorrect names
389
+ if enum_name_replacement. is_none ( ) && enum_variants_replacements. is_empty ( ) {
390
+ return ;
391
+ }
392
+
393
+ let enum_loc = enum_id. lookup ( db. upcast ( ) ) ;
394
+ let enum_src = enum_loc. source ( db. upcast ( ) ) ;
395
+
396
+ if let Some ( replacement) = enum_name_replacement {
397
+ let ast_ptr = if let Some ( name) = enum_src. value . name ( ) {
398
+ name
399
+ } else {
400
+ // We don't want rust-analyzer to panic over this, but it is definitely some kind of error in the logic.
401
+ log:: error!(
402
+ "Replacement ({:?}) was generated for a enum without a name: {:?}" ,
403
+ replacement,
404
+ enum_src
405
+ ) ;
406
+ return ;
407
+ } ;
408
+
409
+ let diagnostic = IncorrectCase {
410
+ file : enum_src. file_id ,
411
+ ident_type : "Enum" . to_string ( ) ,
412
+ ident : AstPtr :: new ( & ast_ptr) . into ( ) ,
413
+ expected_case : replacement. expected_case ,
414
+ ident_text : replacement. current_name . to_string ( ) ,
415
+ suggested_text : replacement. suggested_text ,
416
+ } ;
417
+
418
+ self . sink . push ( diagnostic) ;
419
+ }
420
+
421
+ let enum_variants_list = match enum_src. value . variant_list ( ) {
422
+ Some ( variants) => variants,
423
+ _ => {
424
+ if !enum_variants_replacements. is_empty ( ) {
425
+ log:: error!(
426
+ "Replacements ({:?}) were generated for a enum variants which had no fields list: {:?}" ,
427
+ enum_variants_replacements, enum_src
428
+ ) ;
429
+ }
430
+ return ;
431
+ }
432
+ } ;
433
+ let mut enum_variants_iter = enum_variants_list. variants ( ) ;
434
+ for variant_to_rename in enum_variants_replacements {
435
+ // We assume that parameters in replacement are in the same order as in the
436
+ // actual params list, but just some of them (ones that named correctly) are skipped.
437
+ let ast_ptr = loop {
438
+ match enum_variants_iter. next ( ) {
439
+ Some ( variant)
440
+ if names_equal ( variant. name ( ) , & variant_to_rename. current_name ) =>
441
+ {
442
+ break variant. name ( ) . unwrap ( )
443
+ }
444
+ Some ( _) => { }
445
+ None => {
446
+ log:: error!(
447
+ "Replacement ({:?}) was generated for a enum variant which was not found: {:?}" ,
448
+ variant_to_rename, enum_src
449
+ ) ;
450
+ return ;
451
+ }
452
+ }
453
+ } ;
454
+
455
+ let diagnostic = IncorrectCase {
456
+ file : enum_src. file_id ,
457
+ ident_type : "Variant" . to_string ( ) ,
458
+ ident : AstPtr :: new ( & ast_ptr) . into ( ) ,
459
+ expected_case : variant_to_rename. expected_case ,
460
+ ident_text : variant_to_rename. current_name . to_string ( ) ,
461
+ suggested_text : variant_to_rename. suggested_text ,
462
+ } ;
463
+
464
+ self . sink . push ( diagnostic) ;
465
+ }
341
466
}
342
467
}
343
468
@@ -400,6 +525,26 @@ struct non_camel_case_name {}
400
525
r#"
401
526
struct SomeStruct { SomeField: u8 }
402
527
// ^^^^^^^^^ Field `SomeField` should have a snake_case name, e.g. `some_field`
528
+ "# ,
529
+ ) ;
530
+ }
531
+
532
+ #[ test]
533
+ fn incorrect_enum_name ( ) {
534
+ check_diagnostics (
535
+ r#"
536
+ enum some_enum { Val(u8) }
537
+ // ^^^^^^^^^ Enum `some_enum` should have a CamelCase name, e.g. `SomeEnum`
538
+ "# ,
539
+ ) ;
540
+ }
541
+
542
+ #[ test]
543
+ fn incorrect_enum_variant_name ( ) {
544
+ check_diagnostics (
545
+ r#"
546
+ enum SomeEnum { SOME_VARIANT(u8) }
547
+ // ^^^^^^^^^^^^ Variant `SOME_VARIANT` should have a CamelCase name, e.g. `SomeVariant`
403
548
"# ,
404
549
) ;
405
550
}
0 commit comments