33//! Cargo will compile this to a standalone executable.
44//!
55//! The a2kit library crate provides most of the analysis.
6- //! The server activity is all in this file .
6+ //! The server activity is all in this module .
77
88use lsp_types as lsp;
99use lsp:: { notification:: Notification , request:: Request } ;
@@ -14,9 +14,10 @@ use std::collections::VecDeque;
1414use std:: error:: Error ;
1515use std:: sync:: { Arc , Mutex } ;
1616use a2kit:: lang:: server:: TOKEN_TYPES ; // used if we register tokens on server side
17- use a2kit:: lang:: server:: Analysis ;
17+ use a2kit:: lang:: server:: { Analysis , Checkpoint } ;
1818use a2kit:: lang:: applesoft;
1919use a2kit:: lang:: applesoft:: diagnostics:: Analyzer ;
20+ use a2kit:: lang:: applesoft:: checkpoint:: CheckpointManager ;
2021use a2kit:: lang:: disk_server:: DiskServer ;
2122
2223mod notification;
@@ -33,6 +34,12 @@ mod rpc_error {
3334 // pub const INTERNAL_ERROR: i32 = -32603;
3435}
3536
37+ enum WorkspaceScanMethod {
38+ None ,
39+ UseCheckpoints ,
40+ FullUpdate ,
41+ }
42+
3643#[ derive( thiserror:: Error , Debug ) ]
3744enum ServerError {
3845 #[ error( "Parsing" ) ]
@@ -43,7 +50,8 @@ struct AnalysisResult {
4350 uri : lsp:: Uri ,
4451 version : Option < i32 > ,
4552 diagnostics : Vec < lsp:: Diagnostic > ,
46- symbols : applesoft:: Symbols
53+ symbols : applesoft:: Symbols ,
54+ workspace : applesoft:: Workspace
4755}
4856
4957/// Send log messages to the client.
@@ -97,16 +105,40 @@ fn parse_configuration(resp: lsp_server::Response) -> Result<applesoft::settings
97105 Err ( Box :: new ( ServerError :: Parsing ) )
98106}
99107
100- fn launch_analysis_thread ( analyzer : Arc < Mutex < Analyzer > > , doc : a2kit:: lang:: Document ) -> std:: thread:: JoinHandle < Option < AnalysisResult > > {
108+ fn launch_analysis_thread ( analyzer : Arc < Mutex < Analyzer > > , doc : a2kit:: lang:: Document , ws_scan : WorkspaceScanMethod , chks : & HashMap < String , CheckpointManager > ) -> std:: thread:: JoinHandle < Option < AnalysisResult > > {
109+ let checkpoints = match ws_scan {
110+ WorkspaceScanMethod :: FullUpdate => {
111+ let mut ans = Vec :: new ( ) ;
112+ for chk in chks. values ( ) {
113+ ans. push ( chk. get_doc ( ) ) ;
114+ }
115+ ans
116+ } ,
117+ _ => Vec :: new ( )
118+ } ;
101119 std:: thread:: spawn ( move || {
102120 match analyzer. lock ( ) {
103121 Ok ( mut analyzer) => {
122+ match ws_scan {
123+ WorkspaceScanMethod :: None => { } ,
124+ WorkspaceScanMethod :: UseCheckpoints => {
125+ match analyzer. rescan_workspace ( false ) {
126+ _ => { }
127+ }
128+ } ,
129+ WorkspaceScanMethod :: FullUpdate => {
130+ match analyzer. rescan_workspace_and_update ( checkpoints) {
131+ _ => { }
132+ }
133+ }
134+ } ;
104135 match analyzer. analyze ( & doc) {
105136 Ok ( ( ) ) => Some ( AnalysisResult {
106137 uri : doc. uri . clone ( ) ,
107138 version : doc. version ,
108139 diagnostics : analyzer. get_diags ( & doc) ,
109- symbols : analyzer. get_symbols ( )
140+ symbols : analyzer. get_symbols ( ) ,
141+ workspace : analyzer. get_workspace ( ) . clone ( )
110142 } ) ,
111143 Err ( _) => None
112144 }
@@ -135,6 +167,7 @@ pub fn push_diagnostics(connection: &lsp_server::Connection,uri: lsp::Uri, versi
135167
136168struct Tools {
137169 config : applesoft:: settings:: Settings ,
170+ workspace : applesoft:: Workspace ,
138171 thread_handles : VecDeque < std:: thread:: JoinHandle < Option < AnalysisResult > > > ,
139172 doc_chkpts : HashMap < String , applesoft:: checkpoint:: CheckpointManager > ,
140173 analyzer : Arc < Mutex < applesoft:: diagnostics:: Analyzer > > ,
@@ -150,6 +183,7 @@ impl Tools {
150183 pub fn new ( ) -> Self {
151184 Self {
152185 config : applesoft:: settings:: Settings :: new ( ) ,
186+ workspace : applesoft:: Workspace :: new ( ) ,
153187 thread_handles : VecDeque :: new ( ) ,
154188 doc_chkpts : HashMap :: new ( ) ,
155189 analyzer : Arc :: new ( Mutex :: new ( Analyzer :: new ( ) ) ) ,
@@ -194,6 +228,7 @@ fn main() -> Result<(), Box<dyn Error + Sync + Send>> {
194228 ..lsp:: CompletionOptions :: default ( )
195229 } ) ,
196230 document_symbol_provider : Some ( lsp:: OneOf :: Left ( true ) ) ,
231+ workspace_symbol_provider : Some ( lsp:: OneOf :: Left ( true ) ) ,
197232 rename_provider : Some ( lsp:: OneOf :: Left ( true ) ) ,
198233 semantic_tokens_provider : match suppress_tokens {
199234 true => None ,
@@ -263,6 +298,18 @@ fn main() -> Result<(), Box<dyn Error + Sync + Send>> {
263298 Err ( _) => logger ( & connection, "could not request starting configuration" )
264299 }
265300
301+ // Initial workspace scan
302+ if let Some ( folders) = params. workspace_folders {
303+ let source_dirs = folders. iter ( ) . map ( |f| f. uri . clone ( ) ) . collect :: < Vec < lsp:: Uri > > ( ) ;
304+ //tools.hover_provider.set_workspace_folder(source_dirs.clone());
305+ if let Ok ( mut mutex) = tools. analyzer . lock ( ) {
306+ match mutex. init_workspace ( source_dirs, Vec :: new ( ) ) {
307+ Ok ( ( ) ) => { } ,
308+ Err ( e) => logger ( & connection, & format ! ( "initial workspace scan failed: {}" , e) )
309+ }
310+ }
311+ }
312+
266313 // Main loop
267314 loop {
268315
@@ -271,8 +318,10 @@ fn main() -> Result<(), Box<dyn Error + Sync + Send>> {
271318 if oldest. is_finished ( ) {
272319 let done = tools. thread_handles . pop_front ( ) . unwrap ( ) ;
273320 if let Ok ( Some ( result) ) = done. join ( ) {
321+ tools. workspace = result. workspace ;
274322 if let Some ( chkpt) = tools. doc_chkpts . get_mut ( & result. uri . to_string ( ) ) {
275323 chkpt. update_symbols ( result. symbols ) ;
324+ chkpt. update_ws_symbols ( tools. workspace . borrow_ws_symbols ( ) . clone ( ) ) ;
276325 tools. hover_provider . use_shared_symbols ( chkpt. shared_symbols ( ) ) ;
277326 tools. completion_provider . use_shared_symbols ( chkpt. shared_symbols ( ) ) ;
278327 }
0 commit comments