aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion/src/completions
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_completion/src/completions')
-rw-r--r--crates/ide_completion/src/completions/lifetime.rs285
-rw-r--r--crates/ide_completion/src/completions/pattern.rs2
2 files changed, 286 insertions, 1 deletions
diff --git a/crates/ide_completion/src/completions/lifetime.rs b/crates/ide_completion/src/completions/lifetime.rs
new file mode 100644
index 000000000..628c1fb9b
--- /dev/null
+++ b/crates/ide_completion/src/completions/lifetime.rs
@@ -0,0 +1,285 @@
1//! Completes lifetimes and labels.
2use hir::ScopeDef;
3
4use crate::{completions::Completions, context::CompletionContext};
5
6/// Completes lifetimes.
7pub(crate) fn complete_lifetime(acc: &mut Completions, ctx: &CompletionContext) {
8 if !ctx.lifetime_allowed {
9 return;
10 }
11 let param_lifetime = match (
12 &ctx.lifetime_syntax,
13 ctx.lifetime_param_syntax.as_ref().and_then(|lp| lp.lifetime()),
14 ) {
15 (Some(lt), Some(lp)) if lp == lt.clone() => return,
16 (Some(_), Some(lp)) => Some(lp.to_string()),
17 _ => None,
18 };
19
20 ctx.scope.process_all_names(&mut |name, res| {
21 if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res {
22 if param_lifetime != Some(name.to_string()) {
23 acc.add_resolution(ctx, name.to_string(), &res);
24 }
25 }
26 });
27 if param_lifetime.is_none() {
28 acc.add_static_lifetime(ctx);
29 }
30}
31
32/// Completes labels.
33pub(crate) fn complete_label(acc: &mut Completions, ctx: &CompletionContext) {
34 if !ctx.is_label_ref {
35 return;
36 }
37 ctx.scope.process_all_names(&mut |name, res| {
38 if let ScopeDef::Label(_) = res {
39 acc.add_resolution(ctx, name.to_string(), &res);
40 }
41 });
42}
43
44#[cfg(test)]
45mod tests {
46 use expect_test::{expect, Expect};
47
48 use crate::{
49 test_utils::{check_edit, completion_list_with_config, TEST_CONFIG},
50 CompletionConfig, CompletionKind,
51 };
52
53 fn check(ra_fixture: &str, expect: Expect) {
54 check_with_config(TEST_CONFIG, ra_fixture, expect);
55 }
56
57 fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) {
58 let actual = completion_list_with_config(config, ra_fixture, CompletionKind::Reference);
59 expect.assert_eq(&actual)
60 }
61
62 #[test]
63 fn check_lifetime_edit() {
64 check_edit(
65 "'lifetime",
66 r#"
67fn func<'lifetime>(foo: &'li$0) {}
68"#,
69 r#"
70fn func<'lifetime>(foo: &'lifetime) {}
71"#,
72 );
73 }
74
75 #[test]
76 fn complete_lifetime_in_ref() {
77 check(
78 r#"
79fn foo<'lifetime>(foo: &'a$0 usize) {}
80"#,
81 expect![[r#"
82 lt 'lifetime
83 lt 'static
84 "#]],
85 );
86 }
87
88 #[test]
89 fn complete_lifetime_in_ref_missing_ty() {
90 check(
91 r#"
92fn foo<'lifetime>(foo: &'a$0) {}
93"#,
94 expect![[r#"
95 lt 'lifetime
96 lt 'static
97 "#]],
98 );
99 }
100 #[test]
101 fn complete_lifetime_in_self_ref() {
102 check(
103 r#"
104struct Foo;
105impl<'impl> Foo {
106 fn foo<'func>(&'a$0 self) {}
107}
108"#,
109 expect![[r#"
110 lt 'func
111 lt 'impl
112 lt 'static
113 "#]],
114 );
115 }
116
117 #[test]
118 fn complete_lifetime_in_arg_list() {
119 check(
120 r#"
121struct Foo<'lt>;
122fn foo<'lifetime>(_: Foo<'a$0>) {}
123"#,
124 expect![[r#"
125 lt 'lifetime
126 lt 'static
127 "#]],
128 );
129 }
130
131 #[test]
132 fn complete_lifetime_in_where_pred() {
133 check(
134 r#"
135fn foo2<'lifetime, T>() where 'a$0 {}
136"#,
137 expect![[r#"
138 lt 'lifetime
139 lt 'static
140 "#]],
141 );
142 }
143
144 #[test]
145 fn complete_lifetime_in_ty_bound() {
146 check(
147 r#"
148fn foo2<'lifetime, T>() where T: 'a$0 {}
149"#,
150 expect![[r#"
151 lt 'lifetime
152 lt 'static
153 "#]],
154 );
155 check(
156 r#"
157fn foo2<'lifetime, T>() where T: Trait<'a$0> {}
158"#,
159 expect![[r#"
160 lt 'lifetime
161 lt 'static
162 "#]],
163 );
164 }
165
166 #[test]
167 fn dont_complete_lifetime_in_assoc_ty_bound() {
168 check(
169 r#"
170fn foo2<'lifetime, T>() where T: Trait<Item = 'a$0> {}
171"#,
172 expect![[r#""#]],
173 );
174 }
175
176 #[test]
177 fn complete_lifetime_in_param_list() {
178 check(
179 r#"
180fn foo<'a$0>() {}
181"#,
182 expect![[r#""#]],
183 );
184 check(
185 r#"
186fn foo<'footime, 'lifetime: 'a$0>() {}
187"#,
188 expect![[r#"
189 lt 'footime
190 "#]],
191 );
192 }
193
194 #[test]
195 fn complete_label_in_loop() {
196 check(
197 r#"
198fn foo() {
199 'foop: loop {
200 break '$0
201 }
202}
203"#,
204 expect![[r#"
205 lb 'foop
206 "#]],
207 );
208 check(
209 r#"
210fn foo() {
211 'foop: loop {
212 continue '$0
213 }
214}
215"#,
216 expect![[r#"
217 lb 'foop
218 "#]],
219 );
220 }
221
222 #[test]
223 fn complete_label_in_block_nested() {
224 check(
225 r#"
226fn foo() {
227 'foop: {
228 'baap: {
229 break '$0
230 }
231 }
232}
233"#,
234 expect![[r#"
235 lb 'baap
236 lb 'foop
237 "#]],
238 );
239 }
240
241 #[test]
242 fn complete_label_in_loop_with_value() {
243 check(
244 r#"
245fn foo() {
246 'foop: loop {
247 break '$0 i32;
248 }
249}
250"#,
251 expect![[r#"
252 lb 'foop
253 "#]],
254 );
255 }
256
257 #[test]
258 fn complete_label_in_while_cond() {
259 check(
260 r#"
261fn foo() {
262 'outer: while { 'inner: loop { break '$0 } } {}
263}
264"#,
265 expect![[r#"
266 lb 'inner
267 lb 'outer
268 "#]],
269 );
270 }
271
272 #[test]
273 fn complete_label_in_for_iterable() {
274 check(
275 r#"
276fn foo() {
277 'outer: for _ in [{ 'inner: loop { break '$0 } }] {}
278}
279"#,
280 expect![[r#"
281 lb 'inner
282 "#]],
283 );
284 }
285}
diff --git a/crates/ide_completion/src/completions/pattern.rs b/crates/ide_completion/src/completions/pattern.rs
index 476eecff0..b06498e6d 100644
--- a/crates/ide_completion/src/completions/pattern.rs
+++ b/crates/ide_completion/src/completions/pattern.rs
@@ -1,4 +1,4 @@
1//! Completes constats and paths in patterns. 1//! Completes constants and paths in patterns.
2 2
3use crate::{CompletionContext, Completions}; 3use crate::{CompletionContext, Completions};
4 4