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.rs | 42 |
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", |