@@ -43,44 +43,7 @@ pub(crate) enum Visible {
4343 No ,
4444}
4545
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.
8447#[ derive( Debug , Default ) ]
8548pub ( super ) struct QualifierCtx {
8649 pub ( super ) unsafe_tok : Option < SyntaxToken > ,
@@ -93,6 +56,7 @@ impl QualifierCtx {
9356 }
9457}
9558
59+ /// The state of the path we are currently completing.
9660#[ derive( Debug ) ]
9761pub ( crate ) struct PathCompletionCtx {
9862 /// If this is a call with () already there (or {} in case of record patterns)
@@ -127,6 +91,58 @@ impl PathCompletionCtx {
12791 }
12892}
12993
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.
130146#[ derive( Debug ) ]
131147pub ( crate ) struct PathQualifierCtx {
132148 pub ( crate ) path : ast:: Path ,
@@ -139,6 +155,7 @@ pub(crate) struct PathQualifierCtx {
139155 pub ( crate ) is_infer_qualifier : bool ,
140156}
141157
158+ /// The state of the pattern we are completing.
142159#[ derive( Debug ) ]
143160pub ( super ) struct PatternContext {
144161 pub ( super ) refutability : PatternRefutability ,
@@ -151,12 +168,14 @@ pub(super) struct PatternContext {
151168 pub ( super ) record_pat : Option < ast:: RecordPat > ,
152169}
153170
171+ /// The state of the lifetime we are completing.
154172#[ derive( Debug ) ]
155173pub ( super ) struct LifetimeContext {
156174 pub ( super ) lifetime : Option < ast:: Lifetime > ,
157175 pub ( super ) kind : LifetimeKind ,
158176}
159177
178+ /// The kind of lifetime we are completing.
160179#[ derive( Debug ) ]
161180pub ( super ) enum LifetimeKind {
162181 LifetimeParam { is_decl : bool , param : ast:: LifetimeParam } ,
@@ -165,13 +184,15 @@ pub(super) enum LifetimeKind {
165184 LabelDef ,
166185}
167186
187+ /// The state of the name we are completing.
168188#[ derive( Debug ) ]
169189pub ( super ) struct NameContext {
170190 #[ allow( dead_code) ]
171191 pub ( super ) name : Option < ast:: Name > ,
172192 pub ( super ) kind : NameKind ,
173193}
174194
195+ /// The kind of the name we are completing.
175196#[ derive( Debug ) ]
176197#[ allow( dead_code) ]
177198pub ( super ) enum NameKind {
@@ -196,13 +217,15 @@ pub(super) enum NameKind {
196217 Variant ,
197218}
198219
220+ /// The state of the NameRef we are completing.
199221#[ derive( Debug ) ]
200222pub ( super ) struct NameRefContext {
201223 /// NameRef syntax in the original file
202224 pub ( super ) nameref : Option < ast:: NameRef > ,
203225 pub ( super ) kind : Option < NameRefKind > ,
204226}
205227
228+ /// The kind of the NameRef we are completing.
206229#[ derive( Debug ) ]
207230pub ( super ) enum NameRefKind {
208231 Path ( PathCompletionCtx ) ,
@@ -213,21 +236,26 @@ pub(super) enum NameRefKind {
213236 RecordExpr ( ast:: RecordExpr ) ,
214237}
215238
239+ /// The identifier we are currently completing.
216240#[ derive( Debug ) ]
217241pub ( super ) enum IdentContext {
218242 Name ( NameContext ) ,
219243 NameRef ( NameRefContext ) ,
220244 Lifetime ( LifetimeContext ) ,
221- /// Original token, fake token
245+ /// The string the cursor is currently inside
222246 String {
247+ /// original token
223248 original : ast:: String ,
249+ /// fake token
224250 expanded : Option < ast:: String > ,
225251 } ,
252+ /// Set if we are currently completing in an unexpanded attribute, this usually implies a builtin attribute like `allow($0)`
226253 UnexpandedAttrTT {
227254 fake_attribute_under_caret : Option < ast:: Attr > ,
228255 } ,
229256}
230257
258+ /// Information about the field or method access we are completing.
231259#[ derive( Debug ) ]
232260pub ( super ) struct DotAccess {
233261 pub ( super ) receiver : Option < ast:: Expr > ,
@@ -1161,13 +1189,65 @@ impl<'a> CompletionContext<'a> {
11611189 None
11621190 } ;
11631191
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+
11641240 // Infer the path kind
11651241 let kind = path. syntax ( ) . parent ( ) . and_then ( |it| {
11661242 match_ast ! {
11671243 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+ } ,
11711251 ast:: PathExpr ( it) => {
11721252 if let Some ( p) = it. syntax( ) . parent( ) {
11731253 if ast:: ExprStmt :: can_cast( p. kind( ) ) {
@@ -1178,7 +1258,7 @@ impl<'a> CompletionContext<'a> {
11781258 }
11791259 }
11801260
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( ) ) ) ;
11821262 let in_block_expr = is_in_block( it. syntax( ) ) ;
11831263 let in_loop_body = is_in_loop_body( it. syntax( ) ) ;
11841264 let after_if_expr = after_if_expr( it. syntax( ) . clone( ) ) ;
@@ -1212,7 +1292,7 @@ impl<'a> CompletionContext<'a> {
12121292 let parent = it. syntax( ) . parent( ) ;
12131293 match parent. as_ref( ) . map( |it| it. kind( ) ) {
12141294 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 } ) ,
12161296 Some ( SyntaxKind :: ITEM_LIST ) => Some ( PathKind :: Item { kind: ItemListKind :: Module } ) ,
12171297 Some ( SyntaxKind :: ASSOC_ITEM_LIST ) => Some ( PathKind :: Item { kind: match parent. and_then( |it| it. parent( ) ) {
12181298 Some ( it) => match_ast! {
0 commit comments