aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/completion/complete_scope.rs
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-01-08 19:48:48 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-01-08 19:48:48 +0000
commit46f74e33ca53a7897e9020d3de75cc76a6b89d79 (patch)
tree2bc001c8ecf58b49ac9a0da1f20d5644ce29fb3a /crates/ra_ide_api/src/completion/complete_scope.rs
parent4f4f7933b1b7ff34f8633b1686b18b2d1b994c47 (diff)
parent0c62b1bb7a49bf527780ce1f8cade5eb4fbfdb2d (diff)
Merge #471
471: rename crates to match reality r=matklad a=matklad Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_ide_api/src/completion/complete_scope.rs')
-rw-r--r--crates/ra_ide_api/src/completion/complete_scope.rs192
1 files changed, 192 insertions, 0 deletions
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs
new file mode 100644
index 000000000..ee9052d3d
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/complete_scope.rs
@@ -0,0 +1,192 @@
1use rustc_hash::FxHashSet;
2use ra_syntax::TextUnit;
3
4use crate::{
5 Cancelable,
6 completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext},
7};
8
9pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) -> Cancelable<()> {
10 if !ctx.is_trivial_path {
11 return Ok(());
12 }
13 let module = match &ctx.module {
14 Some(it) => it,
15 None => return Ok(()),
16 };
17 if let Some(function) = &ctx.function {
18 let scopes = function.scopes(ctx.db)?;
19 complete_fn(acc, &scopes, ctx.offset);
20 }
21
22 let module_scope = module.scope(ctx.db)?;
23 let (file_id, _) = module.defenition_source(ctx.db)?;
24 module_scope
25 .entries()
26 .filter(|(_name, res)| {
27 // Don't expose this item
28 // FIXME: this penetrates through all kinds of abstractions,
29 // we need to figura out the way to do it less ugly.
30 match res.import {
31 None => true,
32 Some(import) => {
33 let range = import.range(ctx.db, file_id);
34 !range.is_subrange(&ctx.leaf.range())
35 }
36 }
37 })
38 .for_each(|(name, res)| {
39 CompletionItem::new(CompletionKind::Reference, name.to_string())
40 .from_resolution(ctx, res)
41 .add_to(acc)
42 });
43 Ok(())
44}
45
46fn complete_fn(acc: &mut Completions, scopes: &hir::ScopesWithSyntaxMapping, offset: TextUnit) {
47 let mut shadowed = FxHashSet::default();
48 scopes
49 .scope_chain_for_offset(offset)
50 .flat_map(|scope| scopes.scopes.entries(scope).iter())
51 .filter(|entry| shadowed.insert(entry.name()))
52 .for_each(|entry| {
53 CompletionItem::new(CompletionKind::Reference, entry.name().to_string())
54 .kind(CompletionItemKind::Binding)
55 .add_to(acc)
56 });
57}
58
59#[cfg(test)]
60mod tests {
61 use crate::completion::{CompletionKind, check_completion};
62
63 fn check_reference_completion(code: &str, expected_completions: &str) {
64 check_completion(code, expected_completions, CompletionKind::Reference);
65 }
66
67 #[test]
68 fn completes_bindings_from_let() {
69 check_reference_completion(
70 r"
71 fn quux(x: i32) {
72 let y = 92;
73 1 + <|>;
74 let z = ();
75 }
76 ",
77 r#"y;x;quux "quux($0)""#,
78 );
79 }
80
81 #[test]
82 fn completes_bindings_from_if_let() {
83 check_reference_completion(
84 r"
85 fn quux() {
86 if let Some(x) = foo() {
87 let y = 92;
88 };
89 if let Some(a) = bar() {
90 let b = 62;
91 1 + <|>
92 }
93 }
94 ",
95 r#"b;a;quux "quux()$0""#,
96 );
97 }
98
99 #[test]
100 fn completes_bindings_from_for() {
101 check_reference_completion(
102 r"
103 fn quux() {
104 for x in &[1, 2, 3] {
105 <|>
106 }
107 }
108 ",
109 r#"x;quux "quux()$0""#,
110 );
111 }
112
113 #[test]
114 fn completes_module_items() {
115 check_reference_completion(
116 r"
117 struct Foo;
118 enum Baz {}
119 fn quux() {
120 <|>
121 }
122 ",
123 r#"quux "quux()$0";Foo;Baz"#,
124 );
125 }
126
127 #[test]
128 fn completes_module_items_in_nested_modules() {
129 check_reference_completion(
130 r"
131 struct Foo;
132 mod m {
133 struct Bar;
134 fn quux() { <|> }
135 }
136 ",
137 r#"quux "quux()$0";Bar"#,
138 );
139 }
140
141 #[test]
142 fn completes_return_type() {
143 check_reference_completion(
144 r"
145 struct Foo;
146 fn x() -> <|>
147 ",
148 r#"Foo;x "x()$0""#,
149 )
150 }
151
152 #[test]
153 fn dont_show_both_completions_for_shadowing() {
154 check_reference_completion(
155 r"
156 fn foo() -> {
157 let bar = 92;
158 {
159 let bar = 62;
160 <|>
161 }
162 }
163 ",
164 r#"bar;foo "foo()$0""#,
165 )
166 }
167
168 #[test]
169 fn completes_self_in_methods() {
170 check_reference_completion(r"impl S { fn foo(&self) { <|> } }", "self")
171 }
172
173 #[test]
174 fn inserts_parens_for_function_calls() {
175 check_reference_completion(
176 r"
177 fn no_args() {}
178 fn main() { no_<|> }
179 ",
180 r#"no_args "no_args()$0"
181 main "main()$0""#,
182 );
183 check_reference_completion(
184 r"
185 fn with_args(x: i32, y: String) {}
186 fn main() { with_<|> }
187 ",
188 r#"main "main()$0"
189 with_args "with_args($0)""#,
190 );
191 }
192}