1- use crate :: config:: Config ;
2- use anyhow:: Context ;
31use itertools:: Itertools ;
42use log:: info;
53use ra_ap_base_db:: SourceDatabase ;
@@ -9,6 +7,7 @@ use ra_ap_ide_db::RootDatabase;
97use ra_ap_load_cargo:: { load_workspace_at, LoadCargoConfig , ProcMacroServerChoice } ;
108use ra_ap_paths:: Utf8PathBuf ;
119use ra_ap_project_model:: CargoConfig ;
10+ use ra_ap_project_model:: ProjectManifest ;
1211use ra_ap_project_model:: RustLibSource ;
1312use ra_ap_span:: Edition ;
1413use ra_ap_span:: EditionedFileId ;
@@ -20,19 +19,18 @@ use ra_ap_vfs::AbsPathBuf;
2019use ra_ap_vfs:: Vfs ;
2120use ra_ap_vfs:: VfsPath ;
2221use std:: borrow:: Cow ;
23- use std:: collections:: HashMap ;
2422use std:: path:: { Path , PathBuf } ;
2523use triomphe:: Arc ;
26- pub struct RustAnalyzer {
27- workspace : HashMap < PathBuf , ( Vfs , RootDatabase ) > ,
24+ pub enum RustAnalyzer {
25+ WithDatabase { db : RootDatabase , vfs : Vfs } ,
26+ WithoutDatabase ( ) ,
2827}
2928
3029impl RustAnalyzer {
31- pub fn new ( cfg : & Config ) -> anyhow:: Result < RustAnalyzer > {
32- let mut workspace = HashMap :: new ( ) ;
30+ pub fn new ( project : & ProjectManifest , scratch_dir : & Path ) -> Self {
3331 let config = CargoConfig {
3432 sysroot : Some ( RustLibSource :: Discover ) ,
35- target_dir : ra_ap_paths:: Utf8PathBuf :: from_path_buf ( cfg . scratch_dir . to_path_buf ( ) )
33+ target_dir : ra_ap_paths:: Utf8PathBuf :: from_path_buf ( scratch_dir. to_path_buf ( ) )
3634 . map ( |x| x. join ( "target" ) )
3735 . ok ( ) ,
3836 ..Default :: default ( )
@@ -43,25 +41,19 @@ impl RustAnalyzer {
4341 with_proc_macro_server : ProcMacroServerChoice :: Sysroot ,
4442 prefill_caches : false ,
4543 } ;
46- let projects = find_project_manifests ( & cfg. inputs ) . context ( "loading inputs" ) ?;
47- for project in projects {
48- let manifest = project. manifest_path ( ) ;
44+ let manifest = project. manifest_path ( ) ;
4945
50- match load_workspace_at ( manifest. as_ref ( ) , & config, & load_config, & progress) {
51- Ok ( ( db, vfs, _macro_server) ) => {
52- let path: & Path = manifest. parent ( ) . as_ref ( ) ;
53- workspace. insert ( path. to_path_buf ( ) , ( vfs, db) ) ;
54- }
55- Err ( err) => {
56- log:: error!( "failed to load workspace for {}: {}" , manifest, err) ;
57- }
46+ match load_workspace_at ( manifest. as_ref ( ) , & config, & load_config, & progress) {
47+ Ok ( ( db, vfs, _macro_server) ) => RustAnalyzer :: WithDatabase { db, vfs } ,
48+ Err ( err) => {
49+ log:: error!( "failed to load workspace for {}: {}" , manifest, err) ;
50+ RustAnalyzer :: WithoutDatabase ( )
5851 }
5952 }
60- Ok ( RustAnalyzer { workspace } )
6153 }
6254 pub fn parse (
6355 & mut self ,
64- path : & PathBuf ,
56+ path : & Path ,
6557 ) -> (
6658 SourceFile ,
6759 Arc < str > ,
@@ -82,37 +74,30 @@ impl RustAnalyzer {
8274 } ;
8375 let ( input, err) = from_utf8_lossy ( & input) ;
8476
85- let mut p = path. as_path ( ) ;
86- while let Some ( parent) = p. parent ( ) {
87- p = parent;
88- if self . workspace . contains_key ( parent) {
89- let ( vfs, db) = self . workspace . get_mut ( parent) . unwrap ( ) ;
90- if let Some ( file_id) = Utf8PathBuf :: from_path_buf ( path. to_path_buf ( ) )
91- . ok ( )
92- . and_then ( |x| AbsPathBuf :: try_from ( x) . ok ( ) )
93- . map ( VfsPath :: from)
94- . and_then ( |x| vfs. file_id ( & x) )
95- {
96- db. set_file_text ( file_id, & input) ;
97- let semi = Semantics :: new ( db) ;
77+ if let RustAnalyzer :: WithDatabase { vfs, db } = self {
78+ if let Some ( file_id) = Utf8PathBuf :: from_path_buf ( path. to_path_buf ( ) )
79+ . ok ( )
80+ . and_then ( |x| AbsPathBuf :: try_from ( x) . ok ( ) )
81+ . map ( VfsPath :: from)
82+ . and_then ( |x| vfs. file_id ( & x) )
83+ {
84+ db. set_file_text ( file_id, & input) ;
85+ let semi = Semantics :: new ( db) ;
9886
99- let file_id = EditionedFileId :: current_edition ( file_id) ;
100- let source_file = semi. parse ( file_id) ;
101- errors. extend (
102- db. parse_errors ( file_id)
103- . into_iter ( )
104- . flat_map ( |x| x. to_vec ( ) ) ,
105- ) ;
106- return (
107- source_file,
108- input. as_ref ( ) . into ( ) ,
109- errors,
110- Some ( file_id) ,
111- Some ( semi) ,
112- ) ;
113- } else {
114- break ;
115- }
87+ let file_id = EditionedFileId :: current_edition ( file_id) ;
88+ let source_file = semi. parse ( file_id) ;
89+ errors. extend (
90+ db. parse_errors ( file_id)
91+ . into_iter ( )
92+ . flat_map ( |x| x. to_vec ( ) ) ,
93+ ) ;
94+ return (
95+ source_file,
96+ input. as_ref ( ) . into ( ) ,
97+ errors,
98+ Some ( file_id) ,
99+ Some ( semi) ,
100+ ) ;
116101 }
117102 }
118103 let parse = ra_ap_syntax:: ast:: SourceFile :: parse ( & input, Edition :: CURRENT ) ;
@@ -122,7 +107,7 @@ impl RustAnalyzer {
122107 }
123108}
124109
125- fn find_project_manifests (
110+ pub fn find_project_manifests (
126111 files : & [ PathBuf ] ,
127112) -> anyhow:: Result < Vec < ra_ap_project_model:: ProjectManifest > > {
128113 let current = std:: env:: current_dir ( ) ?;
0 commit comments