@@ -5,7 +5,7 @@ use std::str::from_utf8;
55
66use anyhow:: Context ;
77use base_db:: Env ;
8- use cargo_metadata:: { CargoOpt , MetadataCommand } ;
8+ use cargo_metadata:: { CargoOpt , MetadataCommand , PackageId } ;
99use la_arena:: { Arena , Idx } ;
1010use paths:: { AbsPath , AbsPathBuf , Utf8Path , Utf8PathBuf } ;
1111use rustc_hash:: { FxHashMap , FxHashSet } ;
@@ -14,6 +14,7 @@ use serde_json::from_value;
1414use span:: Edition ;
1515use stdx:: process:: spawn_with_streaming_output;
1616use toolchain:: Tool ;
17+ use triomphe:: Arc ;
1718
1819use crate :: cargo_config_file:: make_lockfile_copy;
1920use crate :: { CfgOverrides , InvocationStrategy } ;
@@ -155,8 +156,8 @@ pub struct PackageData {
155156 pub features : FxHashMap < String , Vec < String > > ,
156157 /// List of features enabled on this package
157158 pub active_features : Vec < String > ,
158- /// String representation of package id
159- pub id : String ,
159+ /// Package id
160+ pub id : Arc < PackageId > ,
160161 /// Authors as given in the `Cargo.toml`
161162 pub authors : Vec < String > ,
162163 /// Description as given in the `Cargo.toml`
@@ -173,6 +174,10 @@ pub struct PackageData {
173174 pub rust_version : Option < semver:: Version > ,
174175 /// The contents of [package.metadata.rust-analyzer]
175176 pub metadata : RustAnalyzerPackageMetaData ,
177+ /// If this package is a member of the workspace, store all direct and transitive
178+ /// dependencies as long as they are workspace members, to track dependency relationships
179+ /// between members.
180+ pub all_member_deps : Option < FxHashSet < Package > > ,
176181}
177182
178183#[ derive( Deserialize , Default , Debug , Clone , Eq , PartialEq ) ]
@@ -334,6 +339,8 @@ impl CargoWorkspace {
334339 let mut is_virtual_workspace = true ;
335340 let mut requires_rustc_private = false ;
336341
342+ let mut members = FxHashSet :: default ( ) ;
343+
337344 meta. packages . sort_by ( |a, b| a. id . cmp ( & b. id ) ) ;
338345 for meta_pkg in meta. packages {
339346 let cargo_metadata:: Package {
@@ -356,6 +363,7 @@ impl CargoWorkspace {
356363 rust_version,
357364 ..
358365 } = meta_pkg;
366+ let id = Arc :: new ( id) ;
359367 let meta = from_value :: < PackageMetadata > ( metadata) . unwrap_or_default ( ) ;
360368 let edition = match edition {
361369 cargo_metadata:: Edition :: E2015 => Edition :: Edition2015 ,
@@ -375,7 +383,7 @@ impl CargoWorkspace {
375383 let manifest = ManifestPath :: try_from ( AbsPathBuf :: assert ( manifest_path) ) . unwrap ( ) ;
376384 is_virtual_workspace &= manifest != ws_manifest_path;
377385 let pkg = packages. alloc ( PackageData {
378- id : id. repr . clone ( ) ,
386+ id : id. clone ( ) ,
379387 name : name. to_string ( ) ,
380388 version,
381389 manifest : manifest. clone ( ) ,
@@ -395,7 +403,11 @@ impl CargoWorkspace {
395403 features : features. into_iter ( ) . collect ( ) ,
396404 active_features : Vec :: new ( ) ,
397405 metadata : meta. rust_analyzer . unwrap_or_default ( ) ,
406+ all_member_deps : None ,
398407 } ) ;
408+ if is_member {
409+ members. insert ( pkg) ;
410+ }
399411 let pkg_data = & mut packages[ pkg] ;
400412 requires_rustc_private |= pkg_data. metadata . rustc_private ;
401413 pkg_by_id. insert ( id, pkg) ;
@@ -440,6 +452,43 @@ impl CargoWorkspace {
440452 . extend ( node. features . into_iter ( ) . map ( |it| it. to_string ( ) ) ) ;
441453 }
442454
455+ fn saturate_all_member_deps (
456+ packages : & mut Arena < PackageData > ,
457+ to_visit : Package ,
458+ visited : & mut FxHashSet < Package > ,
459+ members : & FxHashSet < Package > ,
460+ ) {
461+ let pkg_data = & mut packages[ to_visit] ;
462+
463+ if !visited. insert ( to_visit) {
464+ return ;
465+ }
466+
467+ let deps: Vec < _ > = pkg_data
468+ . dependencies
469+ . iter ( )
470+ . filter_map ( |dep| {
471+ let pkg = dep. pkg ;
472+ if members. contains ( & pkg) { Some ( pkg) } else { None }
473+ } )
474+ . collect ( ) ;
475+
476+ let mut all_member_deps = FxHashSet :: from_iter ( deps. iter ( ) . copied ( ) ) ;
477+ for dep in deps {
478+ saturate_all_member_deps ( packages, dep, visited, members) ;
479+ if let Some ( transitives) = & packages[ dep] . all_member_deps {
480+ all_member_deps. extend ( transitives) ;
481+ }
482+ }
483+
484+ packages[ to_visit] . all_member_deps = Some ( all_member_deps) ;
485+ }
486+
487+ let mut visited = FxHashSet :: default ( ) ;
488+ for member in members. iter ( ) {
489+ saturate_all_member_deps ( & mut packages, * member, & mut visited, & members) ;
490+ }
491+
443492 CargoWorkspace {
444493 packages,
445494 targets,
0 commit comments