mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-03 15:15:24 +00:00
Auto merge of #12588 - Veykril:completions, r=Veykril
internal: More completion reorganizing
This commit is contained in:
commit
a2e7e4e42c
20 changed files with 411 additions and 389 deletions
|
@ -22,12 +22,15 @@ pub(crate) mod vis;
|
||||||
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use hir::{db::HirDatabase, known, ScopeDef};
|
use hir::{known, ScopeDef};
|
||||||
use ide_db::SymbolKind;
|
use ide_db::SymbolKind;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::Visible,
|
context::{
|
||||||
|
ItemListKind, NameContext, NameKind, NameRefContext, NameRefKind, PathKind, PatternContext,
|
||||||
|
TypeLocation, Visible,
|
||||||
|
},
|
||||||
item::Builder,
|
item::Builder,
|
||||||
render::{
|
render::{
|
||||||
const_::render_const,
|
const_::render_const,
|
||||||
|
@ -43,22 +46,6 @@ use crate::{
|
||||||
CompletionContext, CompletionItem, CompletionItemKind,
|
CompletionContext, CompletionItem, CompletionItemKind,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn module_or_attr(db: &dyn HirDatabase, def: ScopeDef) -> Option<ScopeDef> {
|
|
||||||
match def {
|
|
||||||
ScopeDef::ModuleDef(hir::ModuleDef::Macro(m)) if m.is_attr(db) => Some(def),
|
|
||||||
ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) => Some(def),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn module_or_fn_macro(db: &dyn HirDatabase, def: ScopeDef) -> Option<ScopeDef> {
|
|
||||||
match def {
|
|
||||||
ScopeDef::ModuleDef(hir::ModuleDef::Macro(m)) if m.is_fn_like(db) => 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 {
|
||||||
|
@ -181,6 +168,15 @@ impl Completions {
|
||||||
self.add(render_resolution_simple(RenderContext::new(ctx), local_name, resolution).build());
|
self.add(render_resolution_simple(RenderContext::new(ctx), local_name, resolution).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn add_module(
|
||||||
|
&mut self,
|
||||||
|
ctx: &CompletionContext,
|
||||||
|
module: hir::Module,
|
||||||
|
local_name: hir::Name,
|
||||||
|
) {
|
||||||
|
self.add_resolution(ctx, local_name, hir::ScopeDef::ModuleDef(module.into()));
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn add_macro(
|
pub(crate) fn add_macro(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
|
@ -437,3 +433,124 @@ fn enum_variants_with_paths(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn complete_name(
|
||||||
|
acc: &mut Completions,
|
||||||
|
ctx: &CompletionContext,
|
||||||
|
NameContext { name, kind }: &NameContext,
|
||||||
|
) {
|
||||||
|
match kind {
|
||||||
|
NameKind::Const => {
|
||||||
|
item_list::trait_impl::complete_trait_impl_const(acc, ctx, name);
|
||||||
|
}
|
||||||
|
NameKind::Function => {
|
||||||
|
item_list::trait_impl::complete_trait_impl_fn(acc, ctx, name);
|
||||||
|
}
|
||||||
|
NameKind::IdentPat(pattern_ctx) => complete_patterns(acc, ctx, pattern_ctx),
|
||||||
|
NameKind::Module(mod_under_caret) => {
|
||||||
|
mod_::complete_mod(acc, ctx, mod_under_caret);
|
||||||
|
}
|
||||||
|
NameKind::TypeAlias => {
|
||||||
|
item_list::trait_impl::complete_trait_impl_type_alias(acc, ctx, name);
|
||||||
|
}
|
||||||
|
NameKind::RecordField => {
|
||||||
|
field::complete_field_list_record_variant(acc, ctx);
|
||||||
|
}
|
||||||
|
NameKind::ConstParam
|
||||||
|
| NameKind::Enum
|
||||||
|
| NameKind::MacroDef
|
||||||
|
| NameKind::MacroRules
|
||||||
|
| NameKind::Rename
|
||||||
|
| NameKind::SelfParam
|
||||||
|
| NameKind::Static
|
||||||
|
| NameKind::Struct
|
||||||
|
| NameKind::Trait
|
||||||
|
| NameKind::TypeParam
|
||||||
|
| NameKind::Union
|
||||||
|
| NameKind::Variant => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn complete_name_ref(
|
||||||
|
acc: &mut Completions,
|
||||||
|
ctx: &CompletionContext,
|
||||||
|
NameRefContext { nameref, kind }: &NameRefContext,
|
||||||
|
) {
|
||||||
|
match kind {
|
||||||
|
NameRefKind::Path(path_ctx) => {
|
||||||
|
flyimport::import_on_the_fly_path(acc, ctx, path_ctx);
|
||||||
|
|
||||||
|
match &path_ctx.kind {
|
||||||
|
PathKind::Expr { expr_ctx } => {
|
||||||
|
expr::complete_expr_path(acc, ctx, path_ctx, expr_ctx);
|
||||||
|
|
||||||
|
dot::complete_undotted_self(acc, ctx, path_ctx, expr_ctx);
|
||||||
|
item_list::complete_item_list_in_expr(acc, ctx, path_ctx, expr_ctx);
|
||||||
|
record::complete_record_expr_func_update(acc, ctx, path_ctx, expr_ctx);
|
||||||
|
snippet::complete_expr_snippet(acc, ctx, path_ctx, expr_ctx);
|
||||||
|
}
|
||||||
|
PathKind::Type { location } => {
|
||||||
|
r#type::complete_type_path(acc, ctx, path_ctx, location);
|
||||||
|
|
||||||
|
match location {
|
||||||
|
TypeLocation::TupleField => {
|
||||||
|
field::complete_field_list_tuple_variant(acc, ctx, path_ctx);
|
||||||
|
}
|
||||||
|
TypeLocation::TypeAscription(ascription) => {
|
||||||
|
r#type::complete_ascribed_type(acc, ctx, path_ctx, ascription);
|
||||||
|
}
|
||||||
|
TypeLocation::GenericArgList(_)
|
||||||
|
| TypeLocation::TypeBound
|
||||||
|
| TypeLocation::ImplTarget
|
||||||
|
| TypeLocation::ImplTrait
|
||||||
|
| TypeLocation::Other => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PathKind::Attr { attr_ctx } => {
|
||||||
|
attribute::complete_attribute_path(acc, ctx, path_ctx, attr_ctx);
|
||||||
|
}
|
||||||
|
PathKind::Derive { existing_derives } => {
|
||||||
|
attribute::complete_derive_path(acc, ctx, path_ctx, existing_derives);
|
||||||
|
}
|
||||||
|
PathKind::Item { kind } => {
|
||||||
|
item_list::complete_item_list(acc, ctx, path_ctx, kind);
|
||||||
|
|
||||||
|
snippet::complete_item_snippet(acc, ctx, path_ctx, kind);
|
||||||
|
if let ItemListKind::TraitImpl(impl_) = kind {
|
||||||
|
item_list::trait_impl::complete_trait_impl_item_by_name(
|
||||||
|
acc, ctx, path_ctx, nameref, impl_,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PathKind::Pat { .. } => {
|
||||||
|
pattern::complete_pattern_path(acc, ctx, path_ctx);
|
||||||
|
}
|
||||||
|
PathKind::Vis { has_in_token } => {
|
||||||
|
vis::complete_vis_path(acc, ctx, path_ctx, has_in_token);
|
||||||
|
}
|
||||||
|
PathKind::Use => {
|
||||||
|
use_::complete_use_path(acc, ctx, path_ctx, nameref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NameRefKind::DotAccess(dot_access) => {
|
||||||
|
flyimport::import_on_the_fly_dot(acc, ctx, dot_access);
|
||||||
|
dot::complete_dot(acc, ctx, dot_access);
|
||||||
|
postfix::complete_postfix(acc, ctx, dot_access);
|
||||||
|
}
|
||||||
|
NameRefKind::Keyword(item) => {
|
||||||
|
keyword::complete_for_and_where(acc, ctx, item);
|
||||||
|
}
|
||||||
|
NameRefKind::RecordExpr(record_expr) => {
|
||||||
|
record::complete_record_expr_fields(acc, ctx, record_expr);
|
||||||
|
}
|
||||||
|
NameRefKind::Pattern(pattern_ctx) => complete_patterns(acc, ctx, pattern_ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn complete_patterns(acc: &mut Completions, ctx: &CompletionContext, pattern_ctx: &PatternContext) {
|
||||||
|
flyimport::import_on_the_fly_pat(acc, ctx, pattern_ctx);
|
||||||
|
fn_param::complete_fn_param(acc, ctx, pattern_ctx);
|
||||||
|
pattern::complete_pattern(acc, ctx, pattern_ctx);
|
||||||
|
record::complete_record_pattern_fields(acc, ctx, pattern_ctx);
|
||||||
|
}
|
||||||
|
|
|
@ -17,8 +17,7 @@ use syntax::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
completions::module_or_attr,
|
context::{AttrCtx, CompletionContext, PathCompletionCtx, Qualified},
|
||||||
context::{CompletionContext, PathCompletionCtx, PathKind, Qualified},
|
|
||||||
item::CompletionItem,
|
item::CompletionItem,
|
||||||
Completions,
|
Completions,
|
||||||
};
|
};
|
||||||
|
@ -28,7 +27,7 @@ mod derive;
|
||||||
mod lint;
|
mod lint;
|
||||||
mod repr;
|
mod repr;
|
||||||
|
|
||||||
pub(crate) use self::derive::complete_derive;
|
pub(crate) use self::derive::complete_derive_path;
|
||||||
|
|
||||||
/// Complete inputs to known builtin attributes as well as derive attributes
|
/// Complete inputs to known builtin attributes as well as derive attributes
|
||||||
pub(crate) fn complete_known_attribute_input(
|
pub(crate) fn complete_known_attribute_input(
|
||||||
|
@ -69,19 +68,13 @@ pub(crate) fn complete_known_attribute_input(
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn complete_attribute(
|
pub(crate) fn complete_attribute_path(
|
||||||
acc: &mut Completions,
|
acc: &mut Completions,
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
path_ctx: &PathCompletionCtx,
|
PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
|
||||||
|
&AttrCtx { kind, annotated_item_kind }: &AttrCtx,
|
||||||
) {
|
) {
|
||||||
let (qualified, is_inner, annotated_item_kind) = match path_ctx {
|
let is_inner = kind == AttrKind::Inner;
|
||||||
&PathCompletionCtx {
|
|
||||||
kind: PathKind::Attr { kind, annotated_item_kind },
|
|
||||||
ref qualified,
|
|
||||||
..
|
|
||||||
} => (qualified, kind == AttrKind::Inner, annotated_item_kind),
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
match qualified {
|
match qualified {
|
||||||
Qualified::With {
|
Qualified::With {
|
||||||
|
@ -94,8 +87,14 @@ pub(crate) fn complete_attribute(
|
||||||
}
|
}
|
||||||
|
|
||||||
for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
|
for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
|
||||||
if let Some(def) = module_or_attr(ctx.db, def) {
|
match def {
|
||||||
acc.add_resolution(ctx, name, def);
|
hir::ScopeDef::ModuleDef(hir::ModuleDef::Macro(m)) if m.is_attr(ctx.db) => {
|
||||||
|
acc.add_macro(ctx, m, name)
|
||||||
|
}
|
||||||
|
hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) => {
|
||||||
|
acc.add_module(ctx, m, name)
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -104,10 +103,12 @@ pub(crate) fn complete_attribute(
|
||||||
Qualified::Absolute => acc.add_crate_roots(ctx),
|
Qualified::Absolute => acc.add_crate_roots(ctx),
|
||||||
// only show modules in a fresh UseTree
|
// only show modules in a fresh UseTree
|
||||||
Qualified::No => {
|
Qualified::No => {
|
||||||
ctx.process_all_names(&mut |name, def| {
|
ctx.process_all_names(&mut |name, def| match def {
|
||||||
if let Some(def) = module_or_attr(ctx.db, def) {
|
hir::ScopeDef::ModuleDef(hir::ModuleDef::Macro(m)) if m.is_attr(ctx.db) => {
|
||||||
acc.add_resolution(ctx, name, def);
|
acc.add_macro(ctx, m, name)
|
||||||
}
|
}
|
||||||
|
hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) => acc.add_module(ctx, m, name),
|
||||||
|
_ => (),
|
||||||
});
|
});
|
||||||
acc.add_nameref_keywords_with_colon(ctx);
|
acc.add_nameref_keywords_with_colon(ctx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,23 +5,17 @@ use itertools::Itertools;
|
||||||
use syntax::SmolStr;
|
use syntax::SmolStr;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::{CompletionContext, PathCompletionCtx, PathKind, Qualified},
|
context::{CompletionContext, ExistingDerives, PathCompletionCtx, Qualified},
|
||||||
item::CompletionItem,
|
item::CompletionItem,
|
||||||
Completions,
|
Completions,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) fn complete_derive(
|
pub(crate) fn complete_derive_path(
|
||||||
acc: &mut Completions,
|
acc: &mut Completions,
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
path_ctx: &PathCompletionCtx,
|
PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
|
||||||
|
existing_derives: &ExistingDerives,
|
||||||
) {
|
) {
|
||||||
let (qualified, existing_derives) = match path_ctx {
|
|
||||||
PathCompletionCtx { kind: PathKind::Derive { existing_derives }, qualified, .. } => {
|
|
||||||
(qualified, existing_derives)
|
|
||||||
}
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
let core = ctx.famous_defs().core();
|
let core = ctx.famous_defs().core();
|
||||||
|
|
||||||
match qualified {
|
match qualified {
|
||||||
|
@ -35,15 +29,14 @@ pub(crate) fn complete_derive(
|
||||||
}
|
}
|
||||||
|
|
||||||
for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
|
for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
|
||||||
let add_def = match def {
|
match def {
|
||||||
ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => {
|
ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac))
|
||||||
!existing_derives.contains(&mac) && mac.is_derive(ctx.db)
|
if !existing_derives.contains(&mac) && mac.is_derive(ctx.db) =>
|
||||||
|
{
|
||||||
|
acc.add_macro(ctx, mac, name)
|
||||||
}
|
}
|
||||||
ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) => true,
|
ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) => acc.add_module(ctx, m, name),
|
||||||
_ => false,
|
_ => (),
|
||||||
};
|
|
||||||
if add_def {
|
|
||||||
acc.add_resolution(ctx, name, def);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,8 +50,8 @@ pub(crate) fn complete_derive(
|
||||||
{
|
{
|
||||||
mac
|
mac
|
||||||
}
|
}
|
||||||
ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) => {
|
ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) => {
|
||||||
return acc.add_resolution(ctx, name, def);
|
return acc.add_module(ctx, m, name);
|
||||||
}
|
}
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
@ -66,7 +59,7 @@ pub(crate) fn complete_derive(
|
||||||
match (core, mac.module(ctx.db).krate()) {
|
match (core, mac.module(ctx.db).krate()) {
|
||||||
// show derive dependencies for `core`/`std` derives
|
// show derive dependencies for `core`/`std` derives
|
||||||
(Some(core), mac_krate) if core == mac_krate => {}
|
(Some(core), mac_krate) if core == mac_krate => {}
|
||||||
_ => return acc.add_resolution(ctx, name, def),
|
_ => return acc.add_macro(ctx, mac, name),
|
||||||
};
|
};
|
||||||
|
|
||||||
let name_ = name.to_smol_str();
|
let name_ = name.to_smol_str();
|
||||||
|
@ -99,7 +92,7 @@ pub(crate) fn complete_derive(
|
||||||
item.lookup_by(lookup);
|
item.lookup_by(lookup);
|
||||||
item.add_to(acc);
|
item.add_to(acc);
|
||||||
}
|
}
|
||||||
None => acc.add_resolution(ctx, name, def),
|
None => acc.add_macro(ctx, mac, name),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
acc.add_nameref_keywords_with_colon(ctx);
|
acc.add_nameref_keywords_with_colon(ctx);
|
||||||
|
|
|
@ -3,9 +3,7 @@
|
||||||
use ide_db::FxHashSet;
|
use ide_db::FxHashSet;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::{
|
context::{CompletionContext, DotAccess, DotAccessKind, ExprCtx, PathCompletionCtx, Qualified},
|
||||||
CompletionContext, DotAccess, DotAccessKind, PathCompletionCtx, PathKind, Qualified,
|
|
||||||
},
|
|
||||||
CompletionItem, CompletionItemKind, Completions,
|
CompletionItem, CompletionItemKind, Completions,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -42,16 +40,22 @@ pub(crate) fn complete_undotted_self(
|
||||||
acc: &mut Completions,
|
acc: &mut Completions,
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
path_ctx: &PathCompletionCtx,
|
path_ctx: &PathCompletionCtx,
|
||||||
|
expr_ctx: &ExprCtx,
|
||||||
) {
|
) {
|
||||||
if !ctx.config.enable_self_on_the_fly {
|
if !ctx.config.enable_self_on_the_fly {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let self_param = match path_ctx {
|
if !path_ctx.is_trivial_path() {
|
||||||
PathCompletionCtx {
|
return;
|
||||||
qualified: Qualified::No,
|
}
|
||||||
kind: PathKind::Expr { self_param: Some(self_param), .. },
|
if !ctx.qualifier_ctx.none() {
|
||||||
..
|
return;
|
||||||
} if path_ctx.is_trivial_path() && ctx.qualifier_ctx.none() => self_param,
|
}
|
||||||
|
if !matches!(path_ctx.qualified, Qualified::No) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let self_param = match expr_ctx {
|
||||||
|
ExprCtx { self_param: Some(self_param), .. } => self_param,
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,34 +4,15 @@ use hir::ScopeDef;
|
||||||
use ide_db::FxHashSet;
|
use ide_db::FxHashSet;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::{PathCompletionCtx, PathKind, Qualified},
|
context::{ExprCtx, PathCompletionCtx, Qualified},
|
||||||
CompletionContext, Completions,
|
CompletionContext, Completions,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) fn complete_expr_path(
|
pub(crate) fn complete_expr_path(
|
||||||
acc: &mut Completions,
|
acc: &mut Completions,
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
path_ctx: &PathCompletionCtx,
|
PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
|
||||||
) {
|
&ExprCtx {
|
||||||
let _p = profile::span("complete_expr_path");
|
|
||||||
if !ctx.qualifier_ctx.none() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let (
|
|
||||||
qualified,
|
|
||||||
in_block_expr,
|
|
||||||
in_loop_body,
|
|
||||||
is_func_update,
|
|
||||||
after_if_expr,
|
|
||||||
wants_mut_token,
|
|
||||||
in_condition,
|
|
||||||
ty,
|
|
||||||
incomplete_let,
|
|
||||||
impl_,
|
|
||||||
) = match path_ctx {
|
|
||||||
&PathCompletionCtx {
|
|
||||||
kind:
|
|
||||||
PathKind::Expr {
|
|
||||||
in_block_expr,
|
in_block_expr,
|
||||||
in_loop_body,
|
in_loop_body,
|
||||||
after_if_expr,
|
after_if_expr,
|
||||||
|
@ -42,23 +23,15 @@ pub(crate) fn complete_expr_path(
|
||||||
ref innermost_ret_ty,
|
ref innermost_ret_ty,
|
||||||
ref impl_,
|
ref impl_,
|
||||||
..
|
..
|
||||||
},
|
}: &ExprCtx,
|
||||||
ref qualified,
|
) {
|
||||||
..
|
let _p = profile::span("complete_expr_path");
|
||||||
} => (
|
if !ctx.qualifier_ctx.none() {
|
||||||
qualified,
|
return;
|
||||||
in_block_expr,
|
}
|
||||||
in_loop_body,
|
|
||||||
is_func_update.is_some(),
|
let wants_mut_token =
|
||||||
after_if_expr,
|
ref_expr_parent.as_ref().map(|it| it.mut_token().is_none()).unwrap_or(false);
|
||||||
ref_expr_parent.as_ref().map(|it| it.mut_token().is_none()).unwrap_or(false),
|
|
||||||
in_condition,
|
|
||||||
innermost_ret_ty,
|
|
||||||
incomplete_let,
|
|
||||||
impl_,
|
|
||||||
),
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
let scope_def_applicable = |def| {
|
let scope_def_applicable = |def| {
|
||||||
use hir::{GenericParam::*, ModuleDef::*};
|
use hir::{GenericParam::*, ModuleDef::*};
|
||||||
|
@ -230,7 +203,7 @@ pub(crate) fn complete_expr_path(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if !is_func_update {
|
if is_func_update.is_none() {
|
||||||
let mut add_keyword =
|
let mut add_keyword =
|
||||||
|kw, snippet| acc.add_keyword_snippet_expr(ctx, kw, snippet, incomplete_let);
|
|kw, snippet| acc.add_keyword_snippet_expr(ctx, kw, snippet, incomplete_let);
|
||||||
|
|
||||||
|
@ -270,7 +243,7 @@ pub(crate) fn complete_expr_path(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ty) = ty {
|
if let Some(ty) = innermost_ret_ty {
|
||||||
add_keyword(
|
add_keyword(
|
||||||
"return",
|
"return",
|
||||||
match (in_block_expr, ty.is_unit()) {
|
match (in_block_expr, ty.is_unit()) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! Completion of field list position.
|
//! Completion of field list position.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::{NameContext, NameKind, PathCompletionCtx, PathKind, Qualified, TypeLocation},
|
context::{PathCompletionCtx, Qualified},
|
||||||
CompletionContext, Completions,
|
CompletionContext, Completions,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10,37 +10,31 @@ pub(crate) fn complete_field_list_tuple_variant(
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
path_ctx: &PathCompletionCtx,
|
path_ctx: &PathCompletionCtx,
|
||||||
) {
|
) {
|
||||||
|
if ctx.qualifier_ctx.vis_node.is_some() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
match path_ctx {
|
match path_ctx {
|
||||||
PathCompletionCtx {
|
PathCompletionCtx {
|
||||||
has_macro_bang: false,
|
has_macro_bang: false,
|
||||||
qualified: Qualified::No,
|
qualified: Qualified::No,
|
||||||
parent: None,
|
parent: None,
|
||||||
kind: PathKind::Type { location: TypeLocation::TupleField },
|
|
||||||
has_type_args: false,
|
has_type_args: false,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
if ctx.qualifier_ctx.vis_node.is_none() {
|
|
||||||
let mut add_keyword = |kw, snippet| acc.add_keyword_snippet(ctx, kw, snippet);
|
let mut add_keyword = |kw, snippet| acc.add_keyword_snippet(ctx, kw, snippet);
|
||||||
add_keyword("pub(crate)", "pub(crate)");
|
add_keyword("pub(crate)", "pub(crate)");
|
||||||
add_keyword("pub(super)", "pub(super)");
|
add_keyword("pub(super)", "pub(super)");
|
||||||
add_keyword("pub", "pub");
|
add_keyword("pub", "pub");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn complete_field_list_record_variant(
|
pub(crate) fn complete_field_list_record_variant(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
acc: &mut Completions,
|
|
||||||
ctx: &CompletionContext,
|
|
||||||
name_ctx: &NameContext,
|
|
||||||
) {
|
|
||||||
if let NameContext { kind: NameKind::RecordField, .. } = name_ctx {
|
|
||||||
if ctx.qualifier_ctx.vis_node.is_none() {
|
if ctx.qualifier_ctx.vis_node.is_none() {
|
||||||
let mut add_keyword = |kw, snippet| acc.add_keyword_snippet(ctx, kw, snippet);
|
let mut add_keyword = |kw, snippet| acc.add_keyword_snippet(ctx, kw, snippet);
|
||||||
add_keyword("pub(crate)", "pub(crate)");
|
add_keyword("pub(crate)", "pub(crate)");
|
||||||
add_keyword("pub(super)", "pub(super)");
|
add_keyword("pub(super)", "pub(super)");
|
||||||
add_keyword("pub", "pub");
|
add_keyword("pub", "pub");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,37 @@
|
||||||
//! Completion of paths and keywords at item list position.
|
//! Completion of paths and keywords at item list position.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
completions::module_or_fn_macro,
|
context::{ExprCtx, ItemListKind, PathCompletionCtx, Qualified},
|
||||||
context::{ItemListKind, PathCompletionCtx, PathKind, Qualified},
|
|
||||||
CompletionContext, Completions,
|
CompletionContext, Completions,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) mod trait_impl;
|
pub(crate) mod trait_impl;
|
||||||
|
|
||||||
pub(crate) fn complete_item_list(
|
pub(crate) fn complete_item_list_in_expr(
|
||||||
acc: &mut Completions,
|
acc: &mut Completions,
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
path_ctx: &PathCompletionCtx,
|
path_ctx: &PathCompletionCtx,
|
||||||
|
expr_ctx: &ExprCtx,
|
||||||
|
) {
|
||||||
|
if !expr_ctx.in_block_expr {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if !path_ctx.is_trivial_path() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
add_keywords(acc, ctx, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn complete_item_list(
|
||||||
|
acc: &mut Completions,
|
||||||
|
ctx: &CompletionContext,
|
||||||
|
path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
|
||||||
|
kind: &ItemListKind,
|
||||||
) {
|
) {
|
||||||
let _p = profile::span("complete_item_list");
|
let _p = profile::span("complete_item_list");
|
||||||
let qualified = match path_ctx {
|
|
||||||
PathCompletionCtx { kind: PathKind::Item { kind }, qualified, .. } => {
|
|
||||||
if path_ctx.is_trivial_path() {
|
if path_ctx.is_trivial_path() {
|
||||||
add_keywords(acc, ctx, Some(kind));
|
add_keywords(acc, ctx, Some(kind));
|
||||||
}
|
}
|
||||||
qualified
|
|
||||||
}
|
|
||||||
PathCompletionCtx { kind: PathKind::Expr { in_block_expr: true, .. }, .. }
|
|
||||||
if path_ctx.is_trivial_path() =>
|
|
||||||
{
|
|
||||||
add_keywords(acc, ctx, None);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
match qualified {
|
match qualified {
|
||||||
Qualified::With {
|
Qualified::With {
|
||||||
|
@ -37,8 +40,14 @@ pub(crate) fn complete_item_list(
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
|
for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
|
||||||
if let Some(def) = module_or_fn_macro(ctx.db, def) {
|
match def {
|
||||||
acc.add_resolution(ctx, name, def);
|
hir::ScopeDef::ModuleDef(hir::ModuleDef::Macro(m)) if m.is_fn_like(ctx.db) => {
|
||||||
|
acc.add_macro(ctx, m, name)
|
||||||
|
}
|
||||||
|
hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) => {
|
||||||
|
acc.add_module(ctx, m, name)
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,10 +57,12 @@ pub(crate) fn complete_item_list(
|
||||||
}
|
}
|
||||||
Qualified::Absolute => acc.add_crate_roots(ctx),
|
Qualified::Absolute => acc.add_crate_roots(ctx),
|
||||||
Qualified::No if ctx.qualifier_ctx.none() => {
|
Qualified::No if ctx.qualifier_ctx.none() => {
|
||||||
ctx.process_all_names(&mut |name, def| {
|
ctx.process_all_names(&mut |name, def| match def {
|
||||||
if let Some(def) = module_or_fn_macro(ctx.db, def) {
|
hir::ScopeDef::ModuleDef(hir::ModuleDef::Macro(m)) if m.is_fn_like(ctx.db) => {
|
||||||
acc.add_resolution(ctx, name, def);
|
acc.add_macro(ctx, m, name)
|
||||||
}
|
}
|
||||||
|
hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) => acc.add_module(ctx, m, name),
|
||||||
|
_ => (),
|
||||||
});
|
});
|
||||||
acc.add_nameref_keywords_with_colon(ctx);
|
acc.add_nameref_keywords_with_colon(ctx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,11 +43,8 @@ use syntax::{
|
||||||
use text_edit::TextEdit;
|
use text_edit::TextEdit;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::{
|
context::PathCompletionCtx, CompletionContext, CompletionItem, CompletionItemKind,
|
||||||
ItemListKind, NameContext, NameKind, NameRefContext, NameRefKind, PathCompletionCtx,
|
CompletionRelevance, Completions,
|
||||||
PathKind,
|
|
||||||
},
|
|
||||||
CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance, Completions,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
@ -58,17 +55,36 @@ enum ImplCompletionKind {
|
||||||
Const,
|
Const,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn complete_trait_impl_name(
|
pub(crate) fn complete_trait_impl_const(
|
||||||
acc: &mut Completions,
|
acc: &mut Completions,
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
NameContext { name, kind, .. }: &NameContext,
|
name: &Option<ast::Name>,
|
||||||
|
) -> Option<()> {
|
||||||
|
complete_trait_impl_name(acc, ctx, name, ImplCompletionKind::Const)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn complete_trait_impl_type_alias(
|
||||||
|
acc: &mut Completions,
|
||||||
|
ctx: &CompletionContext,
|
||||||
|
name: &Option<ast::Name>,
|
||||||
|
) -> Option<()> {
|
||||||
|
complete_trait_impl_name(acc, ctx, name, ImplCompletionKind::TypeAlias)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn complete_trait_impl_fn(
|
||||||
|
acc: &mut Completions,
|
||||||
|
ctx: &CompletionContext,
|
||||||
|
name: &Option<ast::Name>,
|
||||||
|
) -> Option<()> {
|
||||||
|
complete_trait_impl_name(acc, ctx, name, ImplCompletionKind::Fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn complete_trait_impl_name(
|
||||||
|
acc: &mut Completions,
|
||||||
|
ctx: &CompletionContext,
|
||||||
|
name: &Option<ast::Name>,
|
||||||
|
kind: ImplCompletionKind,
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
let kind = match kind {
|
|
||||||
NameKind::Const => ImplCompletionKind::Const,
|
|
||||||
NameKind::Function => ImplCompletionKind::Fn,
|
|
||||||
NameKind::TypeAlias => ImplCompletionKind::TypeAlias,
|
|
||||||
_ => return None,
|
|
||||||
};
|
|
||||||
let token = ctx.token.clone();
|
let token = ctx.token.clone();
|
||||||
let item = match name {
|
let item = match name {
|
||||||
Some(name) => name.syntax().parent(),
|
Some(name) => name.syntax().parent(),
|
||||||
|
@ -86,34 +102,28 @@ pub(crate) fn complete_trait_impl_name(
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn complete_trait_impl_name_ref(
|
pub(crate) fn complete_trait_impl_item_by_name(
|
||||||
acc: &mut Completions,
|
acc: &mut Completions,
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
name_ref_ctx: &NameRefContext,
|
path_ctx: &PathCompletionCtx,
|
||||||
) -> Option<()> {
|
name_ref: &Option<ast::NameRef>,
|
||||||
match name_ref_ctx {
|
impl_: &Option<ast::Impl>,
|
||||||
NameRefContext {
|
) {
|
||||||
nameref,
|
if !path_ctx.is_trivial_path() {
|
||||||
kind:
|
return;
|
||||||
NameRefKind::Path(
|
}
|
||||||
path_ctx @ PathCompletionCtx {
|
if let Some(impl_) = impl_ {
|
||||||
kind: PathKind::Item { kind: ItemListKind::TraitImpl(Some(impl_)) },
|
complete_trait_impl(
|
||||||
..
|
|
||||||
},
|
|
||||||
),
|
|
||||||
} if path_ctx.is_trivial_path() => complete_trait_impl(
|
|
||||||
acc,
|
acc,
|
||||||
ctx,
|
ctx,
|
||||||
ImplCompletionKind::All,
|
ImplCompletionKind::All,
|
||||||
match nameref {
|
match name_ref {
|
||||||
Some(name) => name.syntax().text_range(),
|
Some(name) => name.syntax().text_range(),
|
||||||
None => ctx.source_range(),
|
None => ctx.source_range(),
|
||||||
},
|
},
|
||||||
impl_,
|
impl_,
|
||||||
),
|
);
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
Some(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn complete_trait_impl(
|
fn complete_trait_impl(
|
||||||
|
|
|
@ -4,7 +4,7 @@ use syntax::ast::{self, Item};
|
||||||
|
|
||||||
use crate::{CompletionContext, Completions};
|
use crate::{CompletionContext, Completions};
|
||||||
|
|
||||||
pub(crate) fn complete_special_keywords(
|
pub(crate) fn complete_for_and_where(
|
||||||
acc: &mut Completions,
|
acc: &mut Completions,
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
keyword_item: &ast::Item,
|
keyword_item: &ast::Item,
|
||||||
|
@ -60,8 +60,6 @@ mod tests {
|
||||||
kw fn
|
kw fn
|
||||||
kw impl
|
kw impl
|
||||||
kw trait
|
kw trait
|
||||||
sn pd
|
|
||||||
sn ppd
|
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,21 +9,14 @@ use ide_db::{
|
||||||
};
|
};
|
||||||
use syntax::{ast, AstNode, SyntaxKind};
|
use syntax::{ast, AstNode, SyntaxKind};
|
||||||
|
|
||||||
use crate::{
|
use crate::{context::CompletionContext, CompletionItem, Completions};
|
||||||
context::{CompletionContext, NameContext, NameKind},
|
|
||||||
CompletionItem, Completions,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Complete mod declaration, i.e. `mod $0;`
|
/// Complete mod declaration, i.e. `mod $0;`
|
||||||
pub(crate) fn complete_mod(
|
pub(crate) fn complete_mod(
|
||||||
acc: &mut Completions,
|
acc: &mut Completions,
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
name_ctx: &NameContext,
|
mod_under_caret: &ast::Module,
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
let mod_under_caret = match name_ctx {
|
|
||||||
NameContext { kind: NameKind::Module(mod_under_caret), .. } => mod_under_caret,
|
|
||||||
_ => return None,
|
|
||||||
};
|
|
||||||
if mod_under_caret.item_list().is_some() {
|
if mod_under_caret.item_list().is_some() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use ide_db::FxHashSet;
|
||||||
use syntax::ast::Pat;
|
use syntax::ast::Pat;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::{PathCompletionCtx, PathKind, PatternContext, PatternRefutability, Qualified},
|
context::{PathCompletionCtx, PatternContext, PatternRefutability, Qualified},
|
||||||
CompletionContext, Completions,
|
CompletionContext, Completions,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -108,14 +108,11 @@ pub(crate) fn complete_pattern(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn pattern_path_completion(
|
pub(crate) fn complete_pattern_path(
|
||||||
acc: &mut Completions,
|
acc: &mut Completions,
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
PathCompletionCtx { qualified, kind, .. }: &PathCompletionCtx,
|
PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
|
||||||
) {
|
) {
|
||||||
if !matches!(kind, PathKind::Pat { .. }) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
match qualified {
|
match qualified {
|
||||||
Qualified::With { resolution: Some(resolution), is_super_chain, .. } => {
|
Qualified::With { resolution: Some(resolution), is_super_chain, .. } => {
|
||||||
if *is_super_chain {
|
if *is_super_chain {
|
||||||
|
|
|
@ -6,7 +6,7 @@ use syntax::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::{PathCompletionCtx, PathKind, PatternContext, Qualified},
|
context::{ExprCtx, PathCompletionCtx, PatternContext, Qualified},
|
||||||
CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance,
|
CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance,
|
||||||
CompletionRelevancePostfixMatch, Completions,
|
CompletionRelevancePostfixMatch, Completions,
|
||||||
};
|
};
|
||||||
|
@ -20,7 +20,7 @@ pub(crate) fn complete_record_pattern_fields(
|
||||||
complete_fields(acc, ctx, ctx.sema.record_pattern_missing_fields(record_pat));
|
complete_fields(acc, ctx, ctx.sema.record_pattern_missing_fields(record_pat));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub(crate) fn complete_record_expr_fields_record_expr(
|
pub(crate) fn complete_record_expr_fields(
|
||||||
acc: &mut Completions,
|
acc: &mut Completions,
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
record_expr: &ast::RecordExpr,
|
record_expr: &ast::RecordExpr,
|
||||||
|
@ -85,13 +85,12 @@ pub(crate) fn complete_record_expr_func_update(
|
||||||
acc: &mut Completions,
|
acc: &mut Completions,
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
path_ctx: &PathCompletionCtx,
|
path_ctx: &PathCompletionCtx,
|
||||||
|
expr_ctx: &ExprCtx,
|
||||||
) {
|
) {
|
||||||
if let PathCompletionCtx {
|
if !matches!(path_ctx.qualified, Qualified::No) {
|
||||||
kind: PathKind::Expr { is_func_update: Some(record_expr), .. },
|
return;
|
||||||
qualified: Qualified::No,
|
}
|
||||||
..
|
if let ExprCtx { is_func_update: Some(record_expr), .. } = expr_ctx {
|
||||||
} = path_ctx
|
|
||||||
{
|
|
||||||
let ty = ctx.sema.type_of_expr(&Expr::RecordExpr(record_expr.clone()));
|
let ty = ctx.sema.type_of_expr(&Expr::RecordExpr(record_expr.clone()));
|
||||||
|
|
||||||
match ty.as_ref().and_then(|t| t.original.as_adt()) {
|
match ty.as_ref().and_then(|t| t.original.as_adt()) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ use hir::Documentation;
|
||||||
use ide_db::{imports::insert_use::ImportScope, SnippetCap};
|
use ide_db::{imports::insert_use::ImportScope, SnippetCap};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::{ItemListKind, PathCompletionCtx, PathKind, Qualified},
|
context::{ExprCtx, ItemListKind, PathCompletionCtx, Qualified},
|
||||||
item::Builder,
|
item::Builder,
|
||||||
CompletionContext, CompletionItem, CompletionItemKind, Completions, SnippetScope,
|
CompletionContext, CompletionItem, CompletionItemKind, Completions, SnippetScope,
|
||||||
};
|
};
|
||||||
|
@ -19,15 +19,14 @@ pub(crate) fn complete_expr_snippet(
|
||||||
acc: &mut Completions,
|
acc: &mut Completions,
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
path_ctx: &PathCompletionCtx,
|
path_ctx: &PathCompletionCtx,
|
||||||
|
&ExprCtx { in_block_expr, .. }: &ExprCtx,
|
||||||
) {
|
) {
|
||||||
let &can_be_stmt = match path_ctx {
|
if !matches!(path_ctx.qualified, Qualified::No) {
|
||||||
PathCompletionCtx {
|
return;
|
||||||
qualified: Qualified::No,
|
}
|
||||||
kind: PathKind::Expr { in_block_expr, .. },
|
if !ctx.qualifier_ctx.none() {
|
||||||
..
|
return;
|
||||||
} => in_block_expr,
|
}
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
let cap = match ctx.config.snippet_cap {
|
let cap = match ctx.config.snippet_cap {
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
|
@ -38,9 +37,21 @@ pub(crate) fn complete_expr_snippet(
|
||||||
add_custom_completions(acc, ctx, cap, SnippetScope::Expr);
|
add_custom_completions(acc, ctx, cap, SnippetScope::Expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if can_be_stmt {
|
if in_block_expr {
|
||||||
snippet(ctx, cap, "pd", "eprintln!(\"$0 = {:?}\", $0);").add_to(acc);
|
snippet(ctx, cap, "pd", "eprintln!(\"$0 = {:?}\", $0);").add_to(acc);
|
||||||
snippet(ctx, cap, "ppd", "eprintln!(\"$0 = {:#?}\", $0);").add_to(acc);
|
snippet(ctx, cap, "ppd", "eprintln!(\"$0 = {:#?}\", $0);").add_to(acc);
|
||||||
|
let item = snippet(
|
||||||
|
ctx,
|
||||||
|
cap,
|
||||||
|
"macro_rules",
|
||||||
|
"\
|
||||||
|
macro_rules! $1 {
|
||||||
|
($2) => {
|
||||||
|
$0
|
||||||
|
};
|
||||||
|
}",
|
||||||
|
);
|
||||||
|
item.add_to(acc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,21 +59,13 @@ pub(crate) fn complete_item_snippet(
|
||||||
acc: &mut Completions,
|
acc: &mut Completions,
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
path_ctx: &PathCompletionCtx,
|
path_ctx: &PathCompletionCtx,
|
||||||
|
kind: &ItemListKind,
|
||||||
) {
|
) {
|
||||||
let path_kind = match path_ctx {
|
if !matches!(path_ctx.qualified, Qualified::No) {
|
||||||
PathCompletionCtx {
|
|
||||||
qualified: Qualified::No,
|
|
||||||
kind: kind @ (PathKind::Item { .. } | PathKind::Expr { in_block_expr: true, .. }),
|
|
||||||
..
|
|
||||||
} => kind,
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
if !ctx.qualifier_ctx.none() {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ctx.qualifier_ctx.vis_node.is_some() {
|
if !ctx.qualifier_ctx.none() {
|
||||||
return; // technically we could do some of these snippet completions if we were to put the
|
return;
|
||||||
// attributes before the vis node.
|
|
||||||
}
|
}
|
||||||
let cap = match ctx.config.snippet_cap {
|
let cap = match ctx.config.snippet_cap {
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
|
@ -74,8 +77,7 @@ pub(crate) fn complete_item_snippet(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test-related snippets shouldn't be shown in blocks.
|
// Test-related snippets shouldn't be shown in blocks.
|
||||||
if let PathKind::Item { kind: ItemListKind::SourceFile | ItemListKind::Module, .. } = path_kind
|
if let ItemListKind::SourceFile | ItemListKind::Module = kind {
|
||||||
{
|
|
||||||
let mut item = snippet(
|
let mut item = snippet(
|
||||||
ctx,
|
ctx,
|
||||||
cap,
|
cap,
|
||||||
|
@ -106,10 +108,7 @@ fn ${1:feature}() {
|
||||||
);
|
);
|
||||||
item.lookup_by("tfn");
|
item.lookup_by("tfn");
|
||||||
item.add_to(acc);
|
item.add_to(acc);
|
||||||
}
|
|
||||||
if let PathKind::Item { kind: ItemListKind::SourceFile | ItemListKind::Module, .. }
|
|
||||||
| PathKind::Expr { .. } = path_kind
|
|
||||||
{
|
|
||||||
let item = snippet(
|
let item = snippet(
|
||||||
ctx,
|
ctx,
|
||||||
cap,
|
cap,
|
||||||
|
|
|
@ -5,7 +5,7 @@ use ide_db::FxHashSet;
|
||||||
use syntax::{ast, AstNode};
|
use syntax::{ast, AstNode};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::{PathCompletionCtx, PathKind, Qualified, TypeAscriptionTarget, TypeLocation},
|
context::{PathCompletionCtx, Qualified, TypeAscriptionTarget, TypeLocation},
|
||||||
render::render_type_inference,
|
render::render_type_inference,
|
||||||
CompletionContext, Completions,
|
CompletionContext, Completions,
|
||||||
};
|
};
|
||||||
|
@ -13,17 +13,11 @@ use crate::{
|
||||||
pub(crate) fn complete_type_path(
|
pub(crate) fn complete_type_path(
|
||||||
acc: &mut Completions,
|
acc: &mut Completions,
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
path_ctx: &PathCompletionCtx,
|
PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
|
||||||
|
location: &TypeLocation,
|
||||||
) {
|
) {
|
||||||
let _p = profile::span("complete_type_path");
|
let _p = profile::span("complete_type_path");
|
||||||
|
|
||||||
let (location, qualified) = match path_ctx {
|
|
||||||
PathCompletionCtx { kind: PathKind::Type { location }, qualified, .. } => {
|
|
||||||
(location, qualified)
|
|
||||||
}
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
let scope_def_applicable = |def| {
|
let scope_def_applicable = |def| {
|
||||||
use hir::{GenericParam::*, ModuleDef::*};
|
use hir::{GenericParam::*, ModuleDef::*};
|
||||||
match def {
|
match def {
|
||||||
|
@ -191,19 +185,16 @@ pub(crate) fn complete_type_path(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn complete_inferred_type(
|
pub(crate) fn complete_ascribed_type(
|
||||||
acc: &mut Completions,
|
acc: &mut Completions,
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
path_ctx: &PathCompletionCtx,
|
path_ctx: &PathCompletionCtx,
|
||||||
|
ascription: &TypeAscriptionTarget,
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
let pat = match path_ctx {
|
if !path_ctx.is_trivial_path() {
|
||||||
PathCompletionCtx {
|
return None;
|
||||||
kind: PathKind::Type { location: TypeLocation::TypeAscription(ascription), .. },
|
}
|
||||||
..
|
let x = match ascription {
|
||||||
} if path_ctx.is_trivial_path() => ascription,
|
|
||||||
_ => return None,
|
|
||||||
};
|
|
||||||
let x = match pat {
|
|
||||||
TypeAscriptionTarget::Let(pat) | TypeAscriptionTarget::FnParam(pat) => {
|
TypeAscriptionTarget::Let(pat) | TypeAscriptionTarget::FnParam(pat) => {
|
||||||
ctx.sema.type_of_pat(pat.as_ref()?)
|
ctx.sema.type_of_pat(pat.as_ref()?)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,33 +5,17 @@ use ide_db::{FxHashSet, SymbolKind};
|
||||||
use syntax::{ast, AstNode};
|
use syntax::{ast, AstNode};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::{
|
context::{CompletionContext, PathCompletionCtx, Qualified},
|
||||||
CompletionContext, NameRefContext, NameRefKind, PathCompletionCtx, PathKind, Qualified,
|
|
||||||
},
|
|
||||||
item::Builder,
|
item::Builder,
|
||||||
CompletionItem, CompletionItemKind, CompletionRelevance, Completions,
|
CompletionItem, CompletionItemKind, CompletionRelevance, Completions,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) fn complete_use_tree(
|
pub(crate) fn complete_use_path(
|
||||||
acc: &mut Completions,
|
acc: &mut Completions,
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
name_ref_ctx: &NameRefContext,
|
PathCompletionCtx { qualified, use_tree_parent, .. }: &PathCompletionCtx,
|
||||||
|
name_ref: &Option<ast::NameRef>,
|
||||||
) {
|
) {
|
||||||
let (qualified, name_ref, use_tree_parent) = match name_ref_ctx {
|
|
||||||
NameRefContext {
|
|
||||||
kind:
|
|
||||||
NameRefKind::Path(PathCompletionCtx {
|
|
||||||
kind: PathKind::Use,
|
|
||||||
qualified,
|
|
||||||
use_tree_parent,
|
|
||||||
..
|
|
||||||
}),
|
|
||||||
nameref,
|
|
||||||
..
|
|
||||||
} => (qualified, nameref, use_tree_parent),
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
match qualified {
|
match qualified {
|
||||||
Qualified::With { path, resolution: Some(resolution), is_super_chain } => {
|
Qualified::With { path, resolution: Some(resolution), is_super_chain } => {
|
||||||
if *is_super_chain {
|
if *is_super_chain {
|
||||||
|
@ -112,8 +96,8 @@ pub(crate) fn complete_use_tree(
|
||||||
cov_mark::hit!(unqualified_path_selected_only);
|
cov_mark::hit!(unqualified_path_selected_only);
|
||||||
ctx.process_all_names(&mut |name, res| {
|
ctx.process_all_names(&mut |name, res| {
|
||||||
match res {
|
match res {
|
||||||
ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) => {
|
ScopeDef::ModuleDef(hir::ModuleDef::Module(module)) => {
|
||||||
acc.add_resolution(ctx, name, res);
|
acc.add_module(ctx, module, name);
|
||||||
}
|
}
|
||||||
ScopeDef::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(e))) => {
|
ScopeDef::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(e))) => {
|
||||||
// exclude prelude enum
|
// exclude prelude enum
|
||||||
|
|
|
@ -1,24 +1,16 @@
|
||||||
//! Completion for visibility specifiers.
|
//! Completion for visibility specifiers.
|
||||||
|
|
||||||
use hir::ScopeDef;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::{CompletionContext, PathCompletionCtx, PathKind, Qualified},
|
context::{CompletionContext, PathCompletionCtx, Qualified},
|
||||||
Completions,
|
Completions,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) fn complete_vis_path(
|
pub(crate) fn complete_vis_path(
|
||||||
acc: &mut Completions,
|
acc: &mut Completions,
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
path_ctx: &PathCompletionCtx,
|
PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
|
||||||
|
&has_in_token: &bool,
|
||||||
) {
|
) {
|
||||||
let (qualified, &has_in_token) = match path_ctx {
|
|
||||||
PathCompletionCtx { kind: PathKind::Vis { has_in_token }, qualified, .. } => {
|
|
||||||
(qualified, has_in_token)
|
|
||||||
}
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
match qualified {
|
match qualified {
|
||||||
Qualified::With {
|
Qualified::With {
|
||||||
resolution: Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))),
|
resolution: Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))),
|
||||||
|
@ -31,7 +23,7 @@ pub(crate) fn complete_vis_path(
|
||||||
if let Some(next) = next_towards_current {
|
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);
|
cov_mark::hit!(visibility_qualified);
|
||||||
acc.add_resolution(ctx, name, ScopeDef::ModuleDef(next.into()));
|
acc.add_module(ctx, next, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,27 +88,16 @@ impl PathCompletionCtx {
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub(super) enum PathKind {
|
pub(super) enum PathKind {
|
||||||
Expr {
|
Expr {
|
||||||
in_block_expr: bool,
|
expr_ctx: ExprCtx,
|
||||||
in_loop_body: bool,
|
|
||||||
after_if_expr: bool,
|
|
||||||
/// Whether this expression is the direct condition of an if or while expression
|
|
||||||
in_condition: bool,
|
|
||||||
incomplete_let: bool,
|
|
||||||
ref_expr_parent: Option<ast::RefExpr>,
|
|
||||||
is_func_update: Option<ast::RecordExpr>,
|
|
||||||
self_param: Option<hir::SelfParam>,
|
|
||||||
innermost_ret_ty: Option<hir::Type>,
|
|
||||||
impl_: Option<ast::Impl>,
|
|
||||||
},
|
},
|
||||||
Type {
|
Type {
|
||||||
location: TypeLocation,
|
location: TypeLocation,
|
||||||
},
|
},
|
||||||
Attr {
|
Attr {
|
||||||
kind: AttrKind,
|
attr_ctx: AttrCtx,
|
||||||
annotated_item_kind: Option<SyntaxKind>,
|
|
||||||
},
|
},
|
||||||
Derive {
|
Derive {
|
||||||
existing_derives: FxHashSet<hir::Macro>,
|
existing_derives: ExistingDerives,
|
||||||
},
|
},
|
||||||
/// Path in item position, that is inside an (Assoc)ItemList
|
/// Path in item position, that is inside an (Assoc)ItemList
|
||||||
Item {
|
Item {
|
||||||
|
@ -123,6 +112,29 @@ pub(super) enum PathKind {
|
||||||
Use,
|
Use,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) type ExistingDerives = FxHashSet<hir::Macro>;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub(crate) struct AttrCtx {
|
||||||
|
pub(crate) kind: AttrKind,
|
||||||
|
pub(crate) annotated_item_kind: Option<SyntaxKind>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub(crate) struct ExprCtx {
|
||||||
|
pub(crate) in_block_expr: bool,
|
||||||
|
pub(crate) in_loop_body: bool,
|
||||||
|
pub(crate) after_if_expr: bool,
|
||||||
|
/// Whether this expression is the direct condition of an if or while expression
|
||||||
|
pub(crate) in_condition: bool,
|
||||||
|
pub(crate) incomplete_let: bool,
|
||||||
|
pub(crate) ref_expr_parent: Option<ast::RefExpr>,
|
||||||
|
pub(crate) is_func_update: Option<ast::RecordExpr>,
|
||||||
|
pub(crate) self_param: Option<hir::SelfParam>,
|
||||||
|
pub(crate) innermost_ret_ty: Option<hir::Type>,
|
||||||
|
pub(crate) impl_: Option<ast::Impl>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Original file ast nodes
|
/// Original file ast nodes
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub(crate) enum TypeLocation {
|
pub(crate) enum TypeLocation {
|
||||||
|
|
|
@ -11,10 +11,10 @@ use syntax::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::context::{
|
use crate::context::{
|
||||||
CompletionContext, DotAccess, DotAccessKind, IdentContext, ItemListKind, LifetimeContext,
|
AttrCtx, CompletionContext, DotAccess, DotAccessKind, ExprCtx, IdentContext, ItemListKind,
|
||||||
LifetimeKind, NameContext, NameKind, NameRefContext, NameRefKind, ParamKind, PathCompletionCtx,
|
LifetimeContext, LifetimeKind, NameContext, NameKind, NameRefContext, NameRefKind, ParamKind,
|
||||||
PathKind, PatternContext, PatternRefutability, Qualified, QualifierCtx, TypeAscriptionTarget,
|
PathCompletionCtx, PathKind, PatternContext, PatternRefutability, Qualified, QualifierCtx,
|
||||||
TypeLocation, COMPLETION_MARKER,
|
TypeAscriptionTarget, TypeLocation, COMPLETION_MARKER,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<'a> CompletionContext<'a> {
|
impl<'a> CompletionContext<'a> {
|
||||||
|
@ -765,6 +765,7 @@ impl<'a> CompletionContext<'a> {
|
||||||
let impl_ = fetch_immediate_impl(sema, original_file, expr.syntax());
|
let impl_ = fetch_immediate_impl(sema, original_file, expr.syntax());
|
||||||
|
|
||||||
PathKind::Expr {
|
PathKind::Expr {
|
||||||
|
expr_ctx: ExprCtx {
|
||||||
in_block_expr,
|
in_block_expr,
|
||||||
in_loop_body,
|
in_loop_body,
|
||||||
after_if_expr,
|
after_if_expr,
|
||||||
|
@ -775,6 +776,7 @@ impl<'a> CompletionContext<'a> {
|
||||||
self_param,
|
self_param,
|
||||||
incomplete_let,
|
incomplete_let,
|
||||||
impl_,
|
impl_,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let make_path_kind_type = |ty: ast::Type| {
|
let make_path_kind_type = |ty: ast::Type| {
|
||||||
|
@ -858,9 +860,11 @@ impl<'a> CompletionContext<'a> {
|
||||||
Some(attached.kind())
|
Some(attached.kind())
|
||||||
};
|
};
|
||||||
PathKind::Attr {
|
PathKind::Attr {
|
||||||
|
attr_ctx: AttrCtx {
|
||||||
kind,
|
kind,
|
||||||
annotated_item_kind,
|
annotated_item_kind,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
ast::Visibility(it) => PathKind::Vis { has_in_token: it.in_token().is_some() },
|
ast::Visibility(it) => PathKind::Vis { has_in_token: it.in_token().is_some() },
|
||||||
ast::UseTree(_) => PathKind::Use,
|
ast::UseTree(_) => PathKind::Use,
|
||||||
|
@ -914,7 +918,7 @@ impl<'a> CompletionContext<'a> {
|
||||||
if path_ctx.is_trivial_path() {
|
if path_ctx.is_trivial_path() {
|
||||||
// fetch the full expression that may have qualifiers attached to it
|
// fetch the full expression that may have qualifiers attached to it
|
||||||
let top_node = match path_ctx.kind {
|
let top_node = match path_ctx.kind {
|
||||||
PathKind::Expr { in_block_expr: true, .. } => {
|
PathKind::Expr { expr_ctx: ExprCtx { in_block_expr: true, .. } } => {
|
||||||
parent.ancestors().find(|it| ast::PathExpr::can_cast(it.kind())).and_then(|p| {
|
parent.ancestors().find(|it| ast::PathExpr::can_cast(it.kind())).and_then(|p| {
|
||||||
let parent = p.parent()?;
|
let parent = p.parent()?;
|
||||||
if ast::StmtList::can_cast(parent.kind()) {
|
if ast::StmtList::can_cast(parent.kind()) {
|
||||||
|
|
|
@ -24,7 +24,9 @@ use text_edit::TextEdit;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
completions::Completions,
|
completions::Completions,
|
||||||
context::{CompletionContext, IdentContext, NameKind, NameRefContext, NameRefKind},
|
context::{
|
||||||
|
CompletionContext, IdentContext, NameRefContext, NameRefKind, PathCompletionCtx, PathKind,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
|
@ -151,10 +153,13 @@ pub fn completions(
|
||||||
|
|
||||||
// prevent `(` from triggering unwanted completion noise
|
// prevent `(` from triggering unwanted completion noise
|
||||||
if trigger_character == Some('(') {
|
if trigger_character == Some('(') {
|
||||||
if let IdentContext::NameRef(NameRefContext { kind: NameRefKind::Path(path_ctx), .. }) =
|
if let IdentContext::NameRef(NameRefContext { kind, .. }) = &ctx.ident_ctx {
|
||||||
&ctx.ident_ctx
|
if let NameRefKind::Path(
|
||||||
|
path_ctx @ PathCompletionCtx { kind: PathKind::Vis { has_in_token }, .. },
|
||||||
|
) = kind
|
||||||
{
|
{
|
||||||
completions::vis::complete_vis_path(&mut completions, ctx, path_ctx);
|
completions::vis::complete_vis_path(&mut completions, ctx, path_ctx, has_in_token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// prevent `(` from triggering unwanted completion noise
|
// prevent `(` from triggering unwanted completion noise
|
||||||
return Some(completions);
|
return Some(completions);
|
||||||
|
@ -164,62 +169,9 @@ pub fn completions(
|
||||||
let acc = &mut completions;
|
let acc = &mut completions;
|
||||||
|
|
||||||
match &ctx.ident_ctx {
|
match &ctx.ident_ctx {
|
||||||
IdentContext::Name(name_ctx) => {
|
IdentContext::Name(name_ctx) => completions::complete_name(acc, ctx, name_ctx),
|
||||||
completions::field::complete_field_list_record_variant(acc, ctx, name_ctx);
|
IdentContext::NameRef(name_ref_ctx) => {
|
||||||
completions::item_list::trait_impl::complete_trait_impl_name(acc, ctx, name_ctx);
|
completions::complete_name_ref(acc, ctx, name_ref_ctx)
|
||||||
completions::mod_::complete_mod(acc, ctx, name_ctx);
|
|
||||||
if let NameKind::IdentPat(pattern_ctx) = &name_ctx.kind {
|
|
||||||
completions::flyimport::import_on_the_fly_pat(acc, ctx, pattern_ctx);
|
|
||||||
completions::fn_param::complete_fn_param(acc, ctx, pattern_ctx);
|
|
||||||
completions::pattern::complete_pattern(acc, ctx, pattern_ctx);
|
|
||||||
completions::record::complete_record_pattern_fields(acc, ctx, pattern_ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IdentContext::NameRef(name_ctx @ NameRefContext { kind, .. }) => {
|
|
||||||
completions::item_list::trait_impl::complete_trait_impl_name_ref(
|
|
||||||
acc, ctx, name_ctx,
|
|
||||||
);
|
|
||||||
completions::use_::complete_use_tree(acc, ctx, name_ctx);
|
|
||||||
|
|
||||||
match kind {
|
|
||||||
NameRefKind::Path(path_ctx) => {
|
|
||||||
completions::attribute::complete_attribute(acc, ctx, path_ctx);
|
|
||||||
completions::attribute::complete_derive(acc, ctx, path_ctx);
|
|
||||||
completions::dot::complete_undotted_self(acc, ctx, path_ctx);
|
|
||||||
completions::expr::complete_expr_path(acc, ctx, path_ctx);
|
|
||||||
completions::field::complete_field_list_tuple_variant(acc, ctx, path_ctx);
|
|
||||||
completions::flyimport::import_on_the_fly_path(acc, ctx, path_ctx);
|
|
||||||
completions::item_list::complete_item_list(acc, ctx, path_ctx);
|
|
||||||
completions::pattern::pattern_path_completion(acc, ctx, path_ctx);
|
|
||||||
completions::r#type::complete_inferred_type(acc, ctx, path_ctx);
|
|
||||||
completions::r#type::complete_type_path(acc, ctx, path_ctx);
|
|
||||||
completions::record::complete_record_expr_func_update(acc, ctx, path_ctx);
|
|
||||||
completions::snippet::complete_expr_snippet(acc, ctx, path_ctx);
|
|
||||||
completions::snippet::complete_item_snippet(acc, ctx, path_ctx);
|
|
||||||
completions::vis::complete_vis_path(acc, ctx, path_ctx);
|
|
||||||
}
|
|
||||||
NameRefKind::DotAccess(dot_access) => {
|
|
||||||
completions::flyimport::import_on_the_fly_dot(acc, ctx, dot_access);
|
|
||||||
completions::dot::complete_dot(acc, ctx, dot_access);
|
|
||||||
completions::postfix::complete_postfix(acc, ctx, dot_access);
|
|
||||||
}
|
|
||||||
NameRefKind::Keyword(item) => {
|
|
||||||
completions::keyword::complete_special_keywords(acc, ctx, item);
|
|
||||||
}
|
|
||||||
NameRefKind::RecordExpr(record_expr) => {
|
|
||||||
completions::record::complete_record_expr_fields_record_expr(
|
|
||||||
acc,
|
|
||||||
ctx,
|
|
||||||
record_expr,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
NameRefKind::Pattern(pattern_ctx) => {
|
|
||||||
completions::flyimport::import_on_the_fly_pat(acc, ctx, pattern_ctx);
|
|
||||||
completions::fn_param::complete_fn_param(acc, ctx, pattern_ctx);
|
|
||||||
completions::pattern::complete_pattern(acc, ctx, pattern_ctx);
|
|
||||||
completions::record::complete_record_pattern_fields(acc, ctx, pattern_ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
IdentContext::Lifetime(lifetime_ctx) => {
|
IdentContext::Lifetime(lifetime_ctx) => {
|
||||||
completions::lifetime::complete_label(acc, ctx, lifetime_ctx);
|
completions::lifetime::complete_label(acc, ctx, lifetime_ctx);
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
//!
|
//!
|
||||||
//! Actual logic is implemented in [`crate::completions::postfix`] and [`crate::completions::snippet`] respectively.
|
//! Actual logic is implemented in [`crate::completions::postfix`] and [`crate::completions::snippet`] respectively.
|
||||||
|
|
||||||
use std::ops::Deref;
|
|
||||||
|
|
||||||
// Feature: User Snippet Completions
|
// Feature: User Snippet Completions
|
||||||
//
|
//
|
||||||
// rust-analyzer allows the user to define custom (postfix)-snippets that may depend on items to be accessible for the current scope to be applicable.
|
// rust-analyzer allows the user to define custom (postfix)-snippets that may depend on items to be accessible for the current scope to be applicable.
|
||||||
|
@ -146,8 +144,8 @@ impl Snippet {
|
||||||
let (requires, snippet, description) = validate_snippet(snippet, description, requires)?;
|
let (requires, snippet, description) = validate_snippet(snippet, description, requires)?;
|
||||||
Some(Snippet {
|
Some(Snippet {
|
||||||
// Box::into doesn't work as that has a Copy bound 😒
|
// Box::into doesn't work as that has a Copy bound 😒
|
||||||
postfix_triggers: postfix_triggers.iter().map(Deref::deref).map(Into::into).collect(),
|
postfix_triggers: postfix_triggers.iter().map(String::as_str).map(Into::into).collect(),
|
||||||
prefix_triggers: prefix_triggers.iter().map(Deref::deref).map(Into::into).collect(),
|
prefix_triggers: prefix_triggers.iter().map(String::as_str).map(Into::into).collect(),
|
||||||
scope,
|
scope,
|
||||||
snippet,
|
snippet,
|
||||||
description,
|
description,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue