@@ -14,7 +14,7 @@ use ide_db::{
1414use itertools:: Itertools ;
1515use stdx:: format_to;
1616use syntax:: {
17- algo, ast, match_ast, AstNode , Direction ,
17+ algo, ast:: { self , RecordPat } , match_ast, AstNode , Direction ,
1818 SyntaxKind :: { LET_EXPR , LET_STMT } ,
1919 SyntaxToken , T ,
2020} ;
@@ -250,6 +250,58 @@ pub(super) fn keyword(
250250 Some ( HoverResult { markup, actions } )
251251}
252252
253+ pub ( super ) fn struct_rest_pat (
254+ sema : & Semantics < ' _ , RootDatabase > ,
255+ config : & HoverConfig ,
256+ expr_or_pat : & Either < ast:: Expr , ast:: Pat > ,
257+ ) -> Option < HoverResult > {
258+ let pat = expr_or_pat. as_ref ( ) . right ( ) ?;
259+
260+ let mut ancestors = sema. ancestors_with_macros ( pat. syntax ( ) . clone ( ) ) ;
261+ let _record_pat_field_list = ancestors. next ( ) ?;
262+ let record_pat = ancestors. next ( ) ?;
263+ let pattern = sema
264+ . find_nodes_at_offset_with_descend :: < RecordPat > (
265+ & record_pat,
266+ record_pat. text_range ( ) . start ( ) )
267+ . next ( ) ?;
268+
269+ let missing_fields = sema. record_pattern_missing_fields ( & pattern) ;
270+
271+ // if there are no missing fields, the end result is a hover that shows ".."
272+ // should be left in to indicate that there are no more fields in the pattern
273+ // example, S {a: 1, b: 2, ..} when struct S {a: u32, b: u32}
274+
275+ let mut res = HoverResult :: default ( ) ;
276+ let mut targets: Vec < hir:: ModuleDef > = Vec :: new ( ) ;
277+ let mut push_new_def = |item : hir:: ModuleDef | {
278+ if !targets. contains ( & item) {
279+ targets. push ( item) ;
280+ }
281+ } ;
282+ for ( _, t) in & missing_fields {
283+ walk_and_push_ty ( sema. db , & t, & mut push_new_def) ;
284+ }
285+
286+ res. markup = {
287+ let mut s = String :: from ( ".., " ) ;
288+ for ( f, _) in & missing_fields {
289+ s += f. display ( sema. db ) . to_string ( ) . as_ref ( ) ;
290+ s += ", " ;
291+ }
292+ // get rid of trailing comma
293+ if s. len ( ) > 0 { s. truncate ( s. len ( ) - 2 ) ; }
294+
295+ if config. markdown ( ) {
296+ Markup :: fenced_block ( & s)
297+ } else {
298+ s. into ( )
299+ }
300+ } ;
301+ res. actions . push ( HoverAction :: goto_type_from_targets ( sema. db , targets) ) ;
302+ Some ( res)
303+ }
304+
253305pub ( super ) fn try_for_lint ( attr : & ast:: Attr , token : & SyntaxToken ) -> Option < HoverResult > {
254306 let ( path, tt) = attr. as_simple_call ( ) ?;
255307 if !tt. syntax ( ) . text_range ( ) . contains ( token. text_range ( ) . start ( ) ) {
0 commit comments