11use std:: collections:: { BTreeMap , BTreeSet } ;
2- use std:: fs:: File ;
32use std:: path:: Path ;
43use std:: path:: PathBuf ;
54use std:: process:: Command ;
@@ -71,7 +70,8 @@ pub fn get_crate_specs(
7170 log:: debug!( "Get crate specs with targets: {:?}" , targets) ;
7271 let target_pattern = format ! ( "deps({})" , targets. join( "+" ) ) ;
7372
74- let aquery_output = Command :: new ( bazel)
73+ let mut aquery_command = Command :: new ( bazel) ;
74+ aquery_command
7575 . current_dir ( workspace)
7676 . env_remove ( "BAZELISK_SKIP_WRAPPER" )
7777 . env_remove ( "BUILD_WORKING_DIRECTORY" )
@@ -86,18 +86,26 @@ pub fn get_crate_specs(
8686 . arg ( format ! (
8787 r#"outputs(".*\.rust_analyzer_crate_spec\.json",{target_pattern})"#
8888 ) )
89- . arg ( "--output=jsonproto" )
90- . output ( ) ?;
89+ . arg ( "--output=jsonproto" ) ;
90+ log:: trace!( "Running aquery: {:#?}" , aquery_command) ;
91+ let aquery_output = aquery_command
92+ . output ( )
93+ . context ( "Failed to spawn aquery command" ) ?;
9194
92- let crate_spec_files =
93- parse_aquery_output_files ( execution_root, & String :: from_utf8 ( aquery_output. stdout ) ?) ?;
95+ let aquery_results = String :: from_utf8 ( aquery_output. stdout )
96+ . context ( "Failed to decode aquery results as utf-8." ) ?;
97+
98+ log:: trace!( "Aquery results: {}" , & aquery_results) ;
99+
100+ let crate_spec_files = parse_aquery_output_files ( execution_root, & aquery_results) ?;
94101
95102 let crate_specs = crate_spec_files
96103 . into_iter ( )
97104 . map ( |file| {
98- let f = File :: open ( & file)
99- . with_context ( || format ! ( "Failed to open file: {}" , file. display( ) ) ) ?;
100- serde_json:: from_reader ( f)
105+ let content = std:: fs:: read_to_string ( & file)
106+ . with_context ( || format ! ( "Failed to read file: {}" , file. display( ) ) ) ?;
107+ log:: trace!( "{}\n {}" , file. display( ) , content) ;
108+ serde_json:: from_str ( & content)
101109 . with_context ( || format ! ( "Failed to deserialize file: {}" , file. display( ) ) )
102110 } )
103111 . collect :: < anyhow:: Result < Vec < CrateSpec > > > ( ) ?;
@@ -177,6 +185,22 @@ fn consolidate_crate_specs(crate_specs: Vec<CrateSpec>) -> anyhow::Result<BTreeS
177185 log:: debug!( "{:?}" , spec) ;
178186 if let Some ( existing) = consolidated_specs. get_mut ( & spec. crate_id ) {
179187 existing. deps . extend ( spec. deps ) ;
188+ existing. aliases . extend ( spec. aliases ) ;
189+
190+ if let Some ( source) = & mut existing. source {
191+ if let Some ( mut new_source) = spec. source {
192+ new_source
193+ . exclude_dirs
194+ . retain ( |src| !source. exclude_dirs . contains ( src) ) ;
195+ new_source
196+ . include_dirs
197+ . retain ( |src| !source. include_dirs . contains ( src) ) ;
198+ source. exclude_dirs . extend ( new_source. exclude_dirs ) ;
199+ source. include_dirs . extend ( new_source. include_dirs ) ;
200+ }
201+ } else {
202+ existing. source = spec. source ;
203+ }
180204
181205 spec. cfg . retain ( |cfg| !existing. cfg . contains ( cfg) ) ;
182206 existing. cfg . extend ( spec. cfg ) ;
@@ -622,4 +646,190 @@ mod test {
622646 ) ;
623647 }
624648 }
649+
650+ #[ test]
651+ fn consolidate_spec_with_aliases ( ) {
652+ let crate_specs = vec ! [
653+ CrateSpec {
654+ aliases: BTreeMap :: new( ) ,
655+ crate_id: "ID-mylib.rs" . into( ) ,
656+ display_name: "mylib" . into( ) ,
657+ edition: "2018" . into( ) ,
658+ root_module: "mylib.rs" . into( ) ,
659+ is_workspace_member: true ,
660+ deps: BTreeSet :: new( ) ,
661+ proc_macro_dylib_path: None ,
662+ source: None ,
663+ cfg: vec![ "test" . into( ) , "debug_assertions" . into( ) ] ,
664+ env: BTreeMap :: new( ) ,
665+ target: "x86_64-unknown-linux-gnu" . into( ) ,
666+ crate_type: "rlib" . into( ) ,
667+ } ,
668+ CrateSpec {
669+ aliases: BTreeMap :: from( [ ( "ID-mylib_dep.rs" . into( ) , "aliased_name" . into( ) ) ] ) ,
670+ crate_id: "ID-mylib.rs" . into( ) ,
671+ display_name: "mylib_test" . into( ) ,
672+ edition: "2018" . into( ) ,
673+ root_module: "mylib.rs" . into( ) ,
674+ is_workspace_member: true ,
675+ deps: BTreeSet :: new( ) ,
676+ proc_macro_dylib_path: None ,
677+ source: None ,
678+ cfg: vec![ "test" . into( ) , "debug_assertions" . into( ) ] ,
679+ env: BTreeMap :: new( ) ,
680+ target: "x86_64-unknown-linux-gnu" . into( ) ,
681+ crate_type: "bin" . into( ) ,
682+ } ,
683+ ] ;
684+
685+ for perm in crate_specs. into_iter ( ) . permutations ( 2 ) {
686+ assert_eq ! (
687+ consolidate_crate_specs( perm) . unwrap( ) ,
688+ BTreeSet :: from( [ CrateSpec {
689+ aliases: BTreeMap :: from( [ ( "ID-mylib_dep.rs" . into( ) , "aliased_name" . into( ) ) ] ) ,
690+ crate_id: "ID-mylib.rs" . into( ) ,
691+ display_name: "mylib" . into( ) ,
692+ edition: "2018" . into( ) ,
693+ root_module: "mylib.rs" . into( ) ,
694+ is_workspace_member: true ,
695+ deps: BTreeSet :: from( [ ] ) ,
696+ proc_macro_dylib_path: None ,
697+ source: None ,
698+ cfg: vec![ "test" . into( ) , "debug_assertions" . into( ) ] ,
699+ env: BTreeMap :: new( ) ,
700+ target: "x86_64-unknown-linux-gnu" . into( ) ,
701+ crate_type: "rlib" . into( ) ,
702+ } ] )
703+ ) ;
704+ }
705+ }
706+
707+ #[ test]
708+ fn consolidate_spec_with_sources ( ) {
709+ let crate_specs = vec ! [
710+ CrateSpec {
711+ aliases: BTreeMap :: new( ) ,
712+ crate_id: "ID-mylib.rs" . into( ) ,
713+ display_name: "mylib" . into( ) ,
714+ edition: "2018" . into( ) ,
715+ root_module: "mylib.rs" . into( ) ,
716+ is_workspace_member: true ,
717+ deps: BTreeSet :: new( ) ,
718+ proc_macro_dylib_path: None ,
719+ source: None ,
720+ cfg: vec![ "test" . into( ) , "debug_assertions" . into( ) ] ,
721+ env: BTreeMap :: new( ) ,
722+ target: "x86_64-unknown-linux-gnu" . into( ) ,
723+ crate_type: "rlib" . into( ) ,
724+ } ,
725+ CrateSpec {
726+ aliases: BTreeMap :: new( ) ,
727+ crate_id: "ID-mylib.rs" . into( ) ,
728+ display_name: "mylib_test" . into( ) ,
729+ edition: "2018" . into( ) ,
730+ root_module: "mylib.rs" . into( ) ,
731+ is_workspace_member: true ,
732+ deps: BTreeSet :: new( ) ,
733+ proc_macro_dylib_path: None ,
734+ source: Some ( CrateSpecSource {
735+ exclude_dirs: vec![ "exclude" . into( ) ] ,
736+ include_dirs: vec![ "include" . into( ) ] ,
737+ } ) ,
738+ cfg: vec![ "test" . into( ) , "debug_assertions" . into( ) ] ,
739+ env: BTreeMap :: new( ) ,
740+ target: "x86_64-unknown-linux-gnu" . into( ) ,
741+ crate_type: "bin" . into( ) ,
742+ } ,
743+ ] ;
744+
745+ for perm in crate_specs. into_iter ( ) . permutations ( 2 ) {
746+ assert_eq ! (
747+ consolidate_crate_specs( perm) . unwrap( ) ,
748+ BTreeSet :: from( [ CrateSpec {
749+ aliases: BTreeMap :: new( ) ,
750+ crate_id: "ID-mylib.rs" . into( ) ,
751+ display_name: "mylib" . into( ) ,
752+ edition: "2018" . into( ) ,
753+ root_module: "mylib.rs" . into( ) ,
754+ is_workspace_member: true ,
755+ deps: BTreeSet :: from( [ ] ) ,
756+ proc_macro_dylib_path: None ,
757+ source: Some ( CrateSpecSource {
758+ exclude_dirs: vec![ "exclude" . into( ) ] ,
759+ include_dirs: vec![ "include" . into( ) ] ,
760+ } ) ,
761+ cfg: vec![ "test" . into( ) , "debug_assertions" . into( ) ] ,
762+ env: BTreeMap :: new( ) ,
763+ target: "x86_64-unknown-linux-gnu" . into( ) ,
764+ crate_type: "rlib" . into( ) ,
765+ } ] )
766+ ) ;
767+ }
768+ }
769+
770+ #[ test]
771+ fn consolidate_spec_with_duplicate_sources ( ) {
772+ let crate_specs = vec ! [
773+ CrateSpec {
774+ aliases: BTreeMap :: new( ) ,
775+ crate_id: "ID-mylib.rs" . into( ) ,
776+ display_name: "mylib" . into( ) ,
777+ edition: "2018" . into( ) ,
778+ root_module: "mylib.rs" . into( ) ,
779+ is_workspace_member: true ,
780+ deps: BTreeSet :: new( ) ,
781+ proc_macro_dylib_path: None ,
782+ source: Some ( CrateSpecSource {
783+ exclude_dirs: vec![ "exclude" . into( ) ] ,
784+ include_dirs: vec![ "include" . into( ) ] ,
785+ } ) ,
786+ cfg: vec![ "test" . into( ) , "debug_assertions" . into( ) ] ,
787+ env: BTreeMap :: new( ) ,
788+ target: "x86_64-unknown-linux-gnu" . into( ) ,
789+ crate_type: "rlib" . into( ) ,
790+ } ,
791+ CrateSpec {
792+ aliases: BTreeMap :: new( ) ,
793+ crate_id: "ID-mylib.rs" . into( ) ,
794+ display_name: "mylib_test" . into( ) ,
795+ edition: "2018" . into( ) ,
796+ root_module: "mylib.rs" . into( ) ,
797+ is_workspace_member: true ,
798+ deps: BTreeSet :: new( ) ,
799+ proc_macro_dylib_path: None ,
800+ source: Some ( CrateSpecSource {
801+ exclude_dirs: vec![ "exclude" . into( ) ] ,
802+ include_dirs: vec![ "include" . into( ) ] ,
803+ } ) ,
804+ cfg: vec![ "test" . into( ) , "debug_assertions" . into( ) ] ,
805+ env: BTreeMap :: new( ) ,
806+ target: "x86_64-unknown-linux-gnu" . into( ) ,
807+ crate_type: "bin" . into( ) ,
808+ } ,
809+ ] ;
810+
811+ for perm in crate_specs. into_iter ( ) . permutations ( 2 ) {
812+ assert_eq ! (
813+ consolidate_crate_specs( perm) . unwrap( ) ,
814+ BTreeSet :: from( [ CrateSpec {
815+ aliases: BTreeMap :: new( ) ,
816+ crate_id: "ID-mylib.rs" . into( ) ,
817+ display_name: "mylib" . into( ) ,
818+ edition: "2018" . into( ) ,
819+ root_module: "mylib.rs" . into( ) ,
820+ is_workspace_member: true ,
821+ deps: BTreeSet :: from( [ ] ) ,
822+ proc_macro_dylib_path: None ,
823+ source: Some ( CrateSpecSource {
824+ exclude_dirs: vec![ "exclude" . into( ) ] ,
825+ include_dirs: vec![ "include" . into( ) ] ,
826+ } ) ,
827+ cfg: vec![ "test" . into( ) , "debug_assertions" . into( ) ] ,
828+ env: BTreeMap :: new( ) ,
829+ target: "x86_64-unknown-linux-gnu" . into( ) ,
830+ crate_type: "rlib" . into( ) ,
831+ } ] )
832+ ) ;
833+ }
834+ }
625835}
0 commit comments