1
1
//! `AstTransformer`s are functions that replace nodes in an AST and can be easily combined.
2
2
use rustc_hash:: FxHashMap ;
3
3
4
- use hir:: { InFile , PathResolution } ;
4
+ use hir:: { PathResolution , SemanticsScope } ;
5
5
use ra_ide_db:: RootDatabase ;
6
6
use ra_syntax:: ast:: { self , AstNode } ;
7
7
8
8
pub trait AstTransform < ' a > {
9
- fn get_substitution (
10
- & self ,
11
- node : InFile < & ra_syntax:: SyntaxNode > ,
12
- ) -> Option < ra_syntax:: SyntaxNode > ;
9
+ fn get_substitution ( & self , node : & ra_syntax:: SyntaxNode ) -> Option < ra_syntax:: SyntaxNode > ;
13
10
14
11
fn chain_before ( self , other : Box < dyn AstTransform < ' a > + ' a > ) -> Box < dyn AstTransform < ' a > + ' a > ;
15
12
fn or < T : AstTransform < ' a > + ' a > ( self , other : T ) -> Box < dyn AstTransform < ' a > + ' a >
@@ -23,10 +20,7 @@ pub trait AstTransform<'a> {
23
20
struct NullTransformer ;
24
21
25
22
impl < ' a > AstTransform < ' a > for NullTransformer {
26
- fn get_substitution (
27
- & self ,
28
- _node : InFile < & ra_syntax:: SyntaxNode > ,
29
- ) -> Option < ra_syntax:: SyntaxNode > {
23
+ fn get_substitution ( & self , _node : & ra_syntax:: SyntaxNode ) -> Option < ra_syntax:: SyntaxNode > {
30
24
None
31
25
}
32
26
fn chain_before ( self , other : Box < dyn AstTransform < ' a > + ' a > ) -> Box < dyn AstTransform < ' a > + ' a > {
@@ -35,14 +29,16 @@ impl<'a> AstTransform<'a> for NullTransformer {
35
29
}
36
30
37
31
pub struct SubstituteTypeParams < ' a > {
38
- db : & ' a RootDatabase ,
32
+ source_scope : & ' a SemanticsScope < ' a , RootDatabase > ,
39
33
substs : FxHashMap < hir:: TypeParam , ast:: TypeRef > ,
40
34
previous : Box < dyn AstTransform < ' a > + ' a > ,
41
35
}
42
36
43
37
impl < ' a > SubstituteTypeParams < ' a > {
44
38
pub fn for_trait_impl (
39
+ source_scope : & ' a SemanticsScope < ' a , RootDatabase > ,
45
40
db : & ' a RootDatabase ,
41
+ // FIXME: there's implicit invariant that `trait_` and `source_scope` match...
46
42
trait_ : hir:: Trait ,
47
43
impl_block : ast:: ImplBlock ,
48
44
) -> SubstituteTypeParams < ' a > {
@@ -56,7 +52,7 @@ impl<'a> SubstituteTypeParams<'a> {
56
52
. zip ( substs. into_iter ( ) )
57
53
. collect ( ) ;
58
54
return SubstituteTypeParams {
59
- db ,
55
+ source_scope ,
60
56
substs : substs_by_param,
61
57
previous : Box :: new ( NullTransformer ) ,
62
58
} ;
@@ -80,15 +76,15 @@ impl<'a> SubstituteTypeParams<'a> {
80
76
}
81
77
fn get_substitution_inner (
82
78
& self ,
83
- node : InFile < & ra_syntax:: SyntaxNode > ,
79
+ node : & ra_syntax:: SyntaxNode ,
84
80
) -> Option < ra_syntax:: SyntaxNode > {
85
- let type_ref = ast:: TypeRef :: cast ( node. value . clone ( ) ) ?;
81
+ let type_ref = ast:: TypeRef :: cast ( node. clone ( ) ) ?;
86
82
let path = match & type_ref {
87
83
ast:: TypeRef :: PathType ( path_type) => path_type. path ( ) ?,
88
84
_ => return None ,
89
85
} ;
90
- let analyzer = hir:: SourceAnalyzer :: new ( self . db , node , None ) ;
91
- let resolution = analyzer . resolve_path ( self . db , & path) ?;
86
+ let path = hir:: Path :: from_ast ( path ) ? ;
87
+ let resolution = self . source_scope . resolve_hir_path ( & path) ?;
92
88
match resolution {
93
89
hir:: PathResolution :: TypeParam ( tp) => Some ( self . substs . get ( & tp) ?. syntax ( ) . clone ( ) ) ,
94
90
_ => None ,
@@ -97,10 +93,7 @@ impl<'a> SubstituteTypeParams<'a> {
97
93
}
98
94
99
95
impl < ' a > AstTransform < ' a > for SubstituteTypeParams < ' a > {
100
- fn get_substitution (
101
- & self ,
102
- node : InFile < & ra_syntax:: SyntaxNode > ,
103
- ) -> Option < ra_syntax:: SyntaxNode > {
96
+ fn get_substitution ( & self , node : & ra_syntax:: SyntaxNode ) -> Option < ra_syntax:: SyntaxNode > {
104
97
self . get_substitution_inner ( node) . or_else ( || self . previous . get_substitution ( node) )
105
98
}
106
99
fn chain_before ( self , other : Box < dyn AstTransform < ' a > + ' a > ) -> Box < dyn AstTransform < ' a > + ' a > {
@@ -109,29 +102,34 @@ impl<'a> AstTransform<'a> for SubstituteTypeParams<'a> {
109
102
}
110
103
111
104
pub struct QualifyPaths < ' a > {
105
+ target_scope : & ' a SemanticsScope < ' a , RootDatabase > ,
106
+ source_scope : & ' a SemanticsScope < ' a , RootDatabase > ,
112
107
db : & ' a RootDatabase ,
113
- from : Option < hir:: Module > ,
114
108
previous : Box < dyn AstTransform < ' a > + ' a > ,
115
109
}
116
110
117
111
impl < ' a > QualifyPaths < ' a > {
118
- pub fn new ( db : & ' a RootDatabase , from : Option < hir:: Module > ) -> Self {
119
- Self { db, from, previous : Box :: new ( NullTransformer ) }
112
+ pub fn new (
113
+ target_scope : & ' a SemanticsScope < ' a , RootDatabase > ,
114
+ source_scope : & ' a SemanticsScope < ' a , RootDatabase > ,
115
+ db : & ' a RootDatabase ,
116
+ ) -> Self {
117
+ Self { target_scope, source_scope, db, previous : Box :: new ( NullTransformer ) }
120
118
}
121
119
122
120
fn get_substitution_inner (
123
121
& self ,
124
- node : InFile < & ra_syntax:: SyntaxNode > ,
122
+ node : & ra_syntax:: SyntaxNode ,
125
123
) -> Option < ra_syntax:: SyntaxNode > {
126
124
// FIXME handle value ns?
127
- let from = self . from ?;
128
- let p = ast:: Path :: cast ( node. value . clone ( ) ) ?;
125
+ let from = self . target_scope . module ( ) ?;
126
+ let p = ast:: Path :: cast ( node. clone ( ) ) ?;
129
127
if p. segment ( ) . and_then ( |s| s. param_list ( ) ) . is_some ( ) {
130
128
// don't try to qualify `Fn(Foo) -> Bar` paths, they are in prelude anyway
131
129
return None ;
132
130
}
133
- let analyzer = hir:: SourceAnalyzer :: new ( self . db , node , None ) ;
134
- let resolution = analyzer . resolve_path ( self . db , & p ) ?;
131
+ let hir_path = hir:: Path :: from_ast ( p . clone ( ) ) ;
132
+ let resolution = self . source_scope . resolve_hir_path ( & hir_path? ) ?;
135
133
match resolution {
136
134
PathResolution :: Def ( def) => {
137
135
let found_path = from. find_use_path ( self . db , def) ?;
@@ -140,7 +138,7 @@ impl<'a> QualifyPaths<'a> {
140
138
let type_args = p
141
139
. segment ( )
142
140
. and_then ( |s| s. type_arg_list ( ) )
143
- . map ( |arg_list| apply ( self , node . with_value ( arg_list) ) ) ;
141
+ . map ( |arg_list| apply ( self , arg_list) ) ;
144
142
if let Some ( type_args) = type_args {
145
143
let last_segment = path. segment ( ) . unwrap ( ) ;
146
144
path = path. with_segment ( last_segment. with_type_args ( type_args) )
@@ -157,11 +155,11 @@ impl<'a> QualifyPaths<'a> {
157
155
}
158
156
}
159
157
160
- pub fn apply < ' a , N : AstNode > ( transformer : & dyn AstTransform < ' a > , node : InFile < N > ) -> N {
161
- let syntax = node. value . syntax ( ) ;
158
+ pub fn apply < ' a , N : AstNode > ( transformer : & dyn AstTransform < ' a > , node : N ) -> N {
159
+ let syntax = node. syntax ( ) ;
162
160
let result = ra_syntax:: algo:: replace_descendants ( syntax, & |element| match element {
163
161
ra_syntax:: SyntaxElement :: Node ( n) => {
164
- let replacement = transformer. get_substitution ( node . with_value ( & n ) ) ?;
162
+ let replacement = transformer. get_substitution ( & n ) ?;
165
163
Some ( replacement. into ( ) )
166
164
}
167
165
_ => None ,
@@ -170,10 +168,7 @@ pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: InFile<N>
170
168
}
171
169
172
170
impl < ' a > AstTransform < ' a > for QualifyPaths < ' a > {
173
- fn get_substitution (
174
- & self ,
175
- node : InFile < & ra_syntax:: SyntaxNode > ,
176
- ) -> Option < ra_syntax:: SyntaxNode > {
171
+ fn get_substitution ( & self , node : & ra_syntax:: SyntaxNode ) -> Option < ra_syntax:: SyntaxNode > {
177
172
self . get_substitution_inner ( node) . or_else ( || self . previous . get_substitution ( node) )
178
173
}
179
174
fn chain_before ( self , other : Box < dyn AstTransform < ' a > + ' a > ) -> Box < dyn AstTransform < ' a > + ' a > {
0 commit comments