@@ -5,7 +5,7 @@ use index::DocumentQueryError;
55use lsp_server:: { Message , RequestId } ;
66use lsp_types:: notification:: { Exit , Notification } ;
77use lsp_types:: request:: {
8- DocumentDiagnosticRequest , RegisterCapability , Request , Shutdown , UnregisterCapability ,
8+ DocumentDiagnosticRequest , RegisterCapability , Rename , Request , Shutdown , UnregisterCapability ,
99 WorkspaceDiagnosticRequest ,
1010} ;
1111use lsp_types:: {
@@ -16,8 +16,7 @@ use options::GlobalOptions;
1616use ruff_db:: Db ;
1717use ruff_db:: files:: File ;
1818use ruff_db:: system:: { System , SystemPath , SystemPathBuf } ;
19- use settings:: GlobalSettings ;
20- use std:: collections:: { BTreeMap , VecDeque } ;
19+ use std:: collections:: { BTreeMap , HashSet , VecDeque } ;
2120use std:: ops:: { Deref , DerefMut } ;
2221use std:: panic:: RefUnwindSafe ;
2322use std:: sync:: Arc ;
@@ -29,8 +28,10 @@ use ty_project::{ChangeResult, CheckMode, Db as _, ProjectDatabase, ProjectMetad
2928pub ( crate ) use self :: index:: DocumentQuery ;
3029pub ( crate ) use self :: options:: InitializationOptions ;
3130pub use self :: options:: { ClientOptions , DiagnosticMode } ;
32- pub ( crate ) use self :: settings:: WorkspaceSettings ;
33- use crate :: capabilities:: { ResolvedClientCapabilities , server_diagnostic_options} ;
31+ pub ( crate ) use self :: settings:: { GlobalSettings , WorkspaceSettings } ;
32+ use crate :: capabilities:: {
33+ ResolvedClientCapabilities , server_diagnostic_options, server_rename_options,
34+ } ;
3435use crate :: document:: { DocumentKey , DocumentVersion , NotebookDocument } ;
3536use crate :: server:: { Action , publish_settings_diagnostics} ;
3637use crate :: session:: client:: Client ;
@@ -91,8 +92,6 @@ pub(crate) struct Session {
9192 shutdown_requested : bool ,
9293
9394 /// Whether the server has dynamically registered the diagnostic capability with the client.
94- diagnostic_capability_registered : bool ,
95-
9695 /// Is the connected client a `TestServer` instance.
9796 in_test : bool ,
9897
@@ -107,6 +106,10 @@ pub(crate) struct Session {
107106 /// We'll re-run the request after every change to `Session` (see `revision`)
108107 /// to see if there are now changes and, if so, respond to the client.
109108 suspended_workspace_diagnostics_request : Option < SuspendedWorkspaceDiagnosticRequest > ,
109+
110+ /// Registrations is a set of LSP methods that have been dynamically registered with the
111+ /// client.
112+ registrations : HashSet < String > ,
110113}
111114
112115/// LSP State for a Project
@@ -166,10 +169,10 @@ impl Session {
166169 resolved_client_capabilities,
167170 request_queue : RequestQueue :: new ( ) ,
168171 shutdown_requested : false ,
169- diagnostic_capability_registered : false ,
170172 in_test,
171173 suspended_workspace_diagnostics_request : None ,
172174 revision : 0 ,
175+ registrations : HashSet :: new ( ) ,
173176 } )
174177 }
175178
@@ -568,6 +571,7 @@ impl Session {
568571 }
569572
570573 self . register_diagnostic_capability ( client) ;
574+ self . register_rename_capability ( client) ;
571575
572576 assert ! (
573577 self . workspaces. all_initialized( ) ,
@@ -583,11 +587,13 @@ impl Session {
583587 }
584588 }
585589
590+ // TODO: Merge the following two methods as `register_capability` and `unregister_capability`
591+
586592 /// Sends a registration notification to the client to enable / disable workspace diagnostics
587- /// as per the `diagnostic_mode` .
593+ /// as per the `ty.diagnosticMode` global setting .
588594 ///
589595 /// This method is a no-op if the client doesn't support dynamic registration of diagnostic
590- /// capabilities .
596+ /// capability .
591597 fn register_diagnostic_capability ( & mut self , client : & Client ) {
592598 static DIAGNOSTIC_REGISTRATION_ID : & str = "ty/textDocument/diagnostic" ;
593599
@@ -598,9 +604,11 @@ impl Session {
598604 return ;
599605 }
600606
601- let diagnostic_mode = self . global_settings . diagnostic_mode ;
607+ let registered = self
608+ . registrations
609+ . contains ( DocumentDiagnosticRequest :: METHOD ) ;
602610
603- if self . diagnostic_capability_registered {
611+ if registered {
604612 client. send_request :: < UnregisterCapability > (
605613 self ,
606614 UnregistrationParams {
@@ -615,6 +623,8 @@ impl Session {
615623 ) ;
616624 }
617625
626+ let diagnostic_mode = self . global_settings . diagnostic_mode ;
627+
618628 let registration = Registration {
619629 id : DIAGNOSTIC_REGISTRATION_ID . into ( ) ,
620630 method : DocumentDiagnosticRequest :: METHOD . into ( ) ,
@@ -643,7 +653,68 @@ impl Session {
643653 } ,
644654 ) ;
645655
646- self . diagnostic_capability_registered = true ;
656+ if !registered {
657+ self . registrations
658+ . insert ( DocumentDiagnosticRequest :: METHOD . to_string ( ) ) ;
659+ }
660+ }
661+
662+ /// Sends a registration notification to the client to enable / disable rename capability as
663+ /// per the `ty.experimental.rename` global setting.
664+ ///
665+ /// This method is a no-op if the client doesn't support dynamic registration of rename
666+ /// capability.
667+ fn register_rename_capability ( & mut self , client : & Client ) {
668+ static RENAME_REGISTRATION_ID : & str = "ty/textDocument/rename" ;
669+
670+ if !self
671+ . resolved_client_capabilities
672+ . supports_rename_dynamic_registration ( )
673+ {
674+ return ;
675+ }
676+
677+ let registered = self . registrations . contains ( Rename :: METHOD ) ;
678+
679+ if registered {
680+ client. send_request :: < UnregisterCapability > (
681+ self ,
682+ UnregistrationParams {
683+ unregisterations : vec ! [ Unregistration {
684+ id: RENAME_REGISTRATION_ID . into( ) ,
685+ method: Rename :: METHOD . into( ) ,
686+ } ] ,
687+ } ,
688+ move |_: & Client , ( ) | {
689+ tracing:: debug!( "Unregistered rename capability" ) ;
690+ } ,
691+ ) ;
692+ }
693+
694+ if !self . global_settings . experimental . rename {
695+ tracing:: debug!( "Rename capability is disabled in the client settings" ) ;
696+ return ;
697+ }
698+
699+ let registration = Registration {
700+ id : RENAME_REGISTRATION_ID . into ( ) ,
701+ method : Rename :: METHOD . into ( ) ,
702+ register_options : Some ( serde_json:: to_value ( server_rename_options ( ) ) . unwrap ( ) ) ,
703+ } ;
704+
705+ client. send_request :: < RegisterCapability > (
706+ self ,
707+ RegistrationParams {
708+ registrations : vec ! [ registration] ,
709+ } ,
710+ move |_: & Client , ( ) | {
711+ tracing:: debug!( "Registered rename capability" ) ;
712+ } ,
713+ ) ;
714+
715+ if !registered {
716+ self . registrations . insert ( Rename :: METHOD . to_string ( ) ) ;
717+ }
647718 }
648719
649720 /// Creates a document snapshot with the URL referencing the document to snapshot.
0 commit comments