@@ -43,44 +43,7 @@ pub(crate) enum Visible {
43
43
No ,
44
44
}
45
45
46
- #[ derive( Clone , Debug , PartialEq , Eq ) ]
47
- pub ( super ) enum PathKind {
48
- Expr {
49
- in_block_expr : bool ,
50
- in_loop_body : bool ,
51
- after_if_expr : bool ,
52
- ref_expr_parent : Option < ast:: RefExpr > ,
53
- is_func_update : Option < ast:: RecordExpr > ,
54
- } ,
55
- Type {
56
- in_tuple_struct : bool ,
57
- } ,
58
- Attr {
59
- kind : AttrKind ,
60
- annotated_item_kind : Option < SyntaxKind > ,
61
- } ,
62
- Derive ,
63
- /// Path in item position, that is inside an (Assoc)ItemList
64
- Item {
65
- kind : ItemListKind ,
66
- } ,
67
- Pat ,
68
- Vis {
69
- has_in_token : bool ,
70
- } ,
71
- Use ,
72
- }
73
-
74
- #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
75
- pub ( super ) enum ItemListKind {
76
- SourceFile ,
77
- Module ,
78
- Impl ,
79
- TraitImpl ,
80
- Trait ,
81
- ExternBlock ,
82
- }
83
-
46
+ /// Existing qualifiers for the thing we are currently completing.
84
47
#[ derive( Debug , Default ) ]
85
48
pub ( super ) struct QualifierCtx {
86
49
pub ( super ) unsafe_tok : Option < SyntaxToken > ,
@@ -93,6 +56,7 @@ impl QualifierCtx {
93
56
}
94
57
}
95
58
59
+ /// The state of the path we are currently completing.
96
60
#[ derive( Debug ) ]
97
61
pub ( crate ) struct PathCompletionCtx {
98
62
/// If this is a call with () already there (or {} in case of record patterns)
@@ -127,6 +91,58 @@ impl PathCompletionCtx {
127
91
}
128
92
}
129
93
94
+ /// The kind of path we are completing right now.
95
+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
96
+ pub ( super ) enum PathKind {
97
+ Expr {
98
+ in_block_expr : bool ,
99
+ in_loop_body : bool ,
100
+ after_if_expr : bool ,
101
+ ref_expr_parent : Option < ast:: RefExpr > ,
102
+ is_func_update : Option < ast:: RecordExpr > ,
103
+ } ,
104
+ Type {
105
+ in_tuple_struct : bool ,
106
+ /// Whether this type path is a type ascription or not
107
+ /// Original file ast node
108
+ ascription : Option < TypeAscriptionTarget > ,
109
+ } ,
110
+ Attr {
111
+ kind : AttrKind ,
112
+ annotated_item_kind : Option < SyntaxKind > ,
113
+ } ,
114
+ Derive ,
115
+ /// Path in item position, that is inside an (Assoc)ItemList
116
+ Item {
117
+ kind : ItemListKind ,
118
+ } ,
119
+ Pat ,
120
+ Vis {
121
+ has_in_token : bool ,
122
+ } ,
123
+ Use ,
124
+ }
125
+
126
+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
127
+ pub ( crate ) enum TypeAscriptionTarget {
128
+ Let ( Option < ast:: Pat > ) ,
129
+ FnParam ( Option < ast:: Pat > ) ,
130
+ RetType ( Option < ast:: Expr > ) ,
131
+ Const ( Option < ast:: Expr > ) ,
132
+ }
133
+
134
+ /// The kind of item list a [`PathKind::Item`] belongs to.
135
+ #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
136
+ pub ( super ) enum ItemListKind {
137
+ SourceFile ,
138
+ Module ,
139
+ Impl ,
140
+ TraitImpl ,
141
+ Trait ,
142
+ ExternBlock ,
143
+ }
144
+
145
+ /// The path qualifier state of the path we are completing.
130
146
#[ derive( Debug ) ]
131
147
pub ( crate ) struct PathQualifierCtx {
132
148
pub ( crate ) path : ast:: Path ,
@@ -139,6 +155,7 @@ pub(crate) struct PathQualifierCtx {
139
155
pub ( crate ) is_infer_qualifier : bool ,
140
156
}
141
157
158
+ /// The state of the pattern we are completing.
142
159
#[ derive( Debug ) ]
143
160
pub ( super ) struct PatternContext {
144
161
pub ( super ) refutability : PatternRefutability ,
@@ -151,12 +168,14 @@ pub(super) struct PatternContext {
151
168
pub ( super ) record_pat : Option < ast:: RecordPat > ,
152
169
}
153
170
171
+ /// The state of the lifetime we are completing.
154
172
#[ derive( Debug ) ]
155
173
pub ( super ) struct LifetimeContext {
156
174
pub ( super ) lifetime : Option < ast:: Lifetime > ,
157
175
pub ( super ) kind : LifetimeKind ,
158
176
}
159
177
178
+ /// The kind of lifetime we are completing.
160
179
#[ derive( Debug ) ]
161
180
pub ( super ) enum LifetimeKind {
162
181
LifetimeParam { is_decl : bool , param : ast:: LifetimeParam } ,
@@ -165,13 +184,15 @@ pub(super) enum LifetimeKind {
165
184
LabelDef ,
166
185
}
167
186
187
+ /// The state of the name we are completing.
168
188
#[ derive( Debug ) ]
169
189
pub ( super ) struct NameContext {
170
190
#[ allow( dead_code) ]
171
191
pub ( super ) name : Option < ast:: Name > ,
172
192
pub ( super ) kind : NameKind ,
173
193
}
174
194
195
+ /// The kind of the name we are completing.
175
196
#[ derive( Debug ) ]
176
197
#[ allow( dead_code) ]
177
198
pub ( super ) enum NameKind {
@@ -196,13 +217,15 @@ pub(super) enum NameKind {
196
217
Variant ,
197
218
}
198
219
220
+ /// The state of the NameRef we are completing.
199
221
#[ derive( Debug ) ]
200
222
pub ( super ) struct NameRefContext {
201
223
/// NameRef syntax in the original file
202
224
pub ( super ) nameref : Option < ast:: NameRef > ,
203
225
pub ( super ) kind : Option < NameRefKind > ,
204
226
}
205
227
228
+ /// The kind of the NameRef we are completing.
206
229
#[ derive( Debug ) ]
207
230
pub ( super ) enum NameRefKind {
208
231
Path ( PathCompletionCtx ) ,
@@ -213,21 +236,26 @@ pub(super) enum NameRefKind {
213
236
RecordExpr ( ast:: RecordExpr ) ,
214
237
}
215
238
239
+ /// The identifier we are currently completing.
216
240
#[ derive( Debug ) ]
217
241
pub ( super ) enum IdentContext {
218
242
Name ( NameContext ) ,
219
243
NameRef ( NameRefContext ) ,
220
244
Lifetime ( LifetimeContext ) ,
221
- /// Original token, fake token
245
+ /// The string the cursor is currently inside
222
246
String {
247
+ /// original token
223
248
original : ast:: String ,
249
+ /// fake token
224
250
expanded : Option < ast:: String > ,
225
251
} ,
252
+ /// Set if we are currently completing in an unexpanded attribute, this usually implies a builtin attribute like `allow($0)`
226
253
UnexpandedAttrTT {
227
254
fake_attribute_under_caret : Option < ast:: Attr > ,
228
255
} ,
229
256
}
230
257
258
+ /// Information about the field or method access we are completing.
231
259
#[ derive( Debug ) ]
232
260
pub ( super ) struct DotAccess {
233
261
pub ( super ) receiver : Option < ast:: Expr > ,
@@ -1161,13 +1189,65 @@ impl<'a> CompletionContext<'a> {
1161
1189
None
1162
1190
} ;
1163
1191
1192
+ let fetch_ascription = |it : Option < SyntaxNode > | {
1193
+ let parent = it?;
1194
+ match_ast ! {
1195
+ match parent {
1196
+ ast:: Const ( it) => {
1197
+ let name = find_in_original_file( it. name( ) , original_file) ?;
1198
+ let original = ast:: Const :: cast( name. syntax( ) . parent( ) ?) ?;
1199
+ Some ( TypeAscriptionTarget :: Const ( original. body( ) ) )
1200
+ } ,
1201
+ ast:: RetType ( it) => {
1202
+ if it. thin_arrow_token( ) . is_none( ) {
1203
+ return None ;
1204
+ }
1205
+ let parent = match ast:: Fn :: cast( parent. parent( ) ?) {
1206
+ Some ( x) => x. param_list( ) ,
1207
+ None => ast:: ClosureExpr :: cast( parent. parent( ) ?) ?. param_list( ) ,
1208
+ } ;
1209
+
1210
+ let parent = find_in_original_file( parent, original_file) ?. syntax( ) . parent( ) ?;
1211
+ Some ( TypeAscriptionTarget :: RetType ( match_ast! {
1212
+ match parent {
1213
+ ast:: ClosureExpr ( it) => {
1214
+ it. body( )
1215
+ } ,
1216
+ ast:: Fn ( it) => {
1217
+ it. body( ) . map( ast:: Expr :: BlockExpr )
1218
+ } ,
1219
+ _ => return None ,
1220
+ }
1221
+ } ) )
1222
+ } ,
1223
+ ast:: Param ( it) => {
1224
+ if it. colon_token( ) . is_none( ) {
1225
+ return None ;
1226
+ }
1227
+ Some ( TypeAscriptionTarget :: FnParam ( find_in_original_file( it. pat( ) , original_file) ) )
1228
+ } ,
1229
+ ast:: LetStmt ( it) => {
1230
+ if it. colon_token( ) . is_none( ) {
1231
+ return None ;
1232
+ }
1233
+ Some ( TypeAscriptionTarget :: Let ( find_in_original_file( it. pat( ) , original_file) ) )
1234
+ } ,
1235
+ _ => None ,
1236
+ }
1237
+ }
1238
+ } ;
1239
+
1164
1240
// Infer the path kind
1165
1241
let kind = path. syntax ( ) . parent ( ) . and_then ( |it| {
1166
1242
match_ast ! {
1167
1243
match it {
1168
- ast:: PathType ( it) => Some ( PathKind :: Type {
1169
- in_tuple_struct: it. syntax( ) . parent( ) . map_or( false , |it| ast:: TupleField :: can_cast( it. kind( ) ) )
1170
- } ) ,
1244
+ ast:: PathType ( it) => {
1245
+ let ascription = fetch_ascription( it. syntax( ) . parent( ) ) ;
1246
+ Some ( PathKind :: Type {
1247
+ in_tuple_struct: it. syntax( ) . parent( ) . map_or( false , |it| ast:: TupleField :: can_cast( it. kind( ) ) ) ,
1248
+ ascription,
1249
+ } )
1250
+ } ,
1171
1251
ast:: PathExpr ( it) => {
1172
1252
if let Some ( p) = it. syntax( ) . parent( ) {
1173
1253
if ast:: ExprStmt :: can_cast( p. kind( ) ) {
@@ -1178,7 +1258,7 @@ impl<'a> CompletionContext<'a> {
1178
1258
}
1179
1259
}
1180
1260
1181
- path_ctx. has_call_parens = it. syntax( ) . parent( ) . map_or( false , |it| ast:: CallExpr :: can_cast( it. kind( ) ) ) ;
1261
+ path_ctx. has_call_parens = it. syntax( ) . parent( ) . map_or( false , |it| ast:: CallExpr :: can_cast( it. kind( ) ) ) ;
1182
1262
let in_block_expr = is_in_block( it. syntax( ) ) ;
1183
1263
let in_loop_body = is_in_loop_body( it. syntax( ) ) ;
1184
1264
let after_if_expr = after_if_expr( it. syntax( ) . clone( ) ) ;
@@ -1212,7 +1292,7 @@ impl<'a> CompletionContext<'a> {
1212
1292
let parent = it. syntax( ) . parent( ) ;
1213
1293
match parent. as_ref( ) . map( |it| it. kind( ) ) {
1214
1294
Some ( SyntaxKind :: MACRO_PAT ) => Some ( PathKind :: Pat ) ,
1215
- Some ( SyntaxKind :: MACRO_TYPE ) => Some ( PathKind :: Type { in_tuple_struct: false } ) ,
1295
+ Some ( SyntaxKind :: MACRO_TYPE ) => Some ( PathKind :: Type { in_tuple_struct: false , ascription : None } ) ,
1216
1296
Some ( SyntaxKind :: ITEM_LIST ) => Some ( PathKind :: Item { kind: ItemListKind :: Module } ) ,
1217
1297
Some ( SyntaxKind :: ASSOC_ITEM_LIST ) => Some ( PathKind :: Item { kind: match parent. and_then( |it| it. parent( ) ) {
1218
1298
Some ( it) => match_ast! {
0 commit comments