Skip to content

Commit 1aa76eb

Browse files
show an error when renaming with an invalid new name
1 parent a228568 commit 1aa76eb

File tree

5 files changed

+173
-54
lines changed

5 files changed

+173
-54
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@
5555
used on tuples.
5656
([Giacomo Cavalieri](https://github.com/giacomocavalieri))
5757

58+
- When renaming, if the new name is invalid, the language server will produce an
59+
error message instead of silently doing nothing.
60+
([Giacomo Cavalieri](https://github.com/giacomocavalieri))
61+
5862
### Formatter
5963

6064
### Bug fixes

compiler-core/src/language_server/engine.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use crate::{
2020
files::FileSystemProxy,
2121
progress::ProgressReporter,
2222
reference::FindVariableReferences,
23+
rename::RenameOutcome,
2324
},
2425
line_numbers::LineNumbers,
2526
paths::ProjectPaths,
@@ -34,6 +35,7 @@ use camino::Utf8PathBuf;
3435
use ecow::EcoString;
3536
use itertools::Itertools;
3637
use lsp::CodeAction;
38+
use lsp_server::ResponseError;
3739
use lsp_types::{
3840
self as lsp, DocumentSymbol, Hover, HoverContents, MarkedString, Position,
3941
PrepareRenameResponse, Range, SignatureHelp, SymbolKind, SymbolTag, TextEdit, Url,
@@ -698,17 +700,20 @@ where
698700
})
699701
}
700702

701-
pub fn rename(&mut self, params: lsp::RenameParams) -> Response<Option<WorkspaceEdit>> {
703+
pub fn rename(
704+
&mut self,
705+
params: lsp::RenameParams,
706+
) -> Response<Result<Option<WorkspaceEdit>, ResponseError>> {
702707
self.respond(|this| {
703708
let position = &params.text_document_position;
704709

705710
let (lines, found) = match this.node_at_position(position) {
706711
Some(value) => value,
707-
None => return Ok(None),
712+
None => return Ok(RenameOutcome::NoRenames.to_result()),
708713
};
709714

710715
let Some(module) = this.module_for_uri(&position.text_document.uri) else {
711-
return Ok(None);
716+
return Ok(RenameOutcome::NoRenames.to_result());
712717
};
713718

714719
Ok(match reference_for_ast_node(found, &module.name) {
@@ -719,7 +724,9 @@ where
719724
..
720725
}) => {
721726
let rename_kind = match origin.map(|origin| origin.syntax) {
722-
Some(VariableSyntax::Generated) => return Ok(None),
727+
Some(VariableSyntax::Generated) => {
728+
return Ok(RenameOutcome::NoRenames.to_result());
729+
}
723730
Some(VariableSyntax::LabelShorthand(_)) => {
724731
VariableReferenceKind::LabelShorthand
725732
}
@@ -736,6 +743,7 @@ where
736743
name,
737744
rename_kind,
738745
)
746+
.to_result()
739747
}
740748
Some(Referenced::ModuleValue {
741749
module: module_name,
@@ -755,7 +763,9 @@ where
755763
target_kind,
756764
layer: ast::Layer::Value,
757765
},
758-
),
766+
)
767+
.to_result(),
768+
759769
Some(Referenced::ModuleType {
760770
module: module_name,
761771
target_kind,
@@ -773,8 +783,10 @@ where
773783
target_kind,
774784
layer: ast::Layer::Type,
775785
},
776-
),
777-
None => None,
786+
)
787+
.to_result(),
788+
789+
None => RenameOutcome::NoRenames.to_result(),
778790
})
779791
})
780792
}

compiler-core/src/language_server/rename.rs

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::collections::HashMap;
22

33
use ecow::EcoString;
4+
use lsp_server::ResponseError;
45
use lsp_types::{Range, RenameParams, TextEdit, Url, WorkspaceEdit};
56

67
use 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+
3665
pub 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

83109
pub 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

161190
fn 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

266299
fn add_import(

0 commit comments

Comments
 (0)