mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-11-03 21:25:25 +00:00 
			
		
		
		
	fix: Implement default member to resolve IdentPat
This commit is contained in:
		
							parent
							
								
									d307bc614e
								
							
						
					
					
						commit
						8ab683759e
					
				
					 2 changed files with 102 additions and 8 deletions
				
			
		| 
						 | 
					@ -2418,6 +2418,55 @@ pub struct MyStruct;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl other_file_2::Trait for MyStruct {
 | 
					impl other_file_2::Trait for MyStruct {
 | 
				
			||||||
    $0type Iter;
 | 
					    $0type Iter;
 | 
				
			||||||
 | 
					}"#,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn test_qualify_ident_pat_in_default_members() {
 | 
				
			||||||
 | 
					        check_assist(
 | 
				
			||||||
 | 
					            add_missing_default_members,
 | 
				
			||||||
 | 
					            r#"
 | 
				
			||||||
 | 
					//- /lib.rs crate:b new_source_root:library
 | 
				
			||||||
 | 
					pub enum State {
 | 
				
			||||||
 | 
					    Active,
 | 
				
			||||||
 | 
					    Inactive,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use State::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub trait Checker {
 | 
				
			||||||
 | 
					    fn check(&self) -> State;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn is_active(&self) -> bool {
 | 
				
			||||||
 | 
					        match self.check() {
 | 
				
			||||||
 | 
					            Active => true,
 | 
				
			||||||
 | 
					            Inactive => false,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//- /main.rs crate:a deps:b
 | 
				
			||||||
 | 
					struct MyChecker;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl b::Checker for MyChecker {
 | 
				
			||||||
 | 
					    fn check(&self) -> b::State {
 | 
				
			||||||
 | 
					        todo!();
 | 
				
			||||||
 | 
					    }$0
 | 
				
			||||||
 | 
					}"#,
 | 
				
			||||||
 | 
					            r#"
 | 
				
			||||||
 | 
					struct MyChecker;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl b::Checker for MyChecker {
 | 
				
			||||||
 | 
					    fn check(&self) -> b::State {
 | 
				
			||||||
 | 
					        todo!();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $0fn is_active(&self) -> bool {
 | 
				
			||||||
 | 
					        match self.check() {
 | 
				
			||||||
 | 
					            b::State::Active => true,
 | 
				
			||||||
 | 
					            b::State::Inactive => false,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}"#,
 | 
					}"#,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ use rustc_hash::FxHashMap;
 | 
				
			||||||
use span::Edition;
 | 
					use span::Edition;
 | 
				
			||||||
use syntax::{
 | 
					use syntax::{
 | 
				
			||||||
    NodeOrToken, SyntaxNode,
 | 
					    NodeOrToken, SyntaxNode,
 | 
				
			||||||
    ast::{self, AstNode, HasGenericArgs, make},
 | 
					    ast::{self, AstNode, HasGenericArgs, HasName, make},
 | 
				
			||||||
    syntax_editor::{self, SyntaxEditor},
 | 
					    syntax_editor::{self, SyntaxEditor},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -315,32 +315,49 @@ impl Ctx<'_> {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn transform_path(&self, path: &SyntaxNode) -> SyntaxNode {
 | 
					    fn transform_path(&self, path: &SyntaxNode) -> SyntaxNode {
 | 
				
			||||||
        fn find_child_paths(root_path: &SyntaxNode) -> Vec<ast::Path> {
 | 
					        fn find_child_paths_and_ident_pats(
 | 
				
			||||||
            let mut result = Vec::new();
 | 
					            root_path: &SyntaxNode,
 | 
				
			||||||
 | 
					        ) -> Vec<Either<ast::Path, ast::IdentPat>> {
 | 
				
			||||||
 | 
					            let mut result: Vec<Either<ast::Path, ast::IdentPat>> = Vec::new();
 | 
				
			||||||
            for child in root_path.children() {
 | 
					            for child in root_path.children() {
 | 
				
			||||||
                if let Some(child_path) = ast::Path::cast(child.clone()) {
 | 
					                if let Some(child_path) = ast::Path::cast(child.clone()) {
 | 
				
			||||||
                    result.push(child_path);
 | 
					                    result.push(either::Left(child_path));
 | 
				
			||||||
 | 
					                } else if let Some(child_ident_pat) = ast::IdentPat::cast(child.clone()) {
 | 
				
			||||||
 | 
					                    result.push(either::Right(child_ident_pat));
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    result.extend(find_child_paths(&child));
 | 
					                    result.extend(find_child_paths_and_ident_pats(&child));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            result
 | 
					            result
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let root_path = path.clone_subtree();
 | 
					        let root_path = path.clone_subtree();
 | 
				
			||||||
        let result = find_child_paths(&root_path);
 | 
					
 | 
				
			||||||
 | 
					        let result = find_child_paths_and_ident_pats(&root_path);
 | 
				
			||||||
        let mut editor = SyntaxEditor::new(root_path.clone());
 | 
					        let mut editor = SyntaxEditor::new(root_path.clone());
 | 
				
			||||||
        for sub_path in result {
 | 
					        for sub_path in result {
 | 
				
			||||||
            let new = self.transform_path(sub_path.syntax());
 | 
					            let new = self.transform_path(sub_path.syntax());
 | 
				
			||||||
            editor.replace(sub_path.syntax(), new);
 | 
					            editor.replace(sub_path.syntax(), new);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let update_sub_item = editor.finish().new_root().clone().clone_subtree();
 | 
					        let update_sub_item = editor.finish().new_root().clone().clone_subtree();
 | 
				
			||||||
        let item = find_child_paths(&update_sub_item);
 | 
					        let item = find_child_paths_and_ident_pats(&update_sub_item);
 | 
				
			||||||
        let mut editor = SyntaxEditor::new(update_sub_item);
 | 
					        let mut editor = SyntaxEditor::new(update_sub_item);
 | 
				
			||||||
        for sub_path in item {
 | 
					        for sub_path in item {
 | 
				
			||||||
            self.transform_path_(&mut editor, &sub_path);
 | 
					            self.transform_path_or_ident_pat(&mut editor, &sub_path);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        editor.finish().new_root().clone()
 | 
					        editor.finish().new_root().clone()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    fn transform_path_or_ident_pat(
 | 
				
			||||||
 | 
					        &self,
 | 
				
			||||||
 | 
					        editor: &mut SyntaxEditor,
 | 
				
			||||||
 | 
					        item: &Either<ast::Path, ast::IdentPat>,
 | 
				
			||||||
 | 
					    ) -> Option<()> {
 | 
				
			||||||
 | 
					        match item {
 | 
				
			||||||
 | 
					            Either::Left(path) => self.transform_path_(editor, path),
 | 
				
			||||||
 | 
					            Either::Right(ident_pat) => self.transform_ident_pat(editor, ident_pat),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn transform_path_(&self, editor: &mut SyntaxEditor, path: &ast::Path) -> Option<()> {
 | 
					    fn transform_path_(&self, editor: &mut SyntaxEditor, path: &ast::Path) -> Option<()> {
 | 
				
			||||||
        if path.qualifier().is_some() {
 | 
					        if path.qualifier().is_some() {
 | 
				
			||||||
| 
						 | 
					@ -515,6 +532,34 @@ impl Ctx<'_> {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Some(())
 | 
					        Some(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn transform_ident_pat(
 | 
				
			||||||
 | 
					        &self,
 | 
				
			||||||
 | 
					        editor: &mut SyntaxEditor,
 | 
				
			||||||
 | 
					        ident_pat: &ast::IdentPat,
 | 
				
			||||||
 | 
					    ) -> Option<()> {
 | 
				
			||||||
 | 
					        let name = ident_pat.name()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let temp_path = make::path_from_text(&name.text());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let resolution = self.source_scope.speculative_resolve(&temp_path)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        match resolution {
 | 
				
			||||||
 | 
					            hir::PathResolution::Def(def) if def.as_assoc_item(self.source_scope.db).is_none() => {
 | 
				
			||||||
 | 
					                let cfg = ImportPathConfig {
 | 
				
			||||||
 | 
					                    prefer_no_std: false,
 | 
				
			||||||
 | 
					                    prefer_prelude: true,
 | 
				
			||||||
 | 
					                    prefer_absolute: false,
 | 
				
			||||||
 | 
					                    allow_unstable: true,
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					                let found_path = self.target_module.find_path(self.source_scope.db, def, cfg)?;
 | 
				
			||||||
 | 
					                let res = mod_path_to_ast(&found_path, self.target_edition).clone_for_update();
 | 
				
			||||||
 | 
					                editor.replace(ident_pat.syntax(), res.syntax());
 | 
				
			||||||
 | 
					                Some(())
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            _ => None,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FIXME: It would probably be nicer if we could get this via HIR (i.e. get the
 | 
					// FIXME: It would probably be nicer if we could get this via HIR (i.e. get the
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue