tinymist/crates/tinymist-query/src/rename.rs
Myriad-Dreamin e2b7bc4b56
refactor: introduce uri_for_id and deref_syntax_at (#267)
* dev: add documentation

* refactor: introduce uri_for_id and deref_syntax_at
2024-05-09 12:32:20 +08:00

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()
})
}
}