mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 22:31:43 +00:00
Cleanup Completions
api a bit
This commit is contained in:
parent
70650897d8
commit
7267749f6b
9 changed files with 70 additions and 77 deletions
|
@ -18,7 +18,7 @@ pub(crate) mod format_string;
|
||||||
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use hir::known;
|
use hir::{known, ScopeDef};
|
||||||
use ide_db::SymbolKind;
|
use ide_db::SymbolKind;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -28,7 +28,6 @@ use crate::{
|
||||||
const_::render_const,
|
const_::render_const,
|
||||||
enum_variant::render_variant,
|
enum_variant::render_variant,
|
||||||
function::{render_fn, render_method},
|
function::{render_fn, render_method},
|
||||||
macro_::render_macro,
|
|
||||||
pattern::{render_struct_pat, render_variant_pat},
|
pattern::{render_struct_pat, render_variant_pat},
|
||||||
render_field, render_resolution, render_tuple_field,
|
render_field, render_resolution, render_tuple_field,
|
||||||
struct_literal::render_struct_literal,
|
struct_literal::render_struct_literal,
|
||||||
|
@ -38,6 +37,22 @@ use crate::{
|
||||||
CompletionContext, CompletionItem, CompletionItemKind,
|
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.
|
/// Represents an in-progress set of completions being built.
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Completions {
|
pub struct Completions {
|
||||||
|
@ -95,19 +110,6 @@ impl Completions {
|
||||||
self.add(render_resolution(RenderContext::new(ctx, false), local_name, resolution));
|
self.add(render_resolution(RenderContext::new(ctx, false), 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, false), None, name, macro_));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn add_function(
|
pub(crate) fn add_function(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
|
@ -227,9 +229,13 @@ impl Completions {
|
||||||
self.add(item);
|
self.add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_static_lifetime(&mut self, ctx: &CompletionContext) {
|
pub(crate) fn add_lifetime(&mut self, ctx: &CompletionContext, name: hir::Name) {
|
||||||
let item = CompletionItem::new(SymbolKind::LifetimeParam, ctx.source_range(), "'static");
|
CompletionItem::new(SymbolKind::LifetimeParam, ctx.source_range(), name.to_smol_str())
|
||||||
self.add(item.build());
|
.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(
|
pub(crate) fn add_variant_pat(
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
//! there is no value in lifting these out into the outline module test since they will either not
|
//! 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
|
//! show up for normal completions, or they won't show completions other than lifetimes depending
|
||||||
//! on the fixture input.
|
//! on the fixture input.
|
||||||
use hir::ScopeDef;
|
use hir::{known, ScopeDef};
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -35,12 +35,12 @@ pub(crate) fn complete_lifetime(acc: &mut Completions, ctx: &CompletionContext)
|
||||||
ctx.scope.process_all_names(&mut |name, res| {
|
ctx.scope.process_all_names(&mut |name, res| {
|
||||||
if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res {
|
if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res {
|
||||||
if param_lifetime != Some(&*name.to_smol_str()) {
|
if param_lifetime != Some(&*name.to_smol_str()) {
|
||||||
acc.add_resolution(ctx, name, res);
|
acc.add_lifetime(ctx, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if param_lifetime.is_none() {
|
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| {
|
ctx.scope.process_all_names(&mut |name, res| {
|
||||||
if let ScopeDef::Label(_) = 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};
|
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<()> {
|
pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
|
||||||
let mod_under_caret = match &ctx.completion_location {
|
let mod_under_caret = match &ctx.completion_location {
|
||||||
Some(ImmediateLocation::ModDeclaration(mod_under_caret)) => mod_under_caret,
|
Some(ImmediateLocation::ModDeclaration(mod_under_caret)) => mod_under_caret,
|
||||||
|
|
|
@ -7,6 +7,7 @@ use rustc_hash::FxHashSet;
|
||||||
use syntax::{ast, AstNode};
|
use syntax::{ast, AstNode};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
completions::{module_or_attr, module_or_fn_macro},
|
||||||
context::{PathCompletionContext, PathKind},
|
context::{PathCompletionContext, PathKind},
|
||||||
patterns::ImmediateLocation,
|
patterns::ImmediateLocation,
|
||||||
CompletionContext, Completions,
|
CompletionContext, Completions,
|
||||||
|
@ -57,12 +58,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
||||||
Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
|
Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
|
||||||
if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
|
if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
|
||||||
for (name, def) in module.scope(ctx.db, context_module) {
|
for (name, def) in module.scope(ctx.db, context_module) {
|
||||||
if let ScopeDef::MacroDef(macro_def) = def {
|
if let Some(def) = module_or_fn_macro(def) {
|
||||||
if macro_def.is_fn_like() {
|
|
||||||
acc.add_macro(ctx, Some(name.clone()), macro_def);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = def {
|
|
||||||
acc.add_resolution(ctx, name, def);
|
acc.add_resolution(ctx, name, def);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,16 +69,18 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
||||||
}
|
}
|
||||||
|
|
||||||
match kind {
|
match kind {
|
||||||
|
// Complete next child module that comes after the qualified module which is still our parent
|
||||||
Some(PathKind::Vis { .. }) => {
|
Some(PathKind::Vis { .. }) => {
|
||||||
if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
|
if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
|
||||||
if let Some(current_module) = ctx.module {
|
if let Some(current_module) = ctx.module {
|
||||||
if let Some(next) = current_module
|
let next_towards_current = current_module
|
||||||
.path_to_root(ctx.db)
|
.path_to_root(ctx.db)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.take_while(|&it| it != module)
|
.take_while(|&it| it != module)
|
||||||
.next()
|
.next();
|
||||||
{
|
if let Some(next) = next_towards_current {
|
||||||
if let Some(name) = next.name(ctx.db) {
|
if let Some(name) = next.name(ctx.db) {
|
||||||
|
cov_mark::hit!(visibility_qualified);
|
||||||
acc.add_resolution(ctx, name, ScopeDef::ModuleDef(next.into()));
|
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) => {
|
Some(PathKind::Attr) => {
|
||||||
if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
|
if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
|
||||||
for (name, def) in module.scope(ctx.db, context_module) {
|
for (name, def) in module.scope(ctx.db, context_module) {
|
||||||
let add_resolution = match def {
|
if let Some(def) = module_or_attr(def) {
|
||||||
ScopeDef::MacroDef(mac) => mac.is_attr(),
|
|
||||||
ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) => true,
|
|
||||||
_ => false,
|
|
||||||
};
|
|
||||||
if add_resolution {
|
|
||||||
acc.add_resolution(ctx, name, 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 syntax::{ast::Expr, T};
|
||||||
|
|
||||||
use crate::{
|
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<()> {
|
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);
|
CompletionItem::new(SymbolKind::Field, ctx.source_range(), completion_text);
|
||||||
let completion_text =
|
let completion_text =
|
||||||
completion_text.strip_prefix(ctx.token.text()).unwrap_or(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);
|
item.add_to(acc);
|
||||||
}
|
}
|
||||||
if ctx.previous_token_is(T![.]) {
|
if ctx.previous_token_is(T![.]) {
|
||||||
|
|
|
@ -42,7 +42,7 @@ use text_edit::TextEdit;
|
||||||
|
|
||||||
use crate::{CompletionContext, CompletionItem, CompletionItemKind, Completions};
|
use crate::{CompletionContext, CompletionItem, CompletionItemKind, Completions};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
enum ImplCompletionKind {
|
enum ImplCompletionKind {
|
||||||
All,
|
All,
|
||||||
Fn,
|
Fn,
|
||||||
|
@ -53,23 +53,22 @@ enum ImplCompletionKind {
|
||||||
pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {
|
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((kind, trigger, impl_def)) = completion_match(ctx.token.clone()) {
|
||||||
if let Some(hir_impl) = ctx.sema.to_def(&impl_def) {
|
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 {
|
get_missing_assoc_items(&ctx.sema, &impl_def).into_iter().for_each(|item| {
|
||||||
hir::AssocItem::Function(fn_item)
|
match (item, kind) {
|
||||||
if kind == ImplCompletionKind::All || kind == ImplCompletionKind::Fn =>
|
(
|
||||||
{
|
hir::AssocItem::Function(fn_item),
|
||||||
add_function_impl(&trigger, acc, ctx, fn_item, hir_impl)
|
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());
|
transform.apply(assoc_item.syntax());
|
||||||
if let ast::AssocItem::Fn(func) = &assoc_item {
|
if let ast::AssocItem::Fn(func) = &assoc_item {
|
||||||
func.remove_attrs_and_docs()
|
func.remove_attrs_and_docs();
|
||||||
}
|
}
|
||||||
Some(assoc_item)
|
Some(assoc_item)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ use hir::ScopeDef;
|
||||||
use syntax::{ast, AstNode};
|
use syntax::{ast, AstNode};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
completions::{module_or_attr, module_or_fn_macro},
|
||||||
context::{PathCompletionContext, PathKind},
|
context::{PathCompletionContext, PathKind},
|
||||||
patterns::ImmediateLocation,
|
patterns::ImmediateLocation,
|
||||||
CompletionContext, Completions,
|
CompletionContext, Completions,
|
||||||
|
@ -36,14 +37,9 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
|
||||||
match kind {
|
match kind {
|
||||||
Some(PathKind::Vis { .. }) => return,
|
Some(PathKind::Vis { .. }) => return,
|
||||||
Some(PathKind::Attr) => {
|
Some(PathKind::Attr) => {
|
||||||
ctx.process_all_names(&mut |name, res| {
|
ctx.process_all_names(&mut |name, def| {
|
||||||
let add_resolution = match res {
|
if let Some(def) = module_or_attr(def) {
|
||||||
ScopeDef::MacroDef(mac) => mac.is_attr(),
|
acc.add_resolution(ctx, name, def);
|
||||||
ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) => true,
|
|
||||||
_ => false,
|
|
||||||
};
|
|
||||||
if add_resolution {
|
|
||||||
acc.add_resolution(ctx, name, res);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
@ -54,14 +50,9 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
|
||||||
match &ctx.completion_location {
|
match &ctx.completion_location {
|
||||||
Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
|
Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
|
||||||
// only show macros in {Assoc}ItemList
|
// only show macros in {Assoc}ItemList
|
||||||
ctx.process_all_names(&mut |name, res| {
|
ctx.process_all_names(&mut |name, def| {
|
||||||
if let hir::ScopeDef::MacroDef(mac) = res {
|
if let Some(def) = module_or_fn_macro(def) {
|
||||||
if mac.is_fn_like() {
|
acc.add_resolution(ctx, name, def);
|
||||||
acc.add_macro(ctx, Some(name.clone()), mac);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
|
|
||||||
acc.add_resolution(ctx, name, res);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -34,7 +34,7 @@ pub(crate) enum PatternRefutability {
|
||||||
Refutable,
|
Refutable,
|
||||||
Irrefutable,
|
Irrefutable,
|
||||||
}
|
}
|
||||||
pub enum Visible {
|
pub(crate) enum Visible {
|
||||||
Yes,
|
Yes,
|
||||||
Editable,
|
Editable,
|
||||||
No,
|
No,
|
||||||
|
@ -108,7 +108,7 @@ pub(crate) struct CompletionContext<'a> {
|
||||||
pub(super) token: SyntaxToken,
|
pub(super) token: SyntaxToken,
|
||||||
/// The crate of the current file.
|
/// The crate of the current file.
|
||||||
pub(super) krate: Option<hir::Crate>,
|
pub(super) krate: Option<hir::Crate>,
|
||||||
/// The crate of the `scope`.
|
/// The module of the `scope`.
|
||||||
pub(super) module: Option<hir::Module>,
|
pub(super) module: Option<hir::Module>,
|
||||||
pub(super) expected_name: Option<NameOrNameRef>,
|
pub(super) expected_name: Option<NameOrNameRef>,
|
||||||
pub(super) expected_type: Option<Type>,
|
pub(super) expected_type: Option<Type>,
|
||||||
|
|
|
@ -40,6 +40,7 @@ pub(in $0)
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn qualified() {
|
fn qualified() {
|
||||||
|
cov_mark::check!(visibility_qualified);
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
mod foo {
|
mod foo {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue