@@ -127,6 +127,7 @@ pub(crate) fn hover(
127127 original_token. parent( ) . and_then( ast:: TokenTree :: cast) ,
128128 Some ( tt) if tt. syntax( ) . ancestors( ) . any( |it| ast:: Meta :: can_cast( it. kind( ) ) )
129129 ) ;
130+
130131 // prefer descending the same token kind in attribute expansions, in normal macros text
131132 // equivalency is more important
132133 let descended = if in_attr {
@@ -135,54 +136,67 @@ pub(crate) fn hover(
135136 sema. descend_into_macros_with_same_text ( original_token. clone ( ) )
136137 } ;
137138
138- // FIXME: Definition should include known lints and the like instead of having this special case here
139- let hovered_lint = descended. iter ( ) . find_map ( |token| {
140- let attr = token. parent_ancestors ( ) . find_map ( ast:: Attr :: cast) ?;
141- render:: try_for_lint ( & attr, token)
142- } ) ;
143- if let Some ( res) = hovered_lint {
144- return Some ( RangeInfo :: new ( original_token. text_range ( ) , res) ) ;
145- }
146-
139+ // try lint hover
147140 let result = descended
148141 . iter ( )
149- . filter_map ( |token| {
150- let node = token. parent ( ) ?;
151- let class = IdentClass :: classify_token ( sema, token) ?;
152- if let IdentClass :: Operator ( OperatorClass :: Await ( _) ) = class {
153- // It's better for us to fall back to the keyword hover here,
154- // rendering poll is very confusing
155- return None ;
156- }
157- Some ( class. definitions ( ) . into_iter ( ) . zip ( iter:: once ( node) . cycle ( ) ) )
142+ . find_map ( |token| {
143+ // FIXME: Definition should include known lints and the like instead of having this special case here
144+ let attr = token. parent_ancestors ( ) . find_map ( ast:: Attr :: cast) ?;
145+ render:: try_for_lint ( & attr, token)
158146 } )
159- . flatten ( )
160- . unique_by ( |& ( def, _) | def)
161- . filter_map ( |( def, node) | hover_for_definition ( sema, file_id, def, & node, config) )
162- . reduce ( |mut acc : HoverResult , HoverResult { markup, actions } | {
163- acc. actions . extend ( actions) ;
164- acc. markup = Markup :: from ( format ! ( "{}\n ---\n {}" , acc. markup, markup) ) ;
165- acc
166- } ) ;
147+ // try item definitions
148+ . or_else ( || {
149+ descended
150+ . iter ( )
151+ . filter_map ( |token| {
152+ let node = token. parent ( ) ?;
153+ let class = IdentClass :: classify_token ( sema, token) ?;
154+ if let IdentClass :: Operator ( OperatorClass :: Await ( _) ) = class {
155+ // It's better for us to fall back to the keyword hover here,
156+ // rendering poll is very confusing
157+ return None ;
158+ }
159+ Some ( class. definitions ( ) . into_iter ( ) . zip ( iter:: once ( node) . cycle ( ) ) )
160+ } )
161+ . flatten ( )
162+ . unique_by ( |& ( def, _) | def)
163+ . filter_map ( |( def, node) | hover_for_definition ( sema, file_id, def, & node, config) )
164+ . reduce ( |mut acc : HoverResult , HoverResult { markup, actions } | {
165+ acc. actions . extend ( actions) ;
166+ acc. markup = Markup :: from ( format ! ( "{}\n ---\n {}" , acc. markup, markup) ) ;
167+ acc
168+ } )
169+ } )
170+ // try keywords
171+ . or_else ( || descended. iter ( ) . find_map ( |token| render:: keyword ( sema, config, token) ) )
172+ // try rest item hover
173+ . or_else ( || {
174+ descended. iter ( ) . find_map ( |token| {
175+ if token. kind ( ) != DOT2 {
176+ return None ;
177+ }
167178
168- if result. is_none ( ) {
169- // fallbacks, show keywords or types
179+ let rest_pat = token. parent ( ) . and_then ( ast:: RestPat :: cast) ?;
180+ let record_pat_field_list =
181+ rest_pat. syntax ( ) . parent ( ) . and_then ( ast:: RecordPatFieldList :: cast) ?;
170182
171- let res = descended. iter ( ) . find_map ( |token| render:: keyword ( sema, config, token) ) ;
172- if let Some ( res) = res {
173- return Some ( RangeInfo :: new ( original_token. text_range ( ) , res) ) ;
174- }
175- let res = descended
176- . iter ( )
177- . find_map ( |token| hover_type_fallback ( sema, config, token, & original_token) ) ;
178- if let Some ( _) = res {
179- return res;
180- }
181- }
182- result. map ( |mut res : HoverResult | {
183- res. actions = dedupe_or_merge_hover_actions ( res. actions ) ;
184- RangeInfo :: new ( original_token. text_range ( ) , res)
185- } )
183+ let record_pat =
184+ record_pat_field_list. syntax ( ) . parent ( ) . and_then ( ast:: RecordPat :: cast) ?;
185+
186+ Some ( render:: struct_rest_pat ( sema, config, & record_pat) )
187+ } )
188+ } ) ;
189+
190+ result
191+ . map ( |mut res : HoverResult | {
192+ res. actions = dedupe_or_merge_hover_actions ( res. actions ) ;
193+ RangeInfo :: new ( original_token. text_range ( ) , res)
194+ } )
195+ // fallback to type hover if there aren't any other suggestions
196+ // this finds its own range instead of using the closest token's range
197+ . or_else ( || {
198+ descended. iter ( ) . find_map ( |token| hover_type_fallback ( sema, config, token, & token) )
199+ } )
186200}
187201
188202pub ( crate ) fn hover_for_definition (
@@ -269,6 +283,7 @@ fn hover_type_fallback(
269283 } ;
270284
271285 let res = render:: type_info ( sema, config, & expr_or_pat) ?;
286+
272287 let range = sema
273288 . original_range_opt ( & node)
274289 . map ( |frange| frange. range )
0 commit comments