diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs b/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs index 7d5070ace619..636acf3f0088 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs @@ -9,6 +9,7 @@ use ide_db::{ SnippetCap, assists::ExprFillDefaultMode, imports::{import_assets::ImportPathConfig, insert_use::InsertUseConfig}, + rename::RenameConfig, }; use crate::AssistKind; @@ -27,6 +28,7 @@ pub struct AssistConfig { pub code_action_grouping: bool, pub expr_fill_default: ExprFillDefaultMode, pub prefer_self_ty: bool, + pub show_rename_conflicts: bool, } impl AssistConfig { @@ -46,4 +48,8 @@ impl AssistConfig { allow_unstable, } } + + pub fn rename_config(&self) -> RenameConfig { + RenameConfig { show_conflicts: self.show_rename_conflicts } + } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_underscore.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_underscore.rs index a8e27416d5ce..1de1c15cf720 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_underscore.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_underscore.rs @@ -62,7 +62,9 @@ pub(crate) fn remove_underscore(acc: &mut Assists, ctx: &AssistContext<'_>) -> O "Remove underscore from a used variable", text_range, |builder| { - let changes = def.rename(&ctx.sema, new_name, RenameDefinition::Yes).unwrap(); + let changes = def + .rename(&ctx.sema, new_name, RenameDefinition::Yes, &ctx.config.rename_config()) + .unwrap(); builder.source_change = changes; }, ) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs index ade60691b57b..112619119269 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs @@ -38,6 +38,7 @@ pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig { code_action_grouping: true, expr_fill_default: ExprFillDefaultMode::Todo, prefer_self_ty: false, + show_rename_conflicts: true, }; pub(crate) const TEST_CONFIG_NO_GROUPING: AssistConfig = AssistConfig { @@ -59,6 +60,7 @@ pub(crate) const TEST_CONFIG_NO_GROUPING: AssistConfig = AssistConfig { code_action_grouping: false, expr_fill_default: ExprFillDefaultMode::Todo, prefer_self_ty: false, + show_rename_conflicts: true, }; pub(crate) const TEST_CONFIG_NO_SNIPPET_CAP: AssistConfig = AssistConfig { @@ -80,6 +82,7 @@ pub(crate) const TEST_CONFIG_NO_SNIPPET_CAP: AssistConfig = AssistConfig { code_action_grouping: true, expr_fill_default: ExprFillDefaultMode::Todo, prefer_self_ty: false, + show_rename_conflicts: true, }; pub(crate) const TEST_CONFIG_IMPORT_ONE: AssistConfig = AssistConfig { @@ -101,6 +104,7 @@ pub(crate) const TEST_CONFIG_IMPORT_ONE: AssistConfig = AssistConfig { code_action_grouping: true, expr_fill_default: ExprFillDefaultMode::Todo, prefer_self_ty: false, + show_rename_conflicts: true, }; fn assists( diff --git a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs index a8800c142a22..aeb7c06582bc 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs @@ -45,6 +45,11 @@ use crate::{ traits::convert_to_def_in_trait, }; +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct RenameConfig { + pub show_conflicts: bool, +} + pub type Result = std::result::Result; #[derive(Debug)] @@ -81,6 +86,7 @@ impl Definition { sema: &Semantics<'_, RootDatabase>, new_name: &str, rename_definition: RenameDefinition, + config: &RenameConfig, ) -> Result { // self.krate() returns None if // self is a built-in attr, built-in type or tool module. @@ -109,10 +115,15 @@ impl Definition { bail!("Cannot rename a builtin attr.") } Definition::SelfType(_) => bail!("Cannot rename `Self`"), - Definition::Macro(mac) => { - rename_reference(sema, Definition::Macro(mac), new_name, rename_definition, edition) - } - def => rename_reference(sema, def, new_name, rename_definition, edition), + Definition::Macro(mac) => rename_reference( + sema, + Definition::Macro(mac), + new_name, + rename_definition, + edition, + config, + ), + def => rename_reference(sema, def, new_name, rename_definition, edition, config), } } @@ -338,6 +349,7 @@ fn rename_reference( new_name: &str, rename_definition: RenameDefinition, edition: Edition, + config: &RenameConfig, ) -> Result { let (mut new_name, ident_kind) = IdentifierKind::classify(edition, new_name)?; @@ -396,7 +408,8 @@ fn rename_reference( if rename_definition == RenameDefinition::Yes { // This needs to come after the references edits, because we change the annotation of existing edits // if a conflict is detected. - let (file_id, edit) = source_edit_from_def(sema, def, &new_name, &mut source_change)?; + let (file_id, edit) = + source_edit_from_def(sema, config, def, &new_name, &mut source_change)?; source_change.insert_source_edit(file_id, edit); } Ok(source_change) @@ -554,6 +567,7 @@ fn source_edit_from_name_ref( fn source_edit_from_def( sema: &Semantics<'_, RootDatabase>, + config: &RenameConfig, def: Definition, new_name: &Name, source_change: &mut SourceChange, @@ -562,21 +576,22 @@ fn source_edit_from_def( if let Definition::Local(local) = def { let mut file_id = None; - let conflict_annotation = if !sema.rename_conflicts(&local, new_name).is_empty() { - Some( - source_change.insert_annotation(ChangeAnnotation { - label: "This rename will change the program's meaning".to_owned(), - needs_confirmation: true, - description: Some( - "Some variable(s) will shadow the renamed variable \ + let conflict_annotation = + if config.show_conflicts && !sema.rename_conflicts(&local, new_name).is_empty() { + Some( + source_change.insert_annotation(ChangeAnnotation { + label: "This rename will change the program's meaning".to_owned(), + needs_confirmation: true, + description: Some( + "Some variable(s) will shadow the renamed variable \ or be shadowed by it if the rename is performed" - .to_owned(), - ), - }), - ) - } else { - None - }; + .to_owned(), + ), + }), + ) + } else { + None + }; for source in local.sources(sema.db) { let source = match source.source.clone().original_ast_node_rooted(sema.db) { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs index 519ff192799d..f52e575133fb 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs @@ -44,7 +44,12 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::IncorrectCase) -> Option RenameConfig { + RenameConfig { show_conflicts: self.show_rename_conflicts } + } } struct DiagnosticsContext<'a> { diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs index ece5bac6df4b..0cb0d33259df 100644 --- a/src/tools/rust-analyzer/crates/ide/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs @@ -846,8 +846,9 @@ impl Analysis { &self, file_id: FileId, new_name_stem: &str, + config: &RenameConfig, ) -> Cancellable> { - self.with_db(|db| rename::will_rename_file(db, file_id, new_name_stem)) + self.with_db(|db| rename::will_rename_file(db, file_id, new_name_stem, config)) } pub fn structural_search_replace( diff --git a/src/tools/rust-analyzer/crates/ide/src/rename.rs b/src/tools/rust-analyzer/crates/ide/src/rename.rs index ce5963919d9a..59343f494a02 100644 --- a/src/tools/rust-analyzer/crates/ide/src/rename.rs +++ b/src/tools/rust-analyzer/crates/ide/src/rename.rs @@ -31,6 +31,7 @@ pub struct RenameConfig { pub prefer_no_std: bool, pub prefer_prelude: bool, pub prefer_absolute: bool, + pub show_conflicts: bool, } impl RenameConfig { @@ -42,6 +43,10 @@ impl RenameConfig { allow_unstable: true, } } + + fn ide_db_config(&self) -> ide_db::rename::RenameConfig { + ide_db::rename::RenameConfig { show_conflicts: self.show_conflicts } + } } /// This is similar to `collect::, _>>`, but unlike it, it succeeds if there is *any* `Ok` item. @@ -190,7 +195,7 @@ pub(crate) fn rename( return rename_to_self(&sema, local); } } - def.rename(&sema, new_name.as_str(), rename_def) + def.rename(&sema, new_name.as_str(), rename_def, &config.ide_db_config()) })), }; @@ -205,11 +210,13 @@ pub(crate) fn will_rename_file( db: &RootDatabase, file_id: FileId, new_name_stem: &str, + config: &RenameConfig, ) -> Option { let sema = Semantics::new(db); let module = sema.file_to_module_def(file_id)?; let def = Definition::Module(module); - let mut change = def.rename(&sema, new_name_stem, RenameDefinition::Yes).ok()?; + let mut change = + def.rename(&sema, new_name_stem, RenameDefinition::Yes, &config.ide_db_config()).ok()?; change.file_system_edits.clear(); Some(change) } @@ -803,8 +810,12 @@ mod tests { use super::{RangeInfo, RenameConfig, RenameError}; - const TEST_CONFIG: RenameConfig = - RenameConfig { prefer_no_std: false, prefer_prelude: true, prefer_absolute: false }; + const TEST_CONFIG: RenameConfig = RenameConfig { + prefer_no_std: false, + prefer_prelude: true, + prefer_absolute: false, + show_conflicts: true, + }; #[track_caller] fn check( @@ -893,7 +904,7 @@ mod tests { ) { let (analysis, position) = fixture::position(ra_fixture); let source_change = analysis - .will_rename_file(position.file_id, new_name) + .will_rename_file(position.file_id, new_name, &TEST_CONFIG) .unwrap() .expect("Expect returned a RenameError"); expect.assert_eq(&filter_expect(source_change)) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index de24bc09ff0f..9d3756e64103 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -1153,6 +1153,7 @@ impl flags::AnalysisStats { style_lints: false, term_search_fuel: 400, term_search_borrowck: true, + show_rename_conflicts: true, }, ide::AssistResolveStrategy::All, analysis.editioned_file_id_to_vfs(file_id), diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 6d2907ee56aa..295e45352728 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -707,6 +707,9 @@ config_data! { /// /// E.g. `use ::std::io::Read;`. imports_prefixExternPrelude: bool = false, + + /// Whether to warn when a rename will cause conflicts (change the meaning of the code). + rename_showConflicts: bool = true, } } @@ -1702,6 +1705,7 @@ impl Config { ExprFillDefaultDef::Underscore => ExprFillDefaultMode::Underscore, }, prefer_self_ty: *self.assist_preferSelf(source_root), + show_rename_conflicts: *self.rename_showConflicts(source_root), } } @@ -1710,6 +1714,7 @@ impl Config { prefer_no_std: self.imports_preferNoStd(source_root).to_owned(), prefer_prelude: self.imports_preferPrelude(source_root).to_owned(), prefer_absolute: self.imports_prefixExternPrelude(source_root).to_owned(), + show_conflicts: *self.rename_showConflicts(source_root), } } @@ -1809,6 +1814,7 @@ impl Config { style_lints: self.diagnostics_styleLints_enable(source_root).to_owned(), term_search_fuel: self.assist_termSearch_fuel(source_root).to_owned() as u64, term_search_borrowck: self.assist_termSearch_borrowcheck(source_root).to_owned(), + show_rename_conflicts: *self.rename_showConflicts(source_root), } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index 2976441d762a..773729be78b3 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -787,7 +787,11 @@ pub(crate) fn handle_will_rename_files( } }) .filter_map(|(file_id, new_name)| { - snap.analysis.will_rename_file(file_id?, &new_name).ok()? + let file_id = file_id?; + let source_root = snap.analysis.source_root_id(file_id).ok(); + snap.analysis + .will_rename_file(file_id, &new_name, &snap.config.rename(source_root)) + .ok()? }) .collect(); diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs index 38ee9cbe7fc8..c61825b99fec 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs @@ -363,6 +363,7 @@ fn integrated_diagnostics_benchmark() { prefer_absolute: false, term_search_fuel: 400, term_search_borrowck: true, + show_rename_conflicts: true, }; host.analysis() .full_diagnostics(&diagnostics_config, ide::AssistResolveStrategy::None, file_id) diff --git a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md index d768993f501f..227282f192bd 100644 --- a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md +++ b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md @@ -1303,6 +1303,13 @@ Default: `false` Exclude tests from find-all-references and call-hierarchy. +## rust-analyzer.rename.showConflicts {#rename.showConflicts} + +Default: `true` + +Whether to warn when a rename will cause conflicts (change the meaning of the code). + + ## rust-analyzer.runnables.command {#runnables.command} Default: `null` diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index d659421a0299..f0414c962295 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -2769,6 +2769,16 @@ } } }, + { + "title": "Rename", + "properties": { + "rust-analyzer.rename.showConflicts": { + "markdownDescription": "Whether to warn when a rename will cause conflicts (change the meaning of the code).", + "default": true, + "type": "boolean" + } + } + }, { "title": "Runnables", "properties": {