@@ -15,7 +15,7 @@ use span::{Edition, EditionedFileId};
1515use stdx:: never;
1616use syntax:: {
1717 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 ,
1919} ;
2020use text_edit:: TextEdit ;
2121
@@ -95,26 +95,27 @@ pub(crate) fn inlay_hints(
9595 let famous_defs = FamousDefs ( & sema, scope. krate ( ) ) ;
9696
9797 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+ }
109102 } ;
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+ }
111113 acc
112114}
113115
114116#[ derive( Default ) ]
115117struct InlayHintCtx {
116118 lifetime_stacks : Vec < Vec < SmolStr > > ,
117- is_param_list : bool ,
118119}
119120
120121pub ( crate ) fn inlay_hints_resolve (
@@ -138,20 +139,52 @@ pub(crate) fn inlay_hints_resolve(
138139 let mut acc = Vec :: new ( ) ;
139140
140141 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+ }
150146 } ;
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+ }
152158 acc. into_iter ( ) . find ( |hint| hasher ( hint) == hash)
153159}
154160
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+
155188// FIXME: At some point when our hir infra is fleshed out enough we should flip this and traverse the
156189// HIR instead of the syntax tree.
157190fn hints (
@@ -160,35 +193,8 @@ fn hints(
160193 famous_defs @ FamousDefs ( sema, _) : & FamousDefs < ' _ , ' _ > ,
161194 config : & InlayHintsConfig ,
162195 file_id : EditionedFileId ,
163- node : WalkEvent < SyntaxNode > ,
196+ node : SyntaxNode ,
164197) {
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-
192198 closing_brace:: hints ( hints, sema, config, file_id, node. clone ( ) ) ;
193199 if let Some ( any_has_generic_args) = ast:: AnyHasGenericArgs :: cast ( node. clone ( ) ) {
194200 generic_param:: hints ( hints, sema, config, any_has_generic_args) ;
@@ -242,10 +248,6 @@ fn hints(
242248 ast:: Type :: PathType ( path) => lifetime:: fn_path_hints( hints, ctx, famous_defs, config, file_id, path) ,
243249 _ => Some ( ( ) ) ,
244250 } ,
245- ast:: ParamList ( _) => {
246- ctx. is_param_list = true ;
247- Some ( ( ) )
248- } ,
249251 _ => Some ( ( ) ) ,
250252 }
251253 } ;
0 commit comments