Skip to content

Commit b2a58b8

Browse files
Merge pull request #20432 from sgasho/fix/20215_implement_default_member_to_resolve_ident_pat
Fix "Implement default members" to resolve IdentPat
2 parents 9db0550 + 8ab6837 commit b2a58b8

File tree

2 files changed

+102
-8
lines changed

2 files changed

+102
-8
lines changed

crates/ide-assists/src/handlers/add_missing_impl_members.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2418,6 +2418,55 @@ pub struct MyStruct;
24182418
24192419
impl other_file_2::Trait for MyStruct {
24202420
$0type Iter;
2421+
}"#,
2422+
);
2423+
}
2424+
2425+
#[test]
2426+
fn test_qualify_ident_pat_in_default_members() {
2427+
check_assist(
2428+
add_missing_default_members,
2429+
r#"
2430+
//- /lib.rs crate:b new_source_root:library
2431+
pub enum State {
2432+
Active,
2433+
Inactive,
2434+
}
2435+
2436+
use State::*;
2437+
2438+
pub trait Checker {
2439+
fn check(&self) -> State;
2440+
2441+
fn is_active(&self) -> bool {
2442+
match self.check() {
2443+
Active => true,
2444+
Inactive => false,
2445+
}
2446+
}
2447+
}
2448+
//- /main.rs crate:a deps:b
2449+
struct MyChecker;
2450+
2451+
impl b::Checker for MyChecker {
2452+
fn check(&self) -> b::State {
2453+
todo!();
2454+
}$0
2455+
}"#,
2456+
r#"
2457+
struct MyChecker;
2458+
2459+
impl b::Checker for MyChecker {
2460+
fn check(&self) -> b::State {
2461+
todo!();
2462+
}
2463+
2464+
$0fn is_active(&self) -> bool {
2465+
match self.check() {
2466+
b::State::Active => true,
2467+
b::State::Inactive => false,
2468+
}
2469+
}
24212470
}"#,
24222471
);
24232472
}

crates/ide-db/src/path_transform.rs

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_hash::FxHashMap;
1111
use span::Edition;
1212
use syntax::{
1313
NodeOrToken, SyntaxNode,
14-
ast::{self, AstNode, HasGenericArgs, make},
14+
ast::{self, AstNode, HasGenericArgs, HasName, make},
1515
syntax_editor::{self, SyntaxEditor},
1616
};
1717

@@ -315,32 +315,49 @@ impl Ctx<'_> {
315315
}
316316

317317
fn transform_path(&self, path: &SyntaxNode) -> SyntaxNode {
318-
fn find_child_paths(root_path: &SyntaxNode) -> Vec<ast::Path> {
319-
let mut result = Vec::new();
318+
fn find_child_paths_and_ident_pats(
319+
root_path: &SyntaxNode,
320+
) -> Vec<Either<ast::Path, ast::IdentPat>> {
321+
let mut result: Vec<Either<ast::Path, ast::IdentPat>> = Vec::new();
320322
for child in root_path.children() {
321323
if let Some(child_path) = ast::Path::cast(child.clone()) {
322-
result.push(child_path);
324+
result.push(either::Left(child_path));
325+
} else if let Some(child_ident_pat) = ast::IdentPat::cast(child.clone()) {
326+
result.push(either::Right(child_ident_pat));
323327
} else {
324-
result.extend(find_child_paths(&child));
328+
result.extend(find_child_paths_and_ident_pats(&child));
325329
}
326330
}
327331
result
328332
}
333+
329334
let root_path = path.clone_subtree();
330-
let result = find_child_paths(&root_path);
335+
336+
let result = find_child_paths_and_ident_pats(&root_path);
331337
let mut editor = SyntaxEditor::new(root_path.clone());
332338
for sub_path in result {
333339
let new = self.transform_path(sub_path.syntax());
334340
editor.replace(sub_path.syntax(), new);
335341
}
342+
336343
let update_sub_item = editor.finish().new_root().clone().clone_subtree();
337-
let item = find_child_paths(&update_sub_item);
344+
let item = find_child_paths_and_ident_pats(&update_sub_item);
338345
let mut editor = SyntaxEditor::new(update_sub_item);
339346
for sub_path in item {
340-
self.transform_path_(&mut editor, &sub_path);
347+
self.transform_path_or_ident_pat(&mut editor, &sub_path);
341348
}
342349
editor.finish().new_root().clone()
343350
}
351+
fn transform_path_or_ident_pat(
352+
&self,
353+
editor: &mut SyntaxEditor,
354+
item: &Either<ast::Path, ast::IdentPat>,
355+
) -> Option<()> {
356+
match item {
357+
Either::Left(path) => self.transform_path_(editor, path),
358+
Either::Right(ident_pat) => self.transform_ident_pat(editor, ident_pat),
359+
}
360+
}
344361

345362
fn transform_path_(&self, editor: &mut SyntaxEditor, path: &ast::Path) -> Option<()> {
346363
if path.qualifier().is_some() {
@@ -515,6 +532,34 @@ impl Ctx<'_> {
515532
}
516533
Some(())
517534
}
535+
536+
fn transform_ident_pat(
537+
&self,
538+
editor: &mut SyntaxEditor,
539+
ident_pat: &ast::IdentPat,
540+
) -> Option<()> {
541+
let name = ident_pat.name()?;
542+
543+
let temp_path = make::path_from_text(&name.text());
544+
545+
let resolution = self.source_scope.speculative_resolve(&temp_path)?;
546+
547+
match resolution {
548+
hir::PathResolution::Def(def) if def.as_assoc_item(self.source_scope.db).is_none() => {
549+
let cfg = ImportPathConfig {
550+
prefer_no_std: false,
551+
prefer_prelude: true,
552+
prefer_absolute: false,
553+
allow_unstable: true,
554+
};
555+
let found_path = self.target_module.find_path(self.source_scope.db, def, cfg)?;
556+
let res = mod_path_to_ast(&found_path, self.target_edition).clone_for_update();
557+
editor.replace(ident_pat.syntax(), res.syntax());
558+
Some(())
559+
}
560+
_ => None,
561+
}
562+
}
518563
}
519564

520565
// FIXME: It would probably be nicer if we could get this via HIR (i.e. get the

0 commit comments

Comments
 (0)