@@ -92,6 +92,11 @@ struct Opt {
92
92
/// Print verbose output.
93
93
#[ structopt( short, long) ]
94
94
verbose : bool ,
95
+ /// Continue with formatting even if there are invalid rustfmt attributes.
96
+ ///
97
+ /// Exits with 1 if there are any invalid rustfmt attributes.
98
+ #[ structopt( long = "format-with-invalid-attrs" ) ]
99
+ format_with_invalid_attributes : bool ,
95
100
96
101
// Nightly-only options.
97
102
/// Limit formatting to specified ranges.
@@ -413,6 +418,10 @@ fn format_string(input: String, opt: Opt) -> Result<i32> {
413
418
verbosity : Verbosity :: Quiet ,
414
419
} ;
415
420
let report = rustfmt_nightly:: format ( Input :: Text ( input) , & config, setting) ?;
421
+ if report. has_invalid_rustfmt_attribute_errors ( ) && !opt. format_with_invalid_attributes {
422
+ eprintln ! ( "Input contained invalid rustfmt attributes" ) ;
423
+ return Ok ( 1 ) ;
424
+ }
416
425
let has_diff = emit_format_report ( report, out, opt. emitter_config ( EmitMode :: Stdout ) ) ?;
417
426
Ok ( if opt. check && has_diff { 1 } else { 0 } )
418
427
}
@@ -521,6 +530,10 @@ fn format(opt: Opt) -> Result<i32> {
521
530
) ;
522
531
}
523
532
533
+ if format_report. has_invalid_rustfmt_attribute_errors ( ) && !opt. format_with_invalid_attributes {
534
+ return Ok ( 1 ) ;
535
+ }
536
+
524
537
let has_diff = emit_format_report (
525
538
format_report,
526
539
& mut stdout ( ) ,
@@ -543,7 +556,16 @@ mod test {
543
556
path : PathBuf ,
544
557
}
545
558
546
- fn make_temp_file ( file_name : & ' static str ) -> TempFile {
559
+ fn assert_temp_file_contents ( expected_contents : & [ u8 ] , actual_file : TempFile ) {
560
+ assert_eq ! (
561
+ expected_contents,
562
+ std:: fs:: read_to_string( & actual_file. path)
563
+ . expect( "couldn't read temp file" )
564
+ . as_bytes( ) ,
565
+ ) ;
566
+ }
567
+
568
+ fn make_temp_file_with_contents ( file_name : & ' static str , content : & [ u8 ] ) -> TempFile {
547
569
use std:: env:: var;
548
570
use std:: fs:: File ;
549
571
@@ -552,11 +574,14 @@ mod test {
552
574
let path = Path :: new ( & target_dir) . join ( file_name) ;
553
575
554
576
let mut file = File :: create ( & path) . expect ( "couldn't create temp file" ) ;
555
- let content = b"fn main() {}\n " ;
556
577
file. write_all ( content) . expect ( "couldn't write temp file" ) ;
557
578
TempFile { path }
558
579
}
559
580
581
+ fn make_temp_file ( file_name : & ' static str ) -> TempFile {
582
+ make_temp_file_with_contents ( file_name, b"fn main() {}\n " )
583
+ }
584
+
560
585
impl Drop for TempFile {
561
586
fn drop ( & mut self ) {
562
587
use std:: fs:: remove_file;
@@ -680,4 +705,112 @@ mod test {
680
705
. expect ( "Failed to wait on rustfmt child" ) ;
681
706
assert ! ( output. status. success( ) ) ;
682
707
}
708
+
709
+ #[ cfg( test) ]
710
+ mod format_with_invalid_attributes {
711
+ use super :: * ;
712
+
713
+ const CONTENTS : & [ u8 ] = br#"
714
+ #![rustfmt::max_width(120)]
715
+ fn foo() {
716
+ println!("bar");
717
+ }
718
+ "# ;
719
+
720
+ const FORMATTED_CONTENTS : & [ u8 ] = br#"
721
+ #![rustfmt::max_width(120)]
722
+ fn foo() {
723
+ println!("bar");
724
+ }
725
+ "# ;
726
+
727
+ #[ test]
728
+ fn verify_default ( ) {
729
+ init_log ( ) ;
730
+ let temp_file = make_temp_file_with_contents ( "temp_invalid_attrs.rs" , CONTENTS ) ;
731
+
732
+ let child = Command :: new ( rustfmt ( ) )
733
+ . arg ( & temp_file. path )
734
+ . stderr ( Stdio :: piped ( ) )
735
+ . spawn ( )
736
+ . expect ( "run with --format-with-invalid-attrs option failed" ) ;
737
+ let output = child
738
+ . wait_with_output ( )
739
+ . expect ( "Failed to wait on rustfmt child" ) ;
740
+
741
+ assert ! ( !output. status. success( ) ) ;
742
+ assert_temp_file_contents ( CONTENTS , temp_file) ;
743
+ }
744
+
745
+ #[ test]
746
+ fn verify_enabled ( ) {
747
+ init_log ( ) ;
748
+ let temp_file = make_temp_file_with_contents ( "temp_invalid_attrs_enabled.rs" , CONTENTS ) ;
749
+
750
+ let child = Command :: new ( rustfmt ( ) )
751
+ . arg ( & temp_file. path )
752
+ . arg ( "--format-with-invalid-attrs" )
753
+ . stderr ( Stdio :: piped ( ) )
754
+ . spawn ( )
755
+ . expect ( "run with --format-with-invalid-attrs option failed" ) ;
756
+ let output = child
757
+ . wait_with_output ( )
758
+ . expect ( "Failed to wait on rustfmt child" ) ;
759
+ assert ! ( output. status. success( ) ) ;
760
+ assert_temp_file_contents ( FORMATTED_CONTENTS , temp_file) ;
761
+ }
762
+
763
+ #[ test]
764
+ fn verify_default_stdin ( ) {
765
+ init_log ( ) ;
766
+
767
+ let mut child = Command :: new ( rustfmt ( ) )
768
+ . stdin ( Stdio :: piped ( ) )
769
+ . stdout ( Stdio :: piped ( ) )
770
+ . stderr ( Stdio :: piped ( ) )
771
+ . spawn ( )
772
+ . expect ( "run with check option failed" ) ;
773
+
774
+ {
775
+ let stdin = child. stdin . as_mut ( ) . expect ( "Failed to open stdin" ) ;
776
+ stdin
777
+ . write_all ( CONTENTS )
778
+ . expect ( "Failed to write to rustfmt --check" ) ;
779
+ }
780
+ let output = child
781
+ . wait_with_output ( )
782
+ . expect ( "Failed to wait on rustfmt child" ) ;
783
+ assert ! ( !output. status. success( ) ) ;
784
+ assert ! ( output. stdout. is_empty( ) ) ;
785
+ assert_eq ! (
786
+ String :: from_utf8( output. stderr) . unwrap( ) ,
787
+ String :: from( "Input contained invalid rustfmt attributes\n " )
788
+ ) ;
789
+ }
790
+
791
+ #[ test]
792
+ fn verify_enabled_stdin ( ) {
793
+ init_log ( ) ;
794
+
795
+ let mut child = Command :: new ( rustfmt ( ) )
796
+ . arg ( "--format-with-invalid-attrs" )
797
+ . stdin ( Stdio :: piped ( ) )
798
+ . stdout ( Stdio :: piped ( ) )
799
+ . stderr ( Stdio :: piped ( ) )
800
+ . spawn ( )
801
+ . expect ( "run with check option failed" ) ;
802
+
803
+ {
804
+ let stdin = child. stdin . as_mut ( ) . expect ( "Failed to open stdin" ) ;
805
+ stdin
806
+ . write_all ( CONTENTS )
807
+ . expect ( "Failed to write to rustfmt --check" ) ;
808
+ }
809
+ let output = child
810
+ . wait_with_output ( )
811
+ . expect ( "Failed to wait on rustfmt child" ) ;
812
+ assert ! ( output. status. success( ) ) ;
813
+ assert_eq ! ( & output. stdout, & FORMATTED_CONTENTS ) ;
814
+ }
815
+ }
683
816
}
0 commit comments