11use itertools:: Itertools ;
2- use log:: { debug, error, info} ;
2+ use log:: { debug, error, info, warn } ;
33use ra_ap_base_db:: SourceDatabase ;
44use ra_ap_hir:: Semantics ;
55use ra_ap_ide_db:: RootDatabase ;
@@ -16,6 +16,7 @@ use ra_ap_syntax::SyntaxError;
1616use ra_ap_vfs:: Vfs ;
1717use ra_ap_vfs:: VfsPath ;
1818use ra_ap_vfs:: { AbsPathBuf , FileId } ;
19+ use serde:: Deserialize ;
1920use std:: borrow:: Cow ;
2021use std:: collections:: { HashMap , HashSet } ;
2122use std:: fs;
@@ -131,8 +132,19 @@ impl<'a> RustAnalyzer<'a> {
131132 }
132133}
133134
135+ #[ derive( Deserialize ) ]
136+ struct CargoManifestMembersSlice {
137+ #[ serde( default ) ]
138+ members : Vec < String > ,
139+ }
140+
141+ #[ derive( Deserialize ) ]
142+ struct CargoManifestSlice {
143+ workspace : Option < CargoManifestMembersSlice > ,
144+ }
145+
134146struct ToMlReader {
135- cache : HashMap < ManifestPath , Rc < toml :: Table > > ,
147+ cache : HashMap < ManifestPath , Rc < CargoManifestSlice > > ,
136148}
137149
138150impl ToMlReader {
@@ -142,15 +154,15 @@ impl ToMlReader {
142154 }
143155 }
144156
145- fn read ( & mut self , manifest : & ManifestPath ) -> anyhow:: Result < Rc < toml :: Table > > {
157+ fn read ( & mut self , manifest : & ManifestPath ) -> anyhow:: Result < Rc < CargoManifestSlice > > {
146158 if let Some ( table) = self . cache . get ( manifest) {
147159 return Ok ( table. clone ( ) ) ;
148160 }
149161 let content = fs:: read_to_string ( manifest) . map_err ( |e| {
150162 error ! ( "failed to read {} ({e})" , manifest. as_str( ) ) ;
151163 e
152164 } ) ?;
153- let table = Rc :: < toml :: Table > :: new ( content . parse ( ) . map_err ( |e| {
165+ let table = Rc :: < CargoManifestSlice > :: new ( toml :: from_str ( & content ) . map_err ( |e| {
154166 error ! ( "failed to parse {} ({e})" , manifest. as_str( ) ) ;
155167 e
156168 } ) ?) ;
@@ -159,46 +171,50 @@ impl ToMlReader {
159171 }
160172}
161173
162- fn find_workspace (
163- reader : & mut ToMlReader ,
164- manifest : & ProjectManifest ,
165- ) -> anyhow:: Result < ProjectManifest > {
174+ fn find_workspace ( reader : & mut ToMlReader , manifest : & ProjectManifest ) -> Option < ProjectManifest > {
166175 let ProjectManifest :: CargoToml ( cargo) = manifest else {
167- return Err ( anyhow :: anyhow! ( "{manifest} not a cargo manifest" ) ) ;
176+ return None ;
168177 } ;
169- let toml = reader. read ( cargo) ?;
170- if toml. contains_key ( "workspace" ) {
171- return Ok ( manifest. clone ( ) ) ;
178+ let parsed_cargo = reader. read ( cargo) . ok ( ) ?;
179+ if parsed_cargo. workspace . is_some ( ) {
180+ debug ! ( "{cargo} is a workspace" ) ;
181+ return Some ( manifest. clone ( ) ) ;
172182 }
173183 let Some ( parent_dir) = cargo. parent ( ) . parent ( ) else {
174- return Err ( anyhow:: anyhow!( "no parent dir for {cargo}" ) ) ;
184+ warn ! ( "no parent dir for {cargo}" ) ;
185+ return None ;
175186 } ;
176- let discovered = ProjectManifest :: discover ( parent_dir) ?;
187+ let discovered = ProjectManifest :: discover ( parent_dir)
188+ . map_err ( |e| {
189+ error ! (
190+ "encountered error while searching for manifests under {}: {e}" ,
191+ parent_dir. as_str( )
192+ ) ;
193+ e
194+ } )
195+ . ok ( ) ?;
177196 discovered
178197 . iter ( )
179- . filter_map ( |it| match it {
198+ . find_map ( |it| match it {
180199 ProjectManifest :: CargoToml ( other)
181200 if cargo. starts_with ( other. parent ( ) )
182201 && reader. read ( other) . is_ok_and ( |it| {
183- it. get ( "workspace" )
184- . and_then ( |w| w. as_table ( ) )
185- . and_then ( |t| t. get ( "members" ) )
186- . and_then ( |ms| ms. as_array ( ) )
187- . is_some_and ( |ms| {
188- ms. iter ( ) . any ( |m| {
189- m. as_str ( )
190- . is_some_and ( |s| other. parent ( ) . join ( s) == cargo. parent ( ) )
191- } )
192- } )
202+ it. workspace . as_ref ( ) . is_some_and ( |w| {
203+ w. members
204+ . iter ( )
205+ . any ( |m| other. parent ( ) . join ( m) == cargo. parent ( ) )
206+ } )
193207 } ) =>
194208 {
195209 debug ! ( "found workspace {other} containing {cargo}" ) ;
196210 Some ( it. clone ( ) )
197211 }
198212 _ => None ,
199213 } )
200- . next ( )
201- . ok_or ( anyhow:: anyhow!( "no workspace found for {manifest}" ) )
214+ . or_else ( || {
215+ debug ! ( "no workspace found for {cargo}" ) ;
216+ None
217+ } )
202218}
203219
204220pub fn find_project_manifests (
0 commit comments