@@ -127,6 +127,7 @@ pub(crate) fn hover(
127
127
original_token. parent( ) . and_then( ast:: TokenTree :: cast) ,
128
128
Some ( tt) if tt. syntax( ) . ancestors( ) . any( |it| ast:: Meta :: can_cast( it. kind( ) ) )
129
129
) ;
130
+
130
131
// prefer descending the same token kind in attribute expansions, in normal macros text
131
132
// equivalency is more important
132
133
let descended = if in_attr {
@@ -135,54 +136,67 @@ pub(crate) fn hover(
135
136
sema. descend_into_macros_with_same_text ( original_token. clone ( ) )
136
137
} ;
137
138
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
147
140
let result = descended
148
141
. 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)
158
146
} )
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
+ }
167
178
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) ?;
170
182
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
+ } )
186
200
}
187
201
188
202
pub ( crate ) fn hover_for_definition (
@@ -269,6 +283,7 @@ fn hover_type_fallback(
269
283
} ;
270
284
271
285
let res = render:: type_info ( sema, config, & expr_or_pat) ?;
286
+
272
287
let range = sema
273
288
. original_range_opt ( & node)
274
289
. map ( |frange| frange. range )
0 commit comments