Skip to content

Commit 6b24629

Browse files
committed
Move more ImmediateLocation::TypeAnnotation into PathKind::Type
1 parent 6e07b17 commit 6b24629

File tree

4 files changed

+142
-122
lines changed

4 files changed

+142
-122
lines changed

crates/ide-completion/src/completions/field.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub(crate) fn complete_field_list(acc: &mut Completions, ctx: &CompletionContext
1818
is_absolute_path: false,
1919
qualifier: None,
2020
parent: None,
21-
kind: PathKind::Type { in_tuple_struct: true },
21+
kind: PathKind::Type { in_tuple_struct: true, ascription: None },
2222
has_type_args: false,
2323
..
2424
})),

crates/ide-completion/src/completions/type.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use ide_db::FxHashSet;
55
use syntax::{ast, AstNode};
66

77
use crate::{
8-
context::{PathCompletionCtx, PathKind, PathQualifierCtx},
9-
patterns::{ImmediateLocation, TypeAnnotation},
8+
context::{PathCompletionCtx, PathKind, PathQualifierCtx, TypeAscriptionTarget},
9+
patterns::ImmediateLocation,
1010
render::render_type_inference,
1111
CompletionContext, Completions,
1212
};
@@ -189,14 +189,22 @@ pub(crate) fn complete_type_path(acc: &mut Completions, ctx: &CompletionContext)
189189
}
190190

191191
pub(crate) fn complete_inferred_type(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
192-
use TypeAnnotation::*;
193-
let pat = match &ctx.completion_location {
194-
Some(ImmediateLocation::TypeAnnotation(t)) => t,
192+
let pat = match dbg!(ctx.path_context()) {
193+
Some(
194+
ctx @ PathCompletionCtx {
195+
kind: PathKind::Type { ascription: Some(ascription), .. },
196+
..
197+
},
198+
) if ctx.is_trivial_path() => ascription,
195199
_ => return None,
196200
};
197201
let x = match pat {
198-
Let(pat) | FnParam(pat) => ctx.sema.type_of_pat(pat.as_ref()?),
199-
Const(exp) | RetType(exp) => ctx.sema.type_of_expr(exp.as_ref()?),
202+
TypeAscriptionTarget::Let(pat) | TypeAscriptionTarget::FnParam(pat) => {
203+
ctx.sema.type_of_pat(pat.as_ref()?)
204+
}
205+
TypeAscriptionTarget::Const(exp) | TypeAscriptionTarget::RetType(exp) => {
206+
ctx.sema.type_of_expr(exp.as_ref()?)
207+
}
200208
}?
201209
.adjusted();
202210
let ty_string = x.display_source_code(ctx.db, ctx.module.into()).ok()?;

crates/ide-completion/src/context.rs

+124-44
Original file line numberDiff line numberDiff line change
@@ -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)]
8548
pub(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)]
9761
pub(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)]
131147
pub(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)]
143160
pub(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)]
155173
pub(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)]
161180
pub(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)]
169189
pub(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)]
177198
pub(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)]
200222
pub(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)]
207230
pub(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)]
217241
pub(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)]
232260
pub(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

Comments
 (0)