Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,37 +1,77 @@
//! This modules takes care of rendering various definitions as completion items.
//! It also handles scoring (sorting) completions.
//! This module defines an accumulator for completions which are going to be presented to user.

pub(crate) mod attribute;
pub(crate) mod dot;
pub(crate) mod record;
pub(crate) mod pattern;
pub(crate) mod fn_param;
pub(crate) mod keyword;
pub(crate) mod snippet;
pub(crate) mod qualified_path;
pub(crate) mod unqualified_path;
pub(crate) mod postfix;
pub(crate) mod macro_in_item_position;
pub(crate) mod trait_impl;
pub(crate) mod mod_;

use hir::{HasAttrs, HasSource, HirDisplay, ModPath, Mutability, ScopeDef, StructKind, Type};
use itertools::Itertools;
use syntax::{ast::NameOwner, display::*};
use test_utils::mark;

use crate::{
// display::{const_label, function_declaration, macro_label, type_label},
CompletionScore,
RootDatabase,
{
completion_item::Builder, CompletionContext, CompletionItem, CompletionItemKind,
CompletionKind, Completions,
},
item::Builder, CompletionContext, CompletionItem, CompletionItemKind, CompletionKind,
CompletionScore, RootDatabase,
};

/// Represents an in-progress set of completions being built.
#[derive(Debug, Default)]
pub struct Completions {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could some of these pubs be reduced to pub(crate)?

buf: Vec<CompletionItem>,
}

impl Into<Vec<CompletionItem>> for Completions {
fn into(self) -> Vec<CompletionItem> {
self.buf
}
}

impl Builder {
/// Convenience method, which allows to add a freshly created completion into accumulator
/// without binding it to the variable.
pub(crate) fn add_to(self, acc: &mut Completions) {
acc.add(self.build())
}
}

impl Completions {
pub(crate) fn add(&mut self, item: 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()))
}

pub(crate) fn add_field(&mut self, ctx: &CompletionContext, field: hir::Field, ty: &Type) {
let is_deprecated = is_deprecated(field, ctx.db);
let name = field.name(ctx.db);
let mut completion_item =
let mut item =
CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string())
.kind(CompletionItemKind::Field)
.detail(ty.display(ctx.db).to_string())
.set_documentation(field.docs(ctx.db))
.set_deprecated(is_deprecated);

if let Some(score) = compute_score(ctx, &ty, &name.to_string()) {
completion_item = completion_item.set_score(score);
item = item.set_score(score);
}

completion_item.add_to(self);
item.add_to(self);
}

pub(crate) fn add_tuple_field(&mut self, ctx: &CompletionContext, field: usize, ty: &Type) {
Expand All @@ -57,15 +97,17 @@ impl Completions {
let kind = match resolution {
ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::Module,
ScopeDef::ModuleDef(Function(func)) => {
return self.add_function(ctx, *func, Some(local_name));
self.add_function(ctx, *func, Some(local_name));
return;
}
ScopeDef::ModuleDef(Adt(hir::Adt::Struct(_))) => CompletionItemKind::Struct,
// FIXME: add CompletionItemKind::Union
ScopeDef::ModuleDef(Adt(hir::Adt::Union(_))) => CompletionItemKind::Struct,
ScopeDef::ModuleDef(Adt(hir::Adt::Enum(_))) => CompletionItemKind::Enum,

ScopeDef::ModuleDef(EnumVariant(var)) => {
return self.add_enum_variant(ctx, *var, Some(local_name));
self.add_enum_variant(ctx, *var, Some(local_name));
return;
}
ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::Const,
ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::Static,
Expand All @@ -77,13 +119,14 @@ impl Completions {
// (does this need its own kind?)
ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => CompletionItemKind::TypeParam,
ScopeDef::MacroDef(mac) => {
return self.add_macro(ctx, Some(local_name), *mac);
self.add_macro(ctx, Some(local_name), *mac);
return;
}
ScopeDef::Unknown => {
return self.add(
CompletionItem::new(CompletionKind::Reference, ctx.source_range(), local_name)
.kind(CompletionItemKind::UnresolvedReference),
);
CompletionItem::new(CompletionKind::Reference, ctx.source_range(), local_name)
.kind(CompletionItemKind::UnresolvedReference)
.add_to(self);
return;
}
};

Expand All @@ -98,12 +141,11 @@ impl Completions {
_ => None,
};

let mut completion_item =
CompletionItem::new(completion_kind, ctx.source_range(), local_name.clone());
let mut item = CompletionItem::new(completion_kind, ctx.source_range(), local_name.clone());
if let ScopeDef::Local(local) = resolution {
let ty = local.ty(ctx.db);
if !ty.is_unknown() {
completion_item = completion_item.detail(ty.display(ctx.db).to_string());
item = item.detail(ty.display(ctx.db).to_string());
}
};

Expand All @@ -114,7 +156,7 @@ impl Completions {
if let Some(score) =
compute_score_from_active(&active_type, &active_name, &ty, &local_name)
{
completion_item = completion_item.set_score(score);
item = item.set_score(score);
}
ref_match = refed_type_matches(&active_type, &active_name, &ty, &local_name);
}
Expand All @@ -130,15 +172,15 @@ impl Completions {
};
if has_non_default_type_params {
mark::hit!(inserts_angle_brackets_for_generics);
completion_item = completion_item
item = item
.lookup_by(local_name.clone())
.label(format!("{}<…>", local_name))
.insert_snippet(cap, format!("{}<$0>", local_name));
}
}
}

completion_item.kind(kind).set_documentation(docs).set_ref_match(ref_match).add_to(self)
item.kind(kind).set_documentation(docs).set_ref_match(ref_match).add_to(self)
}

pub(crate) fn add_macro(
Expand Down Expand Up @@ -190,7 +232,7 @@ impl Completions {
}
};

self.add(builder);
self.add(builder.build());
}

pub(crate) fn add_function(
Expand Down Expand Up @@ -242,7 +284,7 @@ impl Completions {

builder = builder.add_call_parens(ctx, name, Params::Named(params));

self.add(builder)
self.add(builder.build())
}

pub(crate) fn add_const(&mut self, ctx: &CompletionContext, constant: hir::Const) {
Expand Down Expand Up @@ -506,7 +548,7 @@ mod tests {
use test_utils::mark;

use crate::{
test_utils::{check_edit, check_edit_with_config, do_completion, get_all_completion_items},
test_utils::{check_edit, check_edit_with_config, do_completion, get_all_items},
CompletionConfig, CompletionKind, CompletionScore,
};

Expand All @@ -524,7 +566,7 @@ mod tests {
}
}

let mut completions = get_all_completion_items(CompletionConfig::default(), ra_fixture);
let mut completions = get_all_items(CompletionConfig::default(), ra_fixture);
completions.sort_by_key(|it| (Reverse(it.score()), it.label().to_string()));
let actual = completions
.into_iter()
Expand Down Expand Up @@ -661,7 +703,7 @@ fn main() { let _: m::Spam = S<|> }
}

#[test]
fn sets_deprecated_flag_in_completion_items() {
fn sets_deprecated_flag_in_items() {
check(
r#"
#[deprecated]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ use rustc_hash::FxHashSet;
use syntax::{ast, AstNode, SyntaxKind};

use crate::{
completion_context::CompletionContext,
completion_item::{CompletionItem, CompletionItemKind, CompletionKind, Completions},
context::CompletionContext,
generated_lint_completions::{CLIPPY_LINTS, FEATURES},
item::{CompletionItem, CompletionItemKind, CompletionKind},
Completions,
};

pub(super) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
pub(crate) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
if ctx.mod_declaration_under_caret.is_some() {
return None;
}
Expand Down Expand Up @@ -60,7 +61,7 @@ fn complete_attribute_start(acc: &mut Completions, ctx: &CompletionContext, attr
}

if attribute.kind() == ast::AttrKind::Inner || !attr_completion.prefer_inner {
acc.add(item);
acc.add(item.build());
}
}
}
Expand Down Expand Up @@ -152,21 +153,15 @@ fn complete_derive(acc: &mut Completions, ctx: &CompletionContext, derive_input:
label.push_str(", ");
label.push_str(dependency);
}
acc.add(
CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), label)
.kind(CompletionItemKind::Attribute),
);
CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), label)
.kind(CompletionItemKind::Attribute)
.add_to(acc)
}

for custom_derive_name in get_derive_names_in_scope(ctx).difference(&existing_derives) {
acc.add(
CompletionItem::new(
CompletionKind::Attribute,
ctx.source_range(),
custom_derive_name,
)
.kind(CompletionItemKind::Attribute),
);
CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), custom_derive_name)
.kind(CompletionItemKind::Attribute)
.add_to(acc)
}
}
}
Expand All @@ -182,15 +177,14 @@ fn complete_lint(
.into_iter()
.filter(|completion| !existing_lints.contains(completion.label))
{
acc.add(
CompletionItem::new(
CompletionKind::Attribute,
ctx.source_range(),
lint_completion.label,
)
.kind(CompletionItemKind::Attribute)
.detail(lint_completion.description),
);
CompletionItem::new(
CompletionKind::Attribute,
ctx.source_range(),
lint_completion.label,
)
.kind(CompletionItemKind::Attribute)
.detail(lint_completion.description)
.add_to(acc)
}
}
}
Expand Down Expand Up @@ -262,9 +256,9 @@ const DEFAULT_DERIVE_COMPLETIONS: &[DeriveCompletion] = &[
DeriveCompletion { label: "Ord", dependencies: &["PartialOrd", "Eq", "PartialEq"] },
];

pub(super) struct LintCompletion {
pub(super) label: &'static str,
pub(super) description: &'static str,
pub(crate) struct LintCompletion {
pub(crate) label: &'static str,
pub(crate) description: &'static str,
}

#[rustfmt::skip]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ use hir::{HasVisibility, Type};
use rustc_hash::FxHashSet;
use test_utils::mark;

use crate::{completion_context::CompletionContext, completion_item::Completions};
use crate::{context::CompletionContext, Completions};

/// Complete dot accesses, i.e. fields or methods.
pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
pub(crate) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
let dot_receiver = match &ctx.dot_receiver {
Some(expr) => expr,
_ => return,
Expand Down Expand Up @@ -141,7 +141,7 @@ mod inner {
private_field: u32,
pub pub_field: u32,
pub(crate) crate_field: u32,
pub(super) super_field: u32,
pub(crate) super_field: u32,
}
}
fn foo(a: inner::A) { a.<|> }
Expand All @@ -159,13 +159,13 @@ struct A {}
mod m {
impl super::A {
fn private_method(&self) {}
pub(super) fn the_method(&self) {}
pub(crate) fn the_method(&self) {}
}
}
fn foo(a: A) { a.<|> }
"#,
expect![[r#"
me the_method() pub(super) fn the_method(&self)
me the_method() pub(crate) fn the_method(&self)
"#]],
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{CompletionContext, CompletionItem, CompletionKind, 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.
pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) {
pub(crate) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) {
if !ctx.is_param {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use test_utils::mark;

use crate::{CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions};

pub(super) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionContext) {
pub(crate) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionContext) {
// complete keyword "crate" in use stmt
let source_range = ctx.source_range();

Expand Down Expand Up @@ -39,7 +39,7 @@ pub(super) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC
}
}

pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
if ctx.token.kind() == SyntaxKind::COMMENT {
mark::hit!(no_keyword_completion_in_comments);
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use crate::{CompletionContext, Completions};

pub(super) fn complete_macro_in_item_position(acc: &mut Completions, ctx: &CompletionContext) {
pub(crate) fn complete_macro_in_item_position(acc: &mut Completions, ctx: &CompletionContext) {
// Show only macros in top level.
if ctx.is_new_item {
ctx.scope.process_all_names(&mut |name, res| {
Expand Down
Loading