From 7267749f6b4b810f32dc503fe91fd0c03d097c91 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 2 Feb 2022 12:05:21 +0100 Subject: [PATCH] Cleanup `Completions` api a bit --- crates/ide_completion/src/completions.rs | 42 +++++++++++-------- .../src/completions/lifetime.rs | 8 ++-- crates/ide_completion/src/completions/mod_.rs | 2 +- .../src/completions/qualified_path.rs | 24 ++++------- .../ide_completion/src/completions/record.rs | 8 +++- .../src/completions/trait_impl.rs | 35 ++++++++-------- .../src/completions/unqualified_path.rs | 23 ++++------ crates/ide_completion/src/context.rs | 4 +- crates/ide_completion/src/tests/visibility.rs | 1 + 9 files changed, 70 insertions(+), 77 deletions(-) diff --git a/crates/ide_completion/src/completions.rs b/crates/ide_completion/src/completions.rs index 515200ef881..92074b3e10d 100644 --- a/crates/ide_completion/src/completions.rs +++ b/crates/ide_completion/src/completions.rs @@ -18,7 +18,7 @@ pub(crate) mod format_string; use std::iter; -use hir::known; +use hir::{known, ScopeDef}; use ide_db::SymbolKind; use crate::{ @@ -28,7 +28,6 @@ use crate::{ 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, @@ -38,6 +37,22 @@ use crate::{ CompletionContext, CompletionItem, CompletionItemKind, }; +fn module_or_attr(def: ScopeDef) -> Option { + 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 { + 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 { @@ -95,19 +110,6 @@ impl Completions { self.add(render_resolution(RenderContext::new(ctx, false), local_name, resolution)); } - pub(crate) fn add_macro( - &mut self, - ctx: &CompletionContext, - name: Option, - macro_: hir::MacroDef, - ) { - let name = match name { - Some(it) => it, - None => return, - }; - self.add(render_macro(RenderContext::new(ctx, false), None, name, macro_)); - } - pub(crate) fn add_function( &mut self, ctx: &CompletionContext, @@ -227,9 +229,13 @@ impl Completions { 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( diff --git a/crates/ide_completion/src/completions/lifetime.rs b/crates/ide_completion/src/completions/lifetime.rs index 4082414f029..878d72ea0fb 100644 --- a/crates/ide_completion/src/completions/lifetime.rs +++ b/crates/ide_completion/src/completions/lifetime.rs @@ -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); } }); } diff --git a/crates/ide_completion/src/completions/mod_.rs b/crates/ide_completion/src/completions/mod_.rs index 64e992c2e6b..7699c530c63 100644 --- a/crates/ide_completion/src/completions/mod_.rs +++ b/crates/ide_completion/src/completions/mod_.rs @@ -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, diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs index 85df19f1dd4..cd1022b2e35 100644 --- a/crates/ide_completion/src/completions/qualified_path.rs +++ b/crates/ide_completion/src/completions/qualified_path.rs @@ -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), _ => {} } } diff --git a/crates/ide_completion/src/completions/record.rs b/crates/ide_completion/src/completions/record.rs index ec1ee292be4..13b47356197 100644 --- a/crates/ide_completion/src/completions/record.rs +++ b/crates/ide_completion/src/completions/record.rs @@ -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![.]) { diff --git a/crates/ide_completion/src/completions/trait_impl.rs b/crates/ide_completion/src/completions/trait_impl.rs index b214c5c154a..7a42cfbd42e 100644 --- a/crates/ide_completion/src/completions/trait_impl.rs +++ b/crates/ide_completion/src/completions/trait_impl.rs @@ -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) } diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index e7980c12d77..7e06b074ce2 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs @@ -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; diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index 5adb0c856bb..ab55d9cc04a 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs @@ -34,7 +34,7 @@ pub(crate) enum PatternRefutability { Refutable, Irrefutable, } -pub enum Visible { +pub(crate) enum Visible { Yes, Editable, No, @@ -108,7 +108,7 @@ pub(crate) struct CompletionContext<'a> { pub(super) token: SyntaxToken, /// The crate of the current file. pub(super) krate: Option, - /// The crate of the `scope`. + /// The module of the `scope`. pub(super) module: Option, pub(super) expected_name: Option, pub(super) expected_type: Option, diff --git a/crates/ide_completion/src/tests/visibility.rs b/crates/ide_completion/src/tests/visibility.rs index 8a024af24b8..2fd16235dc6 100644 --- a/crates/ide_completion/src/tests/visibility.rs +++ b/crates/ide_completion/src/tests/visibility.rs @@ -40,6 +40,7 @@ pub(in $0) #[test] fn qualified() { + cov_mark::check!(visibility_qualified); check( r#" mod foo {