22// a large repository
33
44use lsp_server:: { Connection , Message } ;
5- use lsp_types:: { PublishDiagnosticsParams , Url } ;
5+ use lsp_types:: { DiagnosticSeverity , PublishDiagnosticsParams , Url } ;
66use moos_parser:: PlugParser ;
7+ use std:: collections:: HashSet ;
78use std:: fs:: { self , DirEntry } ;
89use std:: io;
910use std:: path:: { Path , PathBuf } ;
@@ -105,7 +106,24 @@ pub fn scan_workspace(
105106 root_path : String ,
106107 root_uri : Url ,
107108) -> anyhow:: Result < ( ) > {
108- let added = visit_dirs ( Path :: new ( & root_path) , root_path. as_str ( ) , & root_uri) ;
109+ // NOTE: Need to make sure that the root ends with a '/' so it is treated
110+ // as a directory.
111+ let mut clean_root_path = root_path. clone ( ) ;
112+ let mut clean_root_uri = root_uri. clone ( ) ;
113+ if !clean_root_path. ends_with ( '/' ) {
114+ clean_root_path. push ( '/' ) ;
115+ }
116+ let mut path = root_uri. path ( ) . to_string ( ) ;
117+ if !path. ends_with ( '/' ) {
118+ path. push ( '/' ) ;
119+ }
120+ clean_root_uri. set_path ( & path) ;
121+
122+ let added = visit_dirs (
123+ Path :: new ( & clean_root_path) ,
124+ clean_root_path. as_str ( ) ,
125+ & clean_root_uri,
126+ ) ;
109127
110128 let sender = connection. sender . clone ( ) ;
111129
@@ -117,40 +135,48 @@ pub fn scan_workspace(
117135 std:: thread:: sleep ( std:: time:: Duration :: from_millis ( 2000 ) ) ;
118136
119137 let start = Instant :: now ( ) ;
120-
138+ let mut failed_files : HashSet < String > = HashSet :: new ( ) ;
121139 for path_url in added {
122140 if let Ok ( text) = fs:: read_to_string ( path_url. path ) {
123141 if let Ok ( cache) = & mut cache. lock ( ) {
124142 let document = cache. insert ( & path_url. url , text) ;
125143
126- // TODO: Send diagnostics - Sending the diagnostics using
127- // the method below does not seem to work for VSCode.
128- // There are some mentions that the LSP protocol only
129- // allows sending diagnostics for opened buffers.
130-
131- // let diagnostics = PublishDiagnosticsParams::new(
132- // path_url.url.clone(),
133- // document.diagnostics.clone(),
134- // None,
135- // );
136-
137- // let params = serde_json::to_value(&diagnostics).unwrap();
138- // use lsp_types::notification::Notification;
139- // let notification = lsp_server::Notification {
140- // method: lsp_types::notification::PublishDiagnostics::METHOD.to_string(),
141- // params,
142- // };
143-
144- // if let Ok(r) = sender.send(Message::Notification(notification)) {
145- // } else {
146- // tracing::error!("Failed to send notification: {:?}", root_path);
147- // }
144+ for diag in & document. diagnostics {
145+ if let Some ( severity) = diag. severity {
146+ match severity {
147+ DiagnosticSeverity :: ERROR | DiagnosticSeverity :: WARNING => {
148+ failed_files
149+ . insert ( document. uri . to_string ( ) . replace ( "file://" , "" ) ) ;
150+ }
151+ _ => { }
152+ }
153+ }
154+ }
155+
156+ let diagnostics = PublishDiagnosticsParams :: new (
157+ path_url. url . clone ( ) ,
158+ document. diagnostics . clone ( ) ,
159+ None ,
160+ ) ;
161+
162+ let params = serde_json:: to_value ( & diagnostics) . unwrap ( ) ;
163+ use lsp_types:: notification:: Notification ;
164+ let notification = lsp_server:: Notification {
165+ method : lsp_types:: notification:: PublishDiagnostics :: METHOD . to_string ( ) ,
166+ params,
167+ } ;
168+
169+ if let Ok ( r) = sender. send ( Message :: Notification ( notification) ) {
170+ } else {
171+ tracing:: error!( "Failed to send notification: {:?}" , root_path) ;
172+ }
148173 }
149174 }
150175 }
151176
152177 let diff = ( Instant :: now ( ) - start) . as_millis ( ) as f64 * 1e-3 ;
153- tracing:: info!( "Workspace: parse time: {diff}" )
178+ tracing:: info!( "Workspace: parse time: {diff}" ) ;
179+ tracing:: info!( "Failed files: {:?}" , failed_files) ;
154180 } ) ;
155181
156182 Ok ( ( ) )
0 commit comments