Group file source edits by FileId
This commit is contained in:
parent
f88f3d6885
commit
f51457a643
15 changed files with 188 additions and 180 deletions
|
|
@ -13,8 +13,7 @@ use hir::{
|
|||
diagnostics::{Diagnostic as _, DiagnosticCode, DiagnosticSinkBuilder},
|
||||
Semantics,
|
||||
};
|
||||
use ide_db::base_db::SourceDatabase;
|
||||
use ide_db::RootDatabase;
|
||||
use ide_db::{base_db::SourceDatabase, source_change::SourceFileEdits, RootDatabase};
|
||||
use itertools::Itertools;
|
||||
use rustc_hash::FxHashSet;
|
||||
use syntax::{
|
||||
|
|
@ -23,7 +22,7 @@ use syntax::{
|
|||
};
|
||||
use text_edit::TextEdit;
|
||||
|
||||
use crate::{FileId, Label, SourceChange, SourceFileEdit};
|
||||
use crate::{FileId, Label, SourceChange};
|
||||
|
||||
use self::fixes::DiagnosticWithFix;
|
||||
|
||||
|
|
@ -220,7 +219,7 @@ fn check_unnecessary_braces_in_use_statement(
|
|||
Diagnostic::hint(use_range, "Unnecessary braces in use statement".to_string())
|
||||
.with_fix(Some(Fix::new(
|
||||
"Remove unnecessary braces",
|
||||
SourceFileEdit { file_id, edit }.into(),
|
||||
SourceFileEdits::from_text_edit(file_id, edit).into(),
|
||||
use_range,
|
||||
))),
|
||||
);
|
||||
|
|
@ -265,13 +264,11 @@ mod tests {
|
|||
.unwrap();
|
||||
let fix = diagnostic.fix.unwrap();
|
||||
let actual = {
|
||||
let file_id = fix.source_change.source_file_edits.first().unwrap().file_id;
|
||||
let file_id = *fix.source_change.source_file_edits.edits.keys().next().unwrap();
|
||||
let mut actual = analysis.file_text(file_id).unwrap().to_string();
|
||||
|
||||
// Go from the last one to the first one, so that ranges won't be affected by previous edits.
|
||||
// FIXME: https://github.com/rust-analyzer/rust-analyzer/issues/4901#issuecomment-644675309
|
||||
for edit in fix.source_change.source_file_edits.iter().rev() {
|
||||
edit.edit.apply(&mut actual);
|
||||
for edit in fix.source_change.source_file_edits.edits.values() {
|
||||
edit.apply(&mut actual);
|
||||
}
|
||||
actual
|
||||
};
|
||||
|
|
@ -616,7 +613,9 @@ fn test_fn() {
|
|||
Fix {
|
||||
label: "Create module",
|
||||
source_change: SourceChange {
|
||||
source_file_edits: [],
|
||||
source_file_edits: SourceFileEdits {
|
||||
edits: {},
|
||||
},
|
||||
file_system_edits: [
|
||||
CreateFile {
|
||||
dst: AnchoredPathBuf {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
//! Suggests shortening `Foo { field: field }` to `Foo { field }` in both
|
||||
//! expressions and patterns.
|
||||
|
||||
use ide_db::base_db::FileId;
|
||||
use ide_db::source_change::SourceFileEdit;
|
||||
use ide_db::{base_db::FileId, source_change::SourceFileEdits};
|
||||
use syntax::{ast, match_ast, AstNode, SyntaxNode};
|
||||
use text_edit::TextEdit;
|
||||
|
||||
|
|
@ -50,7 +49,7 @@ fn check_expr_field_shorthand(
|
|||
Diagnostic::hint(field_range, "Shorthand struct initialization".to_string()).with_fix(
|
||||
Some(Fix::new(
|
||||
"Use struct shorthand initialization",
|
||||
SourceFileEdit { file_id, edit }.into(),
|
||||
SourceFileEdits::from_text_edit(file_id, edit).into(),
|
||||
field_range,
|
||||
)),
|
||||
),
|
||||
|
|
@ -89,7 +88,7 @@ fn check_pat_field_shorthand(
|
|||
acc.push(Diagnostic::hint(field_range, "Shorthand struct pattern".to_string()).with_fix(
|
||||
Some(Fix::new(
|
||||
"Use struct field shorthand",
|
||||
SourceFileEdit { file_id, edit }.into(),
|
||||
SourceFileEdits::from_text_edit(file_id, edit).into(),
|
||||
field_range,
|
||||
)),
|
||||
));
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ use hir::{
|
|||
},
|
||||
HasSource, HirDisplay, InFile, Semantics, VariantDef,
|
||||
};
|
||||
use ide_db::base_db::{AnchoredPathBuf, FileId};
|
||||
use ide_db::{
|
||||
source_change::{FileSystemEdit, SourceFileEdit},
|
||||
base_db::{AnchoredPathBuf, FileId},
|
||||
source_change::{FileSystemEdit, SourceFileEdits},
|
||||
RootDatabase,
|
||||
};
|
||||
use syntax::{
|
||||
|
|
@ -88,7 +88,7 @@ impl DiagnosticWithFix for MissingFields {
|
|||
};
|
||||
Some(Fix::new(
|
||||
"Fill struct fields",
|
||||
SourceFileEdit { file_id: self.file.original_file(sema.db), edit }.into(),
|
||||
SourceFileEdits::from_text_edit(self.file.original_file(sema.db), edit).into(),
|
||||
sema.original_range(&field_list_parent.syntax()).range,
|
||||
))
|
||||
}
|
||||
|
|
@ -102,7 +102,7 @@ impl DiagnosticWithFix for MissingOkOrSomeInTailExpr {
|
|||
let replacement = format!("{}({})", self.required, tail_expr.syntax());
|
||||
let edit = TextEdit::replace(tail_expr_range, replacement);
|
||||
let source_change =
|
||||
SourceFileEdit { file_id: self.file.original_file(sema.db), edit }.into();
|
||||
SourceFileEdits::from_text_edit(self.file.original_file(sema.db), edit).into();
|
||||
let name = if self.required == "Ok" { "Wrap with Ok" } else { "Wrap with Some" };
|
||||
Some(Fix::new(name, source_change, tail_expr_range))
|
||||
}
|
||||
|
|
@ -123,7 +123,7 @@ impl DiagnosticWithFix for RemoveThisSemicolon {
|
|||
|
||||
let edit = TextEdit::delete(semicolon);
|
||||
let source_change =
|
||||
SourceFileEdit { file_id: self.file.original_file(sema.db), edit }.into();
|
||||
SourceFileEdits::from_text_edit(self.file.original_file(sema.db), edit).into();
|
||||
|
||||
Some(Fix::new("Remove this semicolon", source_change, semicolon))
|
||||
}
|
||||
|
|
@ -204,10 +204,10 @@ fn missing_record_expr_field_fix(
|
|||
new_field = format!(",{}", new_field);
|
||||
}
|
||||
|
||||
let source_change = SourceFileEdit {
|
||||
file_id: def_file_id,
|
||||
edit: TextEdit::insert(last_field_syntax.text_range().end(), new_field),
|
||||
};
|
||||
let source_change = SourceFileEdits::from_text_edit(
|
||||
def_file_id,
|
||||
TextEdit::insert(last_field_syntax.text_range().end(), new_field),
|
||||
);
|
||||
return Some(Fix::new(
|
||||
"Create field",
|
||||
source_change.into(),
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ pub use ide_db::{
|
|||
label::Label,
|
||||
line_index::{LineCol, LineIndex},
|
||||
search::SearchScope,
|
||||
source_change::{FileSystemEdit, SourceChange, SourceFileEdit},
|
||||
source_change::{FileSystemEdit, SourceChange, SourceFileEdits},
|
||||
symbol_index::Query,
|
||||
RootDatabase,
|
||||
};
|
||||
|
|
@ -553,7 +553,7 @@ impl Analysis {
|
|||
let rule: ssr::SsrRule = query.parse()?;
|
||||
let mut match_finder = ssr::MatchFinder::in_context(db, resolve_context, selections);
|
||||
match_finder.add_rule(rule)?;
|
||||
let edits = if parse_only { Vec::new() } else { match_finder.edits() };
|
||||
let edits = if parse_only { Default::default() } else { match_finder.edits() };
|
||||
Ok(SourceChange::from(edits))
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ use text_edit::TextEdit;
|
|||
|
||||
use crate::{
|
||||
FilePosition, FileSystemEdit, RangeInfo, ReferenceKind, ReferenceSearchResult, SourceChange,
|
||||
SourceFileEdit, TextRange, TextSize,
|
||||
SourceFileEdits, TextRange, TextSize,
|
||||
};
|
||||
|
||||
type RenameResult<T> = Result<T, RenameError>;
|
||||
|
|
@ -58,7 +58,7 @@ pub(crate) fn prepare_rename(
|
|||
rename_self_to_param(&sema, position, self_token, "dummy")
|
||||
} else {
|
||||
let RangeInfo { range, .. } = find_all_refs(&sema, position)?;
|
||||
Ok(RangeInfo::new(range, SourceChange::from(vec![])))
|
||||
Ok(RangeInfo::new(range, SourceChange::default()))
|
||||
}
|
||||
.map(|info| RangeInfo::new(info.range, ()))
|
||||
}
|
||||
|
|
@ -176,7 +176,7 @@ fn source_edit_from_references(
|
|||
file_id: FileId,
|
||||
references: &[FileReference],
|
||||
new_name: &str,
|
||||
) -> SourceFileEdit {
|
||||
) -> (FileId, TextEdit) {
|
||||
let mut edit = TextEdit::builder();
|
||||
for reference in references {
|
||||
let mut replacement_text = String::new();
|
||||
|
|
@ -209,8 +209,7 @@ fn source_edit_from_references(
|
|||
};
|
||||
edit.replace(range, replacement_text);
|
||||
}
|
||||
|
||||
SourceFileEdit { file_id, edit: edit.finish() }
|
||||
(file_id, edit.finish())
|
||||
}
|
||||
|
||||
fn edit_text_range_for_record_field_expr_or_pat(
|
||||
|
|
@ -250,7 +249,7 @@ fn rename_mod(
|
|||
if IdentifierKind::Ident != check_identifier(new_name)? {
|
||||
bail!("Invalid name `{0}`: cannot rename module to {0}", new_name);
|
||||
}
|
||||
let mut source_file_edits = Vec::new();
|
||||
let mut source_file_edits = SourceFileEdits::default();
|
||||
let mut file_system_edits = Vec::new();
|
||||
|
||||
let src = module.definition_source(sema.db);
|
||||
|
|
@ -273,11 +272,8 @@ fn rename_mod(
|
|||
if let Some(src) = module.declaration_source(sema.db) {
|
||||
let file_id = src.file_id.original_file(sema.db);
|
||||
let name = src.value.name().unwrap();
|
||||
let edit = SourceFileEdit {
|
||||
file_id,
|
||||
edit: TextEdit::replace(name.syntax().text_range(), new_name.into()),
|
||||
};
|
||||
source_file_edits.push(edit);
|
||||
source_file_edits
|
||||
.insert(file_id, TextEdit::replace(name.syntax().text_range(), new_name.into()));
|
||||
}
|
||||
|
||||
let RangeInfo { range, info: refs } = find_all_refs(sema, position)?;
|
||||
|
|
@ -335,20 +331,13 @@ fn rename_to_self(
|
|||
|
||||
let RangeInfo { range, info: refs } = find_all_refs(sema, position)?;
|
||||
|
||||
let mut edits = refs
|
||||
.references()
|
||||
.iter()
|
||||
.map(|(&file_id, references)| {
|
||||
source_edit_from_references(sema, file_id, references, "self")
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let mut edits = SourceFileEdits::default();
|
||||
edits.extend(refs.references().iter().map(|(&file_id, references)| {
|
||||
source_edit_from_references(sema, file_id, references, "self")
|
||||
}));
|
||||
edits.insert(position.file_id, TextEdit::replace(param_range, String::from(self_param)));
|
||||
|
||||
edits.push(SourceFileEdit {
|
||||
file_id: position.file_id,
|
||||
edit: TextEdit::replace(param_range, String::from(self_param)),
|
||||
});
|
||||
|
||||
Ok(RangeInfo::new(range, SourceChange::from(edits)))
|
||||
Ok(RangeInfo::new(range, edits.into()))
|
||||
}
|
||||
|
||||
fn text_edit_from_self_param(
|
||||
|
|
@ -402,7 +391,7 @@ fn rename_self_to_param(
|
|||
.ok_or_else(|| format_err!("No surrounding method declaration found"))?;
|
||||
let search_range = fn_def.syntax().text_range();
|
||||
|
||||
let mut edits: Vec<SourceFileEdit> = vec![];
|
||||
let mut edits = SourceFileEdits::default();
|
||||
|
||||
for (idx, _) in text.match_indices("self") {
|
||||
let offset: TextSize = idx.try_into().unwrap();
|
||||
|
|
@ -416,7 +405,7 @@ fn rename_self_to_param(
|
|||
} else {
|
||||
TextEdit::replace(usage.text_range(), String::from(new_name))
|
||||
};
|
||||
edits.push(SourceFileEdit { file_id: position.file_id, edit });
|
||||
edits.insert(position.file_id, edit);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -427,7 +416,7 @@ fn rename_self_to_param(
|
|||
let range = ast::SelfParam::cast(self_token.parent())
|
||||
.map_or(self_token.text_range(), |p| p.syntax().text_range());
|
||||
|
||||
Ok(RangeInfo::new(range, SourceChange::from(edits)))
|
||||
Ok(RangeInfo::new(range, edits.into()))
|
||||
}
|
||||
|
||||
fn rename_reference(
|
||||
|
|
@ -464,14 +453,12 @@ fn rename_reference(
|
|||
(IdentifierKind::Ident, _) | (IdentifierKind::Underscore, _) => mark::hit!(rename_ident),
|
||||
}
|
||||
|
||||
let edit = refs
|
||||
.into_iter()
|
||||
.map(|(file_id, references)| {
|
||||
source_edit_from_references(sema, file_id, &references, new_name)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let mut edits = SourceFileEdits::default();
|
||||
edits.extend(refs.into_iter().map(|(file_id, references)| {
|
||||
source_edit_from_references(sema, file_id, &references, new_name)
|
||||
}));
|
||||
|
||||
Ok(RangeInfo::new(range, SourceChange::from(edit)))
|
||||
Ok(RangeInfo::new(range, edits.into()))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
@ -493,9 +480,9 @@ mod tests {
|
|||
Ok(source_change) => {
|
||||
let mut text_edit_builder = TextEdit::builder();
|
||||
let mut file_id: Option<FileId> = None;
|
||||
for edit in source_change.info.source_file_edits {
|
||||
file_id = Some(edit.file_id);
|
||||
for indel in edit.edit.into_iter() {
|
||||
for edit in source_change.info.source_file_edits.edits {
|
||||
file_id = Some(edit.0);
|
||||
for indel in edit.1.into_iter() {
|
||||
text_edit_builder.replace(indel.delete, indel.insert);
|
||||
}
|
||||
}
|
||||
|
|
@ -895,12 +882,11 @@ mod foo$0;
|
|||
RangeInfo {
|
||||
range: 4..7,
|
||||
info: SourceChange {
|
||||
source_file_edits: [
|
||||
SourceFileEdit {
|
||||
file_id: FileId(
|
||||
source_file_edits: SourceFileEdits {
|
||||
edits: {
|
||||
FileId(
|
||||
1,
|
||||
),
|
||||
edit: TextEdit {
|
||||
): TextEdit {
|
||||
indels: [
|
||||
Indel {
|
||||
insert: "foo2",
|
||||
|
|
@ -909,7 +895,7 @@ mod foo$0;
|
|||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
file_system_edits: [
|
||||
MoveFile {
|
||||
src: FileId(
|
||||
|
|
@ -950,12 +936,11 @@ use crate::foo$0::FooContent;
|
|||
RangeInfo {
|
||||
range: 11..14,
|
||||
info: SourceChange {
|
||||
source_file_edits: [
|
||||
SourceFileEdit {
|
||||
file_id: FileId(
|
||||
source_file_edits: SourceFileEdits {
|
||||
edits: {
|
||||
FileId(
|
||||
0,
|
||||
),
|
||||
edit: TextEdit {
|
||||
): TextEdit {
|
||||
indels: [
|
||||
Indel {
|
||||
insert: "quux",
|
||||
|
|
@ -963,12 +948,9 @@ use crate::foo$0::FooContent;
|
|||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
SourceFileEdit {
|
||||
file_id: FileId(
|
||||
FileId(
|
||||
2,
|
||||
),
|
||||
edit: TextEdit {
|
||||
): TextEdit {
|
||||
indels: [
|
||||
Indel {
|
||||
insert: "quux",
|
||||
|
|
@ -977,7 +959,7 @@ use crate::foo$0::FooContent;
|
|||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
file_system_edits: [
|
||||
MoveFile {
|
||||
src: FileId(
|
||||
|
|
@ -1012,12 +994,11 @@ mod fo$0o;
|
|||
RangeInfo {
|
||||
range: 4..7,
|
||||
info: SourceChange {
|
||||
source_file_edits: [
|
||||
SourceFileEdit {
|
||||
file_id: FileId(
|
||||
source_file_edits: SourceFileEdits {
|
||||
edits: {
|
||||
FileId(
|
||||
0,
|
||||
),
|
||||
edit: TextEdit {
|
||||
): TextEdit {
|
||||
indels: [
|
||||
Indel {
|
||||
insert: "foo2",
|
||||
|
|
@ -1026,7 +1007,7 @@ mod fo$0o;
|
|||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
file_system_edits: [
|
||||
MoveFile {
|
||||
src: FileId(
|
||||
|
|
@ -1062,12 +1043,11 @@ mod outer { mod fo$0o; }
|
|||
RangeInfo {
|
||||
range: 16..19,
|
||||
info: SourceChange {
|
||||
source_file_edits: [
|
||||
SourceFileEdit {
|
||||
file_id: FileId(
|
||||
source_file_edits: SourceFileEdits {
|
||||
edits: {
|
||||
FileId(
|
||||
0,
|
||||
),
|
||||
edit: TextEdit {
|
||||
): TextEdit {
|
||||
indels: [
|
||||
Indel {
|
||||
insert: "bar",
|
||||
|
|
@ -1076,7 +1056,7 @@ mod outer { mod fo$0o; }
|
|||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
file_system_edits: [
|
||||
MoveFile {
|
||||
src: FileId(
|
||||
|
|
@ -1135,12 +1115,21 @@ pub mod foo$0;
|
|||
RangeInfo {
|
||||
range: 8..11,
|
||||
info: SourceChange {
|
||||
source_file_edits: [
|
||||
SourceFileEdit {
|
||||
file_id: FileId(
|
||||
source_file_edits: SourceFileEdits {
|
||||
edits: {
|
||||
FileId(
|
||||
0,
|
||||
): TextEdit {
|
||||
indels: [
|
||||
Indel {
|
||||
insert: "foo2",
|
||||
delete: 27..30,
|
||||
},
|
||||
],
|
||||
},
|
||||
FileId(
|
||||
1,
|
||||
),
|
||||
edit: TextEdit {
|
||||
): TextEdit {
|
||||
indels: [
|
||||
Indel {
|
||||
insert: "foo2",
|
||||
|
|
@ -1149,20 +1138,7 @@ pub mod foo$0;
|
|||
],
|
||||
},
|
||||
},
|
||||
SourceFileEdit {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
edit: TextEdit {
|
||||
indels: [
|
||||
Indel {
|
||||
insert: "foo2",
|
||||
delete: 27..30,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
file_system_edits: [
|
||||
MoveFile {
|
||||
src: FileId(
|
||||
|
|
|
|||
|
|
@ -15,8 +15,11 @@
|
|||
|
||||
mod on_enter;
|
||||
|
||||
use ide_db::base_db::{FilePosition, SourceDatabase};
|
||||
use ide_db::{source_change::SourceFileEdit, RootDatabase};
|
||||
use ide_db::{
|
||||
base_db::{FilePosition, SourceDatabase},
|
||||
source_change::SourceFileEdits,
|
||||
RootDatabase,
|
||||
};
|
||||
use syntax::{
|
||||
algo::find_node_at_offset,
|
||||
ast::{self, edit::IndentLevel, AstToken},
|
||||
|
|
@ -56,7 +59,7 @@ pub(crate) fn on_char_typed(
|
|||
let file = &db.parse(position.file_id).tree();
|
||||
assert_eq!(file.syntax().text().char_at(position.offset), Some(char_typed));
|
||||
let edit = on_char_typed_inner(file, position.offset, char_typed)?;
|
||||
Some(SourceFileEdit { file_id: position.file_id, edit }.into())
|
||||
Some(SourceFileEdits::from_text_edit(position.file_id, edit).into())
|
||||
}
|
||||
|
||||
fn on_char_typed_inner(file: &SourceFile, offset: TextSize, char_typed: char) -> Option<TextEdit> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue