@@ -48,7 +48,6 @@ pub(super) enum PathKind {
48
48
Expr {
49
49
in_block_expr : bool ,
50
50
in_loop_body : bool ,
51
- in_functional_update : bool ,
52
51
} ,
53
52
Type ,
54
53
Attr {
@@ -115,6 +114,8 @@ pub(super) struct PatternContext {
115
114
pub ( super ) parent_pat : Option < ast:: Pat > ,
116
115
pub ( super ) ref_token : Option < SyntaxToken > ,
117
116
pub ( super ) mut_token : Option < SyntaxToken > ,
117
+ /// The record pattern this name or ref is a field of
118
+ pub ( super ) record_pat : Option < ast:: RecordPat > ,
118
119
}
119
120
120
121
#[ derive( Debug ) ]
@@ -166,8 +167,11 @@ pub(super) enum NameKind {
166
167
pub ( super ) struct NameRefContext {
167
168
/// NameRef syntax in the original file
168
169
pub ( super ) nameref : Option < ast:: NameRef > ,
170
+ // FIXME: these fields are actually disjoint -> enum
169
171
pub ( super ) dot_access : Option < DotAccess > ,
170
172
pub ( super ) path_ctx : Option < PathCompletionCtx > ,
173
+ /// The record expression this nameref is a field of
174
+ pub ( super ) record_expr : Option < ( ast:: RecordExpr , bool ) > ,
171
175
}
172
176
173
177
#[ derive( Debug ) ]
@@ -375,14 +379,15 @@ impl<'a> CompletionContext<'a> {
375
379
pub ( crate ) fn is_path_disallowed ( & self ) -> bool {
376
380
self . previous_token_is ( T ! [ unsafe ] )
377
381
|| matches ! ( self . prev_sibling, Some ( ImmediatePrevSibling :: Visibility ) )
378
- || matches ! (
379
- self . completion_location,
380
- Some ( ImmediateLocation :: RecordPat ( _) | ImmediateLocation :: RecordExpr ( _) )
381
- )
382
382
|| matches ! (
383
383
self . name_ctx( ) ,
384
384
Some ( NameContext { kind: NameKind :: Module ( _) | NameKind :: Rename , .. } )
385
385
)
386
+ || matches ! ( self . pattern_ctx, Some ( PatternContext { record_pat: Some ( _) , .. } ) )
387
+ || matches ! (
388
+ self . nameref_ctx( ) ,
389
+ Some ( NameRefContext { record_expr: Some ( ( _, false ) ) , .. } )
390
+ )
386
391
}
387
392
388
393
pub ( crate ) fn path_context ( & self ) -> Option < & PathCompletionCtx > {
@@ -1023,14 +1028,13 @@ impl<'a> CompletionContext<'a> {
1023
1028
ast:: Enum ( _) => NameKind :: Enum ,
1024
1029
ast:: Fn ( _) => NameKind :: Function ,
1025
1030
ast:: IdentPat ( bind_pat) => {
1026
- let is_name_in_field_pat = bind_pat
1027
- . syntax( )
1028
- . parent( )
1029
- . and_then( ast:: RecordPatField :: cast)
1030
- . map_or( false , |pat_field| pat_field. name_ref( ) . is_none( ) ) ;
1031
- if !is_name_in_field_pat {
1032
- pat_ctx = Some ( pattern_context_for( original_file, bind_pat. into( ) ) ) ;
1033
- }
1031
+ pat_ctx = Some ( {
1032
+ let mut pat_ctx = pattern_context_for( original_file, bind_pat. into( ) ) ;
1033
+ if let Some ( record_field) = ast:: RecordPatField :: for_field_name( & name) {
1034
+ pat_ctx. record_pat = find_node_in_file_compensated( original_file, & record_field. parent_record_pat( ) ) ;
1035
+ }
1036
+ pat_ctx
1037
+ } ) ;
1034
1038
1035
1039
NameKind :: IdentPat
1036
1040
} ,
@@ -1062,7 +1066,33 @@ impl<'a> CompletionContext<'a> {
1062
1066
) -> ( NameRefContext , Option < PatternContext > ) {
1063
1067
let nameref = find_node_at_offset ( & original_file, name_ref. syntax ( ) . text_range ( ) . start ( ) ) ;
1064
1068
1065
- let mut nameref_ctx = NameRefContext { dot_access : None , path_ctx : None , nameref } ;
1069
+ let mut nameref_ctx =
1070
+ NameRefContext { dot_access : None , path_ctx : None , nameref, record_expr : None } ;
1071
+
1072
+ if let Some ( record_field) = ast:: RecordExprField :: for_field_name ( & name_ref) {
1073
+ nameref_ctx. record_expr =
1074
+ find_node_in_file_compensated ( original_file, & record_field. parent_record_lit ( ) )
1075
+ . zip ( Some ( false ) ) ;
1076
+ return ( nameref_ctx, None ) ;
1077
+ }
1078
+ if let Some ( record_field) = ast:: RecordPatField :: for_field_name_ref ( & name_ref) {
1079
+ let pat_ctx =
1080
+ pattern_context_for ( original_file, record_field. parent_record_pat ( ) . clone ( ) . into ( ) ) ;
1081
+ return (
1082
+ nameref_ctx,
1083
+ Some ( PatternContext {
1084
+ param_ctx : None ,
1085
+ has_type_ascription : false ,
1086
+ ref_token : None ,
1087
+ mut_token : None ,
1088
+ record_pat : find_node_in_file_compensated (
1089
+ original_file,
1090
+ & record_field. parent_record_pat ( ) ,
1091
+ ) ,
1092
+ ..pat_ctx
1093
+ } ) ,
1094
+ ) ;
1095
+ }
1066
1096
1067
1097
let segment = match_ast ! {
1068
1098
match parent {
@@ -1115,8 +1145,11 @@ impl<'a> CompletionContext<'a> {
1115
1145
} )
1116
1146
. unwrap_or ( false )
1117
1147
} ;
1118
- let is_in_func_update = |it : & SyntaxNode | {
1119
- it. parent ( ) . map_or ( false , |it| ast:: RecordExprFieldList :: can_cast ( it. kind ( ) ) )
1148
+ let mut fill_record_expr = |syn : & SyntaxNode | {
1149
+ if let Some ( record_expr) = syn. ancestors ( ) . nth ( 2 ) . and_then ( ast:: RecordExpr :: cast) {
1150
+ nameref_ctx. record_expr =
1151
+ find_node_in_file_compensated ( original_file, & record_expr) . zip ( Some ( true ) ) ;
1152
+ }
1120
1153
} ;
1121
1154
1122
1155
let kind = path. syntax ( ) . ancestors ( ) . find_map ( |it| {
@@ -1125,11 +1158,12 @@ impl<'a> CompletionContext<'a> {
1125
1158
match it {
1126
1159
ast:: PathType ( _) => Some ( PathKind :: Type ) ,
1127
1160
ast:: PathExpr ( it) => {
1161
+ fill_record_expr( it. syntax( ) ) ;
1162
+
1128
1163
path_ctx. has_call_parens = it. syntax( ) . parent( ) . map_or( false , |it| ast:: CallExpr :: can_cast( it. kind( ) ) ) ;
1129
1164
let in_block_expr = is_in_block( it. syntax( ) ) ;
1130
1165
let in_loop_body = is_in_loop_body( it. syntax( ) ) ;
1131
- let in_functional_update = is_in_func_update( it. syntax( ) ) ;
1132
- Some ( PathKind :: Expr { in_block_expr, in_loop_body, in_functional_update } )
1166
+ Some ( PathKind :: Expr { in_block_expr, in_loop_body } )
1133
1167
} ,
1134
1168
ast:: TupleStructPat ( it) => {
1135
1169
path_ctx. has_call_parens = true ;
@@ -1163,8 +1197,8 @@ impl<'a> CompletionContext<'a> {
1163
1197
return Some ( parent. and_then( ast:: MacroExpr :: cast) . map( |it| {
1164
1198
let in_loop_body = is_in_loop_body( it. syntax( ) ) ;
1165
1199
let in_block_expr = is_in_block( it. syntax( ) ) ;
1166
- let in_functional_update = is_in_func_update ( it. syntax( ) ) ;
1167
- PathKind :: Expr { in_block_expr, in_loop_body, in_functional_update }
1200
+ fill_record_expr ( it. syntax( ) ) ;
1201
+ PathKind :: Expr { in_block_expr, in_loop_body }
1168
1202
} ) ) ;
1169
1203
} ,
1170
1204
}
@@ -1299,6 +1333,7 @@ fn pattern_context_for(original_file: &SyntaxNode, pat: ast::Pat) -> PatternCont
1299
1333
parent_pat : pat. syntax ( ) . parent ( ) . and_then ( ast:: Pat :: cast) ,
1300
1334
mut_token,
1301
1335
ref_token,
1336
+ record_pat : None ,
1302
1337
}
1303
1338
}
1304
1339
0 commit comments