@@ -20,6 +20,7 @@ use crate::config::Config;
2020
2121pub struct Lsp {
2222 lang : String ,
23+ lsp_name : Option < String > ,
2324 kill_send : Option < mpsc:: Sender < ( ) > > ,
2425 stdin_send : Option < mpsc:: Sender < String > > ,
2526 next_id : AtomicUsize ,
@@ -33,6 +34,7 @@ impl Lsp {
3334 pub fn new ( ) -> Self {
3435 Self {
3536 lang : String :: new ( ) ,
37+ lsp_name : None ,
3638 kill_send : None ,
3739 stdin_send : None ,
3840 next_id : AtomicUsize :: new ( 1 ) ,
@@ -44,7 +46,7 @@ impl Lsp {
4446 }
4547
4648 pub fn start (
47- & mut self , lang : & str , cmd : & str ,
49+ & mut self , lang : & str , cmd : & str , lsp_name : Option < String > ,
4850 diagnostic_updates : Option < mpsc:: Sender < PublishDiagnosticsParams > >
4951 ) -> io:: Result < ( ) > {
5052
@@ -53,6 +55,7 @@ impl Lsp {
5355 let args = & s[ 1 ..] ;
5456
5557 self . lang = lang. to_string ( ) ;
58+ self . lsp_name = lsp_name;
5659
5760 let ( kill_send, mut kill_recv) = mpsc:: channel :: < ( ) > ( 1 ) ;
5861 self . kill_send = Some ( kill_send) ;
@@ -197,11 +200,18 @@ impl Lsp {
197200 let id = 0 ;
198201 let ( tx, rx) = mpsc:: channel :: < String > ( 1 ) ;
199202 self . add_pending ( id, tx) . await ;
200- let message = lsp_messages:: initialize ( dir) ;
203+ let message = lsp_messages:: initialize ( dir, self . lsp_name . as_deref ( ) ) ;
201204 self . send_async ( message) ;
202205 self . wait ( 5 , rx) . await ;
203206 self . remove_pending ( id) . await ;
204207 self . initialized ( ) ;
208+
209+ if let Some ( lsp_name) = & self . lsp_name {
210+ let settings = lsp_messages:: read_vscode_settings ( lsp_name, dir)
211+ . unwrap_or_else ( || Value :: Object ( serde_json:: Map :: new ( ) ) ) ;
212+ self . did_change_configuration ( settings) ;
213+ }
214+
205215 self . ready . store ( true , Ordering :: SeqCst )
206216 }
207217
@@ -266,11 +276,22 @@ impl Lsp {
266276 self . ready . load ( Ordering :: SeqCst )
267277 }
268278
279+ pub fn lsp_name ( & self ) -> Option < & str > {
280+ self . lsp_name . as_deref ( )
281+ }
282+
269283 pub fn initialized ( & mut self ) {
270284 let params = InitializedParams { } ;
271285 self . send_notification :: < Initialized > ( params) ;
272286 }
273287
288+ pub fn did_change_configuration ( & self , settings : Value ) {
289+ let params = DidChangeConfigurationParams {
290+ settings,
291+ } ;
292+ self . send_notification :: < DidChangeConfiguration > ( params) ;
293+ }
294+
274295 pub fn did_open ( & mut self , lang : & str , path : & str , text : & str ) {
275296 self . opened . insert ( path. to_string ( ) ) ;
276297
@@ -467,7 +488,7 @@ mod tests {
467488 let lang = "python" ;
468489
469490 let mut lsp = Lsp :: new ( ) ;
470- lsp. start ( lang, "pyright-langserver --stdio" , None ) ?;
491+ lsp. start ( lang, "pyright-langserver --stdio" , Some ( "pyright-langserver" . to_string ( ) ) , None ) ?;
471492
472493 let dir = std:: env:: current_dir ( ) . unwrap ( )
473494 . to_string_lossy ( ) . into_owned ( ) ;
@@ -515,6 +536,7 @@ mod tests {
515536pub mod lsp_messages {
516537 use super :: * ;
517538 use serde_json:: to_string;
539+ use std:: path:: PathBuf ;
518540
519541 #[ derive( Deserialize ) ]
520542 pub struct LspRawResponse {
@@ -524,7 +546,75 @@ pub mod lsp_messages {
524546 pub error : Option < Value > ,
525547 }
526548
527- pub fn initialize ( dir : & str ) -> String {
549+ pub fn read_vscode_settings ( lsp_name : & str , dir : & str ) -> Option < Value > {
550+ let settings_path = PathBuf :: from ( dir) . join ( ".vscode" ) . join ( "settings.json" ) ;
551+
552+ if !settings_path. exists ( ) {
553+ debug ! ( "Settings file not found: {:?}" , settings_path) ;
554+ return None ;
555+ }
556+
557+ let content = match std:: fs:: read_to_string ( & settings_path) {
558+ Ok ( c) => c,
559+ Err ( e) => {
560+ debug ! ( "Failed to read settings file: {:?}" , e) ;
561+ return None ;
562+ }
563+ } ;
564+
565+ let settings: Value = match serde_json:: from_str ( & content) {
566+ Ok ( s) => s,
567+ Err ( e) => {
568+ debug ! ( "Failed to parse settings JSON: {:?}" , e) ;
569+ return None ;
570+ }
571+ } ;
572+
573+ let prefix = format ! ( "{}." , lsp_name) ;
574+ let mut lsp_settings = serde_json:: Map :: new ( ) ;
575+
576+ if let Some ( obj) = settings. as_object ( ) {
577+ for ( key, value) in obj {
578+ if key. starts_with ( & prefix) {
579+ let setting_key = key. strip_prefix ( & prefix) . unwrap ( ) ;
580+
581+ let parts: Vec < & str > = setting_key. split ( '.' ) . collect ( ) ;
582+ if parts. is_empty ( ) {
583+ continue ;
584+ }
585+
586+ let mut current = & mut lsp_settings;
587+ for ( i, part) in parts. iter ( ) . enumerate ( ) {
588+ if i == parts. len ( ) - 1 {
589+ current. insert ( part. to_string ( ) , value. clone ( ) ) ;
590+ } else {
591+ if !current. contains_key ( * part) {
592+ current. insert ( part. to_string ( ) , Value :: Object ( serde_json:: Map :: new ( ) ) ) ;
593+ }
594+ match current. get_mut ( * part) {
595+ Some ( Value :: Object ( obj) ) => {
596+ current = obj;
597+ }
598+ _ => {
599+ break ;
600+ }
601+ }
602+ }
603+ }
604+ }
605+ }
606+ }
607+
608+ if lsp_settings. is_empty ( ) {
609+ None
610+ } else {
611+ let mut wrapper = serde_json:: Map :: new ( ) ;
612+ wrapper. insert ( lsp_name. to_string ( ) , Value :: Object ( lsp_settings) ) ;
613+ Some ( Value :: Object ( wrapper) )
614+ }
615+ }
616+
617+ pub fn initialize ( dir : & str , lsp_name : Option < & str > ) -> String {
528618 let uri: Uri = format ! ( "file://{}" , dir) . parse ( ) . unwrap ( ) ;
529619
530620 let workspace_folders = Some ( vec ! [
@@ -574,6 +664,12 @@ pub mod lsp_messages {
574664 ..Default :: default ( )
575665 } ;
576666
667+ let initialization_options = if let Some ( name) = lsp_name {
668+ read_vscode_settings ( name, dir)
669+ } else {
670+ None
671+ } ;
672+
577673 let params = InitializeParams {
578674 process_id : Some ( std:: process:: id ( ) as u32 ) ,
579675 root_path : Some ( dir. to_string ( ) ) ,
@@ -584,6 +680,7 @@ pub mod lsp_messages {
584680 name : "anycode" . to_string ( ) ,
585681 version : Some ( "1.0.0" . to_string ( ) ) ,
586682 } ) ,
683+ initialization_options,
587684 ..Default :: default ( )
588685 } ;
589686
@@ -632,7 +729,9 @@ impl LspManager {
632729 pub async fn init_new ( & mut self , lang : String , lsp_cmd : & str ) {
633730 let mut lsp = Lsp :: new ( ) ;
634731 let diagnostic_send = self . diagnostics_sender . as_mut ( ) . map ( |s|s. clone ( ) ) ;
635- let result = lsp. start ( & lang, & lsp_cmd, diagnostic_send) ;
732+ let lsp_name = lsp_cmd. split_whitespace ( ) . next ( ) . map ( |s| s. to_string ( ) ) ;
733+
734+ let result = lsp. start ( & lang, & lsp_cmd, lsp_name, diagnostic_send) ;
636735
637736 match result {
638737 Ok ( _) => {
@@ -652,4 +751,24 @@ impl LspManager {
652751
653752 self . lang2lsp . insert ( lang, lsp) ;
654753 }
754+
755+ pub fn notify_configuration_changed ( & mut self , lang : & str , dir : & str ) {
756+ if let Some ( lsp) = self . lang2lsp . get_mut ( lang) {
757+ if let Some ( lsp_name) = lsp. lsp_name ( ) {
758+ if let Some ( settings) = lsp_messages:: read_vscode_settings ( lsp_name, dir) {
759+ lsp. did_change_configuration ( settings) ;
760+ }
761+ }
762+ }
763+ }
764+
765+ pub fn notify_all_configuration_changed ( & mut self , dir : & str ) {
766+ for lsp in self . lang2lsp . values_mut ( ) {
767+ if let Some ( lsp_name) = lsp. lsp_name ( ) {
768+ if let Some ( settings) = lsp_messages:: read_vscode_settings ( lsp_name, dir) {
769+ lsp. did_change_configuration ( settings) ;
770+ }
771+ }
772+ }
773+ }
655774}
0 commit comments