@@ -7,15 +7,12 @@ use std::any::Any;
7
7
8
8
use cfg:: { CfgExpr , CfgOptions , DnfExpr } ;
9
9
use hir_def:: path:: ModPath ;
10
- use hir_expand:: { HirFileId , InFile } ;
10
+ use hir_expand:: { name :: Name , HirFileId , InFile } ;
11
11
use stdx:: format_to;
12
12
use syntax:: { ast, AstPtr , SyntaxNodePtr , TextRange } ;
13
13
14
14
pub use hir_ty:: {
15
- diagnostics:: {
16
- IncorrectCase , MismatchedArgCount , MissingFields , MissingMatchArms ,
17
- MissingOkOrSomeInTailExpr , RemoveThisSemicolon , ReplaceFilterMapNextWithFindMap ,
18
- } ,
15
+ diagnostics:: IncorrectCase ,
19
16
diagnostics_sink:: { Diagnostic , DiagnosticCode , DiagnosticSink , DiagnosticSinkBuilder } ,
20
17
} ;
21
18
@@ -325,3 +322,259 @@ impl Diagnostic for MissingUnsafe {
325
322
self
326
323
}
327
324
}
325
+
326
+ // Diagnostic: missing-structure-fields
327
+ //
328
+ // This diagnostic is triggered if record lacks some fields that exist in the corresponding structure.
329
+ //
330
+ // Example:
331
+ //
332
+ // ```rust
333
+ // struct A { a: u8, b: u8 }
334
+ //
335
+ // let a = A { a: 10 };
336
+ // ```
337
+ #[ derive( Debug ) ]
338
+ pub struct MissingFields {
339
+ pub file : HirFileId ,
340
+ pub field_list_parent : AstPtr < ast:: RecordExpr > ,
341
+ pub field_list_parent_path : Option < AstPtr < ast:: Path > > ,
342
+ pub missed_fields : Vec < Name > ,
343
+ }
344
+
345
+ impl Diagnostic for MissingFields {
346
+ fn code ( & self ) -> DiagnosticCode {
347
+ DiagnosticCode ( "missing-structure-fields" )
348
+ }
349
+ fn message ( & self ) -> String {
350
+ let mut buf = String :: from ( "Missing structure fields:\n " ) ;
351
+ for field in & self . missed_fields {
352
+ format_to ! ( buf, "- {}\n " , field) ;
353
+ }
354
+ buf
355
+ }
356
+
357
+ fn display_source ( & self ) -> InFile < SyntaxNodePtr > {
358
+ InFile {
359
+ file_id : self . file ,
360
+ value : self
361
+ . field_list_parent_path
362
+ . clone ( )
363
+ . map ( SyntaxNodePtr :: from)
364
+ . unwrap_or_else ( || self . field_list_parent . clone ( ) . into ( ) ) ,
365
+ }
366
+ }
367
+
368
+ fn as_any ( & self ) -> & ( dyn Any + Send + ' static ) {
369
+ self
370
+ }
371
+ }
372
+
373
+ // Diagnostic: missing-pat-fields
374
+ //
375
+ // This diagnostic is triggered if pattern lacks some fields that exist in the corresponding structure.
376
+ //
377
+ // Example:
378
+ //
379
+ // ```rust
380
+ // struct A { a: u8, b: u8 }
381
+ //
382
+ // let a = A { a: 10, b: 20 };
383
+ //
384
+ // if let A { a } = a {
385
+ // // ...
386
+ // }
387
+ // ```
388
+ #[ derive( Debug ) ]
389
+ pub struct MissingPatFields {
390
+ pub file : HirFileId ,
391
+ pub field_list_parent : AstPtr < ast:: RecordPat > ,
392
+ pub field_list_parent_path : Option < AstPtr < ast:: Path > > ,
393
+ pub missed_fields : Vec < Name > ,
394
+ }
395
+
396
+ impl Diagnostic for MissingPatFields {
397
+ fn code ( & self ) -> DiagnosticCode {
398
+ DiagnosticCode ( "missing-pat-fields" )
399
+ }
400
+ fn message ( & self ) -> String {
401
+ let mut buf = String :: from ( "Missing structure fields:\n " ) ;
402
+ for field in & self . missed_fields {
403
+ format_to ! ( buf, "- {}\n " , field) ;
404
+ }
405
+ buf
406
+ }
407
+ fn display_source ( & self ) -> InFile < SyntaxNodePtr > {
408
+ InFile {
409
+ file_id : self . file ,
410
+ value : self
411
+ . field_list_parent_path
412
+ . clone ( )
413
+ . map ( SyntaxNodePtr :: from)
414
+ . unwrap_or_else ( || self . field_list_parent . clone ( ) . into ( ) ) ,
415
+ }
416
+ }
417
+ fn as_any ( & self ) -> & ( dyn Any + Send + ' static ) {
418
+ self
419
+ }
420
+ }
421
+
422
+ // Diagnostic: replace-filter-map-next-with-find-map
423
+ //
424
+ // This diagnostic is triggered when `.filter_map(..).next()` is used, rather than the more concise `.find_map(..)`.
425
+ #[ derive( Debug ) ]
426
+ pub struct ReplaceFilterMapNextWithFindMap {
427
+ pub file : HirFileId ,
428
+ /// This expression is the whole method chain up to and including `.filter_map(..).next()`.
429
+ pub next_expr : AstPtr < ast:: Expr > ,
430
+ }
431
+
432
+ impl Diagnostic for ReplaceFilterMapNextWithFindMap {
433
+ fn code ( & self ) -> DiagnosticCode {
434
+ DiagnosticCode ( "replace-filter-map-next-with-find-map" )
435
+ }
436
+ fn message ( & self ) -> String {
437
+ "replace filter_map(..).next() with find_map(..)" . to_string ( )
438
+ }
439
+ fn display_source ( & self ) -> InFile < SyntaxNodePtr > {
440
+ InFile { file_id : self . file , value : self . next_expr . clone ( ) . into ( ) }
441
+ }
442
+ fn as_any ( & self ) -> & ( dyn Any + Send + ' static ) {
443
+ self
444
+ }
445
+ }
446
+
447
+ // Diagnostic: mismatched-arg-count
448
+ //
449
+ // This diagnostic is triggered if a function is invoked with an incorrect amount of arguments.
450
+ #[ derive( Debug ) ]
451
+ pub struct MismatchedArgCount {
452
+ pub file : HirFileId ,
453
+ pub call_expr : AstPtr < ast:: Expr > ,
454
+ pub expected : usize ,
455
+ pub found : usize ,
456
+ }
457
+
458
+ impl Diagnostic for MismatchedArgCount {
459
+ fn code ( & self ) -> DiagnosticCode {
460
+ DiagnosticCode ( "mismatched-arg-count" )
461
+ }
462
+ fn message ( & self ) -> String {
463
+ let s = if self . expected == 1 { "" } else { "s" } ;
464
+ format ! ( "Expected {} argument{}, found {}" , self . expected, s, self . found)
465
+ }
466
+ fn display_source ( & self ) -> InFile < SyntaxNodePtr > {
467
+ InFile { file_id : self . file , value : self . call_expr . clone ( ) . into ( ) }
468
+ }
469
+ fn as_any ( & self ) -> & ( dyn Any + Send + ' static ) {
470
+ self
471
+ }
472
+ fn is_experimental ( & self ) -> bool {
473
+ true
474
+ }
475
+ }
476
+
477
+ #[ derive( Debug ) ]
478
+ pub struct RemoveThisSemicolon {
479
+ pub file : HirFileId ,
480
+ pub expr : AstPtr < ast:: Expr > ,
481
+ }
482
+
483
+ impl Diagnostic for RemoveThisSemicolon {
484
+ fn code ( & self ) -> DiagnosticCode {
485
+ DiagnosticCode ( "remove-this-semicolon" )
486
+ }
487
+
488
+ fn message ( & self ) -> String {
489
+ "Remove this semicolon" . to_string ( )
490
+ }
491
+
492
+ fn display_source ( & self ) -> InFile < SyntaxNodePtr > {
493
+ InFile { file_id : self . file , value : self . expr . clone ( ) . into ( ) }
494
+ }
495
+
496
+ fn as_any ( & self ) -> & ( dyn Any + Send + ' static ) {
497
+ self
498
+ }
499
+ }
500
+
501
+ // Diagnostic: missing-ok-or-some-in-tail-expr
502
+ //
503
+ // This diagnostic is triggered if a block that should return `Result` returns a value not wrapped in `Ok`,
504
+ // or if a block that should return `Option` returns a value not wrapped in `Some`.
505
+ //
506
+ // Example:
507
+ //
508
+ // ```rust
509
+ // fn foo() -> Result<u8, ()> {
510
+ // 10
511
+ // }
512
+ // ```
513
+ #[ derive( Debug ) ]
514
+ pub struct MissingOkOrSomeInTailExpr {
515
+ pub file : HirFileId ,
516
+ pub expr : AstPtr < ast:: Expr > ,
517
+ // `Some` or `Ok` depending on whether the return type is Result or Option
518
+ pub required : String ,
519
+ }
520
+
521
+ impl Diagnostic for MissingOkOrSomeInTailExpr {
522
+ fn code ( & self ) -> DiagnosticCode {
523
+ DiagnosticCode ( "missing-ok-or-some-in-tail-expr" )
524
+ }
525
+ fn message ( & self ) -> String {
526
+ format ! ( "wrap return expression in {}" , self . required)
527
+ }
528
+ fn display_source ( & self ) -> InFile < SyntaxNodePtr > {
529
+ InFile { file_id : self . file , value : self . expr . clone ( ) . into ( ) }
530
+ }
531
+ fn as_any ( & self ) -> & ( dyn Any + Send + ' static ) {
532
+ self
533
+ }
534
+ }
535
+
536
+ // Diagnostic: missing-match-arm
537
+ //
538
+ // This diagnostic is triggered if `match` block is missing one or more match arms.
539
+ #[ derive( Debug ) ]
540
+ pub struct MissingMatchArms {
541
+ pub file : HirFileId ,
542
+ pub match_expr : AstPtr < ast:: Expr > ,
543
+ pub arms : AstPtr < ast:: MatchArmList > ,
544
+ }
545
+
546
+ impl Diagnostic for MissingMatchArms {
547
+ fn code ( & self ) -> DiagnosticCode {
548
+ DiagnosticCode ( "missing-match-arm" )
549
+ }
550
+ fn message ( & self ) -> String {
551
+ String :: from ( "Missing match arm" )
552
+ }
553
+ fn display_source ( & self ) -> InFile < SyntaxNodePtr > {
554
+ InFile { file_id : self . file , value : self . match_expr . clone ( ) . into ( ) }
555
+ }
556
+ fn as_any ( & self ) -> & ( dyn Any + Send + ' static ) {
557
+ self
558
+ }
559
+ }
560
+
561
+ #[ derive( Debug ) ]
562
+ pub struct InternalBailedOut {
563
+ pub file : HirFileId ,
564
+ pub pat_syntax_ptr : SyntaxNodePtr ,
565
+ }
566
+
567
+ impl Diagnostic for InternalBailedOut {
568
+ fn code ( & self ) -> DiagnosticCode {
569
+ DiagnosticCode ( "internal:match-check-bailed-out" )
570
+ }
571
+ fn message ( & self ) -> String {
572
+ format ! ( "Internal: match check bailed out" )
573
+ }
574
+ fn display_source ( & self ) -> InFile < SyntaxNodePtr > {
575
+ InFile { file_id : self . file , value : self . pat_syntax_ptr . clone ( ) }
576
+ }
577
+ fn as_any ( & self ) -> & ( dyn Any + Send + ' static ) {
578
+ self
579
+ }
580
+ }
0 commit comments