9390: fix: Improve type bound completions r=Veykril a=Veykril

Closes #9389
bors r+

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
bors[bot] 2021-06-23 17:14:37 +00:00 committed by GitHub
commit 1deb1d3209
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 211 additions and 70 deletions

View File

@ -33,7 +33,7 @@ fn complete_undotted_self(acc: &mut Completions, ctx: &CompletionContext) {
if !ctx.config.enable_self_on_the_fly {
return;
}
if !ctx.is_trivial_path() || ctx.is_path_disallowed() {
if !ctx.is_trivial_path() || ctx.is_path_disallowed() || !ctx.expects_expression() {
return;
}
ctx.scope.process_all_names(&mut |name, def| {

View File

@ -36,6 +36,20 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
return;
}
if matches!(&ctx.completion_location, Some(ImmediateLocation::TypeBound)) {
ctx.scope.process_all_names(&mut |name, res| {
let add_resolution = match res {
ScopeDef::MacroDef(mac) => mac.is_fn_like(),
ScopeDef::ModuleDef(hir::ModuleDef::Trait(_) | hir::ModuleDef::Module(_)) => true,
_ => false,
};
if add_resolution {
acc.add_resolution(ctx, name, &res);
}
});
return;
}
if !ctx.expects_type() {
if let Some(hir::Adt::Enum(e)) =
ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt())

View File

@ -36,6 +36,7 @@ pub(crate) enum ImmediateLocation {
IdentPat,
BlockExpr,
ItemList,
TypeBound,
// Fake file ast node
Attribute(ast::Attr),
// Fake file ast node
@ -154,6 +155,13 @@ pub(crate) fn determine_location(
ast::NameLike::Lifetime(lt) => lt.syntax().clone(),
};
match_ast! {
match node {
ast::TypeBoundList(_it) => return Some(ImmediateLocation::TypeBound),
_ => (),
}
};
let parent = match node.parent() {
Some(parent) => match ast::MacroCall::cast(parent.clone()) {
// When a path is being typed in an (Assoc)ItemList the parser will always emit a macro_call.
@ -195,6 +203,8 @@ pub(crate) fn determine_location(
},
ast::TupleField(_it) => ImmediateLocation::TupleField,
ast::TupleFieldList(_it) => ImmediateLocation::TupleField,
ast::TypeBound(_it) => ImmediateLocation::TypeBound,
ast::TypeBoundList(_it) => ImmediateLocation::TypeBound,
ast::AssocItemList(it) => match it.syntax().parent().map(|it| it.kind()) {
Some(IMPL) => ImmediateLocation::Impl,
Some(TRAIT) => ImmediateLocation::Trait,

View File

@ -9,6 +9,7 @@ mod use_tree;
mod items;
mod pattern;
mod type_pos;
mod predicate;
use std::mem;
@ -28,6 +29,24 @@ use test_utils::assert_eq_text;
use crate::{item::CompletionKind, CompletionConfig, CompletionItem};
/// Lots of basic item definitions
const BASE_FIXTURE: &str = r#"
enum Enum { TupleV(u32), RecordV { field: u32 }, UnitV }
use self::Enum::TupleV;
mod module {}
trait Trait {}
static STATIC: Unit = Unit;
const CONST: Unit = Unit;
struct Record { field: u32 }
struct Tuple(u32);
struct Unit;
#[macro_export]
macro_rules! makro {}
#[rustc_builtin_macro]
pub macro Clone {}
"#;
pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
enable_postfix_completions: true,
enable_imports_on_the_fly: true,

View File

@ -1,19 +1,9 @@
use expect_test::{expect, Expect};
use crate::tests::completion_list;
use crate::tests::{completion_list, BASE_FIXTURE};
fn check(ra_fixture: &str, expect: Expect) {
let base = r#"#[rustc_builtin_macro]
pub macro Clone {}
enum Enum { Variant }
struct Struct {}
#[macro_export]
macro_rules! foo {}
mod bar {}
const CONST: () = ();
trait Trait {}
"#;
let actual = completion_list(&format!("{}{}", base, ra_fixture));
let actual = completion_list(&format!("{}{}", BASE_FIXTURE, ra_fixture));
expect.assert_eq(&actual)
}
@ -40,7 +30,7 @@ fn in_mod_item_list() {
sn tmod (Test module)
sn tfn (Test function)
sn macro_rules
ma foo!() #[macro_export] macro_rules! foo
ma makro!() #[macro_export] macro_rules! makro
"##]],
)
}
@ -68,9 +58,9 @@ fn in_source_file_item_list() {
sn tmod (Test module)
sn tfn (Test function)
sn macro_rules
md bar
ma foo!() #[macro_export] macro_rules! foo
ma foo!() #[macro_export] macro_rules! foo
ma makro!() #[macro_export] macro_rules! makro
md module
ma makro!() #[macro_export] macro_rules! makro
"##]],
)
}
@ -122,8 +112,8 @@ fn in_qualified_path() {
kw enum
kw struct
kw union
md bar
ma foo!() #[macro_export] macro_rules! foo
ma makro!() #[macro_export] macro_rules! makro
md module
"##]],
)
}
@ -184,9 +174,9 @@ fn in_impl_assoc_item_list() {
kw fn
kw const
kw type
md bar
ma foo!() #[macro_export] macro_rules! foo
ma foo!() #[macro_export] macro_rules! foo
ma makro!() #[macro_export] macro_rules! makro
md module
ma makro!() #[macro_export] macro_rules! makro
"##]],
)
}
@ -215,9 +205,9 @@ fn in_trait_assoc_item_list() {
kw fn
kw const
kw type
md bar
ma foo!() #[macro_export] macro_rules! foo
ma foo!() #[macro_export] macro_rules! foo
md module
ma makro!() #[macro_export] macro_rules! makro
ma makro!() #[macro_export] macro_rules! makro
"##]],
);
}

View File

@ -4,20 +4,10 @@
//! in [crate::completions::mod_].
use expect_test::{expect, Expect};
use crate::tests::completion_list;
use crate::tests::{completion_list, BASE_FIXTURE};
fn check(ra_fixture: &str, expect: Expect) {
let base = r#"#[rustc_builtin_macro]
pub macro Clone {}
enum Enum { Variant }
struct Struct {}
#[macro_export]
macro_rules! foo {}
mod bar {}
const CONST: () = ();
trait Trait {}
"#;
let actual = completion_list(&format!("{}{}", base, ra_fixture));
let actual = completion_list(&format!("{}{}", BASE_FIXTURE, ra_fixture));
expect.assert_eq(&actual)
}
@ -30,10 +20,12 @@ impl Tra$0
expect![[r##"
tt Trait
en Enum
st Struct
md bar
ma foo!() #[macro_export] macro_rules! foo
ma foo!() #[macro_export] macro_rules! foo
st Record
st Tuple
ma makro!() #[macro_export] macro_rules! makro
md module
st Unit
ma makro!() #[macro_export] macro_rules! makro
bt u32
"##]],
)
@ -48,10 +40,12 @@ impl Trait for Str$0
expect![[r##"
tt Trait
en Enum
st Struct
md bar
ma foo!() #[macro_export] macro_rules! foo
ma foo!() #[macro_export] macro_rules! foo
st Record
st Tuple
ma makro!() #[macro_export] macro_rules! makro
md module
st Unit
ma makro!() #[macro_export] macro_rules! makro
bt u32
"##]],
)

View File

@ -1,7 +1,7 @@
//! Completions tests for pattern position.
use expect_test::{expect, Expect};
use crate::tests::completion_list;
use crate::tests::{completion_list, BASE_FIXTURE};
fn check(ra_fixture: &str, expect: Expect) {
let actual = completion_list(ra_fixture);
@ -9,19 +9,7 @@ fn check(ra_fixture: &str, expect: Expect) {
}
fn check_with(ra_fixture: &str, expect: Expect) {
let base = r#"
enum Enum { TupleV(u32), RecordV { field: u32 }, UnitV }
use self::Enum::TupleV;
mod module {}
static STATIC: Unit = Unit;
const CONST: Unit = Unit;
struct Record { field: u32 }
struct Tuple(u32);
struct Unit
macro_rules! makro {}
"#;
let actual = completion_list(&format!("{}\n{}", base, ra_fixture));
let actual = completion_list(&format!("{}\n{}", BASE_FIXTURE, ra_fixture));
expect.assert_eq(&actual)
}
@ -121,20 +109,21 @@ fn foo() {
if let a$0
}
"#,
expect![[r#"
expect![[r##"
kw mut
en Enum
bn Record Record { field$1 }$0
st Record
en Enum
bn Tuple Tuple($1)$0
st Tuple
md module
st Unit
ma makro!() #[macro_export] macro_rules! makro
bn TupleV TupleV($1)$0
ev TupleV
st Unit
ct CONST
ma makro!() macro_rules! makro
"#]],
ma makro!() #[macro_export] macro_rules! makro
"##]],
);
}
@ -146,15 +135,16 @@ fn foo() {
let a$0
}
"#,
expect![[r#"
expect![[r##"
kw mut
bn Record Record { field$1 }$0
st Record
bn Tuple Tuple($1)$0
st Tuple
st Unit
ma makro!() macro_rules! makro
"#]],
ma makro!() #[macro_export] macro_rules! makro
ma makro!() #[macro_export] macro_rules! makro
"##]],
);
}
@ -165,15 +155,16 @@ fn in_param() {
fn foo(a$0) {
}
"#,
expect![[r#"
expect![[r##"
kw mut
bn Record Record { field$1 }: Record$0
st Record
bn Tuple Tuple($1): Tuple$0
st Tuple
st Unit
ma makro!() macro_rules! makro
"#]],
ma makro!() #[macro_export] macro_rules! makro
ma makro!() #[macro_export] macro_rules! makro
"##]],
);
}

View File

@ -0,0 +1,122 @@
//! Completion tests for predicates and bounds.
use expect_test::{expect, Expect};
use crate::tests::{completion_list, BASE_FIXTURE};
fn check(ra_fixture: &str, expect: Expect) {
let actual = completion_list(&format!("{}\n{}", BASE_FIXTURE, ra_fixture));
expect.assert_eq(&actual)
}
#[test]
fn predicate_start() {
// FIXME: `for` kw
check(
r#"
struct Foo<'lt, T, const C: usize> where $0 {}
"#,
expect![[r##"
tt Trait
en Enum
st Record
st Tuple
md module
st Foo<>
st Unit
ma makro!() #[macro_export] macro_rules! makro
ma makro!() #[macro_export] macro_rules! makro
bt u32
"##]],
);
}
#[test]
fn bound_for_type_pred() {
// FIXME: only show traits, macros and modules
check(
r#"
struct Foo<'lt, T, const C: usize> where T: $0 {}
"#,
expect![[r##"
tt Trait
md module
ma makro!() #[macro_export] macro_rules! makro
ma makro!() #[macro_export] macro_rules! makro
"##]],
);
}
#[test]
fn bound_for_lifetime_pred() {
// FIXME: should only show lifetimes here
check(
r#"
struct Foo<'lt, T, const C: usize> where 'lt: $0 {}
"#,
expect![[r##"
tt Trait
md module
ma makro!() #[macro_export] macro_rules! makro
ma makro!() #[macro_export] macro_rules! makro
"##]],
);
}
#[test]
fn bound_for_for_pred() {
check(
r#"
struct Foo<'lt, T, const C: usize> where for<'a> T: $0 {}
"#,
expect![[r##"
tt Trait
md module
ma makro!() #[macro_export] macro_rules! makro
ma makro!() #[macro_export] macro_rules! makro
"##]],
);
}
#[test]
fn param_list_for_for_pred() {
check(
r#"
struct Foo<'lt, T, const C: usize> where for<'a> $0 {}
"#,
expect![[r##"
tt Trait
en Enum
st Record
st Tuple
md module
st Foo<>
st Unit
ma makro!() #[macro_export] macro_rules! makro
ma makro!() #[macro_export] macro_rules! makro
bt u32
"##]],
);
}
#[test]
fn pred_on_fn_in_impl() {
check(
r#"
impl Record {
fn method(self) where $0 {}
}
"#,
expect![[r##"
sp Self
tt Trait
en Enum
st Record
st Tuple
ma makro!() #[macro_export] macro_rules! makro
md module
st Unit
ma makro!() #[macro_export] macro_rules! makro
bt u32
"##]],
);
}

View File

@ -1,3 +1,4 @@
//! Completions tests for use trees.
use expect_test::{expect, Expect};
use crate::tests::completion_list;