]> git.lizzy.rs Git - rust.git/blob - crates/ide_completion/src/completions/lifetime.rs
Add label completion
[rust.git] / crates / ide_completion / src / completions / lifetime.rs
1 //! Completes lifetimes and labels.
2 use hir::ScopeDef;
3
4 use crate::{completions::Completions, context::CompletionContext};
5
6 /// Completes lifetimes.
7 pub(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.
33 pub(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)]
45 mod 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#"
67 fn func<'lifetime>(foo: &'li$0) {}
68 "#,
69             r#"
70 fn func<'lifetime>(foo: &'lifetime) {}
71 "#,
72         );
73     }
74
75     #[test]
76     fn complete_lifetime_in_ref() {
77         check(
78             r#"
79 fn 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#"
92 fn 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#"
104 struct Foo;
105 impl<'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#"
121 struct Foo<'lt>;
122 fn 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#"
135 fn 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#"
148 fn foo2<'lifetime, T>() where T: 'a$0 {}
149 "#,
150             expect![[r#"
151                 lt 'lifetime
152                 lt 'static
153             "#]],
154         );
155         check(
156             r#"
157 fn 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#"
170 fn 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#"
180 fn foo<'a$0>() {}
181 "#,
182             expect![[r#""#]],
183         );
184         check(
185             r#"
186 fn 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#"
198 fn foo() {
199     'foop: loop {
200         break '$0
201     }
202 }
203 "#,
204             expect![[r#"
205                 lb 'foop
206             "#]],
207         );
208         check(
209             r#"
210 fn 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#"
226 fn 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#"
245 fn foo() {
246     'foop: loop {
247         break '$0 i32;
248     }
249 }
250 "#,
251             expect![[r#"
252                 lb 'foop
253             "#]],
254         );
255     }
256 }