use Completions to collect completions

This commit is contained in:
Aleksey Kladov 2018-12-21 15:46:01 +03:00
parent 052e20162a
commit ba0072401c
3 changed files with 38 additions and 26 deletions

View File

@ -15,7 +15,8 @@ use hir::source_binder;
use crate::{
db,
Cancelable, FilePosition
Cancelable, FilePosition,
completion::completion_item::Completions,
};
pub use crate::completion::completion_item::{CompletionItem, InsertText};
@ -33,15 +34,15 @@ pub(crate) fn completions(
let module = ctry!(source_binder::module_from_position(db, position)?);
let mut res = Vec::new();
let mut acc = Completions::default();
let mut has_completions = false;
// First, let's try to complete a reference to some declaration.
if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) {
has_completions = true;
reference_completion::completions(&mut res, db, &module, &file, name_ref)?;
reference_completion::completions(&mut acc, db, &module, &file, name_ref)?;
// special case, `trait T { fn foo(i_am_a_name_ref) {} }`
if is_node::<ast::Param>(name_ref.syntax()) {
param_completions(&mut res, name_ref.syntax());
param_completions(&mut acc, name_ref.syntax());
}
}
@ -49,10 +50,14 @@ pub(crate) fn completions(
if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), position.offset) {
if is_node::<ast::Param>(name.syntax()) {
has_completions = true;
param_completions(&mut res, name.syntax());
param_completions(&mut acc, name.syntax());
}
}
let res = if has_completions { Some(res) } else { None };
let res = if has_completions {
Some(acc.into())
} else {
None
};
Ok(res)
}
@ -60,7 +65,7 @@ pub(crate) fn completions(
/// functions in a file have a `spam: &mut Spam` parameter, a completion with
/// `spam: &mut Spam` insert text/label and `spam` lookup string will be
/// suggested.
fn param_completions(acc: &mut Vec<CompletionItem>, ctx: SyntaxNodeRef) {
fn param_completions(acc: &mut Completions, ctx: SyntaxNodeRef) {
let mut params = FxHashMap::default();
for node in ctx.ancestors() {
let _ = visitor_ctx(&mut params)

View File

@ -53,8 +53,8 @@ pub(crate) struct Builder {
}
impl Builder {
pub fn add_to(self, acc: &mut Vec<CompletionItem>) {
acc.push(self.build())
pub fn add_to(self, acc: &mut Completions) {
acc.add(self.build())
}
pub fn build(self) -> CompletionItem {
@ -81,7 +81,7 @@ impl Into<CompletionItem> for Builder {
}
/// Represents an in-progress set of completions being built.
#[derive(Debug)]
#[derive(Debug, Default)]
pub(crate) struct Completions {
buf: Vec<CompletionItem>,
}
@ -90,6 +90,13 @@ impl Completions {
pub(crate) fn add(&mut self, item: impl Into<CompletionItem>) {
self.buf.push(item.into())
}
pub(crate) fn add_all<I>(&mut self, items: I)
where
I: IntoIterator,
I::Item: Into<CompletionItem>,
{
items.into_iter().for_each(|item| self.add(item.into()))
}
}
impl Into<Vec<CompletionItem>> for Completions {

View File

@ -13,12 +13,12 @@ use hir::{
use crate::{
db::RootDatabase,
completion::CompletionItem,
completion::{CompletionItem, Completions},
Cancelable
};
pub(super) fn completions(
acc: &mut Vec<CompletionItem>,
acc: &mut Completions,
db: &RootDatabase,
module: &hir::Module,
file: &SourceFileNode,
@ -117,7 +117,7 @@ fn classify_name_ref(name_ref: ast::NameRef) -> Option<NameRefKind> {
None
}
fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) {
fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Completions) {
let mut shadowed = FxHashSet::default();
scopes
.scope_chain(name_ref.syntax())
@ -130,7 +130,7 @@ fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<Completi
}
fn complete_path(
acc: &mut Vec<CompletionItem>,
acc: &mut Completions,
db: &RootDatabase,
module: &hir::Module,
mut path: Path,
@ -154,7 +154,7 @@ fn complete_path(
Ok(())
}
fn complete_mod_item_snippets(acc: &mut Vec<CompletionItem>) {
fn complete_mod_item_snippets(acc: &mut Completions) {
CompletionItem::new("Test function")
.lookup_by("tfn")
.snippet(
@ -174,26 +174,26 @@ fn complete_expr_keywords(
file: &SourceFileNode,
fn_def: ast::FnDef,
name_ref: ast::NameRef,
acc: &mut Vec<CompletionItem>,
acc: &mut Completions,
) {
acc.push(keyword("if", "if $0 {}"));
acc.push(keyword("match", "match $0 {}"));
acc.push(keyword("while", "while $0 {}"));
acc.push(keyword("loop", "loop {$0}"));
acc.add(keyword("if", "if $0 {}"));
acc.add(keyword("match", "match $0 {}"));
acc.add(keyword("while", "while $0 {}"));
acc.add(keyword("loop", "loop {$0}"));
if let Some(off) = name_ref.syntax().range().start().checked_sub(2.into()) {
if let Some(if_expr) = find_node_at_offset::<ast::IfExpr>(file.syntax(), off) {
if if_expr.syntax().range().end() < name_ref.syntax().range().start() {
acc.push(keyword("else", "else {$0}"));
acc.push(keyword("else if", "else if $0 {}"));
acc.add(keyword("else", "else {$0}"));
acc.add(keyword("else if", "else if $0 {}"));
}
}
}
if is_in_loop_body(name_ref) {
acc.push(keyword("continue", "continue"));
acc.push(keyword("break", "break"));
acc.add(keyword("continue", "continue"));
acc.add(keyword("break", "break"));
}
acc.extend(complete_return(fn_def, name_ref));
acc.add_all(complete_return(fn_def, name_ref));
}
fn is_in_loop_body(name_ref: ast::NameRef) -> bool {
@ -252,7 +252,7 @@ fn keyword(kw: &str, snippet: &str) -> CompletionItem {
CompletionItem::new(kw).snippet(snippet).build()
}
fn complete_expr_snippets(acc: &mut Vec<CompletionItem>) {
fn complete_expr_snippets(acc: &mut Completions) {
CompletionItem::new("pd")
.snippet("eprintln!(\"$0 = {:?}\", $0);")
.add_to(acc);