aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/completion.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api/src/completion.rs')
-rw-r--r--crates/ra_ide_api/src/completion.rs77
1 files changed, 77 insertions, 0 deletions
diff --git a/crates/ra_ide_api/src/completion.rs b/crates/ra_ide_api/src/completion.rs
new file mode 100644
index 000000000..ce777a771
--- /dev/null
+++ b/crates/ra_ide_api/src/completion.rs
@@ -0,0 +1,77 @@
1mod completion_item;
2mod completion_context;
3
4mod complete_dot;
5mod complete_fn_param;
6mod complete_keyword;
7mod complete_snippet;
8mod complete_path;
9mod complete_scope;
10
11use ra_db::SyntaxDatabase;
12
13use crate::{
14 db,
15 Cancelable, FilePosition,
16 completion::{
17 completion_item::{Completions, CompletionKind},
18 completion_context::CompletionContext,
19 },
20};
21
22pub use crate::completion::completion_item::{CompletionItem, InsertText, CompletionItemKind};
23
24/// Main entry point for completion. We run completion as a two-phase process.
25///
26/// First, we look at the position and collect a so-called `CompletionContext.
27/// This is a somewhat messy process, because, during completion, syntax tree is
28/// incomplete and can look really weird.
29///
30/// Once the context is collected, we run a series of completion routines which
31/// look at the context and produce completion items. One subtelty about this
32/// phase is that completion engine should not filter by the substring which is
33/// already present, it should give all possible variants for the identifier at
34/// the caret. In other words, for
35///
36/// ```no-run
37/// fn f() {
38/// let foo = 92;
39/// let _ = bar<|>
40/// }
41/// ```
42///
43/// `foo` *should* be present among the completion variants. Filtering by
44/// identifier prefix/fuzzy match should be done higher in the stack, together
45/// with ordering of completions (currently this is done by the client).
46pub(crate) fn completions(
47 db: &db::RootDatabase,
48 position: FilePosition,
49) -> Cancelable<Option<Completions>> {
50 let original_file = db.source_file(position.file_id);
51 let ctx = ctry!(CompletionContext::new(db, &original_file, position)?);
52
53 let mut acc = Completions::default();
54
55 complete_fn_param::complete_fn_param(&mut acc, &ctx);
56 complete_keyword::complete_expr_keyword(&mut acc, &ctx);
57 complete_keyword::complete_use_tree_keyword(&mut acc, &ctx);
58 complete_snippet::complete_expr_snippet(&mut acc, &ctx);
59 complete_snippet::complete_item_snippet(&mut acc, &ctx);
60 complete_path::complete_path(&mut acc, &ctx)?;
61 complete_scope::complete_scope(&mut acc, &ctx)?;
62 complete_dot::complete_dot(&mut acc, &ctx)?;
63
64 Ok(Some(acc))
65}
66
67#[cfg(test)]
68fn check_completion(code: &str, expected_completions: &str, kind: CompletionKind) {
69 use crate::mock_analysis::{single_file_with_position, analysis_and_position};
70 let (analysis, position) = if code.contains("//-") {
71 analysis_and_position(code)
72 } else {
73 single_file_with_position(code)
74 };
75 let completions = completions(&analysis.db, position).unwrap().unwrap();
76 completions.assert_match(expected_completions, kind);
77}