11use std:: collections:: HashMap ;
22
33use ecow:: EcoString ;
4+ use lsp_server:: ResponseError ;
45use lsp_types:: { Range , RenameParams , TextEdit , Url , WorkspaceEdit } ;
56
67use crate :: {
@@ -33,22 +34,45 @@ fn workspace_edit(uri: Url, edits: Vec<TextEdit>) -> WorkspaceEdit {
3334 }
3435}
3536
37+ pub enum RenameOutcome {
38+ InvalidName { name : EcoString } ,
39+ NoRenames ,
40+ Renamed { edit : WorkspaceEdit } ,
41+ }
42+
43+ /// Error code for when a request has invalid params as described in:
44+ /// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#errorCodes
45+ ///
46+ const INVALID_PARAMS : i32 = -32602 ;
47+
48+ impl RenameOutcome {
49+ /// Turns the outcome of renaming into a value that's suitable to be used as
50+ /// a response in the language server engine.
51+ ///
52+ pub fn to_result ( self ) -> Result < Option < WorkspaceEdit > , ResponseError > {
53+ match self {
54+ RenameOutcome :: NoRenames => Ok ( None ) ,
55+ RenameOutcome :: Renamed { edit } => Ok ( Some ( edit) ) ,
56+ RenameOutcome :: InvalidName { name } => Err ( ResponseError {
57+ code : INVALID_PARAMS ,
58+ message : format ! ( "{name} is not a valid name" ) ,
59+ data : None ,
60+ } ) ,
61+ }
62+ }
63+ }
64+
3665pub fn rename_local_variable (
3766 module : & Module ,
3867 line_numbers : & LineNumbers ,
3968 params : & RenameParams ,
4069 definition_location : SrcSpan ,
4170 name : EcoString ,
4271 kind : VariableReferenceKind ,
43- ) -> Option < WorkspaceEdit > {
44- if name:: check_name_case (
45- Default :: default ( ) ,
46- & params. new_name . as_str ( ) . into ( ) ,
47- Named :: Variable ,
48- )
49- . is_err ( )
50- {
51- return None ;
72+ ) -> RenameOutcome {
73+ let new_name = EcoString :: from ( & params. new_name ) ;
74+ if name:: check_name_case ( Default :: default ( ) , & new_name, Named :: Variable ) . is_err ( ) {
75+ return RenameOutcome :: InvalidName { name : new_name } ;
5276 }
5377
5478 let uri = params. text_document_position . text_document . uri . clone ( ) ;
@@ -77,7 +101,9 @@ pub fn rename_local_variable(
77101 }
78102 }
79103
80- Some ( workspace_edit ( uri, edits. edits ) )
104+ RenameOutcome :: Renamed {
105+ edit : workspace_edit ( uri, edits. edits ) ,
106+ }
81107}
82108
83109pub enum RenameTarget {
@@ -100,17 +126,18 @@ pub fn rename_module_entity(
100126 modules : & im:: HashMap < EcoString , ModuleInterface > ,
101127 sources : & HashMap < EcoString , ModuleSourceInformation > ,
102128 renamed : Renamed < ' _ > ,
103- ) -> Option < WorkspaceEdit > {
129+ ) -> RenameOutcome {
130+ let new_name = EcoString :: from ( & params. new_name ) ;
104131 if name:: check_name_case (
105132 // We don't care about the actual error here, just whether the name is valid,
106133 // so we just use the default span.
107134 SrcSpan :: default ( ) ,
108- & params . new_name . as_str ( ) . into ( ) ,
135+ & new_name,
109136 renamed. name_kind ,
110137 )
111138 . is_err ( )
112139 {
113- return None ;
140+ return RenameOutcome :: InvalidName { name : new_name } ;
114141 }
115142
116143 match renamed. target_kind {
@@ -155,7 +182,9 @@ pub fn rename_module_entity(
155182 }
156183 }
157184
158- Some ( workspace_edit)
185+ RenameOutcome :: Renamed {
186+ edit : workspace_edit,
187+ }
159188}
160189
161190fn rename_references_in_module (
@@ -204,13 +233,15 @@ fn alias_references_in_module(
204233 module_name : & EcoString ,
205234 name : & EcoString ,
206235 layer : ast:: Layer ,
207- ) -> Option < WorkspaceEdit > {
236+ ) -> RenameOutcome {
208237 let reference_map = match layer {
209238 ast:: Layer :: Value => & module. ast . type_info . references . value_references ,
210239 ast:: Layer :: Type => & module. ast . type_info . references . type_references ,
211240 } ;
212241
213- let references = reference_map. get ( & ( module_name. clone ( ) , name. clone ( ) ) ) ?;
242+ let Some ( references) = reference_map. get ( & ( module_name. clone ( ) , name. clone ( ) ) ) else {
243+ return RenameOutcome :: NoRenames ;
244+ } ;
214245
215246 let mut edits = TextEdits :: new ( & module. ast . type_info . line_numbers ) ;
216247 let mut found_import = false ;
@@ -257,10 +288,12 @@ fn alias_references_in_module(
257288 }
258289 }
259290
260- Some ( workspace_edit (
261- params. text_document_position . text_document . uri . clone ( ) ,
262- edits. edits ,
263- ) )
291+ RenameOutcome :: Renamed {
292+ edit : workspace_edit (
293+ params. text_document_position . text_document . uri . clone ( ) ,
294+ edits. edits ,
295+ ) ,
296+ }
264297}
265298
266299fn add_import (
0 commit comments