@@ -86,30 +86,38 @@ pub struct HoverResult {
8686// image::https://user-images.githubusercontent.com/48062697/113020658-b5f98b80-917a-11eb-9f88-3dbc27320c95.gif[]
8787pub ( crate ) fn hover (
8888 db : & RootDatabase ,
89- file_range : FileRange ,
89+ frange @ FileRange { file_id , range } : FileRange ,
9090 config : & HoverConfig ,
9191) -> Option < RangeInfo < HoverResult > > {
9292 let sema = & hir:: Semantics :: new ( db) ;
93- let mut res = hover_impl ( sema, file_range, config) ?;
93+ let file = sema. parse ( file_id) . syntax ( ) . clone ( ) ;
94+ let mut res = if range. is_empty ( ) {
95+ hover_simple ( sema, FilePosition { file_id, offset : range. start ( ) } , file, config)
96+ } else {
97+ hover_ranged ( sema, frange, file, config)
98+ } ?;
99+
94100 if let HoverDocFormat :: PlainText = config. format {
95101 res. info . markup = remove_markdown ( res. info . markup . as_str ( ) ) . into ( ) ;
96102 }
97103 Some ( res)
98104}
99105
100- fn hover_impl (
106+ fn hover_simple (
101107 sema : & Semantics < ' _ , RootDatabase > ,
102- FileRange { file_id, range } : FileRange ,
108+ FilePosition { file_id, offset } : FilePosition ,
109+ file : SyntaxNode ,
103110 config : & HoverConfig ,
104111) -> Option < RangeInfo < HoverResult > > {
105- let file = sema. parse ( file_id) . syntax ( ) . clone ( ) ;
106- if !range. is_empty ( ) {
107- return hover_ranged ( & file, range, sema, config) ;
108- }
109- let offset = range. start ( ) ;
110-
111112 let original_token = pick_best_token ( file. token_at_offset ( offset) , |kind| match kind {
112- IDENT | INT_NUMBER | LIFETIME_IDENT | T ! [ self ] | T ! [ super ] | T ! [ crate ] | T ! [ Self ] => 4 ,
113+ IDENT
114+ | INT_NUMBER
115+ | LIFETIME_IDENT
116+ | T ! [ self ]
117+ | T ! [ super ]
118+ | T ! [ crate ]
119+ | T ! [ Self ]
120+ | T ! [ _] => 4 ,
113121 // index and prefix ops
114122 T ! [ '[' ] | T ! [ ']' ] | T ! [ ?] | T ! [ * ] | T ! [ -] | T ! [ !] => 3 ,
115123 kind if kind. is_keyword ( ) => 2 ,
@@ -142,19 +150,18 @@ fn hover_impl(
142150 } else {
143151 sema. descend_into_macros_with_same_text ( original_token. clone ( ) )
144152 } ;
153+ let descended = || descended. iter ( ) ;
145154
146- // try lint hover
147- let result = descended
148- . iter ( )
155+ let result = descended ( )
156+ // try lint hover
149157 . find_map ( |token| {
150158 // FIXME: Definition should include known lints and the like instead of having this special case here
151159 let attr = token. parent_ancestors ( ) . find_map ( ast:: Attr :: cast) ?;
152160 render:: try_for_lint ( & attr, token)
153161 } )
154- // try item definitions
162+ // try definitions
155163 . or_else ( || {
156- descended
157- . iter ( )
164+ descended ( )
158165 . filter_map ( |token| {
159166 let node = token. parent ( ) ?;
160167 let class = IdentClass :: classify_token ( sema, token) ?;
@@ -175,10 +182,12 @@ fn hover_impl(
175182 } )
176183 } )
177184 // try keywords
178- . or_else ( || descended. iter ( ) . find_map ( |token| render:: keyword ( sema, config, token) ) )
179- // try rest item hover
185+ . or_else ( || descended ( ) . find_map ( |token| render:: keyword ( sema, config, token) ) )
186+ // try _ hovers
187+ . or_else ( || descended ( ) . find_map ( |token| render:: underscore ( sema, config, token) ) )
188+ // try rest pattern hover
180189 . or_else ( || {
181- descended. iter ( ) . find_map ( |token| {
190+ descended ( ) . find_map ( |token| {
182191 if token. kind ( ) != DOT2 {
183192 return None ;
184193 }
@@ -201,39 +210,13 @@ fn hover_impl(
201210 } )
202211 // fallback to type hover if there aren't any other suggestions
203212 // this finds its own range instead of using the closest token's range
204- . or_else ( || {
205- descended. iter ( ) . find_map ( |token| hover_type_fallback ( sema, config, token, token) )
206- } )
207- }
208-
209- pub ( crate ) fn hover_for_definition (
210- sema : & Semantics < ' _ , RootDatabase > ,
211- file_id : FileId ,
212- definition : Definition ,
213- node : & SyntaxNode ,
214- config : & HoverConfig ,
215- ) -> Option < HoverResult > {
216- let famous_defs = match & definition {
217- Definition :: BuiltinType ( _) => Some ( FamousDefs ( sema, sema. scope ( node) ?. krate ( ) ) ) ,
218- _ => None ,
219- } ;
220- render:: definition ( sema. db , definition, famous_defs. as_ref ( ) , config) . map ( |markup| {
221- HoverResult {
222- markup : render:: process_markup ( sema. db , definition, & markup, config) ,
223- actions : show_implementations_action ( sema. db , definition)
224- . into_iter ( )
225- . chain ( show_fn_references_action ( sema. db , definition) )
226- . chain ( runnable_action ( sema, definition, file_id) )
227- . chain ( goto_type_action_for_def ( sema. db , definition) )
228- . collect ( ) ,
229- }
230- } )
213+ . or_else ( || descended ( ) . find_map ( |token| hover_type_fallback ( sema, config, token, token) ) )
231214}
232215
233216fn hover_ranged (
234- file : & SyntaxNode ,
235- range : syntax:: TextRange ,
236217 sema : & Semantics < ' _ , RootDatabase > ,
218+ FileRange { range, .. } : FileRange ,
219+ file : SyntaxNode ,
237220 config : & HoverConfig ,
238221) -> Option < RangeInfo < HoverResult > > {
239222 // FIXME: make this work in attributes
@@ -248,7 +231,7 @@ fn hover_ranged(
248231 }
249232 _ => None ,
250233 } ;
251- let res = res. or_else ( || render:: type_info ( sema, config, & expr_or_pat) ) ;
234+ let res = res. or_else ( || render:: type_info_of ( sema, config, & expr_or_pat) ) ;
252235 res. map ( |it| {
253236 let range = match expr_or_pat {
254237 Either :: Left ( it) => it. syntax ( ) . text_range ( ) ,
@@ -258,6 +241,33 @@ fn hover_ranged(
258241 } )
259242}
260243
244+ pub ( crate ) fn hover_for_definition (
245+ sema : & Semantics < ' _ , RootDatabase > ,
246+ file_id : FileId ,
247+ definition : Definition ,
248+ node : & SyntaxNode ,
249+ config : & HoverConfig ,
250+ ) -> Option < HoverResult > {
251+ let famous_defs = match & definition {
252+ Definition :: BuiltinType ( _) => Some ( FamousDefs ( sema, sema. scope ( node) ?. krate ( ) ) ) ,
253+ _ => None ,
254+ } ;
255+ render:: definition ( sema. db , definition, famous_defs. as_ref ( ) , config) . map ( |markup| {
256+ HoverResult {
257+ markup : render:: process_markup ( sema. db , definition, & markup, config) ,
258+ actions : [
259+ show_implementations_action ( sema. db , definition) ,
260+ show_fn_references_action ( sema. db , definition) ,
261+ runnable_action ( sema, definition, file_id) ,
262+ goto_type_action_for_def ( sema. db , definition) ,
263+ ]
264+ . into_iter ( )
265+ . flatten ( )
266+ . collect ( ) ,
267+ }
268+ } )
269+ }
270+
261271fn hover_type_fallback (
262272 sema : & Semantics < ' _ , RootDatabase > ,
263273 config : & HoverConfig ,
@@ -282,7 +292,7 @@ fn hover_type_fallback(
282292 }
283293 } ;
284294
285- let res = render:: type_info ( sema, config, & expr_or_pat) ?;
295+ let res = render:: type_info_of ( sema, config, & expr_or_pat) ?;
286296
287297 let range = sema
288298 . original_range_opt ( & node)
0 commit comments