mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-03 20:23:59 +00:00
Merge #11394
11394: feat: Deprioritize completions of private but editable definitions r=Veykril a=Veykril Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
commit
9cb6e3a190
@ -111,6 +111,10 @@ fn gen_fn(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
||||
|
||||
fn gen_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
||||
let call: ast::MethodCallExpr = ctx.find_node_at_offset()?;
|
||||
if ctx.sema.resolve_method_call(&call).is_some() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let fn_name = call.name_ref()?;
|
||||
let adt = ctx.sema.type_of_expr(&call.receiver()?)?.original().strip_references().as_adt()?;
|
||||
|
||||
@ -481,7 +485,12 @@ fn fn_arg_name(sema: &Semantics<RootDatabase>, arg_expr: &ast::Expr) -> String {
|
||||
let name = (|| match arg_expr {
|
||||
ast::Expr::CastExpr(cast_expr) => Some(fn_arg_name(sema, &cast_expr.expr()?)),
|
||||
expr => {
|
||||
let name_ref = expr.syntax().descendants().filter_map(ast::NameRef::cast).last()?;
|
||||
let name_ref = expr
|
||||
.syntax()
|
||||
.descendants()
|
||||
.filter_map(ast::NameRef::cast)
|
||||
.filter(|name| name.ident_token().is_some())
|
||||
.last()?;
|
||||
if let Some(NameRefClass::Definition(Definition::Const(_) | Definition::Static(_))) =
|
||||
NameRefClass::classify(sema, &name_ref)
|
||||
{
|
||||
@ -1660,7 +1669,7 @@ fn main() {
|
||||
foo(a.0);
|
||||
}
|
||||
|
||||
fn foo(arg0: ()) ${0:-> _} {
|
||||
fn foo(a: ()) ${0:-> _} {
|
||||
todo!()
|
||||
}
|
||||
",
|
||||
|
@ -18,16 +18,16 @@ pub(crate) mod format_string;
|
||||
|
||||
use std::iter;
|
||||
|
||||
use hir::known;
|
||||
use hir::{known, ScopeDef};
|
||||
use ide_db::SymbolKind;
|
||||
|
||||
use crate::{
|
||||
context::Visible,
|
||||
item::Builder,
|
||||
render::{
|
||||
const_::render_const,
|
||||
enum_variant::render_variant,
|
||||
function::{render_fn, render_method},
|
||||
macro_::render_macro,
|
||||
pattern::{render_struct_pat, render_variant_pat},
|
||||
render_field, render_resolution, render_tuple_field,
|
||||
struct_literal::render_struct_literal,
|
||||
@ -37,6 +37,22 @@ use crate::{
|
||||
CompletionContext, CompletionItem, CompletionItemKind,
|
||||
};
|
||||
|
||||
fn module_or_attr(def: ScopeDef) -> Option<ScopeDef> {
|
||||
match def {
|
||||
ScopeDef::MacroDef(mac) if mac.is_attr() => Some(def),
|
||||
ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) => Some(def),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn module_or_fn_macro(def: ScopeDef) -> Option<ScopeDef> {
|
||||
match def {
|
||||
ScopeDef::MacroDef(mac) if mac.is_fn_like() => Some(def),
|
||||
ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) => Some(def),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents an in-progress set of completions being built.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Completions {
|
||||
@ -91,20 +107,7 @@ impl Completions {
|
||||
cov_mark::hit!(qualified_path_doc_hidden);
|
||||
return;
|
||||
}
|
||||
self.add(render_resolution(RenderContext::new(ctx), local_name, resolution));
|
||||
}
|
||||
|
||||
pub(crate) fn add_macro(
|
||||
&mut self,
|
||||
ctx: &CompletionContext,
|
||||
name: Option<hir::Name>,
|
||||
macro_: hir::MacroDef,
|
||||
) {
|
||||
let name = match name {
|
||||
Some(it) => it,
|
||||
None => return,
|
||||
};
|
||||
self.add(render_macro(RenderContext::new(ctx), None, name, macro_));
|
||||
self.add(render_resolution(RenderContext::new(ctx, false), local_name, resolution));
|
||||
}
|
||||
|
||||
pub(crate) fn add_function(
|
||||
@ -113,10 +116,12 @@ impl Completions {
|
||||
func: hir::Function,
|
||||
local_name: Option<hir::Name>,
|
||||
) {
|
||||
if !ctx.is_visible(&func) {
|
||||
return;
|
||||
}
|
||||
self.add(render_fn(RenderContext::new(ctx), None, local_name, func));
|
||||
let is_private_editable = match ctx.is_visible(&func) {
|
||||
Visible::Yes => false,
|
||||
Visible::Editable => true,
|
||||
Visible::No => return,
|
||||
};
|
||||
self.add(render_fn(RenderContext::new(ctx, is_private_editable), None, local_name, func));
|
||||
}
|
||||
|
||||
pub(crate) fn add_method(
|
||||
@ -126,24 +131,36 @@ impl Completions {
|
||||
receiver: Option<hir::Name>,
|
||||
local_name: Option<hir::Name>,
|
||||
) {
|
||||
if !ctx.is_visible(&func) {
|
||||
return;
|
||||
}
|
||||
self.add(render_method(RenderContext::new(ctx), None, receiver, local_name, func));
|
||||
let is_private_editable = match ctx.is_visible(&func) {
|
||||
Visible::Yes => false,
|
||||
Visible::Editable => true,
|
||||
Visible::No => return,
|
||||
};
|
||||
self.add(render_method(
|
||||
RenderContext::new(ctx, is_private_editable),
|
||||
None,
|
||||
receiver,
|
||||
local_name,
|
||||
func,
|
||||
));
|
||||
}
|
||||
|
||||
pub(crate) fn add_const(&mut self, ctx: &CompletionContext, konst: hir::Const) {
|
||||
if !ctx.is_visible(&konst) {
|
||||
return;
|
||||
}
|
||||
self.add_opt(render_const(RenderContext::new(ctx), konst));
|
||||
let is_private_editable = match ctx.is_visible(&konst) {
|
||||
Visible::Yes => false,
|
||||
Visible::Editable => true,
|
||||
Visible::No => return,
|
||||
};
|
||||
self.add_opt(render_const(RenderContext::new(ctx, is_private_editable), konst));
|
||||
}
|
||||
|
||||
pub(crate) fn add_type_alias(&mut self, ctx: &CompletionContext, type_alias: hir::TypeAlias) {
|
||||
if !ctx.is_visible(&type_alias) {
|
||||
return;
|
||||
}
|
||||
self.add_opt(render_type_alias(RenderContext::new(ctx), type_alias));
|
||||
let is_private_editable = match ctx.is_visible(&type_alias) {
|
||||
Visible::Yes => false,
|
||||
Visible::Editable => true,
|
||||
Visible::No => return,
|
||||
};
|
||||
self.add_opt(render_type_alias(RenderContext::new(ctx, is_private_editable), type_alias));
|
||||
}
|
||||
|
||||
pub(crate) fn add_type_alias_with_eq(
|
||||
@ -151,7 +168,7 @@ impl Completions {
|
||||
ctx: &CompletionContext,
|
||||
type_alias: hir::TypeAlias,
|
||||
) {
|
||||
self.add_opt(render_type_alias_with_eq(RenderContext::new(ctx), type_alias));
|
||||
self.add_opt(render_type_alias_with_eq(RenderContext::new(ctx, false), type_alias));
|
||||
}
|
||||
|
||||
pub(crate) fn add_qualified_enum_variant(
|
||||
@ -160,7 +177,7 @@ impl Completions {
|
||||
variant: hir::Variant,
|
||||
path: hir::ModPath,
|
||||
) {
|
||||
let item = render_variant(RenderContext::new(ctx), None, None, variant, Some(path));
|
||||
let item = render_variant(RenderContext::new(ctx, false), None, None, variant, Some(path));
|
||||
self.add(item);
|
||||
}
|
||||
|
||||
@ -170,7 +187,7 @@ impl Completions {
|
||||
variant: hir::Variant,
|
||||
local_name: Option<hir::Name>,
|
||||
) {
|
||||
let item = render_variant(RenderContext::new(ctx), None, local_name, variant, None);
|
||||
let item = render_variant(RenderContext::new(ctx, false), None, local_name, variant, None);
|
||||
self.add(item);
|
||||
}
|
||||
|
||||
@ -181,10 +198,12 @@ impl Completions {
|
||||
field: hir::Field,
|
||||
ty: &hir::Type,
|
||||
) {
|
||||
if !ctx.is_visible(&field) {
|
||||
return;
|
||||
}
|
||||
let item = render_field(RenderContext::new(ctx), receiver, field, ty);
|
||||
let is_private_editable = match ctx.is_visible(&field) {
|
||||
Visible::Yes => false,
|
||||
Visible::Editable => true,
|
||||
Visible::No => return,
|
||||
};
|
||||
let item = render_field(RenderContext::new(ctx, is_private_editable), receiver, field, ty);
|
||||
self.add(item);
|
||||
}
|
||||
|
||||
@ -195,7 +214,7 @@ impl Completions {
|
||||
path: Option<hir::ModPath>,
|
||||
local_name: Option<hir::Name>,
|
||||
) {
|
||||
let item = render_struct_literal(RenderContext::new(ctx), strukt, path, local_name);
|
||||
let item = render_struct_literal(RenderContext::new(ctx, false), strukt, path, local_name);
|
||||
self.add_opt(item);
|
||||
}
|
||||
|
||||
@ -206,13 +225,17 @@ impl Completions {
|
||||
field: usize,
|
||||
ty: &hir::Type,
|
||||
) {
|
||||
let item = render_tuple_field(RenderContext::new(ctx), receiver, field, ty);
|
||||
let item = render_tuple_field(RenderContext::new(ctx, false), receiver, field, ty);
|
||||
self.add(item);
|
||||
}
|
||||
|
||||
pub(crate) fn add_static_lifetime(&mut self, ctx: &CompletionContext) {
|
||||
let item = CompletionItem::new(SymbolKind::LifetimeParam, ctx.source_range(), "'static");
|
||||
self.add(item.build());
|
||||
pub(crate) fn add_lifetime(&mut self, ctx: &CompletionContext, name: hir::Name) {
|
||||
CompletionItem::new(SymbolKind::LifetimeParam, ctx.source_range(), name.to_smol_str())
|
||||
.add_to(self)
|
||||
}
|
||||
|
||||
pub(crate) fn add_label(&mut self, ctx: &CompletionContext, name: hir::Name) {
|
||||
CompletionItem::new(SymbolKind::Label, ctx.source_range(), name.to_smol_str()).add_to(self)
|
||||
}
|
||||
|
||||
pub(crate) fn add_variant_pat(
|
||||
@ -221,7 +244,7 @@ impl Completions {
|
||||
variant: hir::Variant,
|
||||
local_name: Option<hir::Name>,
|
||||
) {
|
||||
self.add_opt(render_variant_pat(RenderContext::new(ctx), variant, local_name, None));
|
||||
self.add_opt(render_variant_pat(RenderContext::new(ctx, false), variant, local_name, None));
|
||||
}
|
||||
|
||||
pub(crate) fn add_qualified_variant_pat(
|
||||
@ -230,7 +253,7 @@ impl Completions {
|
||||
variant: hir::Variant,
|
||||
path: hir::ModPath,
|
||||
) {
|
||||
self.add_opt(render_variant_pat(RenderContext::new(ctx), variant, None, Some(path)));
|
||||
self.add_opt(render_variant_pat(RenderContext::new(ctx, false), variant, None, Some(path)));
|
||||
}
|
||||
|
||||
pub(crate) fn add_struct_pat(
|
||||
@ -239,7 +262,7 @@ impl Completions {
|
||||
strukt: hir::Struct,
|
||||
local_name: Option<hir::Name>,
|
||||
) {
|
||||
self.add_opt(render_struct_pat(RenderContext::new(ctx), strukt, local_name));
|
||||
self.add_opt(render_struct_pat(RenderContext::new(ctx, false), strukt, local_name));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,7 +193,7 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext)
|
||||
})
|
||||
.filter_map(|import| {
|
||||
render_resolution_with_import(
|
||||
RenderContext::new(ctx),
|
||||
RenderContext::new(ctx, false),
|
||||
ImportEdit { import, scope: import_scope.clone() },
|
||||
)
|
||||
}),
|
||||
|
@ -7,7 +7,7 @@
|
||||
//! there is no value in lifting these out into the outline module test since they will either not
|
||||
//! show up for normal completions, or they won't show completions other than lifetimes depending
|
||||
//! on the fixture input.
|
||||
use hir::ScopeDef;
|
||||
use hir::{known, ScopeDef};
|
||||
use syntax::ast;
|
||||
|
||||
use crate::{
|
||||
@ -35,12 +35,12 @@ pub(crate) fn complete_lifetime(acc: &mut Completions, ctx: &CompletionContext)
|
||||
ctx.scope.process_all_names(&mut |name, res| {
|
||||
if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res {
|
||||
if param_lifetime != Some(&*name.to_smol_str()) {
|
||||
acc.add_resolution(ctx, name, res);
|
||||
acc.add_lifetime(ctx, name);
|
||||
}
|
||||
}
|
||||
});
|
||||
if param_lifetime.is_none() {
|
||||
acc.add_static_lifetime(ctx);
|
||||
acc.add_lifetime(ctx, known::STATIC_LIFETIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ pub(crate) fn complete_label(acc: &mut Completions, ctx: &CompletionContext) {
|
||||
}
|
||||
ctx.scope.process_all_names(&mut |name, res| {
|
||||
if let ScopeDef::Label(_) = res {
|
||||
acc.add_resolution(ctx, name, res);
|
||||
acc.add_label(ctx, name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ use crate::{patterns::ImmediateLocation, CompletionItem};
|
||||
|
||||
use crate::{context::CompletionContext, Completions};
|
||||
|
||||
/// Complete mod declaration, i.e. `mod $0 ;`
|
||||
/// Complete mod declaration, i.e. `mod $0;`
|
||||
pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
|
||||
let mod_under_caret = match &ctx.completion_location {
|
||||
Some(ImmediateLocation::ModDeclaration(mod_under_caret)) => mod_under_caret,
|
||||
|
@ -7,6 +7,7 @@ use rustc_hash::FxHashSet;
|
||||
use syntax::{ast, AstNode};
|
||||
|
||||
use crate::{
|
||||
completions::{module_or_attr, module_or_fn_macro},
|
||||
context::{PathCompletionContext, PathKind},
|
||||
patterns::ImmediateLocation,
|
||||
CompletionContext, Completions,
|
||||
@ -57,12 +58,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
||||
Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
|
||||
if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
|
||||
for (name, def) in module.scope(ctx.db, context_module) {
|
||||
if let ScopeDef::MacroDef(macro_def) = def {
|
||||
if macro_def.is_fn_like() {
|
||||
acc.add_macro(ctx, Some(name.clone()), macro_def);
|
||||
}
|
||||
}
|
||||
if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = def {
|
||||
if let Some(def) = module_or_fn_macro(def) {
|
||||
acc.add_resolution(ctx, name, def);
|
||||
}
|
||||
}
|
||||
@ -73,16 +69,18 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
||||
}
|
||||
|
||||
match kind {
|
||||
// Complete next child module that comes after the qualified module which is still our parent
|
||||
Some(PathKind::Vis { .. }) => {
|
||||
if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
|
||||
if let Some(current_module) = ctx.module {
|
||||
if let Some(next) = current_module
|
||||
let next_towards_current = current_module
|
||||
.path_to_root(ctx.db)
|
||||
.into_iter()
|
||||
.take_while(|&it| it != module)
|
||||
.next()
|
||||
{
|
||||
.next();
|
||||
if let Some(next) = next_towards_current {
|
||||
if let Some(name) = next.name(ctx.db) {
|
||||
cov_mark::hit!(visibility_qualified);
|
||||
acc.add_resolution(ctx, name, ScopeDef::ModuleDef(next.into()));
|
||||
}
|
||||
}
|
||||
@ -93,12 +91,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
||||
Some(PathKind::Attr) => {
|
||||
if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
|
||||
for (name, def) in module.scope(ctx.db, context_module) {
|
||||
let add_resolution = match def {
|
||||
ScopeDef::MacroDef(mac) => mac.is_attr(),
|
||||
ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) => true,
|
||||
_ => false,
|
||||
};
|
||||
if add_resolution {
|
||||
if let Some(def) = module_or_attr(def) {
|
||||
acc.add_resolution(ctx, name, def);
|
||||
}
|
||||
}
|
||||
@ -263,7 +256,6 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
||||
);
|
||||
}
|
||||
}
|
||||
hir::PathResolution::Macro(mac) => acc.add_macro(ctx, None, mac),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,8 @@ use ide_db::SymbolKind;
|
||||
use syntax::{ast::Expr, T};
|
||||
|
||||
use crate::{
|
||||
patterns::ImmediateLocation, CompletionContext, CompletionItem, CompletionItemKind, Completions,
|
||||
patterns::ImmediateLocation, CompletionContext, CompletionItem, CompletionItemKind,
|
||||
CompletionRelevance, Completions,
|
||||
};
|
||||
|
||||
pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
|
||||
@ -25,7 +26,10 @@ pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) ->
|
||||
CompletionItem::new(SymbolKind::Field, ctx.source_range(), completion_text);
|
||||
let completion_text =
|
||||
completion_text.strip_prefix(ctx.token.text()).unwrap_or(completion_text);
|
||||
item.insert_text(completion_text);
|
||||
item.insert_text(completion_text).set_relevance(CompletionRelevance {
|
||||
exact_postfix_snippet_match: true,
|
||||
..Default::default()
|
||||
});
|
||||
item.add_to(acc);
|
||||
}
|
||||
if ctx.previous_token_is(T![.]) {
|
||||
|
@ -42,7 +42,7 @@ use text_edit::TextEdit;
|
||||
|
||||
use crate::{CompletionContext, CompletionItem, CompletionItemKind, Completions};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
enum ImplCompletionKind {
|
||||
All,
|
||||
Fn,
|
||||
@ -53,23 +53,22 @@ enum ImplCompletionKind {
|
||||
pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {
|
||||
if let Some((kind, trigger, impl_def)) = completion_match(ctx.token.clone()) {
|
||||
if let Some(hir_impl) = ctx.sema.to_def(&impl_def) {
|
||||
get_missing_assoc_items(&ctx.sema, &impl_def).into_iter().for_each(|item| match item {
|
||||
hir::AssocItem::Function(fn_item)
|
||||
if kind == ImplCompletionKind::All || kind == ImplCompletionKind::Fn =>
|
||||
{
|
||||
add_function_impl(&trigger, acc, ctx, fn_item, hir_impl)
|
||||
get_missing_assoc_items(&ctx.sema, &impl_def).into_iter().for_each(|item| {
|
||||
match (item, kind) {
|
||||
(
|
||||
hir::AssocItem::Function(fn_item),
|
||||
ImplCompletionKind::All | ImplCompletionKind::Fn,
|
||||
) => add_function_impl(&trigger, acc, ctx, fn_item, hir_impl),
|
||||
(
|
||||
hir::AssocItem::TypeAlias(type_item),
|
||||
ImplCompletionKind::All | ImplCompletionKind::TypeAlias,
|
||||
) => add_type_alias_impl(&trigger, acc, ctx, type_item),
|
||||
(
|
||||
hir::AssocItem::Const(const_item),
|
||||
ImplCompletionKind::All | ImplCompletionKind::Const,
|
||||
) => add_const_impl(&trigger, acc, ctx, const_item, hir_impl),
|
||||
_ => {}
|
||||
}
|
||||
hir::AssocItem::TypeAlias(type_item)
|
||||
if kind == ImplCompletionKind::All || kind == ImplCompletionKind::TypeAlias =>
|
||||
{
|
||||
add_type_alias_impl(&trigger, acc, ctx, type_item)
|
||||
}
|
||||
hir::AssocItem::Const(const_item)
|
||||
if kind == ImplCompletionKind::All || kind == ImplCompletionKind::Const =>
|
||||
{
|
||||
add_const_impl(&trigger, acc, ctx, const_item, hir_impl)
|
||||
}
|
||||
_ => {}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -194,7 +193,7 @@ fn get_transformed_assoc_item(
|
||||
|
||||
transform.apply(assoc_item.syntax());
|
||||
if let ast::AssocItem::Fn(func) = &assoc_item {
|
||||
func.remove_attrs_and_docs()
|
||||
func.remove_attrs_and_docs();
|
||||
}
|
||||
Some(assoc_item)
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ use hir::ScopeDef;
|
||||
use syntax::{ast, AstNode};
|
||||
|
||||
use crate::{
|
||||
completions::{module_or_attr, module_or_fn_macro},
|
||||
context::{PathCompletionContext, PathKind},
|
||||
patterns::ImmediateLocation,
|
||||
CompletionContext, Completions,
|
||||
@ -36,14 +37,9 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
|
||||
match kind {
|
||||
Some(PathKind::Vis { .. }) => return,
|
||||
Some(PathKind::Attr) => {
|
||||
ctx.process_all_names(&mut |name, res| {
|
||||
let add_resolution = match res {
|
||||
ScopeDef::MacroDef(mac) => mac.is_attr(),
|
||||
ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) => true,
|
||||
_ => false,
|
||||
};
|
||||
if add_resolution {
|
||||
acc.add_resolution(ctx, name, res);
|
||||
ctx.process_all_names(&mut |name, def| {
|
||||
if let Some(def) = module_or_attr(def) {
|
||||
acc.add_resolution(ctx, name, def);
|
||||
}
|
||||
});
|
||||
return;
|
||||
@ -54,14 +50,9 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
|
||||
match &ctx.completion_location {
|
||||
Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
|
||||
// only show macros in {Assoc}ItemList
|
||||
ctx.process_all_names(&mut |name, res| {
|
||||
if let hir::ScopeDef::MacroDef(mac) = res {
|
||||
if mac.is_fn_like() {
|
||||
acc.add_macro(ctx, Some(name.clone()), mac);
|
||||
}
|
||||
}
|
||||
if let hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
|
||||
acc.add_resolution(ctx, name, res);
|
||||
ctx.process_all_names(&mut |name, def| {
|
||||
if let Some(def) = module_or_fn_macro(def) {
|
||||
acc.add_resolution(ctx, name, def);
|
||||
}
|
||||
});
|
||||
return;
|
||||
|
@ -34,6 +34,11 @@ pub(crate) enum PatternRefutability {
|
||||
Refutable,
|
||||
Irrefutable,
|
||||
}
|
||||
pub(crate) enum Visible {
|
||||
Yes,
|
||||
Editable,
|
||||
No,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(super) enum PathKind {
|
||||
@ -103,7 +108,7 @@ pub(crate) struct CompletionContext<'a> {
|
||||
pub(super) token: SyntaxToken,
|
||||
/// The crate of the current file.
|
||||
pub(super) krate: Option<hir::Crate>,
|
||||
/// The crate of the `scope`.
|
||||
/// The module of the `scope`.
|
||||
pub(super) module: Option<hir::Module>,
|
||||
pub(super) expected_name: Option<NameOrNameRef>,
|
||||
pub(super) expected_type: Option<Type>,
|
||||
@ -285,7 +290,7 @@ impl<'a> CompletionContext<'a> {
|
||||
}
|
||||
|
||||
/// Checks if an item is visible and not `doc(hidden)` at the completion site.
|
||||
pub(crate) fn is_visible<I>(&self, item: &I) -> bool
|
||||
pub(crate) fn is_visible<I>(&self, item: &I) -> Visible
|
||||
where
|
||||
I: hir::HasVisibility + hir::HasAttrs + hir::HasCrate + Copy,
|
||||
{
|
||||
@ -339,20 +344,24 @@ impl<'a> CompletionContext<'a> {
|
||||
vis: &hir::Visibility,
|
||||
attrs: &hir::Attrs,
|
||||
defining_crate: hir::Crate,
|
||||
) -> bool {
|
||||
) -> Visible {
|
||||
let module = match self.module {
|
||||
Some(it) => it,
|
||||
None => return false,
|
||||
None => return Visible::No,
|
||||
};
|
||||
if !vis.is_visible_from(self.db, module.into()) {
|
||||
// If the definition location is editable, also show private items
|
||||
let root_file = defining_crate.root_file(self.db);
|
||||
let source_root_id = self.db.file_source_root(root_file);
|
||||
let is_editable = !self.db.source_root(source_root_id).is_library;
|
||||
return is_editable;
|
||||
return if is_editable { Visible::Editable } else { Visible::No };
|
||||
}
|
||||
|
||||
!self.is_doc_hidden(attrs, defining_crate)
|
||||
if self.is_doc_hidden(attrs, defining_crate) {
|
||||
Visible::No
|
||||
} else {
|
||||
Visible::Yes
|
||||
}
|
||||
}
|
||||
|
||||
fn is_doc_hidden(&self, attrs: &hir::Attrs, defining_crate: hir::Crate) -> bool {
|
||||
|
@ -141,6 +141,8 @@ pub struct CompletionRelevance {
|
||||
pub is_local: bool,
|
||||
/// Set for method completions of the `core::ops` and `core::cmp` family.
|
||||
pub is_op_method: bool,
|
||||
/// Set for item completions that are private but in the workspace.
|
||||
pub is_private_editable: bool,
|
||||
/// This is set in cases like these:
|
||||
///
|
||||
/// ```
|
||||
@ -177,7 +179,7 @@ pub enum CompletionRelevanceTypeMatch {
|
||||
}
|
||||
|
||||
impl CompletionRelevance {
|
||||
const BASE_LINE: u32 = 1;
|
||||
const BASE_LINE: u32 = 2;
|
||||
/// Provides a relevance score. Higher values are more relevant.
|
||||
///
|
||||
/// The absolute value of the relevance score is not meaningful, for
|
||||
@ -190,6 +192,15 @@ impl CompletionRelevance {
|
||||
pub fn score(&self) -> u32 {
|
||||
let mut score = Self::BASE_LINE;
|
||||
|
||||
// score decreases
|
||||
if self.is_op_method {
|
||||
score -= 1;
|
||||
}
|
||||
if self.is_private_editable {
|
||||
score -= 1;
|
||||
}
|
||||
|
||||
// score increases
|
||||
if self.exact_name_match {
|
||||
score += 1;
|
||||
}
|
||||
@ -201,9 +212,6 @@ impl CompletionRelevance {
|
||||
if self.is_local {
|
||||
score += 1;
|
||||
}
|
||||
if self.is_op_method {
|
||||
score -= 1;
|
||||
}
|
||||
if self.exact_postfix_snippet_match {
|
||||
score += 100;
|
||||
}
|
||||
@ -214,7 +222,7 @@ impl CompletionRelevance {
|
||||
/// some threshold such that we think it is especially likely
|
||||
/// to be relevant.
|
||||
pub fn is_relevant(&self) -> bool {
|
||||
self.score() > (Self::BASE_LINE + 1)
|
||||
self.score() > Self::BASE_LINE
|
||||
}
|
||||
}
|
||||
|
||||
@ -564,7 +572,15 @@ mod tests {
|
||||
// This test asserts that the relevance score for these items is ascending, and
|
||||
// that any items in the same vec have the same score.
|
||||
let expected_relevance_order = vec![
|
||||
vec![CompletionRelevance { is_op_method: true, ..CompletionRelevance::default() }],
|
||||
vec![CompletionRelevance {
|
||||
is_op_method: true,
|
||||
is_private_editable: true,
|
||||
..CompletionRelevance::default()
|
||||
}],
|
||||
vec![
|
||||
CompletionRelevance { is_private_editable: true, ..CompletionRelevance::default() },
|
||||
CompletionRelevance { is_op_method: true, ..CompletionRelevance::default() },
|
||||
],
|
||||
vec![CompletionRelevance::default()],
|
||||
vec![
|
||||
CompletionRelevance { exact_name_match: true, ..CompletionRelevance::default() },
|
||||
|
@ -28,11 +28,15 @@ use crate::{
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct RenderContext<'a> {
|
||||
completion: &'a CompletionContext<'a>,
|
||||
is_private_editable: bool,
|
||||
}
|
||||
|
||||
impl<'a> RenderContext<'a> {
|
||||
pub(crate) fn new(completion: &'a CompletionContext<'a>) -> RenderContext<'a> {
|
||||
RenderContext { completion }
|
||||
pub(crate) fn new(
|
||||
completion: &'a CompletionContext<'a>,
|
||||
is_private_editable: bool,
|
||||
) -> RenderContext<'a> {
|
||||
RenderContext { completion, is_private_editable }
|
||||
}
|
||||
|
||||
fn snippet_cap(&self) -> Option<SnippetCap> {
|
||||
@ -47,6 +51,10 @@ impl<'a> RenderContext<'a> {
|
||||
self.completion.source_range()
|
||||
}
|
||||
|
||||
fn completion_relevance(&self) -> CompletionRelevance {
|
||||
CompletionRelevance { is_private_editable: self.is_private_editable, ..Default::default() }
|
||||
}
|
||||
|
||||
fn is_deprecated(&self, def: impl HasAttrs) -> bool {
|
||||
let attrs = def.attrs(self.db());
|
||||
attrs.by_key("deprecated").exists() || attrs.by_key("rustc_deprecated").exists()
|
||||
@ -582,6 +590,7 @@ fn main() { let _: m::Spam = S$0 }
|
||||
),
|
||||
is_local: false,
|
||||
is_op_method: false,
|
||||
is_private_editable: false,
|
||||
exact_postfix_snippet_match: false,
|
||||
},
|
||||
trigger_call_info: true,
|
||||
@ -603,6 +612,7 @@ fn main() { let _: m::Spam = S$0 }
|
||||
),
|
||||
is_local: false,
|
||||
is_op_method: false,
|
||||
is_private_editable: false,
|
||||
exact_postfix_snippet_match: false,
|
||||
},
|
||||
},
|
||||
@ -689,6 +699,7 @@ fn foo() { A { the$0 } }
|
||||
),
|
||||
is_local: false,
|
||||
is_op_method: false,
|
||||
is_private_editable: false,
|
||||
exact_postfix_snippet_match: false,
|
||||
},
|
||||
},
|
||||
|
@ -18,7 +18,8 @@ fn render(ctx: RenderContext<'_>, const_: hir::Const) -> Option<CompletionItem>
|
||||
let mut item = CompletionItem::new(SymbolKind::Const, ctx.source_range(), name.clone());
|
||||
item.set_documentation(ctx.docs(const_))
|
||||
.set_deprecated(ctx.is_deprecated(const_) || ctx.is_deprecated_assoc_item(const_))
|
||||
.detail(detail);
|
||||
.detail(detail)
|
||||
.set_relevance(ctx.completion_relevance());
|
||||
|
||||
if let Some(actm) = const_.as_assoc_item(db) {
|
||||
if let Some(trt) = actm.containing_trait_or_trait_impl(db) {
|
||||
|
@ -23,7 +23,7 @@ pub(crate) fn render_variant(
|
||||
}
|
||||
|
||||
fn render(
|
||||
ctx @ RenderContext { completion }: RenderContext<'_>,
|
||||
ctx @ RenderContext { completion, .. }: RenderContext<'_>,
|
||||
local_name: Option<hir::Name>,
|
||||
variant: hir::Variant,
|
||||
path: Option<hir::ModPath>,
|
||||
@ -58,18 +58,18 @@ fn render(
|
||||
if variant_kind == hir::StructKind::Tuple {
|
||||
cov_mark::hit!(inserts_parens_for_tuple_enums);
|
||||
let params = Params::Anonymous(variant.fields(db).len());
|
||||
item.add_call_parens(ctx.completion, short_qualified_name, params);
|
||||
item.add_call_parens(completion, short_qualified_name, params);
|
||||
} else if qualified {
|
||||
item.lookup_by(short_qualified_name);
|
||||
}
|
||||
|
||||
let ty = variant.parent_enum(ctx.completion.db).ty(ctx.completion.db);
|
||||
let ty = variant.parent_enum(completion.db).ty(completion.db);
|
||||
item.set_relevance(CompletionRelevance {
|
||||
type_match: compute_type_match(ctx.completion, &ty),
|
||||
..CompletionRelevance::default()
|
||||
type_match: compute_type_match(completion, &ty),
|
||||
..ctx.completion_relevance()
|
||||
});
|
||||
|
||||
if let Some(ref_match) = compute_ref_match(ctx.completion, &ty) {
|
||||
if let Some(ref_match) = compute_ref_match(completion, &ty) {
|
||||
item.ref_match(ref_match);
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ pub(crate) fn render_method(
|
||||
}
|
||||
|
||||
fn render(
|
||||
ctx @ RenderContext { completion }: RenderContext<'_>,
|
||||
ctx @ RenderContext { completion, .. }: RenderContext<'_>,
|
||||
local_name: Option<hir::Name>,
|
||||
func: hir::Function,
|
||||
func_type: FuncType,
|
||||
@ -75,7 +75,7 @@ fn render(
|
||||
type_match: compute_type_match(completion, &ret_type),
|
||||
exact_name_match: compute_exact_name_match(completion, &call),
|
||||
is_op_method,
|
||||
..CompletionRelevance::default()
|
||||
..ctx.completion_relevance()
|
||||
});
|
||||
|
||||
if let Some(ref_match) = compute_ref_match(completion, &ret_type) {
|
||||
|
@ -25,7 +25,7 @@ pub(crate) fn render_macro(
|
||||
}
|
||||
|
||||
fn render(
|
||||
ctx @ RenderContext { completion }: RenderContext<'_>,
|
||||
ctx @ RenderContext { completion, .. }: RenderContext<'_>,
|
||||
name: hir::Name,
|
||||
macro_: hir::MacroDef,
|
||||
import_to_add: Option<ImportEdit>,
|
||||
@ -53,7 +53,8 @@ fn render(
|
||||
);
|
||||
item.set_deprecated(ctx.is_deprecated(macro_))
|
||||
.set_detail(detail(&completion.sema, macro_))
|
||||
.set_documentation(docs);
|
||||
.set_documentation(docs)
|
||||
.set_relevance(ctx.completion_relevance());
|
||||
|
||||
if let Some(import_to_add) = import_to_add {
|
||||
item.add_import(import_to_add);
|
||||
|
@ -59,7 +59,10 @@ fn build_completion(
|
||||
def: impl HasAttrs + Copy,
|
||||
) -> CompletionItem {
|
||||
let mut item = CompletionItem::new(CompletionItemKind::Binding, ctx.source_range(), name);
|
||||
item.set_documentation(ctx.docs(def)).set_deprecated(ctx.is_deprecated(def)).detail(&pat);
|
||||
item.set_documentation(ctx.docs(def))
|
||||
.set_deprecated(ctx.is_deprecated(def))
|
||||
.detail(&pat)
|
||||
.set_relevance(ctx.completion_relevance());
|
||||
match ctx.snippet_cap() {
|
||||
Some(snippet_cap) => item.insert_snippet(snippet_cap, pat),
|
||||
None => item.insert_text(pat),
|
||||
|
@ -41,7 +41,10 @@ fn build_completion(
|
||||
ctx.source_range(),
|
||||
SmolStr::from_iter([&name, " {…}"]),
|
||||
);
|
||||
item.set_documentation(ctx.docs(def)).set_deprecated(ctx.is_deprecated(def)).detail(&literal);
|
||||
item.set_documentation(ctx.docs(def))
|
||||
.set_deprecated(ctx.is_deprecated(def))
|
||||
.detail(&literal)
|
||||
.set_relevance(ctx.completion_relevance());
|
||||
match ctx.snippet_cap() {
|
||||
Some(snippet_cap) => item.insert_snippet(snippet_cap, literal),
|
||||
None => item.insert_text(literal),
|
||||
|
@ -39,7 +39,8 @@ fn render(
|
||||
let mut item = CompletionItem::new(SymbolKind::TypeAlias, ctx.source_range(), name.clone());
|
||||
item.set_documentation(ctx.docs(type_alias))
|
||||
.set_deprecated(ctx.is_deprecated(type_alias) || ctx.is_deprecated_assoc_item(type_alias))
|
||||
.detail(detail);
|
||||
.detail(detail)
|
||||
.set_relevance(ctx.completion_relevance());
|
||||
|
||||
if let Some(actm) = type_alias.as_assoc_item(db) {
|
||||
if let Some(trt) = actm.containing_trait_or_trait_impl(db) {
|
||||
|
@ -40,6 +40,7 @@ pub(in $0)
|
||||
|
||||
#[test]
|
||||
fn qualified() {
|
||||
cov_mark::check!(visibility_qualified);
|
||||
check(
|
||||
r#"
|
||||
mod foo {
|
||||
|
Loading…
Reference in New Issue
Block a user