Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-diagnostics/src/handlers/unlinked_file.rs')
-rw-r--r--crates/ide-diagnostics/src/handlers/unlinked_file.rs42
1 files changed, 25 insertions, 17 deletions
diff --git a/crates/ide-diagnostics/src/handlers/unlinked_file.rs b/crates/ide-diagnostics/src/handlers/unlinked_file.rs
index 77ffd0fd96..1b71a3a3e6 100644
--- a/crates/ide-diagnostics/src/handlers/unlinked_file.rs
+++ b/crates/ide-diagnostics/src/handlers/unlinked_file.rs
@@ -4,14 +4,14 @@ use std::iter;
use hir::{db::DefDatabase, DefMap, InFile, ModuleSource};
use ide_db::{
- base_db::{FileId, FileLoader, FileRange, SourceDatabase, SourceDatabaseExt},
+ base_db::{FileLoader, SourceDatabaseExt},
source_change::SourceChange,
- RootDatabase,
+ FileId, FileRange, LineIndexDatabase,
};
use paths::Utf8Component;
use syntax::{
ast::{self, edit::IndentLevel, HasModuleItem, HasName},
- AstNode, TextRange,
+ AstNode, TextRange, ToSmolStr,
};
use text_edit::TextEdit;
@@ -26,7 +26,8 @@ pub(crate) fn unlinked_file(
acc: &mut Vec<Diagnostic>,
file_id: FileId,
) {
- let fixes = fixes(ctx, file_id);
+ let mut range = TextRange::up_to(ctx.sema.db.line_index(file_id).len());
+ let fixes = fixes(ctx, file_id, range);
// FIXME: This is a hack for the vscode extension to notice whether there is an autofix or not before having to resolve diagnostics.
// This is to prevent project linking popups from appearing when there is an autofix. https://github.com/rust-lang/rust-analyzer/issues/14523
let message = if fixes.is_none() {
@@ -37,7 +38,6 @@ pub(crate) fn unlinked_file(
let message = format!("{message}\n\nIf you're intentionally working on unowned files, you can silence this warning by adding \"unlinked-file\" to rust-analyzer.diagnostics.disabled in your settings.");
- let mut range = ctx.sema.db.parse(file_id).syntax_node().text_range();
let mut unused = true;
if fixes.is_none() {
@@ -70,7 +70,11 @@ pub(crate) fn unlinked_file(
);
}
-fn fixes(ctx: &DiagnosticsContext<'_>, file_id: FileId) -> Option<Vec<Assist>> {
+fn fixes(
+ ctx: &DiagnosticsContext<'_>,
+ file_id: FileId,
+ trigger_range: TextRange,
+) -> Option<Vec<Assist>> {
// If there's an existing module that could add `mod` or `pub mod` items to include the unlinked file,
// suggest that as a fix.
@@ -94,7 +98,9 @@ fn fixes(ctx: &DiagnosticsContext<'_>, file_id: FileId) -> Option<Vec<Assist>> {
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) else { continue };
+ let Some(crate_root_path) = source_root.path_for_file(&root_file_id.file_id()) else {
+ continue;
+ };
let Some(rel) = parent.strip_prefix(&crate_root_path.parent()?) else { continue };
// try resolving the relative difference of the paths as inline modules
@@ -106,7 +112,8 @@ fn fixes(ctx: &DiagnosticsContext<'_>, file_id: FileId) -> Option<Vec<Assist>> {
// shouldn't occur
_ => continue 'crates,
};
- match current.children.iter().find(|(name, _)| name.to_smol_str() == seg) {
+ match current.children.iter().find(|(name, _)| name.display_no_db().to_smolstr() == seg)
+ {
Some((_, &child)) => current = &crate_def_map[child],
None => continue 'crates,
}
@@ -118,7 +125,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, file_id: FileId) -> Option<Vec<Assist>> {
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(ctx.sema.db, parent_file_id, source, &module_name, file_id);
+ return make_fixes(parent_file_id.file_id(), source, &module_name, trigger_range);
}
// if we aren't adding to a crate root, walk backwards such that we support `#[path = ...]` overrides if possible
@@ -138,25 +145,28 @@ fn fixes(ctx: &DiagnosticsContext<'_>, file_id: FileId) -> Option<Vec<Assist>> {
'crates: for &krate in ctx.sema.db.relevant_crates(parent_id).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() == Some(parent_id) && !module.origin.is_inline()
+ module.origin.file_id().map(Into::into) == Some(parent_id) && !module.origin.is_inline()
}) else {
continue;
};
if stack.is_empty() {
return make_fixes(
- ctx.sema.db,
parent_id,
module.definition_source(ctx.sema.db).value,
&module_name,
- file_id,
+ trigger_range,
);
} else {
// direct parent file is missing,
// try finding a parent that has an inline tree from here on
let mut current = module;
for s in stack.iter().rev() {
- match module.children.iter().find(|(name, _)| name.to_smol_str() == s) {
+ match module
+ .children
+ .iter()
+ .find(|(name, _)| name.display_no_db().to_smolstr() == s)
+ {
Some((_, child)) => {
current = &crate_def_map[*child];
}
@@ -169,7 +179,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, file_id: FileId) -> Option<Vec<Assist>> {
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(ctx.sema.db, parent_file_id, source, &module_name, file_id);
+ return make_fixes(parent_file_id.file_id(), source, &module_name, trigger_range);
}
}
@@ -177,11 +187,10 @@ fn fixes(ctx: &DiagnosticsContext<'_>, file_id: FileId) -> Option<Vec<Assist>> {
}
fn make_fixes(
- db: &RootDatabase,
parent_file_id: FileId,
source: ModuleSource,
new_mod_name: &str,
- added_file_id: FileId,
+ trigger_range: TextRange,
) -> Option<Vec<Assist>> {
fn is_outline_mod(item: &ast::Item) -> bool {
matches!(item, ast::Item::Module(m) if m.item_list().is_none())
@@ -252,7 +261,6 @@ fn make_fixes(
}
}
- let trigger_range = db.parse(added_file_id).tree().syntax().text_range();
Some(vec![
fix(
"add_mod_declaration",