@@ -715,37 +715,43 @@ fn parse_crate(
715
715
struct SilentOnIgnoredFilesEmitter {
716
716
ignore_path_set : Rc < IgnorePathSet > ,
717
717
source_map : Rc < SourceMap > ,
718
- emitter : EmitterWriter ,
718
+ emitter : Box < dyn Emitter + Send > ,
719
719
has_non_ignorable_parser_errors : bool ,
720
720
can_reset : Rc < RefCell < bool > > ,
721
721
}
722
722
723
+ impl SilentOnIgnoredFilesEmitter {
724
+ fn handle_non_ignoreable_error ( & mut self , db : & Diagnostic ) {
725
+ self . has_non_ignorable_parser_errors = true ;
726
+ * self . can_reset . borrow_mut ( ) = false ;
727
+ self . emitter . emit_diagnostic ( db) ;
728
+ }
729
+ }
730
+
723
731
impl Emitter for SilentOnIgnoredFilesEmitter {
724
732
fn source_map ( & self ) -> Option < & Lrc < SourceMap > > {
725
733
None
726
734
}
735
+
727
736
fn emit_diagnostic ( & mut self , db : & Diagnostic ) {
737
+ if db. level == DiagnosticLevel :: Fatal {
738
+ return self . handle_non_ignoreable_error ( db) ;
739
+ }
728
740
if let Some ( primary_span) = & db. span . primary_span ( ) {
729
741
let file_name = self . source_map . span_to_filename ( * primary_span) ;
730
- match file_name {
731
- rustc_span:: FileName :: Real ( ref path) => {
732
- if self
733
- . ignore_path_set
734
- . is_match ( & FileName :: Real ( path. to_path_buf ( ) ) )
735
- {
736
- if !self . has_non_ignorable_parser_errors {
737
- * self . can_reset . borrow_mut ( ) = true ;
738
- }
739
- return ;
742
+ if let rustc_span:: FileName :: Real ( ref path) = file_name {
743
+ if self
744
+ . ignore_path_set
745
+ . is_match ( & FileName :: Real ( path. to_path_buf ( ) ) )
746
+ {
747
+ if !self . has_non_ignorable_parser_errors {
748
+ * self . can_reset . borrow_mut ( ) = true ;
740
749
}
750
+ return ;
741
751
}
742
- _ => ( ) ,
743
752
} ;
744
753
}
745
-
746
- self . has_non_ignorable_parser_errors = true ;
747
- * self . can_reset . borrow_mut ( ) = false ;
748
- self . emitter . emit_diagnostic ( db) ;
754
+ self . handle_non_ignoreable_error ( db) ;
749
755
}
750
756
}
751
757
@@ -759,7 +765,7 @@ impl Emitter for SilentEmitter {
759
765
fn emit_diagnostic ( & mut self , _db : & Diagnostic ) { }
760
766
}
761
767
762
- fn silent_emitter ( ) -> Box < SilentEmitter > {
768
+ fn silent_emitter ( ) -> Box < dyn Emitter + Send > {
763
769
Box :: new ( SilentEmitter { } )
764
770
}
765
771
@@ -769,36 +775,38 @@ fn make_parse_sess(
769
775
ignore_path_set : Rc < IgnorePathSet > ,
770
776
can_reset : Rc < RefCell < bool > > ,
771
777
) -> ParseSess {
772
- let tty_handler = if config . hide_parse_errors ( ) {
773
- let silent_emitter = silent_emitter ( ) ;
774
- Handler :: with_emitter ( true , None , silent_emitter )
778
+ let supports_color = term :: stderr ( ) . map_or ( false , |term| term . supports_color ( ) ) ;
779
+ let color_cfg = if supports_color {
780
+ ColorConfig :: Auto
775
781
} else {
776
- let supports_color = term:: stderr ( ) . map_or ( false , |term| term. supports_color ( ) ) ;
777
- let color_cfg = if supports_color {
778
- ColorConfig :: Auto
779
- } else {
780
- ColorConfig :: Never
781
- } ;
782
+ ColorConfig :: Never
783
+ } ;
782
784
783
- let emitter_writer = EmitterWriter :: stderr (
785
+ let emitter = if config. hide_parse_errors ( ) {
786
+ silent_emitter ( )
787
+ } else {
788
+ Box :: new ( EmitterWriter :: stderr (
784
789
color_cfg,
785
790
Some ( source_map. clone ( ) ) ,
786
791
false ,
787
792
false ,
788
793
None ,
789
794
false ,
790
- ) ;
791
- let emitter = Box :: new ( SilentOnIgnoredFilesEmitter {
795
+ ) )
796
+ } ;
797
+ let handler = Handler :: with_emitter (
798
+ true ,
799
+ None ,
800
+ Box :: new ( SilentOnIgnoredFilesEmitter {
792
801
has_non_ignorable_parser_errors : false ,
793
- ignore_path_set : ignore_path_set ,
794
- source_map : Rc :: clone ( & source_map ) ,
795
- emitter : emitter_writer ,
802
+ source_map : source_map . clone ( ) ,
803
+ emitter ,
804
+ ignore_path_set ,
796
805
can_reset,
797
- } ) ;
798
- Handler :: with_emitter ( true , None , emitter)
799
- } ;
806
+ } ) ,
807
+ ) ;
800
808
801
- ParseSess :: with_span_handler ( tty_handler , source_map)
809
+ ParseSess :: with_span_handler ( handler , source_map)
802
810
}
803
811
804
812
fn should_emit_verbose < F > ( is_stdin : bool , config : & Config , f : F )
@@ -809,3 +817,174 @@ where
809
817
f ( ) ;
810
818
}
811
819
}
820
+
821
+ #[ cfg( test) ]
822
+ mod tests {
823
+ use super :: * ;
824
+
825
+ mod emitter {
826
+ use super :: * ;
827
+ use crate :: config:: IgnoreList ;
828
+ use crate :: is_nightly_channel;
829
+ use crate :: utils:: mk_sp;
830
+ use rustc_span:: { BytePos , FileName as SourceMapFileName , MultiSpan , DUMMY_SP } ;
831
+ use std:: path:: { Path , PathBuf } ;
832
+
833
+ struct TestEmitter {
834
+ num_emitted_errors : Rc < RefCell < u32 > > ,
835
+ }
836
+
837
+ impl Emitter for TestEmitter {
838
+ fn source_map ( & self ) -> Option < & Lrc < SourceMap > > {
839
+ None
840
+ }
841
+ fn emit_diagnostic ( & mut self , _db : & Diagnostic ) {
842
+ * self . num_emitted_errors . borrow_mut ( ) += 1 ;
843
+ }
844
+ }
845
+
846
+ fn build_diagnostic ( level : DiagnosticLevel , span : Option < MultiSpan > ) -> Diagnostic {
847
+ Diagnostic {
848
+ level,
849
+ code : None ,
850
+ message : vec ! [ ] ,
851
+ children : vec ! [ ] ,
852
+ suggestions : vec ! [ ] ,
853
+ span : span. unwrap_or_else ( MultiSpan :: new) ,
854
+ sort_span : DUMMY_SP ,
855
+ }
856
+ }
857
+
858
+ fn build_emitter (
859
+ num_emitted_errors : Rc < RefCell < u32 > > ,
860
+ can_reset : Rc < RefCell < bool > > ,
861
+ source_map : Option < Rc < SourceMap > > ,
862
+ ignore_list : Option < IgnoreList > ,
863
+ ) -> SilentOnIgnoredFilesEmitter {
864
+ let emitter_writer = TestEmitter { num_emitted_errors } ;
865
+ let source_map =
866
+ source_map. unwrap_or_else ( || Rc :: new ( SourceMap :: new ( FilePathMapping :: empty ( ) ) ) ) ;
867
+ let ignore_path_set =
868
+ Rc :: new ( IgnorePathSet :: from_ignore_list ( & ignore_list. unwrap_or_default ( ) ) . unwrap ( ) ) ;
869
+ SilentOnIgnoredFilesEmitter {
870
+ has_non_ignorable_parser_errors : false ,
871
+ source_map,
872
+ emitter : Box :: new ( emitter_writer) ,
873
+ ignore_path_set,
874
+ can_reset,
875
+ }
876
+ }
877
+
878
+ fn get_ignore_list ( config : & str ) -> IgnoreList {
879
+ Config :: from_toml ( config, Path :: new ( "" ) ) . unwrap ( ) . ignore ( )
880
+ }
881
+
882
+ #[ test]
883
+ fn handles_fatal_parse_error_in_ignored_file ( ) {
884
+ let num_emitted_errors = Rc :: new ( RefCell :: new ( 0 ) ) ;
885
+ let can_reset_errors = Rc :: new ( RefCell :: new ( false ) ) ;
886
+ let ignore_list = get_ignore_list ( r#"ignore = ["foo.rs"]"# ) ;
887
+ let source_map = Rc :: new ( SourceMap :: new ( FilePathMapping :: empty ( ) ) ) ;
888
+ let source =
889
+ String :: from ( r#"extern "system" fn jni_symbol!( funcName ) ( ... ) -> {} "# ) ;
890
+ source_map. new_source_file ( SourceMapFileName :: Real ( PathBuf :: from ( "foo.rs" ) ) , source) ;
891
+ let mut emitter = build_emitter (
892
+ Rc :: clone ( & num_emitted_errors) ,
893
+ Rc :: clone ( & can_reset_errors) ,
894
+ Some ( Rc :: clone ( & source_map) ) ,
895
+ Some ( ignore_list) ,
896
+ ) ;
897
+ let span = MultiSpan :: from_span ( mk_sp ( BytePos ( 0 ) , BytePos ( 1 ) ) ) ;
898
+ let fatal_diagnostic = build_diagnostic ( DiagnosticLevel :: Fatal , Some ( span) ) ;
899
+ emitter. emit_diagnostic ( & fatal_diagnostic) ;
900
+ assert_eq ! ( * num_emitted_errors. borrow( ) , 1 ) ;
901
+ assert_eq ! ( * can_reset_errors. borrow( ) , false ) ;
902
+ }
903
+
904
+ #[ test]
905
+ fn handles_recoverable_parse_error_in_ignored_file ( ) {
906
+ if !is_nightly_channel ! ( ) {
907
+ return ;
908
+ }
909
+ let num_emitted_errors = Rc :: new ( RefCell :: new ( 0 ) ) ;
910
+ let can_reset_errors = Rc :: new ( RefCell :: new ( false ) ) ;
911
+ let ignore_list = get_ignore_list ( r#"ignore = ["foo.rs"]"# ) ;
912
+ let source_map = Rc :: new ( SourceMap :: new ( FilePathMapping :: empty ( ) ) ) ;
913
+ let source = String :: from ( r#"pub fn bar() { 1x; }"# ) ;
914
+ source_map. new_source_file ( SourceMapFileName :: Real ( PathBuf :: from ( "foo.rs" ) ) , source) ;
915
+ let mut emitter = build_emitter (
916
+ Rc :: clone ( & num_emitted_errors) ,
917
+ Rc :: clone ( & can_reset_errors) ,
918
+ Some ( Rc :: clone ( & source_map) ) ,
919
+ Some ( ignore_list) ,
920
+ ) ;
921
+ let span = MultiSpan :: from_span ( mk_sp ( BytePos ( 0 ) , BytePos ( 1 ) ) ) ;
922
+ let non_fatal_diagnostic = build_diagnostic ( DiagnosticLevel :: Warning , Some ( span) ) ;
923
+ emitter. emit_diagnostic ( & non_fatal_diagnostic) ;
924
+ assert_eq ! ( * num_emitted_errors. borrow( ) , 0 ) ;
925
+ assert_eq ! ( * can_reset_errors. borrow( ) , true ) ;
926
+ }
927
+
928
+ #[ test]
929
+ fn handles_recoverable_parse_error_in_non_ignored_file ( ) {
930
+ if !is_nightly_channel ! ( ) {
931
+ return ;
932
+ }
933
+ let num_emitted_errors = Rc :: new ( RefCell :: new ( 0 ) ) ;
934
+ let can_reset_errors = Rc :: new ( RefCell :: new ( false ) ) ;
935
+ let source_map = Rc :: new ( SourceMap :: new ( FilePathMapping :: empty ( ) ) ) ;
936
+ let source = String :: from ( r#"pub fn bar() { 1x; }"# ) ;
937
+ source_map. new_source_file ( SourceMapFileName :: Real ( PathBuf :: from ( "foo.rs" ) ) , source) ;
938
+ let mut emitter = build_emitter (
939
+ Rc :: clone ( & num_emitted_errors) ,
940
+ Rc :: clone ( & can_reset_errors) ,
941
+ Some ( Rc :: clone ( & source_map) ) ,
942
+ None ,
943
+ ) ;
944
+ let span = MultiSpan :: from_span ( mk_sp ( BytePos ( 0 ) , BytePos ( 1 ) ) ) ;
945
+ let non_fatal_diagnostic = build_diagnostic ( DiagnosticLevel :: Warning , Some ( span) ) ;
946
+ emitter. emit_diagnostic ( & non_fatal_diagnostic) ;
947
+ assert_eq ! ( * num_emitted_errors. borrow( ) , 1 ) ;
948
+ assert_eq ! ( * can_reset_errors. borrow( ) , false ) ;
949
+ }
950
+
951
+ #[ test]
952
+ fn handles_mix_of_recoverable_parse_error ( ) {
953
+ if !is_nightly_channel ! ( ) {
954
+ return ;
955
+ }
956
+ let num_emitted_errors = Rc :: new ( RefCell :: new ( 0 ) ) ;
957
+ let can_reset_errors = Rc :: new ( RefCell :: new ( false ) ) ;
958
+ let source_map = Rc :: new ( SourceMap :: new ( FilePathMapping :: empty ( ) ) ) ;
959
+ let ignore_list = get_ignore_list ( r#"ignore = ["foo.rs"]"# ) ;
960
+ let bar_source = String :: from ( r#"pub fn bar() { 1x; }"# ) ;
961
+ let foo_source = String :: from ( r#"pub fn foo() { 1x; }"# ) ;
962
+ let fatal_source =
963
+ String :: from ( r#"extern "system" fn jni_symbol!( funcName ) ( ... ) -> {} "# ) ;
964
+ source_map
965
+ . new_source_file ( SourceMapFileName :: Real ( PathBuf :: from ( "bar.rs" ) ) , bar_source) ;
966
+ source_map
967
+ . new_source_file ( SourceMapFileName :: Real ( PathBuf :: from ( "foo.rs" ) ) , foo_source) ;
968
+ source_map. new_source_file (
969
+ SourceMapFileName :: Real ( PathBuf :: from ( "fatal.rs" ) ) ,
970
+ fatal_source,
971
+ ) ;
972
+ let mut emitter = build_emitter (
973
+ Rc :: clone ( & num_emitted_errors) ,
974
+ Rc :: clone ( & can_reset_errors) ,
975
+ Some ( Rc :: clone ( & source_map) ) ,
976
+ Some ( ignore_list) ,
977
+ ) ;
978
+ let bar_span = MultiSpan :: from_span ( mk_sp ( BytePos ( 0 ) , BytePos ( 1 ) ) ) ;
979
+ let foo_span = MultiSpan :: from_span ( mk_sp ( BytePos ( 21 ) , BytePos ( 22 ) ) ) ;
980
+ let bar_diagnostic = build_diagnostic ( DiagnosticLevel :: Warning , Some ( bar_span) ) ;
981
+ let foo_diagnostic = build_diagnostic ( DiagnosticLevel :: Warning , Some ( foo_span) ) ;
982
+ let fatal_diagnostic = build_diagnostic ( DiagnosticLevel :: Fatal , None ) ;
983
+ emitter. emit_diagnostic ( & bar_diagnostic) ;
984
+ emitter. emit_diagnostic ( & foo_diagnostic) ;
985
+ emitter. emit_diagnostic ( & fatal_diagnostic) ;
986
+ assert_eq ! ( * num_emitted_errors. borrow( ) , 2 ) ;
987
+ assert_eq ! ( * can_reset_errors. borrow( ) , false ) ;
988
+ }
989
+ }
990
+ }
0 commit comments