Skip to content

Commit f360d6c

Browse files
authored
Merge pull request #20351 from ChayimFriedman2/rename-self1
feat: When renaming a parameter to `self`, change callers to use method call syntax
2 parents 4c6e804 + ac34f3d commit f360d6c

File tree

11 files changed

+186
-25
lines changed

11 files changed

+186
-25
lines changed

src/tools/rust-analyzer/crates/base-db/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ impl EditionedFileId {
206206

207207
#[salsa_macros::input(debug)]
208208
pub struct FileText {
209+
#[returns(ref)]
209210
pub text: Arc<str>,
210211
pub file_id: vfs::FileId,
211212
}
@@ -357,7 +358,7 @@ fn parse(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Parse<ast::SourceFil
357358
let _p = tracing::info_span!("parse", ?file_id).entered();
358359
let (file_id, edition) = file_id.unpack(db.as_dyn_database());
359360
let text = db.file_text(file_id).text(db);
360-
ast::SourceFile::parse(&text, edition)
361+
ast::SourceFile::parse(text, edition)
361362
}
362363

363364
fn parse_errors(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Option<&[SyntaxError]> {

src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -890,7 +890,7 @@ fn include_str_expand(
890890
};
891891

892892
let text = db.file_text(file_id.file_id(db));
893-
let text = &*text.text(db);
893+
let text = &**text.text(db);
894894

895895
ExpandResult::ok(quote!(call_site =>#text))
896896
}

src/tools/rust-analyzer/crates/hir-expand/src/files.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,16 @@ impl FileRange {
9999
pub fn into_file_id(self, db: &dyn ExpandDatabase) -> FileRangeWrapper<FileId> {
100100
FileRangeWrapper { file_id: self.file_id.file_id(db), range: self.range }
101101
}
102+
103+
#[inline]
104+
pub fn file_text(self, db: &dyn ExpandDatabase) -> &triomphe::Arc<str> {
105+
db.file_text(self.file_id.file_id(db)).text(db)
106+
}
107+
108+
#[inline]
109+
pub fn text(self, db: &dyn ExpandDatabase) -> &str {
110+
&self.file_text(db)[self.range]
111+
}
102112
}
103113

104114
/// `AstId` points to an AST node in any file.

src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ impl TestDB {
149149
.into_iter()
150150
.filter_map(|file_id| {
151151
let text = self.file_text(file_id.file_id(self));
152-
let annotations = extract_annotations(&text.text(self));
152+
let annotations = extract_annotations(text.text(self));
153153
if annotations.is_empty() {
154154
return None;
155155
}

src/tools/rust-analyzer/crates/ide-db/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ pub trait LineIndexDatabase: base_db::RootQueryDb {
244244

245245
fn line_index(db: &dyn LineIndexDatabase, file_id: FileId) -> Arc<LineIndex> {
246246
let text = db.file_text(file_id).text(db);
247-
Arc::new(LineIndex::new(&text))
247+
Arc::new(LineIndex::new(text))
248248
}
249249

250250
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]

src/tools/rust-analyzer/crates/ide-db/src/search.rs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -487,9 +487,9 @@ impl<'a> FindUsages<'a> {
487487
scope.entries.iter().map(|(&file_id, &search_range)| {
488488
let text = db.file_text(file_id.file_id(db)).text(db);
489489
let search_range =
490-
search_range.unwrap_or_else(|| TextRange::up_to(TextSize::of(&*text)));
490+
search_range.unwrap_or_else(|| TextRange::up_to(TextSize::of(&**text)));
491491

492-
(text, file_id, search_range)
492+
(text.clone(), file_id, search_range)
493493
})
494494
}
495495

@@ -854,14 +854,7 @@ impl<'a> FindUsages<'a> {
854854
&finder,
855855
name,
856856
is_possibly_self.into_iter().map(|position| {
857-
(
858-
self.sema
859-
.db
860-
.file_text(position.file_id.file_id(self.sema.db))
861-
.text(self.sema.db),
862-
position.file_id,
863-
position.range,
864-
)
857+
(position.file_text(self.sema.db).clone(), position.file_id, position.range)
865858
}),
866859
|path, name_position| {
867860
let has_self = path
@@ -1067,12 +1060,12 @@ impl<'a> FindUsages<'a> {
10671060
let file_text = sema.db.file_text(file_id.file_id(self.sema.db));
10681061
let text = file_text.text(sema.db);
10691062
let search_range =
1070-
search_range.unwrap_or_else(|| TextRange::up_to(TextSize::of(&*text)));
1063+
search_range.unwrap_or_else(|| TextRange::up_to(TextSize::of(&**text)));
10711064

10721065
let tree = LazyCell::new(|| sema.parse(file_id).syntax().clone());
10731066
let finder = &Finder::new("self");
10741067

1075-
for offset in Self::match_indices(&text, finder, search_range) {
1068+
for offset in Self::match_indices(text, finder, search_range) {
10761069
for name_ref in Self::find_nodes(sema, "self", file_id, &tree, offset)
10771070
.filter_map(ast::NameRef::cast)
10781071
{

src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ pub(crate) fn check_diagnostics_with_config(
229229
let line_index = db.line_index(file_id);
230230

231231
let mut actual = annotations.remove(&file_id).unwrap_or_default();
232-
let mut expected = extract_annotations(&db.file_text(file_id).text(&db));
232+
let mut expected = extract_annotations(db.file_text(file_id).text(&db));
233233
expected.sort_by_key(|(range, s)| (range.start(), s.clone()));
234234
actual.sort_by_key(|(range, s)| (range.start(), s.clone()));
235235
// FIXME: We should panic on duplicates instead, but includes currently cause us to report

src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ impl<'db> MatchFinder<'db> {
186186
replacing::matches_to_edit(
187187
self.sema.db,
188188
&matches,
189-
&self.sema.db.file_text(file_id).text(self.sema.db),
189+
self.sema.db.file_text(file_id).text(self.sema.db),
190190
&self.rules,
191191
),
192192
)
@@ -228,7 +228,7 @@ impl<'db> MatchFinder<'db> {
228228
let file = self.sema.parse(file_id);
229229
let mut res = Vec::new();
230230
let file_text = self.sema.db.file_text(file_id.file_id(self.sema.db)).text(self.sema.db);
231-
let mut remaining_text = &*file_text;
231+
let mut remaining_text = &**file_text;
232232
let mut base = 0;
233233
let len = snippet.len() as u32;
234234
while let Some(offset) = remaining_text.find(snippet) {

src/tools/rust-analyzer/crates/ide/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ impl Analysis {
299299

300300
/// Gets the text of the source file.
301301
pub fn file_text(&self, file_id: FileId) -> Cancellable<Arc<str>> {
302-
self.with_db(|db| SourceDatabase::file_text(db, file_id).text(db))
302+
self.with_db(|db| SourceDatabase::file_text(db, file_id).text(db).clone())
303303
}
304304

305305
/// Gets the syntax tree of the file.

src/tools/rust-analyzer/crates/ide/src/rename.rs

Lines changed: 159 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@ use ide_db::{
1313
};
1414
use itertools::Itertools;
1515
use std::fmt::Write;
16-
use stdx::{always, never};
17-
use syntax::{AstNode, SyntaxKind, SyntaxNode, TextRange, TextSize, ast};
16+
use stdx::{always, format_to, never};
17+
use syntax::{
18+
AstNode, SyntaxKind, SyntaxNode, TextRange, TextSize,
19+
ast::{self, HasArgList, prec::ExprPrecedence},
20+
};
1821

1922
use ide_db::text_edit::TextEdit;
2023

@@ -331,6 +334,85 @@ fn find_definitions(
331334
}
332335
}
333336

337+
fn transform_assoc_fn_into_method_call(
338+
sema: &Semantics<'_, RootDatabase>,
339+
source_change: &mut SourceChange,
340+
f: hir::Function,
341+
) {
342+
let calls = Definition::Function(f).usages(sema).all();
343+
for (file_id, calls) in calls {
344+
for call in calls {
345+
let Some(fn_name) = call.name.as_name_ref() else { continue };
346+
let Some(path) = fn_name.syntax().parent().and_then(ast::PathSegment::cast) else {
347+
continue;
348+
};
349+
let path = path.parent_path();
350+
// The `PathExpr` is the direct parent, above it is the `CallExpr`.
351+
let Some(call) =
352+
path.syntax().parent().and_then(|it| ast::CallExpr::cast(it.parent()?))
353+
else {
354+
continue;
355+
};
356+
357+
let Some(arg_list) = call.arg_list() else { continue };
358+
let mut args = arg_list.args();
359+
let Some(mut self_arg) = args.next() else { continue };
360+
let second_arg = args.next();
361+
362+
// Strip (de)references, as they will be taken automatically by auto(de)ref.
363+
loop {
364+
let self_ = match &self_arg {
365+
ast::Expr::RefExpr(self_) => self_.expr(),
366+
ast::Expr::ParenExpr(self_) => self_.expr(),
367+
ast::Expr::PrefixExpr(self_)
368+
if self_.op_kind() == Some(ast::UnaryOp::Deref) =>
369+
{
370+
self_.expr()
371+
}
372+
_ => break,
373+
};
374+
self_arg = match self_ {
375+
Some(it) => it,
376+
None => break,
377+
};
378+
}
379+
380+
let self_needs_parens =
381+
self_arg.precedence().needs_parentheses_in(ExprPrecedence::Postfix);
382+
383+
let replace_start = path.syntax().text_range().start();
384+
let replace_end = match second_arg {
385+
Some(second_arg) => second_arg.syntax().text_range().start(),
386+
None => arg_list
387+
.r_paren_token()
388+
.map(|it| it.text_range().start())
389+
.unwrap_or_else(|| arg_list.syntax().text_range().end()),
390+
};
391+
let replace_range = TextRange::new(replace_start, replace_end);
392+
393+
let Some(macro_mapped_self) = sema.original_range_opt(self_arg.syntax()) else {
394+
continue;
395+
};
396+
let mut replacement = String::new();
397+
if self_needs_parens {
398+
replacement.push('(');
399+
}
400+
replacement.push_str(macro_mapped_self.text(sema.db));
401+
if self_needs_parens {
402+
replacement.push(')');
403+
}
404+
replacement.push('.');
405+
format_to!(replacement, "{fn_name}");
406+
replacement.push('(');
407+
408+
source_change.insert_source_edit(
409+
file_id.file_id(sema.db),
410+
TextEdit::replace(replace_range, replacement),
411+
);
412+
}
413+
}
414+
}
415+
334416
fn rename_to_self(
335417
sema: &Semantics<'_, RootDatabase>,
336418
local: hir::Local,
@@ -408,6 +490,7 @@ fn rename_to_self(
408490
file_id.original_file(sema.db).file_id(sema.db),
409491
TextEdit::replace(param_source.syntax().text_range(), String::from(self_param)),
410492
);
493+
transform_assoc_fn_into_method_call(sema, &mut source_change, fn_def);
411494
Ok(source_change)
412495
}
413496

@@ -3412,4 +3495,78 @@ fn other_place() { Quux::Bar$0; }
34123495
"#,
34133496
);
34143497
}
3498+
3499+
#[test]
3500+
fn rename_to_self_callers() {
3501+
check(
3502+
"self",
3503+
r#"
3504+
//- minicore: add
3505+
struct Foo;
3506+
impl core::ops::Add for Foo {
3507+
type Target = Foo;
3508+
fn add(self, _: Self) -> Foo { Foo }
3509+
}
3510+
3511+
impl Foo {
3512+
fn foo(th$0is: &Self) {}
3513+
}
3514+
3515+
fn bar(v: &Foo) {
3516+
Foo::foo(v);
3517+
}
3518+
3519+
fn baz() {
3520+
Foo::foo(&Foo);
3521+
Foo::foo(Foo + Foo);
3522+
}
3523+
"#,
3524+
r#"
3525+
struct Foo;
3526+
impl core::ops::Add for Foo {
3527+
type Target = Foo;
3528+
fn add(self, _: Self) -> Foo { Foo }
3529+
}
3530+
3531+
impl Foo {
3532+
fn foo(&self) {}
3533+
}
3534+
3535+
fn bar(v: &Foo) {
3536+
v.foo();
3537+
}
3538+
3539+
fn baz() {
3540+
Foo.foo();
3541+
(Foo + Foo).foo();
3542+
}
3543+
"#,
3544+
);
3545+
// Multiple arguments:
3546+
check(
3547+
"self",
3548+
r#"
3549+
struct Foo;
3550+
3551+
impl Foo {
3552+
fn foo(th$0is: &Self, v: i32) {}
3553+
}
3554+
3555+
fn bar(v: Foo) {
3556+
Foo::foo(&v, 123);
3557+
}
3558+
"#,
3559+
r#"
3560+
struct Foo;
3561+
3562+
impl Foo {
3563+
fn foo(&self, v: i32) {}
3564+
}
3565+
3566+
fn bar(v: Foo) {
3567+
v.foo(123);
3568+
}
3569+
"#,
3570+
);
3571+
}
34153572
}

0 commit comments

Comments
 (0)