@@ -5,12 +5,13 @@ use hir::{HirDisplay, PathResolution, SemanticsScope};
5
5
use syntax:: {
6
6
algo:: SyntaxRewriter ,
7
7
ast:: { self , AstNode } ,
8
+ SyntaxNode ,
8
9
} ;
9
10
10
11
pub fn apply < ' a , N : AstNode > ( transformer : & dyn AstTransform < ' a > , node : N ) -> N {
11
12
SyntaxRewriter :: from_fn ( |element| match element {
12
13
syntax:: SyntaxElement :: Node ( n) => {
13
- let replacement = transformer. get_substitution ( & n) ?;
14
+ let replacement = transformer. get_substitution ( & n, transformer ) ?;
14
15
Some ( replacement. into ( ) )
15
16
}
16
17
_ => None ,
@@ -47,32 +48,35 @@ pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: N) -> N {
47
48
/// We'd want to somehow express this concept simpler, but so far nobody got to
48
49
/// simplifying this!
49
50
pub 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 > ;
51
56
52
- fn chain_before ( self , other : Box < dyn AstTransform < ' a > + ' a > ) -> Box < dyn AstTransform < ' a > + ' a > ;
53
57
fn or < T : AstTransform < ' a > + ' a > ( self , other : T ) -> Box < dyn AstTransform < ' a > + ' a >
54
58
where
55
59
Self : Sized + ' a ,
56
60
{
57
- self . chain_before ( Box :: new ( other) )
61
+ Box :: new ( Or ( Box :: new ( self ) , Box :: new ( other) ) )
58
62
}
59
63
}
60
64
61
- struct NullTransformer ;
65
+ struct Or < ' a > ( Box < dyn AstTransform < ' a > + ' a > , Box < dyn AstTransform < ' a > + ' a > ) ;
62
66
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) )
69
74
}
70
75
}
71
76
72
77
pub struct SubstituteTypeParams < ' a > {
73
78
source_scope : & ' a SemanticsScope < ' a > ,
74
79
substs : FxHashMap < hir:: TypeParam , ast:: Type > ,
75
- previous : Box < dyn AstTransform < ' a > + ' a > ,
76
80
}
77
81
78
82
impl < ' a > SubstituteTypeParams < ' a > {
@@ -111,11 +115,7 @@ impl<'a> SubstituteTypeParams<'a> {
111
115
}
112
116
} )
113
117
. 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 } ;
119
119
120
120
// FIXME: It would probably be nicer if we could get this via HIR (i.e. get the
121
121
// trait ref, and then go from the types in the substs back to the syntax).
@@ -140,7 +140,14 @@ impl<'a> SubstituteTypeParams<'a> {
140
140
Some ( result)
141
141
}
142
142
}
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 > {
144
151
let type_ref = ast:: Type :: cast ( node. clone ( ) ) ?;
145
152
let path = match & type_ref {
146
153
ast:: Type :: PathType ( path_type) => path_type. path ( ) ?,
@@ -154,27 +161,23 @@ impl<'a> SubstituteTypeParams<'a> {
154
161
}
155
162
}
156
163
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
-
166
164
pub struct QualifyPaths < ' a > {
167
165
target_scope : & ' a SemanticsScope < ' a > ,
168
166
source_scope : & ' a SemanticsScope < ' a > ,
169
- previous : Box < dyn AstTransform < ' a > + ' a > ,
170
167
}
171
168
172
169
impl < ' a > QualifyPaths < ' a > {
173
170
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 }
175
172
}
173
+ }
176
174
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 > {
178
181
// FIXME handle value ns?
179
182
let from = self . target_scope . module ( ) ?;
180
183
let p = ast:: Path :: cast ( node. clone ( ) ) ?;
@@ -191,7 +194,7 @@ impl<'a> QualifyPaths<'a> {
191
194
let type_args = p
192
195
. segment ( )
193
196
. and_then ( |s| s. generic_arg_list ( ) )
194
- . map ( |arg_list| apply ( self , arg_list) ) ;
197
+ . map ( |arg_list| apply ( recur , arg_list) ) ;
195
198
if let Some ( type_args) = type_args {
196
199
let last_segment = path. segment ( ) . unwrap ( ) ;
197
200
path = path. with_segment ( last_segment. with_generic_args ( type_args) )
@@ -208,15 +211,6 @@ impl<'a> QualifyPaths<'a> {
208
211
}
209
212
}
210
213
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
-
220
214
pub ( crate ) fn path_to_ast ( path : hir:: ModPath ) -> ast:: Path {
221
215
let parse = ast:: SourceFile :: parse ( & path. to_string ( ) ) ;
222
216
parse
0 commit comments