mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 06:11:35 +00:00
use Completions to collect completions
This commit is contained in:
parent
052e20162a
commit
ba0072401c
3 changed files with 38 additions and 26 deletions
|
@ -15,7 +15,8 @@ use hir::source_binder;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db,
|
db,
|
||||||
Cancelable, FilePosition
|
Cancelable, FilePosition,
|
||||||
|
completion::completion_item::Completions,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use crate::completion::completion_item::{CompletionItem, InsertText};
|
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 module = ctry!(source_binder::module_from_position(db, position)?);
|
||||||
|
|
||||||
let mut res = Vec::new();
|
let mut acc = Completions::default();
|
||||||
let mut has_completions = false;
|
let mut has_completions = false;
|
||||||
// First, let's try to complete a reference to some declaration.
|
// 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) {
|
if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) {
|
||||||
has_completions = true;
|
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) {} }`
|
// special case, `trait T { fn foo(i_am_a_name_ref) {} }`
|
||||||
if is_node::<ast::Param>(name_ref.syntax()) {
|
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 let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), position.offset) {
|
||||||
if is_node::<ast::Param>(name.syntax()) {
|
if is_node::<ast::Param>(name.syntax()) {
|
||||||
has_completions = true;
|
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)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +65,7 @@ pub(crate) fn completions(
|
||||||
/// functions in a file have a `spam: &mut Spam` parameter, a completion with
|
/// 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
|
/// `spam: &mut Spam` insert text/label and `spam` lookup string will be
|
||||||
/// suggested.
|
/// suggested.
|
||||||
fn param_completions(acc: &mut Vec<CompletionItem>, ctx: SyntaxNodeRef) {
|
fn param_completions(acc: &mut Completions, ctx: SyntaxNodeRef) {
|
||||||
let mut params = FxHashMap::default();
|
let mut params = FxHashMap::default();
|
||||||
for node in ctx.ancestors() {
|
for node in ctx.ancestors() {
|
||||||
let _ = visitor_ctx(&mut params)
|
let _ = visitor_ctx(&mut params)
|
||||||
|
|
|
@ -53,8 +53,8 @@ pub(crate) struct Builder {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Builder {
|
impl Builder {
|
||||||
pub fn add_to(self, acc: &mut Vec<CompletionItem>) {
|
pub fn add_to(self, acc: &mut Completions) {
|
||||||
acc.push(self.build())
|
acc.add(self.build())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(self) -> CompletionItem {
|
pub fn build(self) -> CompletionItem {
|
||||||
|
@ -81,7 +81,7 @@ impl Into<CompletionItem> for Builder {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents an in-progress set of completions being built.
|
/// Represents an in-progress set of completions being built.
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Default)]
|
||||||
pub(crate) struct Completions {
|
pub(crate) struct Completions {
|
||||||
buf: Vec<CompletionItem>,
|
buf: Vec<CompletionItem>,
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,13 @@ impl Completions {
|
||||||
pub(crate) fn add(&mut self, item: impl Into<CompletionItem>) {
|
pub(crate) fn add(&mut self, item: impl Into<CompletionItem>) {
|
||||||
self.buf.push(item.into())
|
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 {
|
impl Into<Vec<CompletionItem>> for Completions {
|
||||||
|
|
|
@ -13,12 +13,12 @@ use hir::{
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::RootDatabase,
|
db::RootDatabase,
|
||||||
completion::CompletionItem,
|
completion::{CompletionItem, Completions},
|
||||||
Cancelable
|
Cancelable
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(super) fn completions(
|
pub(super) fn completions(
|
||||||
acc: &mut Vec<CompletionItem>,
|
acc: &mut Completions,
|
||||||
db: &RootDatabase,
|
db: &RootDatabase,
|
||||||
module: &hir::Module,
|
module: &hir::Module,
|
||||||
file: &SourceFileNode,
|
file: &SourceFileNode,
|
||||||
|
@ -117,7 +117,7 @@ fn classify_name_ref(name_ref: ast::NameRef) -> Option<NameRefKind> {
|
||||||
None
|
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();
|
let mut shadowed = FxHashSet::default();
|
||||||
scopes
|
scopes
|
||||||
.scope_chain(name_ref.syntax())
|
.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(
|
fn complete_path(
|
||||||
acc: &mut Vec<CompletionItem>,
|
acc: &mut Completions,
|
||||||
db: &RootDatabase,
|
db: &RootDatabase,
|
||||||
module: &hir::Module,
|
module: &hir::Module,
|
||||||
mut path: Path,
|
mut path: Path,
|
||||||
|
@ -154,7 +154,7 @@ fn complete_path(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn complete_mod_item_snippets(acc: &mut Vec<CompletionItem>) {
|
fn complete_mod_item_snippets(acc: &mut Completions) {
|
||||||
CompletionItem::new("Test function")
|
CompletionItem::new("Test function")
|
||||||
.lookup_by("tfn")
|
.lookup_by("tfn")
|
||||||
.snippet(
|
.snippet(
|
||||||
|
@ -174,26 +174,26 @@ fn complete_expr_keywords(
|
||||||
file: &SourceFileNode,
|
file: &SourceFileNode,
|
||||||
fn_def: ast::FnDef,
|
fn_def: ast::FnDef,
|
||||||
name_ref: ast::NameRef,
|
name_ref: ast::NameRef,
|
||||||
acc: &mut Vec<CompletionItem>,
|
acc: &mut Completions,
|
||||||
) {
|
) {
|
||||||
acc.push(keyword("if", "if $0 {}"));
|
acc.add(keyword("if", "if $0 {}"));
|
||||||
acc.push(keyword("match", "match $0 {}"));
|
acc.add(keyword("match", "match $0 {}"));
|
||||||
acc.push(keyword("while", "while $0 {}"));
|
acc.add(keyword("while", "while $0 {}"));
|
||||||
acc.push(keyword("loop", "loop {$0}"));
|
acc.add(keyword("loop", "loop {$0}"));
|
||||||
|
|
||||||
if let Some(off) = name_ref.syntax().range().start().checked_sub(2.into()) {
|
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 let Some(if_expr) = find_node_at_offset::<ast::IfExpr>(file.syntax(), off) {
|
||||||
if if_expr.syntax().range().end() < name_ref.syntax().range().start() {
|
if if_expr.syntax().range().end() < name_ref.syntax().range().start() {
|
||||||
acc.push(keyword("else", "else {$0}"));
|
acc.add(keyword("else", "else {$0}"));
|
||||||
acc.push(keyword("else if", "else if $0 {}"));
|
acc.add(keyword("else if", "else if $0 {}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if is_in_loop_body(name_ref) {
|
if is_in_loop_body(name_ref) {
|
||||||
acc.push(keyword("continue", "continue"));
|
acc.add(keyword("continue", "continue"));
|
||||||
acc.push(keyword("break", "break"));
|
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 {
|
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()
|
CompletionItem::new(kw).snippet(snippet).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn complete_expr_snippets(acc: &mut Vec<CompletionItem>) {
|
fn complete_expr_snippets(acc: &mut Completions) {
|
||||||
CompletionItem::new("pd")
|
CompletionItem::new("pd")
|
||||||
.snippet("eprintln!(\"$0 = {:?}\", $0);")
|
.snippet("eprintln!(\"$0 = {:?}\", $0);")
|
||||||
.add_to(acc);
|
.add_to(acc);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue