@@ -24,7 +24,8 @@ use ide_db::{
2424use  itertools:: Itertools ; 
2525use  paths:: { Utf8Path ,  Utf8PathBuf } ; 
2626use  project_model:: { 
27-     CargoConfig ,  CargoFeatures ,  ProjectJson ,  ProjectJsonData ,  ProjectManifest ,  RustLibSource , 
27+     CargoConfig ,  CargoFeatures ,  ProjectJson ,  ProjectJsonData ,  ProjectJsonFromCommand , 
28+     ProjectManifest ,  RustLibSource , 
2829} ; 
2930use  rustc_hash:: { FxHashMap ,  FxHashSet } ; 
3031use  semver:: Version ; 
@@ -761,7 +762,13 @@ enum RatomlFile {
761762
762763#[ derive( Debug ,  Clone ) ]  
763764pub  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 > , 
765772    /// The workspace roots as registered by the LSP client 
766773     workspace_roots :  Vec < AbsPathBuf > , 
767774    caps :  ClientCapabilities , 
@@ -1054,19 +1061,19 @@ impl Config {
10541061        ( config,  e,  should_update) 
10551062    } 
10561063
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 ; 
10671073            } 
1068-             None  => * linked_projects = Some ( vec ! [ new_project] ) , 
10691074        } 
1075+ 
1076+         self . discovered_projects_from_command . push ( ProjectJsonFromCommand  {  data,  buildfile } ) ; 
10701077    } 
10711078} 
10721079
@@ -1344,7 +1351,8 @@ impl Config {
13441351
13451352        Config  { 
13461353            caps :  ClientCapabilities :: new ( caps) , 
1347-             discovered_projects :  Vec :: new ( ) , 
1354+             discovered_projects_from_filesystem :  Vec :: new ( ) , 
1355+             discovered_projects_from_command :  Vec :: new ( ) , 
13481356            root_path, 
13491357            snippets :  Default :: default ( ) , 
13501358            workspace_roots, 
@@ -1365,7 +1373,7 @@ impl Config {
13651373        if  discovered. is_empty ( )  { 
13661374            tracing:: error!( "failed to find any projects in {:?}" ,  & self . workspace_roots) ; 
13671375        } 
1368-         self . discovered_projects  = discovered; 
1376+         self . discovered_projects_from_filesystem  = discovered; 
13691377    } 
13701378
13711379    pub  fn  remove_workspace ( & mut  self ,  path :  & AbsPath )  { 
@@ -1687,42 +1695,59 @@ impl Config {
16871695        self . workspace_discoverConfig ( ) . as_ref ( ) 
16881696    } 
16891697
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 ; 
17031707            } 
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" ) ; 
17171708
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+             } ) ; 
17251718        } 
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 ( ) 
17261751    } 
17271752
17281753    pub  fn  prefill_caches ( & self )  -> bool  { 
@@ -2282,18 +2307,6 @@ where
22822307    se. serialize_str ( path. as_str ( ) ) 
22832308} 
22842309
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- 
22972310#[ derive( Serialize ,  Deserialize ,  Debug ,  Clone ) ]  
22982311#[ serde( rename_all = "snake_case" ) ]  
22992312enum  ExprFillDefaultDef  { 
0 commit comments