Remove the second code-path for completing names in patterns

This commit is contained in:
Aleksey Kladov 2020-04-03 19:59:28 +02:00
parent 6a2dd7bafc
commit adbcedde18
4 changed files with 31 additions and 70 deletions

View file

@ -4,23 +4,25 @@ use crate::completion::{CompletionContext, Completions};
/// Completes constats and paths in patterns. /// Completes constats and paths in patterns.
pub(super) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { pub(super) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
if !ctx.is_pat_binding { if !ctx.is_pat_binding_or_const {
return; return;
} }
// FIXME: ideally, we should look at the type we are matching against and // FIXME: ideally, we should look at the type we are matching against and
// suggest variants + auto-imports // suggest variants + auto-imports
ctx.scope().process_all_names(&mut |name, res| { ctx.scope().process_all_names(&mut |name, res| {
let def = match &res { match &res {
hir::ScopeDef::ModuleDef(def) => def, hir::ScopeDef::ModuleDef(def) => match def {
_ => return,
};
match def {
hir::ModuleDef::Adt(hir::Adt::Enum(..)) hir::ModuleDef::Adt(hir::Adt::Enum(..))
| hir::ModuleDef::Adt(hir::Adt::Struct(..))
| hir::ModuleDef::EnumVariant(..) | hir::ModuleDef::EnumVariant(..)
| hir::ModuleDef::Const(..) | hir::ModuleDef::Const(..)
| hir::ModuleDef::Module(..) => (), | hir::ModuleDef::Module(..) => (),
_ => return, _ => return,
} },
hir::ScopeDef::MacroDef(_) => (),
_ => return,
};
acc.add_resolution(ctx, name.to_string(), &res) acc.add_resolution(ctx, name.to_string(), &res)
}); });
} }
@ -69,20 +71,6 @@ mod tests {
insert: "E", insert: "E",
kind: Enum, kind: Enum,
}, },
CompletionItem {
label: "E",
source_range: [246; 246),
delete: [246; 246),
insert: "E",
kind: Enum,
},
CompletionItem {
label: "X",
source_range: [246; 246),
delete: [246; 246),
insert: "X",
kind: EnumVariant,
},
CompletionItem { CompletionItem {
label: "X", label: "X",
source_range: [246; 246), source_range: [246; 246),
@ -97,20 +85,6 @@ mod tests {
insert: "Z", insert: "Z",
kind: Const, kind: Const,
}, },
CompletionItem {
label: "Z",
source_range: [246; 246),
delete: [246; 246),
insert: "Z",
kind: Const,
},
CompletionItem {
label: "m",
source_range: [246; 246),
delete: [246; 246),
insert: "m",
kind: Module,
},
CompletionItem { CompletionItem {
label: "m", label: "m",
source_range: [246; 246), source_range: [246; 246),
@ -138,13 +112,6 @@ mod tests {
); );
assert_debug_snapshot!(completions, @r###" assert_debug_snapshot!(completions, @r###"
[ [
CompletionItem {
label: "E",
source_range: [151; 151),
delete: [151; 151),
insert: "E",
kind: Enum,
},
CompletionItem { CompletionItem {
label: "E", label: "E",
source_range: [151; 151), source_range: [151; 151),

View file

@ -1,19 +1,13 @@
//! Completion of names from the current scope, e.g. locals and imported items. //! Completion of names from the current scope, e.g. locals and imported items.
use crate::completion::{CompletionContext, Completions}; use crate::completion::{CompletionContext, Completions};
use hir::{ModuleDef, ScopeDef};
pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
if !ctx.is_trivial_path && !ctx.is_pat_binding_and_path { if !(ctx.is_trivial_path && !ctx.is_pat_binding_or_const) {
return; return;
} }
ctx.scope().process_all_names(&mut |name, res| match (ctx.is_pat_binding_and_path, &res) { ctx.scope().process_all_names(&mut |name, res| acc.add_resolution(ctx, name.to_string(), &res));
(true, ScopeDef::ModuleDef(ModuleDef::Function(..))) => (),
(true, ScopeDef::ModuleDef(ModuleDef::Static(..))) => (),
(true, ScopeDef::Local(..)) => (),
_ => acc.add_resolution(ctx, name.to_string(), &res),
});
} }
#[cfg(test)] #[cfg(test)]

View file

@ -35,10 +35,7 @@ pub(crate) struct CompletionContext<'a> {
pub(super) is_param: bool, pub(super) is_param: bool,
/// If a name-binding or reference to a const in a pattern. /// If a name-binding or reference to a const in a pattern.
/// Irrefutable patterns (like let) are excluded. /// Irrefutable patterns (like let) are excluded.
pub(super) is_pat_binding: bool, pub(super) is_pat_binding_or_const: bool,
// A bind battern which may also be part of a path.
// if let Some(En<|>) = Some(Enum::A)
pub(super) is_pat_binding_and_path: bool,
/// A single-indent path, like `foo`. `::foo` should not be considered a trivial path. /// A single-indent path, like `foo`. `::foo` should not be considered a trivial path.
pub(super) is_trivial_path: bool, pub(super) is_trivial_path: bool,
/// If not a trivial path, the prefix (qualifier). /// If not a trivial path, the prefix (qualifier).
@ -97,8 +94,7 @@ impl<'a> CompletionContext<'a> {
record_lit_pat: None, record_lit_pat: None,
impl_def: None, impl_def: None,
is_param: false, is_param: false,
is_pat_binding: false, is_pat_binding_or_const: false,
is_pat_binding_and_path: false,
is_trivial_path: false, is_trivial_path: false,
path_prefix: None, path_prefix: None,
after_if: false, after_if: false,
@ -190,18 +186,19 @@ impl<'a> CompletionContext<'a> {
// suggest declaration names, see `CompletionKind::Magic`. // suggest declaration names, see `CompletionKind::Magic`.
if let Some(name) = find_node_at_offset::<ast::Name>(&file_with_fake_ident, offset) { if let Some(name) = find_node_at_offset::<ast::Name>(&file_with_fake_ident, offset) {
if let Some(bind_pat) = name.syntax().ancestors().find_map(ast::BindPat::cast) { if let Some(bind_pat) = name.syntax().ancestors().find_map(ast::BindPat::cast) {
let parent = bind_pat.syntax().parent(); self.is_pat_binding_or_const = true;
if parent.clone().and_then(ast::MatchArm::cast).is_some() if bind_pat.has_at() || bind_pat.is_ref() || bind_pat.is_mutable() {
|| parent.clone().and_then(ast::Condition::cast).is_some() self.is_pat_binding_or_const = false;
{ }
self.is_pat_binding = true; if bind_pat.syntax().parent().and_then(ast::RecordFieldPatList::cast).is_some() {
self.is_pat_binding_or_const = false;
}
if let Some(let_stmt) = bind_pat.syntax().ancestors().find_map(ast::LetStmt::cast) {
if let Some(pat) = let_stmt.pat() {
if bind_pat.syntax().text_range().is_subrange(&pat.syntax().text_range()) {
self.is_pat_binding_or_const = false;
}
} }
if parent.and_then(ast::RecordFieldPatList::cast).is_none()
&& bind_pat.pat().is_none()
&& !bind_pat.is_ref()
{
self.is_pat_binding_and_path = true;
} }
} }
if is_node::<ast::Param>(name.syntax()) { if is_node::<ast::Param>(name.syntax()) {

View file

@ -325,6 +325,9 @@ impl ast::BindPat {
pub fn is_ref(&self) -> bool { pub fn is_ref(&self) -> bool {
self.syntax().children_with_tokens().any(|n| n.kind() == T![ref]) self.syntax().children_with_tokens().any(|n| n.kind() == T![ref])
} }
pub fn has_at(&self) -> bool {
self.syntax().children_with_tokens().any(|it| it.kind() == T![@])
}
} }
pub struct SlicePatComponents { pub struct SlicePatComponents {