use Completions to collect completions
This commit is contained in:
parent
052e20162a
commit
ba0072401c
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user