@@ -15,7 +15,7 @@ use span::{Edition, EditionedFileId};
15
15
use stdx:: never;
16
16
use syntax:: {
17
17
ast:: { self , AstNode , HasGenericParams } ,
18
- format_smolstr, match_ast, NodeOrToken , SmolStr , SyntaxNode , TextRange , TextSize , WalkEvent ,
18
+ format_smolstr, match_ast, SmolStr , SyntaxNode , TextRange , TextSize , WalkEvent ,
19
19
} ;
20
20
use text_edit:: TextEdit ;
21
21
@@ -95,26 +95,27 @@ pub(crate) fn inlay_hints(
95
95
let famous_defs = FamousDefs ( & sema, scope. krate ( ) ) ;
96
96
97
97
let ctx = & mut InlayHintCtx :: default ( ) ;
98
- let hints = |node| hints ( & mut acc, ctx, & famous_defs, config, file_id, node) ;
99
- match range_limit {
100
- // FIXME: This can miss some hints that require the parent of the range to calculate
101
- Some ( range) => match file. covering_element ( range) {
102
- NodeOrToken :: Token ( _) => return acc,
103
- NodeOrToken :: Node ( n) => n
104
- . preorder ( )
105
- . filter ( |event| matches ! ( event, WalkEvent :: Enter ( node) if range. intersect( node. text_range( ) ) . is_some( ) ) )
106
- . for_each ( hints) ,
107
- } ,
108
- None => file. preorder ( ) . for_each ( hints) ,
98
+ let mut hints = |event| {
99
+ if let Some ( node) = handle_event ( ctx, event) {
100
+ hints ( & mut acc, ctx, & famous_defs, config, file_id, node) ;
101
+ }
109
102
} ;
110
-
103
+ let mut preorder = file. preorder ( ) ;
104
+ while let Some ( event) = preorder. next ( ) {
105
+ // FIXME: This can miss some hints that require the parent of the range to calculate
106
+ if matches ! ( ( & event, range_limit) , ( WalkEvent :: Enter ( node) , Some ( range) ) if range. intersect( node. text_range( ) ) . is_none( ) )
107
+ {
108
+ preorder. skip_subtree ( ) ;
109
+ continue ;
110
+ }
111
+ hints ( event) ;
112
+ }
111
113
acc
112
114
}
113
115
114
116
#[ derive( Default ) ]
115
117
struct InlayHintCtx {
116
118
lifetime_stacks : Vec < Vec < SmolStr > > ,
117
- is_param_list : bool ,
118
119
}
119
120
120
121
pub ( crate ) fn inlay_hints_resolve (
@@ -138,20 +139,52 @@ pub(crate) fn inlay_hints_resolve(
138
139
let mut acc = Vec :: new ( ) ;
139
140
140
141
let ctx = & mut InlayHintCtx :: default ( ) ;
141
- let hints = |node| hints ( & mut acc, ctx, & famous_defs, config, file_id, node) ;
142
-
143
- let mut res = file. clone ( ) ;
144
- let res = loop {
145
- res = match res. child_or_token_at_range ( resolve_range) {
146
- Some ( NodeOrToken :: Node ( n) ) if n. text_range ( ) == resolve_range => break n,
147
- Some ( NodeOrToken :: Node ( n) ) => n,
148
- _ => break res,
149
- } ;
142
+ let mut hints = |event| {
143
+ if let Some ( node) = handle_event ( ctx, event) {
144
+ hints ( & mut acc, ctx, & famous_defs, config, file_id, node) ;
145
+ }
150
146
} ;
151
- res. preorder ( ) . for_each ( hints) ;
147
+
148
+ let mut preorder = file. preorder ( ) ;
149
+ while let Some ( event) = preorder. next ( ) {
150
+ // FIXME: This can miss some hints that require the parent of the range to calculate
151
+ if matches ! ( & event, WalkEvent :: Enter ( node) if resolve_range. intersect( node. text_range( ) ) . is_none( ) )
152
+ {
153
+ preorder. skip_subtree ( ) ;
154
+ continue ;
155
+ }
156
+ hints ( event) ;
157
+ }
152
158
acc. into_iter ( ) . find ( |hint| hasher ( hint) == hash)
153
159
}
154
160
161
+ fn handle_event ( ctx : & mut InlayHintCtx , node : WalkEvent < SyntaxNode > ) -> Option < SyntaxNode > {
162
+ match node {
163
+ WalkEvent :: Enter ( node) => {
164
+ if let Some ( node) = ast:: AnyHasGenericParams :: cast ( node. clone ( ) ) {
165
+ let params = node
166
+ . generic_param_list ( )
167
+ . map ( |it| {
168
+ it. lifetime_params ( )
169
+ . filter_map ( |it| {
170
+ it. lifetime ( ) . map ( |it| format_smolstr ! ( "{}" , & it. text( ) [ 1 ..] ) )
171
+ } )
172
+ . collect ( )
173
+ } )
174
+ . unwrap_or_default ( ) ;
175
+ ctx. lifetime_stacks . push ( params) ;
176
+ }
177
+ Some ( node)
178
+ }
179
+ WalkEvent :: Leave ( n) => {
180
+ if ast:: AnyHasGenericParams :: can_cast ( n. kind ( ) ) {
181
+ ctx. lifetime_stacks . pop ( ) ;
182
+ }
183
+ None
184
+ }
185
+ }
186
+ }
187
+
155
188
// FIXME: At some point when our hir infra is fleshed out enough we should flip this and traverse the
156
189
// HIR instead of the syntax tree.
157
190
fn hints (
@@ -160,35 +193,8 @@ fn hints(
160
193
famous_defs @ FamousDefs ( sema, _) : & FamousDefs < ' _ , ' _ > ,
161
194
config : & InlayHintsConfig ,
162
195
file_id : EditionedFileId ,
163
- node : WalkEvent < SyntaxNode > ,
196
+ node : SyntaxNode ,
164
197
) {
165
- let node = match node {
166
- WalkEvent :: Enter ( node) => node,
167
- WalkEvent :: Leave ( n) => {
168
- if ast:: AnyHasGenericParams :: can_cast ( n. kind ( ) ) {
169
- ctx. lifetime_stacks . pop ( ) ;
170
- // pop
171
- }
172
- if ast:: ParamList :: can_cast ( n. kind ( ) ) {
173
- ctx. is_param_list = false ;
174
- // pop
175
- }
176
- return ;
177
- }
178
- } ;
179
-
180
- if let Some ( node) = ast:: AnyHasGenericParams :: cast ( node. clone ( ) ) {
181
- let params = node
182
- . generic_param_list ( )
183
- . map ( |it| {
184
- it. lifetime_params ( )
185
- . filter_map ( |it| it. lifetime ( ) . map ( |it| format_smolstr ! ( "{}" , & it. text( ) [ 1 ..] ) ) )
186
- . collect ( )
187
- } )
188
- . unwrap_or_default ( ) ;
189
- ctx. lifetime_stacks . push ( params) ;
190
- }
191
-
192
198
closing_brace:: hints ( hints, sema, config, file_id, node. clone ( ) ) ;
193
199
if let Some ( any_has_generic_args) = ast:: AnyHasGenericArgs :: cast ( node. clone ( ) ) {
194
200
generic_param:: hints ( hints, sema, config, any_has_generic_args) ;
@@ -242,10 +248,6 @@ fn hints(
242
248
ast:: Type :: PathType ( path) => lifetime:: fn_path_hints( hints, ctx, famous_defs, config, file_id, path) ,
243
249
_ => Some ( ( ) ) ,
244
250
} ,
245
- ast:: ParamList ( _) => {
246
- ctx. is_param_list = true ;
247
- Some ( ( ) )
248
- } ,
249
251
_ => Some ( ( ) ) ,
250
252
}
251
253
} ;
0 commit comments