2 mod completion_context;
12 use ra_db::SourceDatabase;
13 use ra_syntax::ast::{self, AstNode};
19 completion_item::{Completions, CompletionKind},
20 completion_context::CompletionContext,
24 pub use crate::completion::completion_item::{CompletionItem, CompletionItemKind, InsertTextFormat};
26 /// Main entry point for completion. We run completion as a two-phase process.
28 /// First, we look at the position and collect a so-called `CompletionContext.
29 /// This is a somewhat messy process, because, during completion, syntax tree is
30 /// incomplete and can look really weird.
32 /// Once the context is collected, we run a series of completion routines which
33 /// look at the context and produce completion items. One subtelty about this
34 /// phase is that completion engine should not filter by the substring which is
35 /// already present, it should give all possible variants for the identifier at
36 /// the caret. In other words, for
45 /// `foo` *should* be present among the completion variants. Filtering by
46 /// identifier prefix/fuzzy match should be done higher in the stack, together
47 /// with ordering of completions (currently this is done by the client).
48 pub(crate) fn completions(db: &db::RootDatabase, position: FilePosition) -> Option<Completions> {
49 let original_file = db.parse(position.file_id);
50 let ctx = CompletionContext::new(db, &original_file, position)?;
52 let mut acc = Completions::default();
54 complete_fn_param::complete_fn_param(&mut acc, &ctx);
55 complete_keyword::complete_expr_keyword(&mut acc, &ctx);
56 complete_keyword::complete_use_tree_keyword(&mut acc, &ctx);
57 complete_snippet::complete_expr_snippet(&mut acc, &ctx);
58 complete_snippet::complete_item_snippet(&mut acc, &ctx);
59 complete_path::complete_path(&mut acc, &ctx);
60 complete_scope::complete_scope(&mut acc, &ctx);
61 complete_dot::complete_dot(&mut acc, &ctx);
62 complete_postfix::complete_postfix(&mut acc, &ctx);
66 pub fn function_label(node: &ast::FnDef) -> Option<String> {
67 let label: String = if let Some(body) = node.body() {
68 let body_range = body.syntax().range();
69 let label: String = node
72 .filter(|child| !child.range().is_subrange(&body_range)) // Filter out body
73 .filter(|child| ast::Comment::cast(child).is_none()) // Filter out comments
74 .map(|node| node.text().to_string())
78 node.syntax().text().to_string()
81 Some(label.trim().to_owned())