@@ -24,7 +24,8 @@ use ide_db::{
24
24
use itertools:: Itertools ;
25
25
use paths:: { Utf8Path , Utf8PathBuf } ;
26
26
use project_model:: {
27
- CargoConfig , CargoFeatures , ProjectJson , ProjectJsonData , ProjectManifest , RustLibSource ,
27
+ CargoConfig , CargoFeatures , ProjectJson , ProjectJsonData , ProjectJsonFromCommand , ProjectManifest ,
28
+ RustLibSource ,
28
29
} ;
29
30
use rustc_hash:: { FxHashMap , FxHashSet } ;
30
31
use semver:: Version ;
@@ -761,7 +762,13 @@ enum RatomlFile {
761
762
762
763
#[ derive( Debug , Clone ) ]
763
764
pub struct Config {
764
- discovered_projects : Vec < ProjectManifest > ,
765
+ /// Projects that have a Cargo.toml or a rust-project.json in a
766
+ /// parent directory, so we can discover them by walking the
767
+ /// file system.
768
+ discovered_projects_from_filesystem : Vec < ProjectManifest > ,
769
+ /// Projects whose configuration was generated by a command
770
+ /// configured in discoverConfig.
771
+ discovered_projects_from_command : Vec < ProjectJsonFromCommand > ,
765
772
/// The workspace roots as registered by the LSP client
766
773
workspace_roots : Vec < AbsPathBuf > ,
767
774
caps : ClientCapabilities ,
@@ -1054,19 +1061,19 @@ impl Config {
1054
1061
( config, e, should_update)
1055
1062
}
1056
1063
1057
- pub fn add_linked_projects ( & mut self , data : ProjectJsonData , buildfile : AbsPathBuf ) {
1058
- let linked_projects = & mut self . client_config . 0 . global . linkedProjects ;
1059
-
1060
- let new_project = ManifestOrProjectJson :: DiscoveredProjectJson { data, buildfile } ;
1061
- match linked_projects {
1062
- Some ( projects) => {
1063
- match projects. iter_mut ( ) . find ( |p| p. manifest ( ) == new_project. manifest ( ) ) {
1064
- Some ( p) => * p = new_project,
1065
- None => projects. push ( new_project) ,
1066
- }
1064
+ pub fn add_discovered_project_from_command (
1065
+ & mut self ,
1066
+ data : ProjectJsonData ,
1067
+ buildfile : AbsPathBuf ,
1068
+ ) {
1069
+ for proj in self . discovered_projects_from_command . iter_mut ( ) {
1070
+ if proj. buildfile == buildfile {
1071
+ proj. data = data;
1072
+ return ;
1067
1073
}
1068
- None => * linked_projects = Some ( vec ! [ new_project] ) ,
1069
1074
}
1075
+
1076
+ self . discovered_projects_from_command . push ( ProjectJsonFromCommand { data, buildfile } ) ;
1070
1077
}
1071
1078
}
1072
1079
@@ -1344,7 +1351,8 @@ impl Config {
1344
1351
1345
1352
Config {
1346
1353
caps : ClientCapabilities :: new ( caps) ,
1347
- discovered_projects : Vec :: new ( ) ,
1354
+ discovered_projects_from_filesystem : Vec :: new ( ) ,
1355
+ discovered_projects_from_command : Vec :: new ( ) ,
1348
1356
root_path,
1349
1357
snippets : Default :: default ( ) ,
1350
1358
workspace_roots,
@@ -1365,7 +1373,7 @@ impl Config {
1365
1373
if discovered. is_empty ( ) {
1366
1374
tracing:: error!( "failed to find any projects in {:?}" , & self . workspace_roots) ;
1367
1375
}
1368
- self . discovered_projects = discovered;
1376
+ self . discovered_projects_from_filesystem = discovered;
1369
1377
}
1370
1378
1371
1379
pub fn remove_workspace ( & mut self , path : & AbsPath ) {
@@ -1687,42 +1695,59 @@ impl Config {
1687
1695
self . workspace_discoverConfig ( ) . as_ref ( )
1688
1696
}
1689
1697
1690
- pub fn linked_or_discovered_projects ( & self ) -> Vec < LinkedProject > {
1691
- match self . linkedProjects ( ) . as_slice ( ) {
1692
- [ ] => {
1693
- let exclude_dirs: Vec < _ > =
1694
- self . files_excludeDirs ( ) . iter ( ) . map ( |p| self . root_path . join ( p) ) . collect ( ) ;
1695
- self . discovered_projects
1696
- . iter ( )
1697
- . filter ( |project| {
1698
- !exclude_dirs. iter ( ) . any ( |p| project. manifest_path ( ) . starts_with ( p) )
1699
- } )
1700
- . cloned ( )
1701
- . map ( LinkedProject :: from)
1702
- . collect ( )
1698
+ fn discovered_projects ( & self ) -> Vec < ManifestOrProjectJson > {
1699
+ let exclude_dirs: Vec < _ > =
1700
+ self . files_excludeDirs ( ) . iter ( ) . map ( |p| self . root_path . join ( p) ) . collect ( ) ;
1701
+
1702
+ let mut projects = vec ! [ ] ;
1703
+ for fs_proj in & self . discovered_projects_from_filesystem {
1704
+ let manifest_path = fs_proj. manifest_path ( ) ;
1705
+ if exclude_dirs. iter ( ) . any ( |p| manifest_path. starts_with ( p) ) {
1706
+ continue ;
1703
1707
}
1704
- linked_projects => linked_projects
1705
- . iter ( )
1706
- . filter_map ( |linked_project| match linked_project {
1707
- ManifestOrProjectJson :: Manifest ( it) => {
1708
- let path = self . root_path . join ( it) ;
1709
- ProjectManifest :: from_manifest_file ( path)
1710
- . map_err ( |e| tracing:: error!( "failed to load linked project: {}" , e) )
1711
- . ok ( )
1712
- . map ( Into :: into)
1713
- }
1714
- ManifestOrProjectJson :: DiscoveredProjectJson { data, buildfile } => {
1715
- let root_path =
1716
- buildfile. parent ( ) . expect ( "Unable to get parent of buildfile" ) ;
1717
1708
1718
- Some ( ProjectJson :: new ( None , root_path, data. clone ( ) ) . into ( ) )
1719
- }
1720
- ManifestOrProjectJson :: ProjectJson ( it) => {
1721
- Some ( ProjectJson :: new ( None , & self . root_path , it. clone ( ) ) . into ( ) )
1722
- }
1723
- } )
1724
- . collect ( ) ,
1709
+ let buf: Utf8PathBuf = manifest_path. to_path_buf ( ) . into ( ) ;
1710
+ projects. push ( ManifestOrProjectJson :: Manifest ( buf) ) ;
1711
+ }
1712
+
1713
+ for dis_proj in & self . discovered_projects_from_command {
1714
+ projects. push ( ManifestOrProjectJson :: DiscoveredProjectJson {
1715
+ data : dis_proj. data . clone ( ) ,
1716
+ buildfile : dis_proj. buildfile . clone ( ) ,
1717
+ } ) ;
1725
1718
}
1719
+
1720
+ projects
1721
+ }
1722
+
1723
+ pub fn linked_or_discovered_projects ( & self ) -> Vec < LinkedProject > {
1724
+ let linked_projects = self . linkedProjects ( ) ;
1725
+ let projects = if linked_projects. is_empty ( ) {
1726
+ self . discovered_projects ( )
1727
+ } else {
1728
+ linked_projects. clone ( )
1729
+ } ;
1730
+
1731
+ projects
1732
+ . iter ( )
1733
+ . filter_map ( |linked_project| match linked_project {
1734
+ ManifestOrProjectJson :: Manifest ( it) => {
1735
+ let path = self . root_path . join ( it) ;
1736
+ ProjectManifest :: from_manifest_file ( path)
1737
+ . map_err ( |e| tracing:: error!( "failed to load linked project: {}" , e) )
1738
+ . ok ( )
1739
+ . map ( Into :: into)
1740
+ }
1741
+ ManifestOrProjectJson :: DiscoveredProjectJson { data, buildfile } => {
1742
+ let root_path = buildfile. parent ( ) . expect ( "Unable to get parent of buildfile" ) ;
1743
+
1744
+ Some ( ProjectJson :: new ( None , root_path, data. clone ( ) ) . into ( ) )
1745
+ }
1746
+ ManifestOrProjectJson :: ProjectJson ( it) => {
1747
+ Some ( ProjectJson :: new ( None , & self . root_path , it. clone ( ) ) . into ( ) )
1748
+ }
1749
+ } )
1750
+ . collect ( )
1726
1751
}
1727
1752
1728
1753
pub fn prefill_caches ( & self ) -> bool {
@@ -2282,18 +2307,6 @@ where
2282
2307
se. serialize_str ( path. as_str ( ) )
2283
2308
}
2284
2309
2285
- impl ManifestOrProjectJson {
2286
- fn manifest ( & self ) -> Option < & Utf8Path > {
2287
- match self {
2288
- ManifestOrProjectJson :: Manifest ( manifest) => Some ( manifest) ,
2289
- ManifestOrProjectJson :: DiscoveredProjectJson { buildfile, .. } => {
2290
- Some ( buildfile. as_ref ( ) )
2291
- }
2292
- ManifestOrProjectJson :: ProjectJson ( _) => None ,
2293
- }
2294
- }
2295
- }
2296
-
2297
2310
#[ derive( Serialize , Deserialize , Debug , Clone ) ]
2298
2311
#[ serde( rename_all = "snake_case" ) ]
2299
2312
enum ExprFillDefaultDef {
0 commit comments