mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-03 15:15:24 +00:00
Merge #3541
3541: Completition for type name? #3418 r=matklad a=slyngbaek Iterate through TupleStructPat's until a MatchArm if one exists. Store in a new is_pat_bind_and_path bool and allow the `complete_scope` to find matches. Added some tests to ensure it works in simple and nested cases. Co-authored-by: Steffen Lyngbaek <steffenlyngbaek@gmail.com>
This commit is contained in:
commit
1878fbe8bd
3 changed files with 143 additions and 3 deletions
|
@ -55,6 +55,20 @@ mod tests {
|
||||||
);
|
);
|
||||||
assert_debug_snapshot!(completions, @r###"
|
assert_debug_snapshot!(completions, @r###"
|
||||||
[
|
[
|
||||||
|
CompletionItem {
|
||||||
|
label: "Bar",
|
||||||
|
source_range: [246; 246),
|
||||||
|
delete: [246; 246),
|
||||||
|
insert: "Bar",
|
||||||
|
kind: Struct,
|
||||||
|
},
|
||||||
|
CompletionItem {
|
||||||
|
label: "E",
|
||||||
|
source_range: [246; 246),
|
||||||
|
delete: [246; 246),
|
||||||
|
insert: "E",
|
||||||
|
kind: Enum,
|
||||||
|
},
|
||||||
CompletionItem {
|
CompletionItem {
|
||||||
label: "E",
|
label: "E",
|
||||||
source_range: [246; 246),
|
source_range: [246; 246),
|
||||||
|
@ -69,6 +83,13 @@ mod tests {
|
||||||
insert: "X",
|
insert: "X",
|
||||||
kind: EnumVariant,
|
kind: EnumVariant,
|
||||||
},
|
},
|
||||||
|
CompletionItem {
|
||||||
|
label: "X",
|
||||||
|
source_range: [246; 246),
|
||||||
|
delete: [246; 246),
|
||||||
|
insert: "X",
|
||||||
|
kind: EnumVariant,
|
||||||
|
},
|
||||||
CompletionItem {
|
CompletionItem {
|
||||||
label: "Z",
|
label: "Z",
|
||||||
source_range: [246; 246),
|
source_range: [246; 246),
|
||||||
|
@ -76,6 +97,20 @@ 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),
|
||||||
|
@ -110,6 +145,21 @@ mod tests {
|
||||||
insert: "E",
|
insert: "E",
|
||||||
kind: Enum,
|
kind: Enum,
|
||||||
},
|
},
|
||||||
|
CompletionItem {
|
||||||
|
label: "E",
|
||||||
|
source_range: [151; 151),
|
||||||
|
delete: [151; 151),
|
||||||
|
insert: "E",
|
||||||
|
kind: Enum,
|
||||||
|
},
|
||||||
|
CompletionItem {
|
||||||
|
label: "m!",
|
||||||
|
source_range: [151; 151),
|
||||||
|
delete: [151; 151),
|
||||||
|
insert: "m!($0)",
|
||||||
|
kind: Macro,
|
||||||
|
detail: "macro_rules! m",
|
||||||
|
},
|
||||||
]
|
]
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,19 @@
|
||||||
//! 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 {
|
if !ctx.is_trivial_path && !ctx.is_pat_binding_and_path {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.scope().process_all_names(&mut |name, res| acc.add_resolution(ctx, name.to_string(), &res));
|
ctx.scope().process_all_names(&mut |name, res| match (ctx.is_pat_binding_and_path, &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)]
|
||||||
|
@ -20,6 +26,79 @@ mod tests {
|
||||||
do_completion(ra_fixture, CompletionKind::Reference)
|
do_completion(ra_fixture, CompletionKind::Reference)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bind_pat_and_path_ignore_at() {
|
||||||
|
assert_debug_snapshot!(
|
||||||
|
do_reference_completion(
|
||||||
|
r"
|
||||||
|
enum Enum {
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
}
|
||||||
|
fn quux(x: Option<Enum>) {
|
||||||
|
match x {
|
||||||
|
None => (),
|
||||||
|
Some(en<|> @ Enum::A) => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
),
|
||||||
|
@r###"[]"###
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bind_pat_and_path_ignore_ref() {
|
||||||
|
assert_debug_snapshot!(
|
||||||
|
do_reference_completion(
|
||||||
|
r"
|
||||||
|
enum Enum {
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
}
|
||||||
|
fn quux(x: Option<Enum>) {
|
||||||
|
match x {
|
||||||
|
None => (),
|
||||||
|
Some(ref en<|>) => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
),
|
||||||
|
@r###"[]"###
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bind_pat_and_path() {
|
||||||
|
assert_debug_snapshot!(
|
||||||
|
do_reference_completion(
|
||||||
|
r"
|
||||||
|
enum Enum {
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
}
|
||||||
|
fn quux(x: Option<Enum>) {
|
||||||
|
match x {
|
||||||
|
None => (),
|
||||||
|
Some(En<|>) => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
),
|
||||||
|
@r###"
|
||||||
|
[
|
||||||
|
CompletionItem {
|
||||||
|
label: "Enum",
|
||||||
|
source_range: [231; 233),
|
||||||
|
delete: [231; 233),
|
||||||
|
insert: "Enum",
|
||||||
|
kind: Enum,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn completes_bindings_from_let() {
|
fn completes_bindings_from_let() {
|
||||||
assert_debug_snapshot!(
|
assert_debug_snapshot!(
|
||||||
|
|
|
@ -36,6 +36,9 @@ pub(crate) struct CompletionContext<'a> {
|
||||||
/// 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: 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).
|
||||||
|
@ -95,6 +98,7 @@ impl<'a> CompletionContext<'a> {
|
||||||
impl_def: None,
|
impl_def: None,
|
||||||
is_param: false,
|
is_param: false,
|
||||||
is_pat_binding: false,
|
is_pat_binding: 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,
|
||||||
|
@ -188,10 +192,17 @@ impl<'a> CompletionContext<'a> {
|
||||||
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();
|
let parent = bind_pat.syntax().parent();
|
||||||
if parent.clone().and_then(ast::MatchArm::cast).is_some()
|
if parent.clone().and_then(ast::MatchArm::cast).is_some()
|
||||||
|| parent.and_then(ast::Condition::cast).is_some()
|
|| parent.clone().and_then(ast::Condition::cast).is_some()
|
||||||
{
|
{
|
||||||
self.is_pat_binding = true;
|
self.is_pat_binding = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()) {
|
||||||
self.is_param = true;
|
self.is_param = true;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue