mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +00:00
Prevent being able to rename items that are not part of the workspace
This commit is contained in:
parent
75371eb0fa
commit
c447a795ab
10 changed files with 92 additions and 15 deletions
|
@ -244,6 +244,12 @@ impl Analysis {
|
||||||
self.with_db(|db| db.parse(file_id).tree())
|
self.with_db(|db| db.parse(file_id).tree())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if this file belongs to an immutable library.
|
||||||
|
pub fn is_library_file(&self, file_id: FileId) -> Cancelable<bool> {
|
||||||
|
use ide_db::base_db::SourceDatabaseExt;
|
||||||
|
self.with_db(|db| db.source_root(db.file_source_root(file_id)).is_library)
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets the file's `LineIndex`: data structure to convert between absolute
|
/// Gets the file's `LineIndex`: data structure to convert between absolute
|
||||||
/// offsets and line/column representation.
|
/// offsets and line/column representation.
|
||||||
pub fn file_line_index(&self, file_id: FileId) -> Cancelable<Arc<LineIndex>> {
|
pub fn file_line_index(&self, file_id: FileId) -> Cancelable<Arc<LineIndex>> {
|
||||||
|
|
|
@ -400,6 +400,17 @@ impl Config {
|
||||||
pub fn will_rename(&self) -> bool {
|
pub fn will_rename(&self) -> bool {
|
||||||
try_or!(self.caps.workspace.as_ref()?.file_operations.as_ref()?.will_rename?, false)
|
try_or!(self.caps.workspace.as_ref()?.file_operations.as_ref()?.will_rename?, false)
|
||||||
}
|
}
|
||||||
|
pub fn change_annotation_support(&self) -> bool {
|
||||||
|
try_!(self
|
||||||
|
.caps
|
||||||
|
.workspace
|
||||||
|
.as_ref()?
|
||||||
|
.workspace_edit
|
||||||
|
.as_ref()?
|
||||||
|
.change_annotation_support
|
||||||
|
.as_ref()?)
|
||||||
|
.is_some()
|
||||||
|
}
|
||||||
pub fn code_action_resolve(&self) -> bool {
|
pub fn code_action_resolve(&self) -> bool {
|
||||||
try_or!(
|
try_or!(
|
||||||
self.caps
|
self.caps
|
||||||
|
|
|
@ -326,6 +326,7 @@
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
document_changes: None,
|
document_changes: None,
|
||||||
|
change_annotations: None,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
is_preferred: Some(
|
is_preferred: Some(
|
||||||
|
|
|
@ -179,6 +179,7 @@
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
document_changes: None,
|
document_changes: None,
|
||||||
|
change_annotations: None,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
is_preferred: Some(
|
is_preferred: Some(
|
||||||
|
|
|
@ -179,6 +179,7 @@
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
document_changes: None,
|
document_changes: None,
|
||||||
|
change_annotations: None,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
is_preferred: Some(
|
is_preferred: Some(
|
||||||
|
|
|
@ -179,6 +179,7 @@
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
document_changes: None,
|
document_changes: None,
|
||||||
|
change_annotations: None,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
is_preferred: Some(
|
is_preferred: Some(
|
||||||
|
|
|
@ -339,6 +339,7 @@
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
document_changes: None,
|
document_changes: None,
|
||||||
|
change_annotations: None,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
is_preferred: Some(
|
is_preferred: Some(
|
||||||
|
|
|
@ -136,6 +136,7 @@ fn map_rust_child_diagnostic(
|
||||||
// FIXME: there's no good reason to use edit_map here....
|
// FIXME: there's no good reason to use edit_map here....
|
||||||
changes: Some(edit_map),
|
changes: Some(edit_map),
|
||||||
document_changes: None,
|
document_changes: None,
|
||||||
|
change_annotations: None,
|
||||||
}),
|
}),
|
||||||
is_preferred: Some(true),
|
is_preferred: Some(true),
|
||||||
data: None,
|
data: None,
|
||||||
|
|
|
@ -312,6 +312,9 @@ pub struct SnippetWorkspaceEdit {
|
||||||
pub changes: Option<HashMap<lsp_types::Url, Vec<lsp_types::TextEdit>>>,
|
pub changes: Option<HashMap<lsp_types::Url, Vec<lsp_types::TextEdit>>>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub document_changes: Option<Vec<SnippetDocumentChangeOperation>>,
|
pub document_changes: Option<Vec<SnippetDocumentChangeOperation>>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub change_annotations:
|
||||||
|
Option<HashMap<lsp_types::ChangeAnnotationIdentifier, lsp_types::ChangeAnnotation>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
|
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
|
||||||
|
@ -335,6 +338,9 @@ pub struct SnippetTextEdit {
|
||||||
pub new_text: String,
|
pub new_text: String,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub insert_text_format: Option<lsp_types::InsertTextFormat>,
|
pub insert_text_format: Option<lsp_types::InsertTextFormat>,
|
||||||
|
/// The annotation id if this is an annotated
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub annotation_id: Option<lsp_types::ChangeAnnotationIdentifier>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum HoverRequest {}
|
pub enum HoverRequest {}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//! Conversion of rust-analyzer specific types to lsp_types equivalents.
|
//! Conversion of rust-analyzer specific types to lsp_types equivalents.
|
||||||
use std::{
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
path::{self, Path},
|
path::{self, Path},
|
||||||
sync::atomic::{AtomicU32, Ordering},
|
sync::atomic::{AtomicU32, Ordering},
|
||||||
};
|
};
|
||||||
|
@ -174,6 +175,7 @@ pub(crate) fn snippet_text_edit(
|
||||||
range: text_edit.range,
|
range: text_edit.range,
|
||||||
new_text: text_edit.new_text,
|
new_text: text_edit.new_text,
|
||||||
insert_text_format,
|
insert_text_format,
|
||||||
|
annotation_id: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -688,6 +690,10 @@ pub(crate) fn goto_definition_response(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn outside_workspace_annotation(snap: &GlobalStateSnapshot) -> Option<String> {
|
||||||
|
snap.config.change_annotation_support().then(|| String::from("OutsideWorkspace"))
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn snippet_text_document_edit(
|
pub(crate) fn snippet_text_document_edit(
|
||||||
snap: &GlobalStateSnapshot,
|
snap: &GlobalStateSnapshot,
|
||||||
is_snippet: bool,
|
is_snippet: bool,
|
||||||
|
@ -696,7 +702,19 @@ pub(crate) fn snippet_text_document_edit(
|
||||||
) -> Result<lsp_ext::SnippetTextDocumentEdit> {
|
) -> Result<lsp_ext::SnippetTextDocumentEdit> {
|
||||||
let text_document = optional_versioned_text_document_identifier(snap, file_id);
|
let text_document = optional_versioned_text_document_identifier(snap, file_id);
|
||||||
let line_index = snap.file_line_index(file_id)?;
|
let line_index = snap.file_line_index(file_id)?;
|
||||||
let edits = edit.into_iter().map(|it| snippet_text_edit(&line_index, is_snippet, it)).collect();
|
let outside_workspace_annotation = snap
|
||||||
|
.analysis
|
||||||
|
.is_library_file(file_id)?
|
||||||
|
.then(|| outside_workspace_annotation(snap))
|
||||||
|
.flatten();
|
||||||
|
let edits = edit
|
||||||
|
.into_iter()
|
||||||
|
.map(|it| {
|
||||||
|
let mut edit = snippet_text_edit(&line_index, is_snippet, it);
|
||||||
|
edit.annotation_id = outside_workspace_annotation.clone();
|
||||||
|
edit
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
Ok(lsp_ext::SnippetTextDocumentEdit { text_document, edits })
|
Ok(lsp_ext::SnippetTextDocumentEdit { text_document, edits })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -721,6 +739,7 @@ pub(crate) fn snippet_text_document_ops(
|
||||||
range: lsp_types::Range::default(),
|
range: lsp_types::Range::default(),
|
||||||
new_text: initial_contents,
|
new_text: initial_contents,
|
||||||
insert_text_format: Some(lsp_types::InsertTextFormat::PlainText),
|
insert_text_format: Some(lsp_types::InsertTextFormat::PlainText),
|
||||||
|
annotation_id: None,
|
||||||
};
|
};
|
||||||
let edit_file =
|
let edit_file =
|
||||||
lsp_ext::SnippetTextDocumentEdit { text_document, edits: vec![text_edit] };
|
lsp_ext::SnippetTextDocumentEdit { text_document, edits: vec![text_edit] };
|
||||||
|
@ -734,7 +753,12 @@ pub(crate) fn snippet_text_document_ops(
|
||||||
old_uri,
|
old_uri,
|
||||||
new_uri,
|
new_uri,
|
||||||
options: None,
|
options: None,
|
||||||
annotation_id: None,
|
annotation_id: snap
|
||||||
|
.analysis
|
||||||
|
.is_library_file(src)
|
||||||
|
.unwrap()
|
||||||
|
.then(|| outside_workspace_annotation(snap))
|
||||||
|
.flatten(),
|
||||||
});
|
});
|
||||||
ops.push(lsp_ext::SnippetDocumentChangeOperation::Op(rename_file))
|
ops.push(lsp_ext::SnippetDocumentChangeOperation::Op(rename_file))
|
||||||
}
|
}
|
||||||
|
@ -747,6 +771,7 @@ pub(crate) fn snippet_workspace_edit(
|
||||||
source_change: SourceChange,
|
source_change: SourceChange,
|
||||||
) -> Result<lsp_ext::SnippetWorkspaceEdit> {
|
) -> Result<lsp_ext::SnippetWorkspaceEdit> {
|
||||||
let mut document_changes: Vec<lsp_ext::SnippetDocumentChangeOperation> = Vec::new();
|
let mut document_changes: Vec<lsp_ext::SnippetDocumentChangeOperation> = Vec::new();
|
||||||
|
|
||||||
for op in source_change.file_system_edits {
|
for op in source_change.file_system_edits {
|
||||||
let ops = snippet_text_document_ops(snap, op);
|
let ops = snippet_text_document_ops(snap, op);
|
||||||
document_changes.extend_from_slice(&ops);
|
document_changes.extend_from_slice(&ops);
|
||||||
|
@ -755,8 +780,24 @@ pub(crate) fn snippet_workspace_edit(
|
||||||
let edit = snippet_text_document_edit(&snap, source_change.is_snippet, file_id, edit)?;
|
let edit = snippet_text_document_edit(&snap, source_change.is_snippet, file_id, edit)?;
|
||||||
document_changes.push(lsp_ext::SnippetDocumentChangeOperation::Edit(edit));
|
document_changes.push(lsp_ext::SnippetDocumentChangeOperation::Edit(edit));
|
||||||
}
|
}
|
||||||
let workspace_edit =
|
let change_annotations = outside_workspace_annotation(snap).map(|annotation| {
|
||||||
lsp_ext::SnippetWorkspaceEdit { changes: None, document_changes: Some(document_changes) };
|
use std::iter::FromIterator;
|
||||||
|
HashMap::from_iter(Some((
|
||||||
|
annotation,
|
||||||
|
lsp_types::ChangeAnnotation {
|
||||||
|
label: String::from("Edit outside of the workspace"),
|
||||||
|
needs_confirmation: Some(true),
|
||||||
|
description: Some(String::from(
|
||||||
|
"This edit lies outside of the workspace and may affect dependencies",
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
)))
|
||||||
|
});
|
||||||
|
let workspace_edit = lsp_ext::SnippetWorkspaceEdit {
|
||||||
|
changes: None,
|
||||||
|
document_changes: Some(document_changes),
|
||||||
|
change_annotations,
|
||||||
|
};
|
||||||
Ok(workspace_edit)
|
Ok(workspace_edit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -784,16 +825,7 @@ impl From<lsp_ext::SnippetWorkspaceEdit> for lsp_types::WorkspaceEdit {
|
||||||
lsp_types::DocumentChangeOperation::Edit(
|
lsp_types::DocumentChangeOperation::Edit(
|
||||||
lsp_types::TextDocumentEdit {
|
lsp_types::TextDocumentEdit {
|
||||||
text_document: edit.text_document,
|
text_document: edit.text_document,
|
||||||
edits: edit
|
edits: edit.edits.into_iter().map(From::from).collect(),
|
||||||
.edits
|
|
||||||
.into_iter()
|
|
||||||
.map(|edit| {
|
|
||||||
lsp_types::OneOf::Left(lsp_types::TextEdit {
|
|
||||||
range: edit.range,
|
|
||||||
new_text: edit.new_text,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -801,7 +833,23 @@ impl From<lsp_ext::SnippetWorkspaceEdit> for lsp_types::WorkspaceEdit {
|
||||||
.collect(),
|
.collect(),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
change_annotations: None,
|
change_annotations: snippet_workspace_edit.change_annotations,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<lsp_ext::SnippetTextEdit>
|
||||||
|
for lsp_types::OneOf<lsp_types::TextEdit, lsp_types::AnnotatedTextEdit>
|
||||||
|
{
|
||||||
|
fn from(
|
||||||
|
lsp_ext::SnippetTextEdit { annotation_id, insert_text_format:_, new_text, range }: lsp_ext::SnippetTextEdit,
|
||||||
|
) -> Self {
|
||||||
|
match annotation_id {
|
||||||
|
Some(annotation_id) => lsp_types::OneOf::Right(lsp_types::AnnotatedTextEdit {
|
||||||
|
text_edit: lsp_types::TextEdit { range, new_text },
|
||||||
|
annotation_id,
|
||||||
|
}),
|
||||||
|
None => lsp_types::OneOf::Left(lsp_types::TextEdit { range, new_text }),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue