@@ -48,6 +48,7 @@ use rustc::hir::def::Def;
4848use rustc:: hir:: map:: Node ;
4949use rustc:: hir:: def_id:: DefId ;
5050use rustc:: session:: config:: CrateType :: CrateTypeExecutable ;
51+ use rustc:: session:: Session ;
5152use rustc:: ty:: { self , TyCtxt } ;
5253
5354use std:: env;
@@ -866,55 +867,131 @@ impl Format {
866867 }
867868}
868869
869- pub fn process_crate < ' l , ' tcx > ( tcx : TyCtxt < ' l , ' tcx , ' tcx > ,
870- krate : & ast :: Crate ,
871- analysis : & ' l ty :: CrateAnalysis ,
872- cratename : & str ,
873- odir : Option < & Path > ,
874- format : Format ) {
875- let _ignore = tcx . dep_graph . in_ignore ( ) ;
870+ /// Defines what to do with the results of saving the analysis.
871+ pub trait SaveHandler {
872+ fn save < ' l , ' tcx > ( & mut self ,
873+ save_ctxt : SaveContext < ' l , ' tcx > ,
874+ krate : & ast :: Crate ,
875+ cratename : & str ) ;
876+ }
876877
877- assert ! ( analysis. glob_map. is_some( ) ) ;
878+ /// Dump the save-analysis results to a file.
879+ pub struct DumpHandler < ' a > {
880+ format : Format ,
881+ odir : Option < & ' a Path > ,
882+ cratename : String
883+ }
878884
879- info ! ( "Dumping crate {}" , cratename) ;
885+ impl < ' a > DumpHandler < ' a > {
886+ pub fn new ( format : Format , odir : Option < & ' a Path > , cratename : & str ) -> DumpHandler < ' a > {
887+ DumpHandler {
888+ format : format,
889+ odir : odir,
890+ cratename : cratename. to_owned ( )
891+ }
892+ }
880893
881- // find a path to dump our data to
882- let mut root_path = match env:: var_os ( "RUST_SAVE_ANALYSIS_FOLDER" ) {
883- Some ( val) => PathBuf :: from ( val) ,
884- None => match odir {
885- Some ( val) => val. join ( "save-analysis" ) ,
886- None => PathBuf :: from ( "save-analysis-temp" ) ,
887- } ,
888- } ;
894+ fn output_file ( & self , sess : & Session ) -> File {
895+ let mut root_path = match env:: var_os ( "RUST_SAVE_ANALYSIS_FOLDER" ) {
896+ Some ( val) => PathBuf :: from ( val) ,
897+ None => match self . odir {
898+ Some ( val) => val. join ( "save-analysis" ) ,
899+ None => PathBuf :: from ( "save-analysis-temp" ) ,
900+ } ,
901+ } ;
889902
890- if let Err ( e) = std:: fs:: create_dir_all ( & root_path) {
891- tcx. sess . err ( & format ! ( "Could not create directory {}: {}" ,
892- root_path. display( ) ,
893- e) ) ;
903+ if let Err ( e) = std:: fs:: create_dir_all ( & root_path) {
904+ error ! ( "Could not create directory {}: {}" , root_path. display( ) , e) ;
905+ }
906+
907+ {
908+ let disp = root_path. display ( ) ;
909+ info ! ( "Writing output to {}" , disp) ;
910+ }
911+
912+ let executable = sess. crate_types . borrow ( ) . iter ( ) . any ( |ct| * ct == CrateTypeExecutable ) ;
913+ let mut out_name = if executable {
914+ "" . to_owned ( )
915+ } else {
916+ "lib" . to_owned ( )
917+ } ;
918+ out_name. push_str ( & self . cratename ) ;
919+ out_name. push_str ( & sess. opts . cg . extra_filename ) ;
920+ out_name. push_str ( self . format . extension ( ) ) ;
921+ root_path. push ( & out_name) ;
922+ let output_file = File :: create ( & root_path) . unwrap_or_else ( |e| {
923+ let disp = root_path. display ( ) ;
924+ sess. fatal ( & format ! ( "Could not open {}: {}" , disp, e) ) ;
925+ } ) ;
926+ root_path. pop ( ) ;
927+ output_file
894928 }
929+ }
930+
931+ impl < ' a > SaveHandler for DumpHandler < ' a > {
932+ fn save < ' l , ' tcx > ( & mut self ,
933+ save_ctxt : SaveContext < ' l , ' tcx > ,
934+ krate : & ast:: Crate ,
935+ cratename : & str ) {
936+ macro_rules! dump {
937+ ( $new_dumper: expr) => { {
938+ let mut dumper = $new_dumper;
939+ let mut visitor = DumpVisitor :: new( save_ctxt, & mut dumper) ;
940+
941+ visitor. dump_crate_info( cratename, krate) ;
942+ visit:: walk_crate( & mut visitor, krate) ;
943+ } }
944+ }
945+
946+ let output = & mut self . output_file ( & save_ctxt. tcx . sess ) ;
895947
896- {
897- let disp = root_path. display ( ) ;
898- info ! ( "Writing output to {}" , disp) ;
948+ match self . format {
949+ Format :: Csv => dump ! ( CsvDumper :: new( output) ) ,
950+ Format :: Json => dump ! ( JsonDumper :: new( output) ) ,
951+ Format :: JsonApi => dump ! ( JsonApiDumper :: new( output) ) ,
952+ }
899953 }
954+ }
900955
901- // Create output file.
902- let executable = tcx. sess . crate_types . borrow ( ) . iter ( ) . any ( |ct| * ct == CrateTypeExecutable ) ;
903- let mut out_name = if executable {
904- "" . to_owned ( )
905- } else {
906- "lib" . to_owned ( )
907- } ;
908- out_name. push_str ( & cratename) ;
909- out_name. push_str ( & tcx. sess . opts . cg . extra_filename ) ;
910- out_name. push_str ( format. extension ( ) ) ;
911- root_path. push ( & out_name) ;
912- let mut output_file = File :: create ( & root_path) . unwrap_or_else ( |e| {
913- let disp = root_path. display ( ) ;
914- tcx. sess . fatal ( & format ! ( "Could not open {}: {}" , disp, e) ) ;
915- } ) ;
916- root_path. pop ( ) ;
917- let output = & mut output_file;
956+ /// Call a callback with the results of save-analysis.
957+ pub struct CallbackHandler < ' b > {
958+ pub callback : & ' b mut FnMut ( & rls_data:: Analysis ) ,
959+ }
960+
961+ impl < ' b > SaveHandler for CallbackHandler < ' b > {
962+ fn save < ' l , ' tcx > ( & mut self ,
963+ save_ctxt : SaveContext < ' l , ' tcx > ,
964+ krate : & ast:: Crate ,
965+ cratename : & str ) {
966+ macro_rules! dump {
967+ ( $new_dumper: expr) => { {
968+ let mut dumper = $new_dumper;
969+ let mut visitor = DumpVisitor :: new( save_ctxt, & mut dumper) ;
970+
971+ visitor. dump_crate_info( cratename, krate) ;
972+ visit:: walk_crate( & mut visitor, krate) ;
973+ } }
974+ }
975+
976+ // We're using the JsonDumper here because it has the format of the
977+ // save-analysis results that we will pass to the callback. IOW, we are
978+ // using the JsonDumper to collect the save-analysis results, but not
979+ // actually to dump them to a file. This is all a bit convoluted and
980+ // there is certainly a simpler design here trying to get out (FIXME).
981+ dump ! ( JsonDumper :: with_callback( self . callback) )
982+ }
983+ }
984+
985+ pub fn process_crate < ' l , ' tcx , H : SaveHandler > ( tcx : TyCtxt < ' l , ' tcx , ' tcx > ,
986+ krate : & ast:: Crate ,
987+ analysis : & ' l ty:: CrateAnalysis ,
988+ cratename : & str ,
989+ mut handler : H ) {
990+ let _ignore = tcx. dep_graph . in_ignore ( ) ;
991+
992+ assert ! ( analysis. glob_map. is_some( ) ) ;
993+
994+ info ! ( "Dumping crate {}" , cratename) ;
918995
919996 let save_ctxt = SaveContext {
920997 tcx : tcx,
@@ -923,21 +1000,7 @@ pub fn process_crate<'l, 'tcx>(tcx: TyCtxt<'l, 'tcx, 'tcx>,
9231000 span_utils : SpanUtils :: new ( & tcx. sess ) ,
9241001 } ;
9251002
926- macro_rules! dump {
927- ( $new_dumper: expr) => { {
928- let mut dumper = $new_dumper;
929- let mut visitor = DumpVisitor :: new( save_ctxt, & mut dumper) ;
930-
931- visitor. dump_crate_info( cratename, krate) ;
932- visit:: walk_crate( & mut visitor, krate) ;
933- } }
934- }
935-
936- match format {
937- Format :: Csv => dump ! ( CsvDumper :: new( output) ) ,
938- Format :: Json => dump ! ( JsonDumper :: new( output) ) ,
939- Format :: JsonApi => dump ! ( JsonApiDumper :: new( output) ) ,
940- }
1003+ handler. save ( save_ctxt, krate, cratename)
9411004}
9421005
9431006// Utility functions for the module.
0 commit comments