mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-07-24 05:05:00 +00:00
72 lines
2.3 KiB
Rust
72 lines
2.3 KiB
Rust
use crate::{analysis::find_definition, find_references, prelude::*, validate_renaming_definition};
|
|
|
|
/// The [`textDocument/rename`] request is sent from the client to the server to
|
|
/// ask the server to compute a workspace change so that the client can perform
|
|
/// a workspace-wide rename of a symbol.
|
|
///
|
|
/// [`textDocument/rename`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_rename
|
|
#[derive(Debug, Clone)]
|
|
pub struct RenameRequest {
|
|
/// The path of the document to request for.
|
|
pub path: PathBuf,
|
|
/// The source code position to request for.
|
|
pub position: LspPosition,
|
|
/// The new name to rename to.
|
|
pub new_name: String,
|
|
}
|
|
|
|
impl StatefulRequest for RenameRequest {
|
|
type Response = WorkspaceEdit;
|
|
|
|
fn request(
|
|
self,
|
|
ctx: &mut AnalysisContext,
|
|
doc: Option<VersionedDocument>,
|
|
) -> Option<Self::Response> {
|
|
let source = ctx.source_by_path(&self.path).ok()?;
|
|
let deref_target = ctx.deref_syntax_at(&source, self.position, 1)?;
|
|
|
|
let lnk = find_definition(ctx, source.clone(), doc.as_ref(), deref_target.clone())?;
|
|
|
|
validate_renaming_definition(&lnk)?;
|
|
|
|
let def_use = ctx.def_use(source.clone())?;
|
|
let references = find_references(ctx, def_use, deref_target, ctx.position_encoding())?;
|
|
|
|
let mut editions = HashMap::new();
|
|
|
|
let (fid, _def_range) = lnk.def_at?;
|
|
|
|
let def_loc = {
|
|
let def_source = ctx.source_by_id(fid).ok()?;
|
|
|
|
let uri = ctx.uri_for_id(fid).ok()?;
|
|
|
|
let Some(range) = lnk.name_range else {
|
|
log::warn!("rename: no name range");
|
|
return None;
|
|
};
|
|
|
|
LspLocation {
|
|
uri,
|
|
range: ctx.to_lsp_range(range, &def_source),
|
|
}
|
|
};
|
|
|
|
for i in (Some(def_loc).into_iter()).chain(references) {
|
|
let uri = i.uri;
|
|
let range = i.range;
|
|
let edits = editions.entry(uri).or_insert_with(Vec::new);
|
|
edits.push(TextEdit {
|
|
range,
|
|
new_text: self.new_name.clone(),
|
|
});
|
|
}
|
|
|
|
// todo: name conflict analysis
|
|
Some(WorkspaceEdit {
|
|
changes: Some(editions),
|
|
..Default::default()
|
|
})
|
|
}
|
|
}
|