@@ -5,7 +5,7 @@ use hir::{HirDisplay, SemanticsScope};
55use rustc_hash:: FxHashMap ;
66use syntax:: {
77 ast:: { self , AstNode } ,
8- ted,
8+ ted, SyntaxNode ,
99} ;
1010
1111/// `PathTransform` substitutes path in SyntaxNodes in bulk.
@@ -32,38 +32,70 @@ use syntax::{
3232/// }
3333/// ```
3434pub struct PathTransform < ' a > {
35- pub subst : ( hir:: Trait , ast:: Impl ) ,
36- pub target_scope : & ' a SemanticsScope < ' a > ,
37- pub source_scope : & ' a SemanticsScope < ' a > ,
35+ generic_def : hir:: GenericDef ,
36+ substs : Vec < ast:: Type > ,
37+ target_scope : & ' a SemanticsScope < ' a > ,
38+ source_scope : & ' a SemanticsScope < ' a > ,
3839}
3940
4041impl < ' a > PathTransform < ' a > {
41- pub fn apply ( & self , item : ast:: AssocItem ) {
42+ pub fn trait_impl (
43+ target_scope : & ' a SemanticsScope < ' a > ,
44+ source_scope : & ' a SemanticsScope < ' a > ,
45+ trait_ : hir:: Trait ,
46+ impl_ : ast:: Impl ,
47+ ) -> PathTransform < ' a > {
48+ PathTransform {
49+ source_scope,
50+ target_scope,
51+ generic_def : trait_. into ( ) ,
52+ substs : get_syntactic_substs ( impl_) . unwrap_or_default ( ) ,
53+ }
54+ }
55+
56+ pub fn function_call (
57+ target_scope : & ' a SemanticsScope < ' a > ,
58+ source_scope : & ' a SemanticsScope < ' a > ,
59+ function : hir:: Function ,
60+ generic_arg_list : ast:: GenericArgList ,
61+ ) -> PathTransform < ' a > {
62+ PathTransform {
63+ source_scope,
64+ target_scope,
65+ generic_def : function. into ( ) ,
66+ substs : get_type_args_from_arg_list ( generic_arg_list) . unwrap_or_default ( ) ,
67+ }
68+ }
69+
70+ pub fn apply ( & self , syntax : & SyntaxNode ) {
4271 if let Some ( ctx) = self . build_ctx ( ) {
43- ctx. apply ( item )
72+ ctx. apply ( syntax )
4473 }
4574 }
75+
4676 fn build_ctx ( & self ) -> Option < Ctx < ' a > > {
4777 let db = self . source_scope . db ;
4878 let target_module = self . target_scope . module ( ) ?;
4979 let source_module = self . source_scope . module ( ) ?;
50-
51- let substs = get_syntactic_substs ( self . subst . 1 . clone ( ) ) . unwrap_or_default ( ) ;
52- let generic_def: hir:: GenericDef = self . subst . 0 . into ( ) ;
53- let substs_by_param: FxHashMap < _ , _ > = generic_def
80+ let skip = match self . generic_def {
81+ // this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky
82+ hir:: GenericDef :: Trait ( _) => 1 ,
83+ _ => 0 ,
84+ } ;
85+ let substs_by_param: FxHashMap < _ , _ > = self
86+ . generic_def
5487 . type_params ( db)
5588 . into_iter ( )
56- // this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky
57- . skip ( 1 )
89+ . skip ( skip)
5890 // The actual list of trait type parameters may be longer than the one
5991 // used in the `impl` block due to trailing default type parameters.
6092 // For that case we extend the `substs` with an empty iterator so we
6193 // can still hit those trailing values and check if they actually have
6294 // a default type. If they do, go for that type from `hir` to `ast` so
6395 // the resulting change can be applied correctly.
64- . zip ( substs. into_iter ( ) . map ( Some ) . chain ( std:: iter:: repeat ( None ) ) )
96+ . zip ( self . substs . iter ( ) . map ( Some ) . chain ( std:: iter:: repeat ( None ) ) )
6597 . filter_map ( |( k, v) | match v {
66- Some ( v) => Some ( ( k, v) ) ,
98+ Some ( v) => Some ( ( k, v. clone ( ) ) ) ,
6799 None => {
68100 let default = k. default ( db) ?;
69101 Some ( (
@@ -73,7 +105,6 @@ impl<'a> PathTransform<'a> {
73105 }
74106 } )
75107 . collect ( ) ;
76-
77108 let res = Ctx { substs : substs_by_param, target_module, source_scope : self . source_scope } ;
78109 Some ( res)
79110 }
@@ -86,8 +117,8 @@ struct Ctx<'a> {
86117}
87118
88119impl < ' a > Ctx < ' a > {
89- fn apply ( & self , item : ast :: AssocItem ) {
90- for event in item. syntax ( ) . preorder ( ) {
120+ fn apply ( & self , item : & SyntaxNode ) {
121+ for event in item. preorder ( ) {
91122 let node = match event {
92123 syntax:: WalkEvent :: Enter ( _) => continue ,
93124 syntax:: WalkEvent :: Leave ( it) => it,
@@ -149,13 +180,14 @@ fn get_syntactic_substs(impl_def: ast::Impl) -> Option<Vec<ast::Type>> {
149180 } ;
150181 let generic_arg_list = path_type. path ( ) ?. segment ( ) ?. generic_arg_list ( ) ?;
151182
183+ get_type_args_from_arg_list ( generic_arg_list)
184+ }
185+
186+ fn get_type_args_from_arg_list ( generic_arg_list : ast:: GenericArgList ) -> Option < Vec < ast:: Type > > {
152187 let mut result = Vec :: new ( ) ;
153188 for generic_arg in generic_arg_list. generic_args ( ) {
154- match generic_arg {
155- ast:: GenericArg :: TypeArg ( type_arg) => result. push ( type_arg. ty ( ) ?) ,
156- ast:: GenericArg :: AssocTypeArg ( _)
157- | ast:: GenericArg :: LifetimeArg ( _)
158- | ast:: GenericArg :: ConstArg ( _) => ( ) ,
189+ if let ast:: GenericArg :: TypeArg ( type_arg) = generic_arg {
190+ result. push ( type_arg. ty ( ) ?)
159191 }
160192 }
161193
0 commit comments