Make HirFileId, EditionedFileId and macro files Salsa struct

And make more queries non-interned.

Also flip the default for queries, now the default is to not intern and to intern a query you need to say `invoke_interned`.
This commit is contained in:
Chayim Refael Friedman 2025-04-18 12:10:29 +03:00
parent 02ade79631
commit c58ddafe90
195 changed files with 1473 additions and 1525 deletions

View file

@ -1,6 +1,7 @@
//! Suggests shortening `Foo { field: field }` to `Foo { field }` in both
//! expressions and patterns.
use ide_db::RootDatabase;
use ide_db::text_edit::TextEdit;
use ide_db::{EditionedFileId, FileRange, source_change::SourceChange};
use syntax::{AstNode, SyntaxNode, ast, match_ast};
@ -8,20 +9,22 @@ use syntax::{AstNode, SyntaxNode, ast, match_ast};
use crate::{Diagnostic, DiagnosticCode, fix};
pub(crate) fn field_shorthand(
db: &RootDatabase,
acc: &mut Vec<Diagnostic>,
file_id: EditionedFileId,
node: &SyntaxNode,
) {
match_ast! {
match node {
ast::RecordExpr(it) => check_expr_field_shorthand(acc, file_id, it),
ast::RecordPat(it) => check_pat_field_shorthand(acc, file_id, it),
ast::RecordExpr(it) => check_expr_field_shorthand(db, acc, file_id, it),
ast::RecordPat(it) => check_pat_field_shorthand(db, acc, file_id, it),
_ => ()
}
};
}
fn check_expr_field_shorthand(
db: &RootDatabase,
acc: &mut Vec<Diagnostic>,
file_id: EditionedFileId,
record_expr: ast::RecordExpr,
@ -49,16 +52,17 @@ fn check_expr_field_shorthand(
let edit = edit_builder.finish();
let field_range = record_field.syntax().text_range();
let vfs_file_id = file_id.file_id(db);
acc.push(
Diagnostic::new(
DiagnosticCode::Clippy("redundant_field_names"),
"Shorthand struct initialization",
FileRange { file_id: file_id.into(), range: field_range },
FileRange { file_id: vfs_file_id, range: field_range },
)
.with_fixes(Some(vec![fix(
"use_expr_field_shorthand",
"Use struct shorthand initialization",
SourceChange::from_text_edit(file_id, edit),
SourceChange::from_text_edit(vfs_file_id, edit),
field_range,
)])),
);
@ -66,6 +70,7 @@ fn check_expr_field_shorthand(
}
fn check_pat_field_shorthand(
db: &RootDatabase,
acc: &mut Vec<Diagnostic>,
file_id: EditionedFileId,
record_pat: ast::RecordPat,
@ -93,16 +98,17 @@ fn check_pat_field_shorthand(
let edit = edit_builder.finish();
let field_range = record_pat_field.syntax().text_range();
let vfs_file_id = file_id.file_id(db);
acc.push(
Diagnostic::new(
DiagnosticCode::Clippy("redundant_field_names"),
"Shorthand struct pattern",
FileRange { file_id: file_id.into(), range: field_range },
FileRange { file_id: vfs_file_id, range: field_range },
)
.with_fixes(Some(vec![fix(
"use_pat_field_shorthand",
"Use struct field shorthand",
SourceChange::from_text_edit(file_id, edit),
SourceChange::from_text_edit(vfs_file_id, edit),
field_range,
)])),
);

View file

@ -63,7 +63,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::GenericArgsProhibited) -> Option
Some(vec![fix(
"remove_generic_args",
"Remove these generics",
SourceChange::from_text_edit(file_id, TextEdit::delete(range)),
SourceChange::from_text_edit(file_id.file_id(ctx.sema.db), TextEdit::delete(range)),
syntax.syntax().text_range(),
)])
}

View file

@ -128,14 +128,15 @@ pub(crate) fn json_in_items(
state.has_serialize = serialize_resolved.is_some();
state.build_struct("Root", &it);
edit.insert(range.start(), state.result);
let vfs_file_id = file_id.file_id(sema.db);
acc.push(
Diagnostic::new(
DiagnosticCode::Ra("json-is-not-rust", Severity::WeakWarning),
"JSON syntax is not valid as a Rust item",
FileRange { file_id: file_id.into(), range },
FileRange { file_id: vfs_file_id, range },
)
.with_fixes(Some(vec![{
let mut scb = SourceChangeBuilder::new(file_id);
let mut scb = SourceChangeBuilder::new(vfs_file_id);
let scope = match import_scope {
ImportScope::File(it) => ImportScope::File(scb.make_mut(it)),
ImportScope::Module(it) => ImportScope::Module(scb.make_mut(it)),
@ -183,7 +184,7 @@ pub(crate) fn json_in_items(
}
}
let mut sc = scb.finish();
sc.insert_source_edit(file_id, edit.finish());
sc.insert_source_edit(vfs_file_id, edit.finish());
fix("convert_json_to_struct", "Convert JSON to struct", sc, range)
}])),
);

View file

@ -1,6 +1,6 @@
use either::Either;
use hir::{
AssocItem, HirDisplay, HirFileIdExt, ImportPathConfig, InFile, Type,
AssocItem, HirDisplay, ImportPathConfig, InFile, Type,
db::{ExpandDatabase, HirDatabase},
sym,
};
@ -85,7 +85,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
Some(vec![fix(
"fill_missing_fields",
"Fill struct fields",
SourceChange::from_text_edit(range.file_id, edit),
SourceChange::from_text_edit(range.file_id.file_id(ctx.sema.db), edit),
range.range,
)])
};
@ -207,7 +207,10 @@ fn get_default_constructor(
}
}
let krate = ctx.sema.file_to_module_def(d.file.original_file(ctx.sema.db))?.krate();
let krate = ctx
.sema
.file_to_module_def(d.file.original_file(ctx.sema.db).file_id(ctx.sema.db))?
.krate();
let module = krate.root_module();
// Look for a ::new() associated function

View file

@ -1,5 +1,5 @@
use hir::db::ExpandDatabase;
use hir::{HirFileIdExt, UnsafeLint, UnsafetyReason};
use hir::{UnsafeLint, UnsafetyReason};
use ide_db::text_edit::TextEdit;
use ide_db::{assists::Assist, source_change::SourceChange};
use syntax::{AstNode, match_ast};
@ -51,8 +51,10 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingUnsafe) -> Option<Vec<Ass
let replacement = format!("unsafe {{ {} }}", node_to_add_unsafe_block.text());
let edit = TextEdit::replace(node_to_add_unsafe_block.text_range(), replacement);
let source_change =
SourceChange::from_text_edit(d.node.file_id.original_file(ctx.sema.db), edit);
let source_change = SourceChange::from_text_edit(
d.node.file_id.original_file(ctx.sema.db).file_id(ctx.sema.db),
edit,
);
Some(vec![fix("add_unsafe", "Add unsafe block", source_change, expr.syntax().text_range())])
}

View file

@ -39,7 +39,7 @@ pub(crate) fn need_mut(ctx: &DiagnosticsContext<'_>, d: &hir::NeedMut) -> Option
Some(vec![fix(
"add_mut",
"Change it to be mutable",
SourceChange::from_text_edit(file_id, edit),
SourceChange::from_text_edit(file_id.file_id(ctx.sema.db), edit),
use_range,
)])
})();
@ -82,7 +82,7 @@ pub(crate) fn unused_mut(ctx: &DiagnosticsContext<'_>, d: &hir::UnusedMut) -> Op
Some(vec![fix(
"remove_mut",
"Remove unnecessary `mut`",
SourceChange::from_text_edit(file_id, edit),
SourceChange::from_text_edit(file_id.file_id(ctx.sema.db), edit),
use_range,
)])
})();

View file

@ -1,5 +1,5 @@
use either::Either;
use hir::{HasSource, HirDisplay, HirFileIdExt, Semantics, VariantId, db::ExpandDatabase};
use hir::{HasSource, HirDisplay, Semantics, VariantId, db::ExpandDatabase};
use ide_db::text_edit::TextEdit;
use ide_db::{EditionedFileId, RootDatabase, source_change::SourceChange};
use syntax::{
@ -108,7 +108,7 @@ fn missing_record_expr_field_fixes(
}
let source_change = SourceChange::from_text_edit(
def_file_id,
def_file_id.file_id(sema.db),
TextEdit::insert(last_field_syntax.text_range().end(), new_field),
);

View file

@ -49,7 +49,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &RemoveTrailingReturn) -> Option<Vec<A
let replacement =
return_expr.expr().map_or_else(String::new, |expr| format!("{}", expr.syntax().text()));
let edit = TextEdit::replace(range, replacement);
let source_change = SourceChange::from_text_edit(file_id, edit);
let source_change = SourceChange::from_text_edit(file_id.file_id(ctx.sema.db), edit);
Some(vec![fix(
"remove_trailing_return",

View file

@ -1,4 +1,4 @@
use hir::{HirFileIdExt, db::ExpandDatabase, diagnostics::RemoveUnnecessaryElse};
use hir::{db::ExpandDatabase, diagnostics::RemoveUnnecessaryElse};
use ide_db::text_edit::TextEdit;
use ide_db::{assists::Assist, source_change::SourceChange};
use itertools::Itertools;
@ -90,8 +90,10 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &RemoveUnnecessaryElse) -> Option<Vec<
};
let edit = TextEdit::replace(range, replacement);
let source_change =
SourceChange::from_text_edit(d.if_expr.file_id.original_file(ctx.sema.db), edit);
let source_change = SourceChange::from_text_edit(
d.if_expr.file_id.original_file(ctx.sema.db).file_id(ctx.sema.db),
edit,
);
Some(vec![fix(
"remove_unnecessary_else",

View file

@ -1,4 +1,4 @@
use hir::{HirFileIdExt, InFile, db::ExpandDatabase};
use hir::{InFile, db::ExpandDatabase};
use ide_db::source_change::SourceChange;
use ide_db::text_edit::TextEdit;
use syntax::{
@ -43,7 +43,8 @@ fn fixes(
let edit = TextEdit::replace(range_to_replace, replacement);
let source_change = SourceChange::from_text_edit(d.file.original_file(ctx.sema.db), edit);
let source_change =
SourceChange::from_text_edit(d.file.original_file(ctx.sema.db).file_id(ctx.sema.db), edit);
Some(vec![fix(
"replace_with_find_map",

View file

@ -54,10 +54,12 @@ pub(crate) fn trait_impl_redundant_assoc_item(
}
};
let hir::FileRange { file_id, range } =
hir::InFile::new(d.file_id, diagnostic_range).original_node_file_range_rooted(db);
Diagnostic::new(
DiagnosticCode::RustcHardError("E0407"),
format!("{redundant_item_name} is not a member of trait `{trait_name}`"),
hir::InFile::new(d.file_id, diagnostic_range).original_node_file_range_rooted(db),
ide_db::FileRange { file_id: file_id.file_id(ctx.sema.db), range },
)
.with_fixes(quickfix_for_redundant_assoc_item(
ctx,
@ -93,7 +95,7 @@ fn quickfix_for_redundant_assoc_item(
Some(())
};
let file_id = d.file_id.file_id()?;
let mut source_change_builder = SourceChangeBuilder::new(file_id);
let mut source_change_builder = SourceChangeBuilder::new(file_id.file_id(ctx.sema.db));
add_assoc_item_def(&mut source_change_builder)?;
Some(vec![Assist {

View file

@ -1,5 +1,5 @@
use either::Either;
use hir::{CallableKind, ClosureStyle, HirDisplay, HirFileIdExt, InFile, db::ExpandDatabase};
use hir::{CallableKind, ClosureStyle, HirDisplay, InFile, db::ExpandDatabase};
use ide_db::{
famous_defs::FamousDefs,
source_change::{SourceChange, SourceChangeBuilder},
@ -150,7 +150,7 @@ fn add_missing_ok_or_some(
}
let source_change = SourceChange::from_text_edit(
expr_ptr.file_id.original_file(ctx.sema.db),
expr_ptr.file_id.original_file(ctx.sema.db).file_id(ctx.sema.db),
builder.finish(),
);
let name = format!("Insert {variant_name}(()) as the tail of this block");
@ -164,7 +164,7 @@ fn add_missing_ok_or_some(
builder
.insert(ret_expr.syntax().text_range().end(), format!(" {variant_name}(())"));
let source_change = SourceChange::from_text_edit(
expr_ptr.file_id.original_file(ctx.sema.db),
expr_ptr.file_id.original_file(ctx.sema.db).file_id(ctx.sema.db),
builder.finish(),
);
let name = format!("Insert {variant_name}(()) as the return value");
@ -177,8 +177,10 @@ fn add_missing_ok_or_some(
let mut builder = TextEdit::builder();
builder.insert(expr.syntax().text_range().start(), format!("{variant_name}("));
builder.insert(expr.syntax().text_range().end(), ")".to_owned());
let source_change =
SourceChange::from_text_edit(expr_ptr.file_id.original_file(ctx.sema.db), builder.finish());
let source_change = SourceChange::from_text_edit(
expr_ptr.file_id.original_file(ctx.sema.db).file_id(ctx.sema.db),
builder.finish(),
);
let name = format!("Wrap in {variant_name}");
acc.push(fix("wrap_in_constructor", &name, source_change, expr_range));
Some(())
@ -220,7 +222,7 @@ fn remove_unnecessary_wrapper(
let inner_arg = call_expr.arg_list()?.args().next()?;
let file_id = expr_ptr.file_id.original_file(db);
let mut builder = SourceChangeBuilder::new(file_id);
let mut builder = SourceChangeBuilder::new(file_id.file_id(ctx.sema.db));
let mut editor;
match inner_arg {
// We're returning `()`
@ -256,7 +258,7 @@ fn remove_unnecessary_wrapper(
}
}
builder.add_file_edits(file_id, editor);
builder.add_file_edits(file_id.file_id(ctx.sema.db), editor);
let name = format!("Remove unnecessary {}() wrapper", variant.name(db).as_str());
acc.push(fix(
"remove_unnecessary_wrapper",
@ -288,8 +290,10 @@ fn remove_semicolon(
let semicolon_range = expr_before_semi.semicolon_token()?.text_range();
let edit = TextEdit::delete(semicolon_range);
let source_change =
SourceChange::from_text_edit(expr_ptr.file_id.original_file(ctx.sema.db), edit);
let source_change = SourceChange::from_text_edit(
expr_ptr.file_id.original_file(ctx.sema.db).file_id(ctx.sema.db),
edit,
);
acc.push(fix("remove_semicolon", "Remove this semicolon", source_change, semicolon_range));
Some(())
@ -316,8 +320,10 @@ fn str_ref_to_owned(
let to_owned = ".to_owned()".to_owned();
let edit = TextEdit::insert(expr.syntax().text_range().end(), to_owned);
let source_change =
SourceChange::from_text_edit(expr_ptr.file_id.original_file(ctx.sema.db), edit);
let source_change = SourceChange::from_text_edit(
expr_ptr.file_id.original_file(ctx.sema.db).file_id(ctx.sema.db),
edit,
);
acc.push(fix("str_ref_to_owned", "Add .to_owned() here", source_change, expr_range));
Some(())

View file

@ -83,7 +83,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option<Vec<Assist>
group: Some(GroupLabel("Replace `_` with a term".to_owned())),
target: original_range.range,
source_change: Some(SourceChange::from_text_edit(
original_range.file_id,
original_range.file_id.file_id(ctx.sema.db),
TextEdit::replace(original_range.range, code),
)),
command: None,

View file

@ -105,7 +105,8 @@ fn fixes(
let root_module = &crate_def_map[DefMap::ROOT];
let Some(root_file_id) = root_module.origin.file_id() else { continue };
let Some(crate_root_path) = source_root.path_for_file(&root_file_id.file_id()) else {
let Some(crate_root_path) = source_root.path_for_file(&root_file_id.file_id(ctx.sema.db))
else {
continue;
};
let Some(rel) = parent.strip_prefix(&crate_root_path.parent()?) else { continue };
@ -131,7 +132,12 @@ fn fixes(
let InFile { file_id: parent_file_id, value: source } =
current.definition_source(ctx.sema.db);
let parent_file_id = parent_file_id.file_id()?;
return make_fixes(parent_file_id.file_id(), source, &module_name, trigger_range);
return make_fixes(
parent_file_id.file_id(ctx.sema.db),
source,
&module_name,
trigger_range,
);
}
// if we aren't adding to a crate root, walk backwards such that we support `#[path = ...]` overrides if possible
@ -152,7 +158,8 @@ fn fixes(
'crates: for &krate in relevant_crates.iter() {
let crate_def_map = ctx.sema.db.crate_def_map(krate);
let Some((_, module)) = crate_def_map.modules().find(|(_, module)| {
module.origin.file_id().map(Into::into) == Some(parent_id) && !module.origin.is_inline()
module.origin.file_id().map(|file_id| file_id.file_id(ctx.sema.db)) == Some(parent_id)
&& !module.origin.is_inline()
}) else {
continue;
};
@ -182,7 +189,12 @@ fn fixes(
let InFile { file_id: parent_file_id, value: source } =
current.definition_source(ctx.sema.db);
let parent_file_id = parent_file_id.file_id()?;
return make_fixes(parent_file_id.file_id(), source, &module_name, trigger_range);
return make_fixes(
parent_file_id.file_id(ctx.sema.db),
source,
&module_name,
trigger_range,
);
}
}

View file

@ -119,7 +119,7 @@ fn add_variant_to_union(
let (offset, record_field) =
record_field_layout(None, field_name, suggested_type, field_list, adt_syntax.value)?;
let mut src_change_builder = SourceChangeBuilder::new(range.file_id);
let mut src_change_builder = SourceChangeBuilder::new(range.file_id.file_id(ctx.sema.db));
src_change_builder.insert(offset, record_field);
Some(Assist {
id: AssistId::quick_fix("add-variant-to-union"),
@ -165,7 +165,8 @@ fn add_field_to_struct_fix(
struct_syntax.value,
)?;
let mut src_change_builder = SourceChangeBuilder::new(struct_range.file_id);
let mut src_change_builder =
SourceChangeBuilder::new(struct_range.file_id.file_id(ctx.sema.db));
// FIXME: Allow for choosing a visibility modifier see https://github.com/rust-lang/rust-analyzer/issues/11563
src_change_builder.insert(offset, record_field);
@ -180,7 +181,8 @@ fn add_field_to_struct_fix(
}
None => {
// Add a field list to the Unit Struct
let mut src_change_builder = SourceChangeBuilder::new(struct_range.file_id);
let mut src_change_builder =
SourceChangeBuilder::new(struct_range.file_id.file_id(ctx.sema.db));
let field_name = match field_name.chars().next() {
// FIXME : See match arm below regarding tuple structs.
Some(ch) if ch.is_numeric() => return None,
@ -270,7 +272,7 @@ fn method_fix(
group: None,
target: range,
source_change: Some(SourceChange::from_text_edit(
file_id,
file_id.file_id(ctx.sema.db),
TextEdit::insert(range.end(), "()".to_owned()),
)),
command: None,

View file

@ -101,8 +101,8 @@ fn field_fix(
group: None,
target: range,
source_change: Some(SourceChange::from_iter([
(file_id.into(), TextEdit::insert(range.start(), "(".to_owned())),
(file_id.into(), TextEdit::insert(range.end(), ")".to_owned())),
(file_id.file_id(ctx.sema.db), TextEdit::insert(range.start(), "(".to_owned())),
(file_id.file_id(ctx.sema.db), TextEdit::insert(range.end(), ")".to_owned())),
])),
command: None,
})
@ -182,7 +182,7 @@ fn assoc_func_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) -
group: None,
target: range,
source_change: Some(SourceChange::from_text_edit(
file_id,
file_id.file_id(ctx.sema.db),
TextEdit::replace(range, assoc_func_call_expr_string),
)),
command: None,

View file

@ -1,4 +1,4 @@
use hir::{HirFileIdExt, db::ExpandDatabase};
use hir::db::ExpandDatabase;
use ide_db::{assists::Assist, base_db::AnchoredPathBuf, source_change::FileSystemEdit};
use itertools::Itertools;
use syntax::AstNode;
@ -43,7 +43,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedModule) -> Option<Vec<
&format!("Create module at `{candidate}`"),
FileSystemEdit::CreateFile {
dst: AnchoredPathBuf {
anchor: d.decl.file_id.original_file(ctx.sema.db).file_id(),
anchor: d.decl.file_id.original_file(ctx.sema.db).file_id(ctx.sema.db),
path: candidate.clone(),
},
initial_contents: "".to_owned(),

View file

@ -46,7 +46,7 @@ pub(crate) fn unused_variables(
ctx.sema.db,
var_name,
it.range,
diagnostic_range.into(),
diagnostic_range,
ast.file_id.is_macro(),
ctx.edition,
)

View file

@ -1,4 +1,5 @@
use hir::InFile;
use ide_db::RootDatabase;
use ide_db::text_edit::TextEdit;
use ide_db::{EditionedFileId, FileRange, source_change::SourceChange};
use itertools::Itertools;
@ -10,6 +11,7 @@ use crate::{Diagnostic, DiagnosticCode, fix};
//
// Diagnostic for unnecessary braces in `use` items.
pub(crate) fn useless_braces(
db: &RootDatabase,
acc: &mut Vec<Diagnostic>,
file_id: EditionedFileId,
node: &SyntaxNode,
@ -38,13 +40,13 @@ pub(crate) fn useless_braces(
Diagnostic::new(
DiagnosticCode::RustcLint("unused_braces"),
"Unnecessary braces in use statement".to_owned(),
FileRange { file_id: file_id.into(), range: use_range },
FileRange { file_id: file_id.file_id(db), range: use_range },
)
.with_main_node(InFile::new(file_id.into(), SyntaxNodePtr::new(node)))
.with_fixes(Some(vec![fix(
"remove_braces",
"Remove unnecessary braces",
SourceChange::from_text_edit(file_id, edit),
SourceChange::from_text_edit(file_id.file_id(db), edit),
use_range,
)])),
);