Unnamed repository; edit this file 'description' to name the repository.
fix: self type replacement in inline-function
roife 2023-12-13
parent 94af6c6 · commit 3449222
-rw-r--r--crates/ide-assists/src/handlers/inline_call.rs74
1 files changed, 63 insertions, 11 deletions
diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs
index 5b9cc5f66c..5b368c2b40 100644
--- a/crates/ide-assists/src/handlers/inline_call.rs
+++ b/crates/ide-assists/src/handlers/inline_call.rs
@@ -315,17 +315,6 @@ fn inline(
} else {
fn_body.clone_for_update()
};
- if let Some(imp) = body.syntax().ancestors().find_map(ast::Impl::cast) {
- if !node.syntax().ancestors().any(|anc| &anc == imp.syntax()) {
- if let Some(t) = imp.self_ty() {
- body.syntax()
- .descendants_with_tokens()
- .filter_map(NodeOrToken::into_token)
- .filter(|tok| tok.kind() == SyntaxKind::SELF_TYPE_KW)
- .for_each(|tok| ted::replace(tok, t.syntax()));
- }
- }
- }
let usages_for_locals = |local| {
Definition::Local(local)
.usages(sema)
@@ -381,6 +370,25 @@ fn inline(
}
}
+ // We should place the following code after last usage of `usages_for_locals`
+ // because `ted::replace` will change the offset in syntax tree, which makes
+ // `FileReference` incorrect
+ if let Some(imp) = body.syntax().ancestors().find_map(ast::Impl::cast) {
+ if !node.syntax().ancestors().any(|anc| &anc == imp.syntax()) {
+ if let Some(t) = imp.self_ty() {
+ while let Some(self_tok) = body
+ .syntax()
+ .descendants_with_tokens()
+ .filter_map(NodeOrToken::into_token)
+ .find(|tok| tok.kind() == SyntaxKind::SELF_TYPE_KW)
+ {
+ let replace_with = t.clone_subtree().syntax().clone_for_update();
+ ted::replace(self_tok, replace_with);
+ }
+ }
+ }
+ }
+
let mut func_let_vars: BTreeSet<String> = BTreeSet::new();
// grab all of the local variable declarations in the function
@@ -1510,4 +1518,48 @@ fn main() {
"#,
);
}
+
+ #[test]
+ fn inline_call_with_multiple_self_types_eq() {
+ check_assist(
+ inline_call,
+ r#"
+#[derive(PartialEq, Eq)]
+enum Enum {
+ A,
+ B,
+}
+
+impl Enum {
+ fn a_or_b_eq(&self) -> bool {
+ self == &Self::A || self == &Self::B
+ }
+}
+
+fn a() -> bool {
+ Enum::A.$0a_or_b_eq()
+}
+"#,
+ r#"
+#[derive(PartialEq, Eq)]
+enum Enum {
+ A,
+ B,
+}
+
+impl Enum {
+ fn a_or_b_eq(&self) -> bool {
+ self == &Self::A || self == &Self::B
+ }
+}
+
+fn a() -> bool {
+ {
+ let ref this = Enum::A;
+ this == &Enum::A || this == &Enum::B
+ }
+}
+"#,
+ )
+ }
}