@@ -5,12 +5,13 @@ use hir::{HirDisplay, PathResolution, SemanticsScope};
55use syntax:: {
66 algo:: SyntaxRewriter ,
77 ast:: { self , AstNode } ,
8+ SyntaxNode ,
89} ;
910
1011pub fn apply < ' a , N : AstNode > ( transformer : & dyn AstTransform < ' a > , node : N ) -> N {
1112 SyntaxRewriter :: from_fn ( |element| match element {
1213 syntax:: SyntaxElement :: Node ( n) => {
13- let replacement = transformer. get_substitution ( & n) ?;
14+ let replacement = transformer. get_substitution ( & n, transformer ) ?;
1415 Some ( replacement. into ( ) )
1516 }
1617 _ => None ,
@@ -47,32 +48,35 @@ pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: N) -> N {
4748/// We'd want to somehow express this concept simpler, but so far nobody got to
4849/// simplifying this!
4950pub trait AstTransform < ' a > {
50- fn get_substitution ( & self , node : & syntax:: SyntaxNode ) -> Option < syntax:: SyntaxNode > ;
51+ fn get_substitution (
52+ & self ,
53+ node : & SyntaxNode ,
54+ recur : & dyn AstTransform < ' a > ,
55+ ) -> Option < SyntaxNode > ;
5156
52- fn chain_before ( self , other : Box < dyn AstTransform < ' a > + ' a > ) -> Box < dyn AstTransform < ' a > + ' a > ;
5357 fn or < T : AstTransform < ' a > + ' a > ( self , other : T ) -> Box < dyn AstTransform < ' a > + ' a >
5458 where
5559 Self : Sized + ' a ,
5660 {
57- self . chain_before ( Box :: new ( other) )
61+ Box :: new ( Or ( Box :: new ( self ) , Box :: new ( other) ) )
5862 }
5963}
6064
61- struct NullTransformer ;
65+ struct Or < ' a > ( Box < dyn AstTransform < ' a > + ' a > , Box < dyn AstTransform < ' a > + ' a > ) ;
6266
63- impl < ' a > AstTransform < ' a > for NullTransformer {
64- fn get_substitution ( & self , _node : & syntax:: SyntaxNode ) -> Option < syntax:: SyntaxNode > {
65- None
66- }
67- fn chain_before ( self , other : Box < dyn AstTransform < ' a > + ' a > ) -> Box < dyn AstTransform < ' a > + ' a > {
68- other
67+ impl < ' a > AstTransform < ' a > for Or < ' a > {
68+ fn get_substitution (
69+ & self ,
70+ node : & SyntaxNode ,
71+ recur : & dyn AstTransform < ' a > ,
72+ ) -> Option < SyntaxNode > {
73+ self . 0 . get_substitution ( node, recur) . or_else ( || self . 1 . get_substitution ( node, recur) )
6974 }
7075}
7176
7277pub struct SubstituteTypeParams < ' a > {
7378 source_scope : & ' a SemanticsScope < ' a > ,
7479 substs : FxHashMap < hir:: TypeParam , ast:: Type > ,
75- previous : Box < dyn AstTransform < ' a > + ' a > ,
7680}
7781
7882impl < ' a > SubstituteTypeParams < ' a > {
@@ -111,11 +115,7 @@ impl<'a> SubstituteTypeParams<'a> {
111115 }
112116 } )
113117 . collect ( ) ;
114- return SubstituteTypeParams {
115- source_scope,
116- substs : substs_by_param,
117- previous : Box :: new ( NullTransformer ) ,
118- } ;
118+ return SubstituteTypeParams { source_scope, substs : substs_by_param } ;
119119
120120 // FIXME: It would probably be nicer if we could get this via HIR (i.e. get the
121121 // trait ref, and then go from the types in the substs back to the syntax).
@@ -140,7 +140,14 @@ impl<'a> SubstituteTypeParams<'a> {
140140 Some ( result)
141141 }
142142 }
143- fn get_substitution_inner ( & self , node : & syntax:: SyntaxNode ) -> Option < syntax:: SyntaxNode > {
143+ }
144+
145+ impl < ' a > AstTransform < ' a > for SubstituteTypeParams < ' a > {
146+ fn get_substitution (
147+ & self ,
148+ node : & SyntaxNode ,
149+ _recur : & dyn AstTransform < ' a > ,
150+ ) -> Option < SyntaxNode > {
144151 let type_ref = ast:: Type :: cast ( node. clone ( ) ) ?;
145152 let path = match & type_ref {
146153 ast:: Type :: PathType ( path_type) => path_type. path ( ) ?,
@@ -154,27 +161,23 @@ impl<'a> SubstituteTypeParams<'a> {
154161 }
155162}
156163
157- impl < ' a > AstTransform < ' a > for SubstituteTypeParams < ' a > {
158- fn get_substitution ( & self , node : & syntax:: SyntaxNode ) -> Option < syntax:: SyntaxNode > {
159- self . get_substitution_inner ( node) . or_else ( || self . previous . get_substitution ( node) )
160- }
161- fn chain_before ( self , other : Box < dyn AstTransform < ' a > + ' a > ) -> Box < dyn AstTransform < ' a > + ' a > {
162- Box :: new ( SubstituteTypeParams { previous : other, ..self } )
163- }
164- }
165-
166164pub struct QualifyPaths < ' a > {
167165 target_scope : & ' a SemanticsScope < ' a > ,
168166 source_scope : & ' a SemanticsScope < ' a > ,
169- previous : Box < dyn AstTransform < ' a > + ' a > ,
170167}
171168
172169impl < ' a > QualifyPaths < ' a > {
173170 pub fn new ( target_scope : & ' a SemanticsScope < ' a > , source_scope : & ' a SemanticsScope < ' a > ) -> Self {
174- Self { target_scope, source_scope, previous : Box :: new ( NullTransformer ) }
171+ Self { target_scope, source_scope }
175172 }
173+ }
176174
177- fn get_substitution_inner ( & self , node : & syntax:: SyntaxNode ) -> Option < syntax:: SyntaxNode > {
175+ impl < ' a > AstTransform < ' a > for QualifyPaths < ' a > {
176+ fn get_substitution (
177+ & self ,
178+ node : & SyntaxNode ,
179+ recur : & dyn AstTransform < ' a > ,
180+ ) -> Option < SyntaxNode > {
178181 // FIXME handle value ns?
179182 let from = self . target_scope . module ( ) ?;
180183 let p = ast:: Path :: cast ( node. clone ( ) ) ?;
@@ -191,7 +194,7 @@ impl<'a> QualifyPaths<'a> {
191194 let type_args = p
192195 . segment ( )
193196 . and_then ( |s| s. generic_arg_list ( ) )
194- . map ( |arg_list| apply ( self , arg_list) ) ;
197+ . map ( |arg_list| apply ( recur , arg_list) ) ;
195198 if let Some ( type_args) = type_args {
196199 let last_segment = path. segment ( ) . unwrap ( ) ;
197200 path = path. with_segment ( last_segment. with_generic_args ( type_args) )
@@ -208,15 +211,6 @@ impl<'a> QualifyPaths<'a> {
208211 }
209212}
210213
211- impl < ' a > AstTransform < ' a > for QualifyPaths < ' a > {
212- fn get_substitution ( & self , node : & syntax:: SyntaxNode ) -> Option < syntax:: SyntaxNode > {
213- self . get_substitution_inner ( node) . or_else ( || self . previous . get_substitution ( node) )
214- }
215- fn chain_before ( self , other : Box < dyn AstTransform < ' a > + ' a > ) -> Box < dyn AstTransform < ' a > + ' a > {
216- Box :: new ( QualifyPaths { previous : other, ..self } )
217- }
218- }
219-
220214pub ( crate ) fn path_to_ast ( path : hir:: ModPath ) -> ast:: Path {
221215 let parse = ast:: SourceFile :: parse ( & path. to_string ( ) ) ;
222216 parse
0 commit comments