1
- use crate :: utils:: Version ;
1
+ use crate :: utils:: { Token , Version , new_rust_searcher } ;
2
2
use clap:: ValueEnum ;
3
3
use indoc:: { formatdoc, writedoc} ;
4
4
use std:: fmt:: { self , Write as _} ;
@@ -360,8 +360,7 @@ fn get_lint_declaration(version: Version, name_upper: &str, category: &str) -> S
360
360
pub {name_upper},
361
361
{category},
362
362
"default lint description"
363
- }}
364
- "# ,
363
+ }}"# ,
365
364
version. rust_display( ) ,
366
365
)
367
366
}
@@ -446,9 +445,6 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R
446
445
447
446
#[ allow( clippy:: too_many_lines) ]
448
447
fn setup_mod_file ( path : & Path , lint : & LintData < ' _ > ) -> io:: Result < & ' static str > {
449
- use super :: update_lints:: { LintDeclSearchResult , match_tokens} ;
450
- use rustc_lexer:: TokenKind ;
451
-
452
448
let lint_name_upper = lint. name . to_uppercase ( ) ;
453
449
454
450
let mut file_contents = fs:: read_to_string ( path) ?;
@@ -459,81 +455,11 @@ fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str>
459
455
path. display( )
460
456
) ;
461
457
462
- let mut offset = 0usize ;
463
- let mut last_decl_curly_offset = None ;
464
- let mut lint_context = None ;
465
-
466
- let mut iter = rustc_lexer:: tokenize ( & file_contents) . map ( |t| {
467
- let range = offset..offset + t. len as usize ;
468
- offset = range. end ;
469
-
470
- LintDeclSearchResult {
471
- token_kind : t. kind ,
472
- content : & file_contents[ range. clone ( ) ] ,
473
- range,
474
- }
475
- } ) ;
476
-
477
- // Find both the last lint declaration (declare_clippy_lint!) and the lint pass impl
478
- while let Some ( LintDeclSearchResult { content, .. } ) = iter. find ( |result| result. token_kind == TokenKind :: Ident ) {
479
- let mut iter = iter
480
- . by_ref ( )
481
- . filter ( |t| !matches ! ( t. token_kind, TokenKind :: Whitespace | TokenKind :: LineComment { .. } ) ) ;
482
-
483
- match content {
484
- "declare_clippy_lint" => {
485
- // matches `!{`
486
- match_tokens ! ( iter, Bang OpenBrace ) ;
487
- if let Some ( LintDeclSearchResult { range, .. } ) =
488
- iter. find ( |result| result. token_kind == TokenKind :: CloseBrace )
489
- {
490
- last_decl_curly_offset = Some ( range. end ) ;
491
- }
492
- } ,
493
- "impl" => {
494
- let mut token = iter. next ( ) ;
495
- match token {
496
- // matches <'foo>
497
- Some ( LintDeclSearchResult {
498
- token_kind : TokenKind :: Lt ,
499
- ..
500
- } ) => {
501
- match_tokens ! ( iter, Lifetime { .. } Gt ) ;
502
- token = iter. next ( ) ;
503
- } ,
504
- None => break ,
505
- _ => { } ,
506
- }
507
-
508
- if let Some ( LintDeclSearchResult {
509
- token_kind : TokenKind :: Ident ,
510
- content,
511
- ..
512
- } ) = token
513
- {
514
- // Get the appropriate lint context struct
515
- lint_context = match content {
516
- "LateLintPass" => Some ( "LateContext" ) ,
517
- "EarlyLintPass" => Some ( "EarlyContext" ) ,
518
- _ => continue ,
519
- } ;
520
- }
521
- } ,
522
- _ => { } ,
523
- }
524
- }
525
-
526
- drop ( iter) ;
527
-
528
- let last_decl_curly_offset =
529
- last_decl_curly_offset. unwrap_or_else ( || panic ! ( "No lint declarations found in `{}`" , path. display( ) ) ) ;
530
- let lint_context =
531
- lint_context. unwrap_or_else ( || panic ! ( "No lint pass implementation found in `{}`" , path. display( ) ) ) ;
458
+ let ( lint_context, lint_decl_end) = parse_mod_file ( path, & file_contents) ;
532
459
533
460
// Add the lint declaration to `mod.rs`
534
- file_contents. replace_range (
535
- // Remove the trailing newline, which should always be present
536
- last_decl_curly_offset..=last_decl_curly_offset,
461
+ file_contents. insert_str (
462
+ lint_decl_end,
537
463
& format ! (
538
464
"\n \n {}" ,
539
465
get_lint_declaration( lint. clippy_version, & lint_name_upper, lint. category)
@@ -588,6 +514,42 @@ fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str>
588
514
Ok ( lint_context)
589
515
}
590
516
517
+ // Find both the last lint declaration (declare_clippy_lint!) and the lint pass impl
518
+ fn parse_mod_file ( path : & Path , contents : & str ) -> ( & ' static str , usize ) {
519
+ #[ allow( clippy:: enum_glob_use) ]
520
+ use Token :: * ;
521
+
522
+ let mut context = None ;
523
+ let mut decl_end = None ;
524
+ let mut name = "" ;
525
+ let mut searcher = new_rust_searcher ( contents) ;
526
+ while searcher. find_capture_token ( CaptureIdent , & mut name) {
527
+ match name {
528
+ "declare_clippy_lint" => {
529
+ if searcher. match_tokens ( & [ Bang , OpenBrace ] , & mut [ ] ) && searcher. find_token ( CloseBrace ) {
530
+ decl_end = Some ( searcher. pos ( ) ) ;
531
+ }
532
+ } ,
533
+ "impl" => {
534
+ if searcher. match_tokens ( & [ Lt , Lifetime , Gt , CaptureIdent ] , & mut [ & mut name] ) {
535
+ match name {
536
+ "LateLintPass" => context = Some ( "LateContext" ) ,
537
+ "EarlyLintPass" => context = Some ( "EarlyContext" ) ,
538
+ _ => { } ,
539
+ }
540
+ }
541
+ } ,
542
+ _ => { } ,
543
+ }
544
+ }
545
+ drop ( searcher) ;
546
+
547
+ (
548
+ context. unwrap_or_else ( || panic ! ( "No lint pass implementation found in `{}`" , path. display( ) ) ) ,
549
+ decl_end. unwrap_or_else ( || panic ! ( "No lint declarations found in `{}`" , path. display( ) ) ) as usize ,
550
+ )
551
+ }
552
+
591
553
#[ test]
592
554
fn test_camel_case ( ) {
593
555
let s = "a_lint" ;
0 commit comments