mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-11-03 13:13:18 +00:00 
			
		
		
		
	refactoring
This commit is contained in:
		
							parent
							
								
									b07490ffe9
								
							
						
					
					
						commit
						8a3c21442e
					
				@ -17,11 +17,6 @@ struct AstSubsts {
 | 
				
			|||||||
    lifetimes: Vec<ast::LifetimeArg>,
 | 
					    lifetimes: Vec<ast::LifetimeArg>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct TypeOrConstSubst {
 | 
					 | 
				
			||||||
    subst: ast::Type,
 | 
					 | 
				
			||||||
    to_be_transformed: bool,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type LifetimeName = String;
 | 
					type LifetimeName = String;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// `PathTransform` substitutes path in SyntaxNodes in bulk.
 | 
					/// `PathTransform` substitutes path in SyntaxNodes in bulk.
 | 
				
			||||||
@ -115,8 +110,10 @@ impl<'a> PathTransform<'a> {
 | 
				
			|||||||
            Some(hir::GenericDef::Trait(_)) => 1,
 | 
					            Some(hir::GenericDef::Trait(_)) => 1,
 | 
				
			||||||
            _ => 0,
 | 
					            _ => 0,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        let type_and_const_substs: FxHashMap<_, _> = self
 | 
					        let mut type_substs: FxHashMap<hir::TypeParam, ast::Type> = Default::default();
 | 
				
			||||||
            .generic_def
 | 
					        let mut const_substs: FxHashMap<hir::ConstParam, SyntaxNode> = Default::default();
 | 
				
			||||||
 | 
					        let mut default_types: Vec<hir::TypeParam> = Default::default();
 | 
				
			||||||
 | 
					        self.generic_def
 | 
				
			||||||
            .into_iter()
 | 
					            .into_iter()
 | 
				
			||||||
            .flat_map(|it| it.type_params(db))
 | 
					            .flat_map(|it| it.type_params(db))
 | 
				
			||||||
            .skip(skip)
 | 
					            .skip(skip)
 | 
				
			||||||
@ -127,26 +124,29 @@ impl<'a> PathTransform<'a> {
 | 
				
			|||||||
            // a default type. If they do, go for that type from `hir` to `ast` so
 | 
					            // a default type. If they do, go for that type from `hir` to `ast` so
 | 
				
			||||||
            // the resulting change can be applied correctly.
 | 
					            // the resulting change can be applied correctly.
 | 
				
			||||||
            .zip(self.substs.types_and_consts.iter().map(Some).chain(std::iter::repeat(None)))
 | 
					            .zip(self.substs.types_and_consts.iter().map(Some).chain(std::iter::repeat(None)))
 | 
				
			||||||
            .filter_map(|(k, v)| match (k.split(db), v) {
 | 
					            .for_each(|(k, v)| match (k.split(db), v) {
 | 
				
			||||||
                (_, Some(v)) => {
 | 
					                (Either::Right(t), Some(v)) => {
 | 
				
			||||||
                    let subst =
 | 
					                    if let Some(ty) = v.ty() {
 | 
				
			||||||
                        TypeOrConstSubst { subst: v.ty()?.clone(), to_be_transformed: false };
 | 
					                        type_substs.insert(t, ty.clone());
 | 
				
			||||||
                    Some((k, subst))
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                (Either::Right(t), None) => {
 | 
					                (Either::Right(t), None) => {
 | 
				
			||||||
                    let default = t.default(db)?;
 | 
					                    if let Some(default) = t.default(db) {
 | 
				
			||||||
                    let subst = TypeOrConstSubst {
 | 
					                        if let Some(default) =
 | 
				
			||||||
                        subst: ast::make::ty(
 | 
					                            &default.display_source_code(db, source_module.into(), false).ok()
 | 
				
			||||||
                            &default.display_source_code(db, source_module.into(), false).ok()?,
 | 
					                        {
 | 
				
			||||||
                        )
 | 
					                            type_substs.insert(t, ast::make::ty(default).clone_for_update());
 | 
				
			||||||
                        .clone_for_update(),
 | 
					                            default_types.push(t);
 | 
				
			||||||
                        to_be_transformed: true,
 | 
					 | 
				
			||||||
                    };
 | 
					 | 
				
			||||||
                    Some((k, subst))
 | 
					 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                (Either::Left(_), None) => None, // FIXME: get default const value
 | 
					                    }
 | 
				
			||||||
            })
 | 
					                }
 | 
				
			||||||
            .collect();
 | 
					                (Either::Left(c), Some(v)) => {
 | 
				
			||||||
 | 
					                    if let Some(ty) = v.ty() {
 | 
				
			||||||
 | 
					                        const_substs.insert(c, ty.syntax().clone());
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                (Either::Left(_), None) => (), // FIXME: get default const value
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
        let lifetime_substs: FxHashMap<_, _> = self
 | 
					        let lifetime_substs: FxHashMap<_, _> = self
 | 
				
			||||||
            .generic_def
 | 
					            .generic_def
 | 
				
			||||||
            .into_iter()
 | 
					            .into_iter()
 | 
				
			||||||
@ -154,23 +154,27 @@ impl<'a> PathTransform<'a> {
 | 
				
			|||||||
            .zip(self.substs.lifetimes.clone())
 | 
					            .zip(self.substs.lifetimes.clone())
 | 
				
			||||||
            .filter_map(|(k, v)| Some((k.name(db).display(db.upcast()).to_string(), v.lifetime()?)))
 | 
					            .filter_map(|(k, v)| Some((k.name(db).display(db.upcast()).to_string(), v.lifetime()?)))
 | 
				
			||||||
            .collect();
 | 
					            .collect();
 | 
				
			||||||
        Ctx {
 | 
					        let ctx = Ctx {
 | 
				
			||||||
            type_and_const_substs,
 | 
					            type_substs,
 | 
				
			||||||
 | 
					            const_substs,
 | 
				
			||||||
            lifetime_substs,
 | 
					            lifetime_substs,
 | 
				
			||||||
            target_module,
 | 
					            target_module,
 | 
				
			||||||
            source_scope: self.source_scope,
 | 
					            source_scope: self.source_scope,
 | 
				
			||||||
        }
 | 
					        };
 | 
				
			||||||
 | 
					        ctx.transform_default_type_substs(default_types);
 | 
				
			||||||
 | 
					        ctx
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Ctx<'a> {
 | 
					struct Ctx<'a> {
 | 
				
			||||||
    type_and_const_substs: FxHashMap<hir::TypeOrConstParam, TypeOrConstSubst>,
 | 
					    type_substs: FxHashMap<hir::TypeParam, ast::Type>,
 | 
				
			||||||
 | 
					    const_substs: FxHashMap<hir::ConstParam, SyntaxNode>,
 | 
				
			||||||
    lifetime_substs: FxHashMap<LifetimeName, ast::Lifetime>,
 | 
					    lifetime_substs: FxHashMap<LifetimeName, ast::Lifetime>,
 | 
				
			||||||
    target_module: hir::Module,
 | 
					    target_module: hir::Module,
 | 
				
			||||||
    source_scope: &'a SemanticsScope<'a>,
 | 
					    source_scope: &'a SemanticsScope<'a>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn preorder(item: &SyntaxNode) -> impl Iterator<Item = SyntaxNode> {
 | 
					fn postorder(item: &SyntaxNode) -> impl Iterator<Item = SyntaxNode> {
 | 
				
			||||||
    item.preorder().filter_map(|event| match event {
 | 
					    item.preorder().filter_map(|event| match event {
 | 
				
			||||||
        syntax::WalkEvent::Enter(_) => None,
 | 
					        syntax::WalkEvent::Enter(_) => None,
 | 
				
			||||||
        syntax::WalkEvent::Leave(node) => Some(node),
 | 
					        syntax::WalkEvent::Leave(node) => Some(node),
 | 
				
			||||||
@ -179,31 +183,31 @@ fn preorder(item: &SyntaxNode) -> impl Iterator<Item = SyntaxNode> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
impl<'a> Ctx<'a> {
 | 
					impl<'a> Ctx<'a> {
 | 
				
			||||||
    fn apply(&self, item: &SyntaxNode) {
 | 
					    fn apply(&self, item: &SyntaxNode) {
 | 
				
			||||||
        for (_, subst) in &self.type_and_const_substs {
 | 
					 | 
				
			||||||
            if subst.to_be_transformed {
 | 
					 | 
				
			||||||
                let paths =
 | 
					 | 
				
			||||||
                    preorder(&subst.subst.syntax()).filter_map(ast::Path::cast).collect::<Vec<_>>();
 | 
					 | 
				
			||||||
                for path in paths {
 | 
					 | 
				
			||||||
                    self.transform_path(path);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // `transform_path` may update a node's parent and that would break the
 | 
					        // `transform_path` may update a node's parent and that would break the
 | 
				
			||||||
        // tree traversal. Thus all paths in the tree are collected into a vec
 | 
					        // tree traversal. Thus all paths in the tree are collected into a vec
 | 
				
			||||||
        // so that such operation is safe.
 | 
					        // so that such operation is safe.
 | 
				
			||||||
        let paths = preorder(item).filter_map(ast::Path::cast).collect::<Vec<_>>();
 | 
					        let paths = postorder(item).filter_map(ast::Path::cast).collect::<Vec<_>>();
 | 
				
			||||||
        for path in paths {
 | 
					        for path in paths {
 | 
				
			||||||
            self.transform_path(path);
 | 
					            self.transform_path(path);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        preorder(item).filter_map(ast::Lifetime::cast).for_each(|lifetime| {
 | 
					        postorder(item).filter_map(ast::Lifetime::cast).for_each(|lifetime| {
 | 
				
			||||||
            if let Some(subst) = self.lifetime_substs.get(&lifetime.syntax().text().to_string()) {
 | 
					            if let Some(subst) = self.lifetime_substs.get(&lifetime.syntax().text().to_string()) {
 | 
				
			||||||
                ted::replace(lifetime.syntax(), subst.clone_subtree().clone_for_update().syntax());
 | 
					                ted::replace(lifetime.syntax(), subst.clone_subtree().clone_for_update().syntax());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn transform_default_type_substs(&self, default_types: Vec<hir::TypeParam>) {
 | 
				
			||||||
 | 
					        for k in default_types {
 | 
				
			||||||
 | 
					            let v = self.type_substs.get(&k).unwrap();
 | 
				
			||||||
 | 
					            let paths = postorder(&v.syntax()).filter_map(ast::Path::cast).collect::<Vec<_>>();
 | 
				
			||||||
 | 
					            for path in paths {
 | 
				
			||||||
 | 
					                self.transform_path(path);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn transform_path(&self, path: ast::Path) -> Option<()> {
 | 
					    fn transform_path(&self, path: ast::Path) -> Option<()> {
 | 
				
			||||||
        if path.qualifier().is_some() {
 | 
					        if path.qualifier().is_some() {
 | 
				
			||||||
            return None;
 | 
					            return None;
 | 
				
			||||||
@ -220,9 +224,7 @@ impl<'a> Ctx<'a> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        match resolution {
 | 
					        match resolution {
 | 
				
			||||||
            hir::PathResolution::TypeParam(tp) => {
 | 
					            hir::PathResolution::TypeParam(tp) => {
 | 
				
			||||||
                if let Some(TypeOrConstSubst { subst, .. }) =
 | 
					                if let Some(subst) = self.type_substs.get(&tp) {
 | 
				
			||||||
                    self.type_and_const_substs.get(&tp.merge())
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    let parent = path.syntax().parent()?;
 | 
					                    let parent = path.syntax().parent()?;
 | 
				
			||||||
                    if let Some(parent) = ast::Path::cast(parent.clone()) {
 | 
					                    if let Some(parent) = ast::Path::cast(parent.clone()) {
 | 
				
			||||||
                        // Path inside path means that there is an associated
 | 
					                        // Path inside path means that there is an associated
 | 
				
			||||||
@ -290,10 +292,8 @@ impl<'a> Ctx<'a> {
 | 
				
			|||||||
                ted::replace(path.syntax(), res.syntax())
 | 
					                ted::replace(path.syntax(), res.syntax())
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            hir::PathResolution::ConstParam(cp) => {
 | 
					            hir::PathResolution::ConstParam(cp) => {
 | 
				
			||||||
                if let Some(TypeOrConstSubst { subst, .. }) =
 | 
					                if let Some(subst) = self.const_substs.get(&cp) {
 | 
				
			||||||
                    self.type_and_const_substs.get(&cp.merge())
 | 
					                    ted::replace(path.syntax(), subst.clone_subtree().clone_for_update());
 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    ted::replace(path.syntax(), subst.clone_subtree().clone_for_update().syntax());
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            hir::PathResolution::Local(_)
 | 
					            hir::PathResolution::Local(_)
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user