99// except according to those terms.
1010
1111use common:: { Config , TestPaths } ;
12+ use common:: { UI_FIXED , UI_STDERR , UI_STDOUT } ;
1213use common:: { CompileFail , ParseFail , Pretty , RunFail , RunPass , RunPassValgrind } ;
1314use common:: { Codegen , DebugInfoLldb , DebugInfoGdb , Rustdoc , CodegenUnits } ;
1415use common:: { Incremental , RunMake , Ui , MirOpt } ;
@@ -17,6 +18,7 @@ use errors::{self, ErrorKind, Error};
1718use filetime:: FileTime ;
1819use json;
1920use regex:: Regex ;
21+ use rustfix:: { apply_suggestions, get_suggestions_from_json, Filter } ;
2022use header:: TestProps ;
2123use util:: logv;
2224
@@ -1430,7 +1432,16 @@ actual:\n\
14301432
14311433 rustc. arg ( dir_opt) ;
14321434 }
1433- RunPass |
1435+ RunPass | Ui => {
1436+ if !self
1437+ . props
1438+ . compile_flags
1439+ . iter ( )
1440+ . any ( |s| s. starts_with ( "--error-format" ) )
1441+ {
1442+ rustc. args ( & [ "--error-format" , "json" ] ) ;
1443+ }
1444+ }
14341445 RunFail |
14351446 RunPassValgrind |
14361447 Pretty |
@@ -1439,7 +1450,6 @@ actual:\n\
14391450 Codegen |
14401451 Rustdoc |
14411452 RunMake |
1442- Ui |
14431453 CodegenUnits => {
14441454 // do not use JSON output
14451455 }
@@ -2222,22 +2232,68 @@ actual:\n\
22222232 }
22232233
22242234 fn run_ui_test ( & self ) {
2235+ // if the user specified a format in the ui test
2236+ // print the output to the stderr file, otherwise extract
2237+ // the rendered error messages from json and print them
2238+ let explicit = self
2239+ . props
2240+ . compile_flags
2241+ . iter ( )
2242+ . any ( |s| s. contains ( "--error-format" ) ) ;
22252243 let proc_res = self . compile_test ( ) ;
22262244
2227- let expected_stderr_path = self . expected_output_path ( "stderr" ) ;
2245+ let expected_stderr_path = self . expected_output_path ( UI_STDERR ) ;
22282246 let expected_stderr = self . load_expected_output ( & expected_stderr_path) ;
22292247
2230- let expected_stdout_path = self . expected_output_path ( "stdout" ) ;
2248+ let expected_stdout_path = self . expected_output_path ( UI_STDOUT ) ;
22312249 let expected_stdout = self . load_expected_output ( & expected_stdout_path) ;
22322250
2251+ let expected_fixed_path = self . expected_output_path ( UI_FIXED ) ;
2252+ let expected_fixed = self . load_expected_output ( & expected_fixed_path) ;
2253+
22332254 let normalized_stdout =
22342255 self . normalize_output ( & proc_res. stdout , & self . props . normalize_stdout ) ;
2256+
2257+ let stderr = if explicit {
2258+ proc_res. stderr . clone ( )
2259+ } else {
2260+ json:: extract_rendered ( & proc_res. stderr , & proc_res)
2261+ } ;
2262+
22352263 let normalized_stderr =
2236- self . normalize_output ( & proc_res . stderr , & self . props . normalize_stderr ) ;
2264+ self . normalize_output ( & stderr, & self . props . normalize_stderr ) ;
22372265
22382266 let mut errors = 0 ;
2239- errors += self . compare_output ( "stdout" , & normalized_stdout, & expected_stdout) ;
2240- errors += self . compare_output ( "stderr" , & normalized_stderr, & expected_stderr) ;
2267+ errors += self . compare_output ( UI_STDOUT , & normalized_stdout, & expected_stdout) ;
2268+ errors += self . compare_output ( UI_STDERR , & normalized_stderr, & expected_stderr) ;
2269+
2270+
2271+ if self . props . run_rustfix {
2272+ // Apply suggestions from lints to the code itself
2273+ let unfixed_code = self
2274+ . load_expected_output_from_path ( & self . testpaths . file )
2275+ . expect ( "Could not load output from path" ) ;
2276+ let suggestions = get_suggestions_from_json (
2277+ & proc_res. stderr ,
2278+ & HashSet :: new ( ) ,
2279+ if self . props . rustfix_only_machine_applicable {
2280+ Filter :: MachineApplicableOnly
2281+ } else {
2282+ Filter :: Everything
2283+ } ,
2284+ ) . expect ( "Could not retrieve suggestions from JSON" ) ;
2285+ let fixed_code = apply_suggestions ( & unfixed_code, & suggestions) . expect ( & format ! (
2286+ "failed to apply suggestions for {:?} with rustfix" ,
2287+ self . testpaths. file
2288+ ) ) ;
2289+
2290+ errors += self . compare_output ( UI_FIXED , & fixed_code, & expected_fixed) ;
2291+ } else if !expected_fixed. is_empty ( ) {
2292+ panic ! (
2293+ "the `// run-rustfix` directive wasn't found but a `*.fixed` \
2294+ file was found"
2295+ ) ;
2296+ }
22412297
22422298 if errors > 0 {
22432299 println ! ( "To update references, run this command from build directory:" ) ;
@@ -2259,6 +2315,23 @@ actual:\n\
22592315 self . fatal_proc_rec ( "test run failed!" , & proc_res) ;
22602316 }
22612317 }
2318+
2319+ if self . props . run_rustfix {
2320+ // And finally, compile the fixed code and make sure it both
2321+ // succeeds and has no diagnostics.
2322+ let mut rustc = self . make_compile_args (
2323+ & self . testpaths . file . with_extension ( UI_FIXED ) ,
2324+ TargetLocation :: ThisFile ( self . make_exe_name ( ) ) ,
2325+ ) ;
2326+ rustc. arg ( "-L" ) . arg ( & self . aux_output_dir_name ( ) ) ;
2327+ let res = self . compose_and_run_compiler ( rustc, None ) ;
2328+ if !res. status . success ( ) {
2329+ self . fatal_proc_rec ( "failed to compile fixed code" , & res) ;
2330+ }
2331+ if !res. stderr . is_empty ( ) && !self . props . rustfix_only_machine_applicable {
2332+ self . fatal_proc_rec ( "fixed code is still producing diagnostics" , & res) ;
2333+ }
2334+ }
22622335 }
22632336
22642337 fn run_mir_opt_test ( & self ) {
@@ -2487,6 +2560,12 @@ actual:\n\
24872560 }
24882561 }
24892562
2563+ fn load_expected_output_from_path ( & self , path : & Path ) -> Result < String , String > {
2564+ fs:: read_to_string ( path) . map_err ( |err| {
2565+ format ! ( "failed to load expected output from `{}`: {}" , path. display( ) , err)
2566+ } )
2567+ }
2568+
24902569 fn compare_output ( & self , kind : & str , actual : & str , expected : & str ) -> usize {
24912570 if actual == expected {
24922571 return 0 ;
0 commit comments