1
1
// High level formatting functions.
2
2
3
+ use std:: cell:: RefCell ;
3
4
use std:: collections:: HashMap ;
4
5
use std:: io:: { self , Write } ;
5
6
use std:: panic:: { catch_unwind, AssertUnwindSafe } ;
@@ -70,17 +71,19 @@ fn format_project<T: FormatHandler>(
70
71
Ok ( set) => set,
71
72
Err ( e) => return Err ( ErrorKind :: InvalidGlobPattern ( e) ) ,
72
73
} ;
73
- let is_ignore_match = ignore_path_set. is_match ( & main_file) ;
74
- if config. skip_children ( ) && is_ignore_match {
74
+ if config. skip_children ( ) && ignore_path_set. is_match ( & main_file) {
75
75
return Ok ( FormatReport :: new ( ) ) ;
76
76
}
77
77
78
78
// Parse the crate.
79
+ let can_reset = Rc :: new ( RefCell :: new ( false ) ) ;
79
80
let source_map = Rc :: new ( SourceMap :: new ( FilePathMapping :: empty ( ) ) ) ;
80
- let mut parse_session = make_parse_sess ( source_map. clone ( ) , config, & ignore_path_set) ;
81
- if is_ignore_match {
82
- parse_session. span_diagnostic = Handler :: with_emitter ( true , None , silent_emitter ( ) ) ;
83
- }
81
+ let mut parse_session = make_parse_sess (
82
+ source_map. clone ( ) ,
83
+ config,
84
+ & ignore_path_set,
85
+ can_reset. clone ( ) ,
86
+ ) ;
84
87
let mut report = FormatReport :: new ( ) ;
85
88
let directory_ownership = input. to_directory_ownership ( ) ;
86
89
let krate = match parse_crate (
@@ -89,16 +92,11 @@ fn format_project<T: FormatHandler>(
89
92
config,
90
93
& mut report,
91
94
directory_ownership,
95
+ can_reset. clone ( ) ,
92
96
) {
93
97
Ok ( krate) => krate,
94
98
// Surface parse error via Session (errors are merged there from report)
95
- Err ( ErrorKind :: ParseError ) => {
96
- // https://github.com/rust-lang/rustfmt/issues/3779
97
- if is_ignore_match {
98
- return Ok ( FormatReport :: new ( ) ) ;
99
- }
100
- return Ok ( report) ;
101
- }
99
+ Err ( ErrorKind :: ParseError ) => return Ok ( report) ,
102
100
Err ( e) => return Err ( e) ,
103
101
} ;
104
102
timer = timer. done_parsing ( ) ;
@@ -630,6 +628,7 @@ fn parse_crate(
630
628
config : & Config ,
631
629
report : & mut FormatReport ,
632
630
directory_ownership : Option < parse:: DirectoryOwnership > ,
631
+ parser_error_resetter : Rc < RefCell < bool > > ,
633
632
) -> Result < ast:: Crate , ErrorKind > {
634
633
let input_is_stdin = input. is_text ( ) ;
635
634
@@ -677,6 +676,15 @@ fn parse_crate(
677
676
if !parse_session. span_diagnostic . has_errors ( ) {
678
677
return Ok ( c) ;
679
678
}
679
+ // This scenario occurs when the parser encountered errors
680
+ // but was still able to recover. If all of the parser errors
681
+ // occurred in files that are ignored, then reset
682
+ // the error count and continue.
683
+ // https://github.com/rust-lang/rustfmt/issues/3779
684
+ if * parser_error_resetter. borrow ( ) {
685
+ parse_session. span_diagnostic . reset_err_count ( ) ;
686
+ return Ok ( c) ;
687
+ }
680
688
}
681
689
Ok ( Err ( mut diagnostics) ) => diagnostics. iter_mut ( ) . for_each ( DiagnosticBuilder :: emit) ,
682
690
Err ( _) => {
@@ -697,6 +705,9 @@ struct SilentOnIgnoredFilesEmitter {
697
705
ignore_path_set : IgnorePathSet ,
698
706
source_map : Rc < SourceMap > ,
699
707
emitter : EmitterWriter ,
708
+ can_reset : bool ,
709
+ has_non_ignorable_parser_errors : bool ,
710
+ parser_error_resetter : Rc < RefCell < bool > > ,
700
711
}
701
712
702
713
impl Emitter for SilentOnIgnoredFilesEmitter {
@@ -709,13 +720,22 @@ impl Emitter for SilentOnIgnoredFilesEmitter {
709
720
. ignore_path_set
710
721
. is_match ( & FileName :: Real ( path. to_path_buf ( ) ) )
711
722
{
712
- db. handler . reset_err_count ( ) ;
723
+ if !self . has_non_ignorable_parser_errors && !self . can_reset {
724
+ self . can_reset = true ;
725
+ * self . parser_error_resetter . borrow_mut ( ) = true ;
726
+ }
713
727
return ;
714
728
}
715
729
}
716
730
_ => ( ) ,
717
731
} ;
718
732
}
733
+
734
+ self . has_non_ignorable_parser_errors = true ;
735
+ if self . can_reset {
736
+ * self . parser_error_resetter . borrow_mut ( ) = false ;
737
+ }
738
+ self . can_reset = false ;
719
739
self . emitter . emit_diagnostic ( db) ;
720
740
}
721
741
}
@@ -735,6 +755,7 @@ fn make_parse_sess(
735
755
source_map : Rc < SourceMap > ,
736
756
config : & Config ,
737
757
ignore_path_set : & IgnorePathSet ,
758
+ parser_error_resetter : Rc < RefCell < bool > > ,
738
759
) -> ParseSess {
739
760
let tty_handler = if config. hide_parse_errors ( ) {
740
761
let silent_emitter = silent_emitter ( ) ;
@@ -746,12 +767,16 @@ fn make_parse_sess(
746
767
} else {
747
768
ColorConfig :: Never
748
769
} ;
770
+
749
771
let emitter_writer =
750
- EmitterWriter :: stderr ( color_cfg, Some ( source_map. clone ( ) ) , false , false ) ;
772
+ EmitterWriter :: stderr ( color_cfg, Some ( source_map. clone ( ) ) , false , false , None ) ;
751
773
let emitter = Box :: new ( SilentOnIgnoredFilesEmitter {
774
+ has_non_ignorable_parser_errors : false ,
775
+ can_reset : false ,
752
776
ignore_path_set : ignore_path_set. clone ( ) ,
753
777
source_map : source_map. clone ( ) ,
754
778
emitter : emitter_writer,
779
+ parser_error_resetter,
755
780
} ) ;
756
781
Handler :: with_emitter_and_flags (
757
782
emitter,
0 commit comments