mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
Add convenience functions to SourceChange for creating single edits
This commit is contained in:
parent
449eea1161
commit
22e1c7a112
@ -17,14 +17,9 @@ pub(crate) fn assists(db: &RootDatabase, frange: FileRange) -> Vec<Assist> {
|
|||||||
let file_id = frange.file_id;
|
let file_id = frange.file_id;
|
||||||
let file_edit = SourceFileEdit { file_id, edit: action.edit };
|
let file_edit = SourceFileEdit { file_id, edit: action.edit };
|
||||||
let id = label.id;
|
let id = label.id;
|
||||||
let change = SourceChange {
|
let change = SourceChange::source_edit(label.label, file_edit).with_cursor_opt(
|
||||||
label: label.label,
|
action.cursor_position.map(|offset| FilePosition { offset, file_id }),
|
||||||
source_file_edits: vec![file_edit],
|
);
|
||||||
file_system_edits: vec![],
|
|
||||||
cursor_position: action
|
|
||||||
.cursor_position
|
|
||||||
.map(|offset| FilePosition { offset, file_id }),
|
|
||||||
};
|
|
||||||
Assist { id, change }
|
Assist { id, change }
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
@ -71,12 +71,10 @@ fn check_unnecessary_braces_in_use_statement(
|
|||||||
range,
|
range,
|
||||||
message: format!("Unnecessary braces in use statement"),
|
message: format!("Unnecessary braces in use statement"),
|
||||||
severity: Severity::WeakWarning,
|
severity: Severity::WeakWarning,
|
||||||
fix: Some(SourceChange {
|
fix: Some(SourceChange::source_edit(
|
||||||
label: "Remove unnecessary braces".to_string(),
|
"Remove unnecessary braces",
|
||||||
source_file_edits: vec![SourceFileEdit { file_id, edit }],
|
SourceFileEdit { file_id, edit },
|
||||||
file_system_edits: Vec::new(),
|
)),
|
||||||
cursor_position: None,
|
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,12 +117,10 @@ fn check_struct_shorthand_initialization(
|
|||||||
range: named_field.syntax().range(),
|
range: named_field.syntax().range(),
|
||||||
message: format!("Shorthand struct initialization"),
|
message: format!("Shorthand struct initialization"),
|
||||||
severity: Severity::WeakWarning,
|
severity: Severity::WeakWarning,
|
||||||
fix: Some(SourceChange {
|
fix: Some(SourceChange::source_edit(
|
||||||
label: "use struct shorthand initialization".to_string(),
|
"use struct shorthand initialization",
|
||||||
source_file_edits: vec![SourceFileEdit { file_id, edit }],
|
SourceFileEdit { file_id, edit },
|
||||||
file_system_edits: Vec::new(),
|
)),
|
||||||
cursor_position: None,
|
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,12 +140,7 @@ fn check_module(
|
|||||||
Problem::UnresolvedModule { candidate } => {
|
Problem::UnresolvedModule { candidate } => {
|
||||||
let create_file =
|
let create_file =
|
||||||
FileSystemEdit::CreateFile { source_root, path: candidate.clone() };
|
FileSystemEdit::CreateFile { source_root, path: candidate.clone() };
|
||||||
let fix = SourceChange {
|
let fix = SourceChange::system_edit("create module", create_file);
|
||||||
label: "create module".to_string(),
|
|
||||||
source_file_edits: Vec::new(),
|
|
||||||
file_system_edits: vec![create_file],
|
|
||||||
cursor_position: None,
|
|
||||||
};
|
|
||||||
Diagnostic {
|
Diagnostic {
|
||||||
range: name_node.range(),
|
range: name_node.range(),
|
||||||
message: "unresolved module".to_string(),
|
message: "unresolved module".to_string(),
|
||||||
|
@ -97,6 +97,44 @@ pub struct SourceChange {
|
|||||||
pub cursor_position: Option<FilePosition>,
|
pub cursor_position: Option<FilePosition>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SourceChange {
|
||||||
|
pub fn source_edits<L: Into<String>>(label: L, edits: Vec<SourceFileEdit>) -> Self {
|
||||||
|
SourceChange {
|
||||||
|
label: label.into(),
|
||||||
|
source_file_edits: edits,
|
||||||
|
file_system_edits: vec![],
|
||||||
|
cursor_position: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn system_edits<L: Into<String>>(label: L, edits: Vec<FileSystemEdit>) -> Self {
|
||||||
|
SourceChange {
|
||||||
|
label: label.into(),
|
||||||
|
source_file_edits: vec![],
|
||||||
|
file_system_edits: edits,
|
||||||
|
cursor_position: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn source_edit<L: Into<String>>(label: L, edit: SourceFileEdit) -> Self {
|
||||||
|
SourceChange::source_edits(label, vec![edit])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn system_edit<L: Into<String>>(label: L, edit: FileSystemEdit) -> Self {
|
||||||
|
SourceChange::system_edits(label, vec![edit])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_cursor(mut self, cursor_position: FilePosition) -> Self {
|
||||||
|
self.cursor_position = Some(cursor_position);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_cursor_opt(mut self, cursor_position: Option<FilePosition>) -> Self {
|
||||||
|
self.cursor_position = cursor_position;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SourceFileEdit {
|
pub struct SourceFileEdit {
|
||||||
pub file_id: FileId,
|
pub file_id: FileId,
|
||||||
@ -285,12 +323,7 @@ impl Analysis {
|
|||||||
file_id: frange.file_id,
|
file_id: frange.file_id,
|
||||||
edit: join_lines::join_lines(&file, frange.range),
|
edit: join_lines::join_lines(&file, frange.range),
|
||||||
};
|
};
|
||||||
SourceChange {
|
SourceChange::source_edit("join lines", file_edit)
|
||||||
label: "join lines".to_string(),
|
|
||||||
source_file_edits: vec![file_edit],
|
|
||||||
file_system_edits: vec![],
|
|
||||||
cursor_position: None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an edit which should be applied when opening a new line, fixing
|
/// Returns an edit which should be applied when opening a new line, fixing
|
||||||
@ -305,12 +338,10 @@ impl Analysis {
|
|||||||
pub fn on_eq_typed(&self, position: FilePosition) -> Option<SourceChange> {
|
pub fn on_eq_typed(&self, position: FilePosition) -> Option<SourceChange> {
|
||||||
let file = self.db.parse(position.file_id);
|
let file = self.db.parse(position.file_id);
|
||||||
let edit = typing::on_eq_typed(&file, position.offset)?;
|
let edit = typing::on_eq_typed(&file, position.offset)?;
|
||||||
Some(SourceChange {
|
Some(SourceChange::source_edit(
|
||||||
label: "add semicolon".to_string(),
|
"add semicolon",
|
||||||
source_file_edits: vec![SourceFileEdit { edit, file_id: position.file_id }],
|
SourceFileEdit { edit, file_id: position.file_id },
|
||||||
file_system_edits: vec![],
|
))
|
||||||
cursor_position: None,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an edit which should be applied when a dot ('.') is typed on a blank line, indenting the line appropriately.
|
/// Returns an edit which should be applied when a dot ('.') is typed on a blank line, indenting the line appropriately.
|
||||||
|
@ -31,12 +31,14 @@ pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<Sour
|
|||||||
let cursor_position = position.offset + TextUnit::of_str(&inserted);
|
let cursor_position = position.offset + TextUnit::of_str(&inserted);
|
||||||
let mut edit = TextEditBuilder::default();
|
let mut edit = TextEditBuilder::default();
|
||||||
edit.insert(position.offset, inserted);
|
edit.insert(position.offset, inserted);
|
||||||
Some(SourceChange {
|
|
||||||
label: "on enter".to_string(),
|
Some(
|
||||||
source_file_edits: vec![SourceFileEdit { edit: edit.finish(), file_id: position.file_id }],
|
SourceChange::source_edit(
|
||||||
file_system_edits: vec![],
|
"on enter",
|
||||||
cursor_position: Some(FilePosition { offset: cursor_position, file_id: position.file_id }),
|
SourceFileEdit { edit: edit.finish(), file_id: position.file_id },
|
||||||
})
|
)
|
||||||
|
.with_cursor(FilePosition { offset: cursor_position, file_id: position.file_id }),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn node_indent<'a>(file: &'a SourceFile, node: &SyntaxNode) -> Option<&'a str> {
|
fn node_indent<'a>(file: &'a SourceFile, node: &SyntaxNode) -> Option<&'a str> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user