mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
Auto merge of #12164 - Veykril:completion-rev, r=Veykril
internal: Remove `unqualified_path` completions module cc https://github.com/rust-lang/rust-analyzer/issues/12144
This commit is contained in:
commit
7dfd1cb572
14 changed files with 464 additions and 421 deletions
|
@ -2,6 +2,7 @@
|
|||
|
||||
pub(crate) mod attribute;
|
||||
pub(crate) mod dot;
|
||||
pub(crate) mod expr;
|
||||
pub(crate) mod extern_abi;
|
||||
pub(crate) mod flyimport;
|
||||
pub(crate) mod fn_param;
|
||||
|
@ -16,7 +17,7 @@ pub(crate) mod qualified_path;
|
|||
pub(crate) mod record;
|
||||
pub(crate) mod snippet;
|
||||
pub(crate) mod trait_impl;
|
||||
pub(crate) mod unqualified_path;
|
||||
pub(crate) mod r#type;
|
||||
pub(crate) mod use_;
|
||||
pub(crate) mod vis;
|
||||
|
||||
|
|
49
crates/ide-completion/src/completions/expr.rs
Normal file
49
crates/ide-completion/src/completions/expr.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
//! Completion of names from the current scope in expression position.
|
||||
|
||||
use hir::ScopeDef;
|
||||
|
||||
use crate::{
|
||||
context::{PathCompletionCtx, PathKind, PathQualifierCtx},
|
||||
CompletionContext, Completions,
|
||||
};
|
||||
|
||||
pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext) {
|
||||
let _p = profile::span("complete_expr_path");
|
||||
if ctx.is_path_disallowed() {
|
||||
return;
|
||||
}
|
||||
|
||||
let (&is_absolute_path, qualifier) = match &ctx.path_context {
|
||||
Some(PathCompletionCtx {
|
||||
kind: Some(PathKind::Expr), is_absolute_path, qualifier, ..
|
||||
}) => (is_absolute_path, qualifier),
|
||||
_ => return,
|
||||
};
|
||||
|
||||
match qualifier {
|
||||
Some(PathQualifierCtx { .. }) => return,
|
||||
None if is_absolute_path => acc.add_crate_roots(ctx),
|
||||
None => {
|
||||
acc.add_nameref_keywords_with_colon(ctx);
|
||||
if let Some(hir::Adt::Enum(e)) =
|
||||
ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt())
|
||||
{
|
||||
super::enum_variants_with_paths(acc, ctx, e, |acc, ctx, variant, path| {
|
||||
acc.add_qualified_enum_variant(ctx, variant, path)
|
||||
});
|
||||
}
|
||||
ctx.process_all_names(&mut |name, def| {
|
||||
use hir::{GenericParam::*, ModuleDef::*};
|
||||
let add_resolution = match def {
|
||||
ScopeDef::GenericParam(LifetimeParam(_)) | ScopeDef::Label(_) => false,
|
||||
// Don't suggest attribute macros and derives.
|
||||
ScopeDef::ModuleDef(Macro(mac)) => mac.is_fn_like(ctx.db),
|
||||
_ => true,
|
||||
};
|
||||
if add_resolution {
|
||||
acc.add_resolution(ctx, name, def);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ use crate::{
|
|||
};
|
||||
|
||||
pub(crate) fn complete_item_list(acc: &mut Completions, ctx: &CompletionContext) {
|
||||
let _p = profile::span("complete_unqualified_path");
|
||||
let _p = profile::span("complete_item_list");
|
||||
if ctx.is_path_disallowed() || ctx.has_unfinished_impl_or_trait_prev_sibling() {
|
||||
return;
|
||||
}
|
||||
|
|
90
crates/ide-completion/src/completions/type.rs
Normal file
90
crates/ide-completion/src/completions/type.rs
Normal file
|
@ -0,0 +1,90 @@
|
|||
//! Completion of names from the current scope in type position.
|
||||
|
||||
use hir::ScopeDef;
|
||||
use syntax::{ast, AstNode};
|
||||
|
||||
use crate::{
|
||||
context::{PathCompletionCtx, PathKind, PathQualifierCtx},
|
||||
patterns::ImmediateLocation,
|
||||
CompletionContext, Completions,
|
||||
};
|
||||
|
||||
pub(crate) fn complete_type_path(acc: &mut Completions, ctx: &CompletionContext) {
|
||||
let _p = profile::span("complete_type_path");
|
||||
if ctx.is_path_disallowed() {
|
||||
return;
|
||||
}
|
||||
|
||||
let (&is_absolute_path, qualifier) = match &ctx.path_context {
|
||||
Some(PathCompletionCtx {
|
||||
kind: Some(PathKind::Type), is_absolute_path, qualifier, ..
|
||||
}) => (is_absolute_path, qualifier),
|
||||
_ => return,
|
||||
};
|
||||
|
||||
match qualifier {
|
||||
Some(PathQualifierCtx { .. }) => return,
|
||||
None if is_absolute_path => acc.add_crate_roots(ctx),
|
||||
None => {
|
||||
acc.add_nameref_keywords_with_colon(ctx);
|
||||
if let Some(ImmediateLocation::TypeBound) = &ctx.completion_location {
|
||||
ctx.process_all_names(&mut |name, res| {
|
||||
let add_resolution = match res {
|
||||
ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => mac.is_fn_like(ctx.db),
|
||||
ScopeDef::ModuleDef(
|
||||
hir::ModuleDef::Trait(_) | hir::ModuleDef::Module(_),
|
||||
) => true,
|
||||
_ => false,
|
||||
};
|
||||
if add_resolution {
|
||||
acc.add_resolution(ctx, name, res);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
if let Some(ImmediateLocation::GenericArgList(arg_list)) = &ctx.completion_location {
|
||||
if let Some(path_seg) = arg_list.syntax().parent().and_then(ast::PathSegment::cast)
|
||||
{
|
||||
if let Some(hir::PathResolution::Def(hir::ModuleDef::Trait(trait_))) =
|
||||
ctx.sema.resolve_path(&path_seg.parent_path())
|
||||
{
|
||||
trait_.items(ctx.sema.db).into_iter().for_each(|it| {
|
||||
if let hir::AssocItem::TypeAlias(alias) = it {
|
||||
acc.add_type_alias_with_eq(ctx, alias)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.process_all_names(&mut |name, def| {
|
||||
use hir::{GenericParam::*, ModuleDef::*};
|
||||
let add_resolution = match def {
|
||||
ScopeDef::GenericParam(LifetimeParam(_)) | ScopeDef::Label(_) => false,
|
||||
// no values in type places
|
||||
ScopeDef::ModuleDef(Function(_) | Variant(_) | Static(_))
|
||||
| ScopeDef::Local(_) => false,
|
||||
// unless its a constant in a generic arg list position
|
||||
ScopeDef::ModuleDef(Const(_)) | ScopeDef::GenericParam(ConstParam(_)) => {
|
||||
ctx.expects_generic_arg()
|
||||
}
|
||||
ScopeDef::ImplSelfType(_) => {
|
||||
!ctx.previous_token_is(syntax::T![impl])
|
||||
&& !ctx.previous_token_is(syntax::T![for])
|
||||
}
|
||||
// Don't suggest attribute macros and derives.
|
||||
ScopeDef::ModuleDef(Macro(mac)) => mac.is_fn_like(ctx.db),
|
||||
// Type things are fine
|
||||
ScopeDef::ModuleDef(
|
||||
BuiltinType(_) | Adt(_) | Module(_) | Trait(_) | TypeAlias(_),
|
||||
)
|
||||
| ScopeDef::AdtSelfType(_)
|
||||
| ScopeDef::Unknown
|
||||
| ScopeDef::GenericParam(TypeParam(_)) => true,
|
||||
};
|
||||
if add_resolution {
|
||||
acc.add_resolution(ctx, name, def);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,289 +0,0 @@
|
|||
//! Completion of names from the current scope, e.g. locals and imported items.
|
||||
|
||||
use hir::ScopeDef;
|
||||
use syntax::{ast, AstNode};
|
||||
|
||||
use crate::{
|
||||
context::{PathCompletionCtx, PathKind},
|
||||
patterns::ImmediateLocation,
|
||||
CompletionContext, Completions,
|
||||
};
|
||||
|
||||
pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) {
|
||||
let _p = profile::span("complete_unqualified_path");
|
||||
if ctx.is_path_disallowed() || ctx.has_unfinished_impl_or_trait_prev_sibling() {
|
||||
return;
|
||||
}
|
||||
|
||||
match &ctx.path_context {
|
||||
Some(PathCompletionCtx {
|
||||
is_absolute_path: false,
|
||||
qualifier: None,
|
||||
kind: None | Some(PathKind::Expr | PathKind::Type),
|
||||
..
|
||||
}) => (),
|
||||
_ => return,
|
||||
}
|
||||
|
||||
acc.add_nameref_keywords(ctx);
|
||||
|
||||
match &ctx.completion_location {
|
||||
Some(ImmediateLocation::TypeBound) => {
|
||||
ctx.process_all_names(&mut |name, res| {
|
||||
let add_resolution = match res {
|
||||
ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => mac.is_fn_like(ctx.db),
|
||||
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())
|
||||
{
|
||||
super::enum_variants_with_paths(acc, ctx, e, |acc, ctx, variant, path| {
|
||||
acc.add_qualified_enum_variant(ctx, variant, path)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ImmediateLocation::GenericArgList(arg_list)) = &ctx.completion_location {
|
||||
if let Some(path_seg) = arg_list.syntax().parent().and_then(ast::PathSegment::cast) {
|
||||
if let Some(hir::PathResolution::Def(hir::ModuleDef::Trait(trait_))) =
|
||||
ctx.sema.resolve_path(&path_seg.parent_path())
|
||||
{
|
||||
trait_.items(ctx.sema.db).into_iter().for_each(|it| {
|
||||
if let hir::AssocItem::TypeAlias(alias) = it {
|
||||
acc.add_type_alias_with_eq(ctx, alias)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx.process_all_names(&mut |name, res| {
|
||||
let add_resolution = match res {
|
||||
ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) | ScopeDef::Label(_) => {
|
||||
cov_mark::hit!(unqualified_skip_lifetime_completion);
|
||||
return;
|
||||
}
|
||||
ScopeDef::ImplSelfType(_) => {
|
||||
!ctx.previous_token_is(syntax::T![impl]) && !ctx.previous_token_is(syntax::T![for])
|
||||
}
|
||||
// Don't suggest attribute macros and derives.
|
||||
ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => mac.is_fn_like(ctx.db),
|
||||
// no values in type places
|
||||
ScopeDef::ModuleDef(
|
||||
hir::ModuleDef::Function(_)
|
||||
| hir::ModuleDef::Variant(_)
|
||||
| hir::ModuleDef::Static(_),
|
||||
)
|
||||
| ScopeDef::Local(_) => !ctx.expects_type(),
|
||||
// unless its a constant in a generic arg list position
|
||||
ScopeDef::ModuleDef(hir::ModuleDef::Const(_))
|
||||
| ScopeDef::GenericParam(hir::GenericParam::ConstParam(_)) => {
|
||||
!ctx.expects_type() || ctx.expects_generic_arg()
|
||||
}
|
||||
_ => true,
|
||||
};
|
||||
if add_resolution {
|
||||
acc.add_resolution(ctx, name, res);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use expect_test::{expect, Expect};
|
||||
|
||||
use crate::tests::{check_edit, completion_list_no_kw};
|
||||
|
||||
fn check(ra_fixture: &str, expect: Expect) {
|
||||
let actual = completion_list_no_kw(ra_fixture);
|
||||
expect.assert_eq(&actual)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn completes_if_prefix_is_keyword() {
|
||||
check_edit(
|
||||
"wherewolf",
|
||||
r#"
|
||||
fn main() {
|
||||
let wherewolf = 92;
|
||||
drop(where$0)
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
fn main() {
|
||||
let wherewolf = 92;
|
||||
drop(wherewolf)
|
||||
}
|
||||
"#,
|
||||
)
|
||||
}
|
||||
|
||||
/// Regression test for issue #6091.
|
||||
#[test]
|
||||
fn correctly_completes_module_items_prefixed_with_underscore() {
|
||||
check_edit(
|
||||
"_alpha",
|
||||
r#"
|
||||
fn main() {
|
||||
_$0
|
||||
}
|
||||
fn _alpha() {}
|
||||
"#,
|
||||
r#"
|
||||
fn main() {
|
||||
_alpha()$0
|
||||
}
|
||||
fn _alpha() {}
|
||||
"#,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn completes_prelude() {
|
||||
check(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:std
|
||||
fn foo() { let x: $0 }
|
||||
|
||||
//- /std/lib.rs crate:std
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
pub struct Option;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
md std
|
||||
st Option
|
||||
bt u32
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn completes_prelude_macros() {
|
||||
check(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:std
|
||||
fn f() {$0}
|
||||
|
||||
//- /std/lib.rs crate:std
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
pub use crate::concat;
|
||||
}
|
||||
}
|
||||
|
||||
mod macros {
|
||||
#[rustc_builtin_macro]
|
||||
#[macro_export]
|
||||
macro_rules! concat { }
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
fn f() fn()
|
||||
ma concat!(…) macro_rules! concat
|
||||
md std
|
||||
bt u32
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn completes_std_prelude_if_core_is_defined() {
|
||||
check(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:core,std
|
||||
fn foo() { let x: $0 }
|
||||
|
||||
//- /core/lib.rs crate:core
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
pub struct Option;
|
||||
}
|
||||
}
|
||||
|
||||
//- /std/lib.rs crate:std deps:core
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
pub struct String;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
md core
|
||||
md std
|
||||
st String
|
||||
bt u32
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn respects_doc_hidden() {
|
||||
check(
|
||||
r#"
|
||||
//- /lib.rs crate:lib deps:std
|
||||
fn f() {
|
||||
format_$0
|
||||
}
|
||||
|
||||
//- /std.rs crate:std
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! format_args_nl {
|
||||
() => {}
|
||||
}
|
||||
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
fn f() fn()
|
||||
md std
|
||||
bt u32
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn respects_doc_hidden_in_assoc_item_list() {
|
||||
check(
|
||||
r#"
|
||||
//- /lib.rs crate:lib deps:std
|
||||
struct S;
|
||||
impl S {
|
||||
format_$0
|
||||
}
|
||||
|
||||
//- /std.rs crate:std
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! format_args_nl {
|
||||
() => {}
|
||||
}
|
||||
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
md std
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -71,6 +71,10 @@ pub(crate) struct PathCompletionCtx {
|
|||
pub(super) is_absolute_path: bool,
|
||||
/// The qualifier of the current path if it exists.
|
||||
pub(super) qualifier: Option<PathQualifierCtx>,
|
||||
#[allow(dead_code)]
|
||||
// FIXME: use this
|
||||
/// The parent of the path we are completing.
|
||||
pub(super) parent: Option<ast::Path>,
|
||||
pub(super) kind: Option<PathKind>,
|
||||
/// Whether the path segment has type args or not.
|
||||
pub(super) has_type_args: bool,
|
||||
|
@ -949,13 +953,14 @@ impl<'a> CompletionContext<'a> {
|
|||
|
||||
let mut path_ctx = PathCompletionCtx {
|
||||
has_call_parens: false,
|
||||
has_macro_bang: false,
|
||||
is_absolute_path: false,
|
||||
qualifier: None,
|
||||
parent: path.parent_path(),
|
||||
kind: None,
|
||||
has_type_args: false,
|
||||
can_be_stmt: false,
|
||||
in_loop_body: false,
|
||||
has_macro_bang: false,
|
||||
kind: None,
|
||||
};
|
||||
let mut pat_ctx = None;
|
||||
path_ctx.in_loop_body = is_in_loop_body(name_ref.syntax());
|
||||
|
|
|
@ -144,34 +144,38 @@ pub fn completions(
|
|||
config: &CompletionConfig,
|
||||
position: FilePosition,
|
||||
) -> Option<Completions> {
|
||||
let ctx = CompletionContext::new(db, position, config)?;
|
||||
|
||||
let ctx = &CompletionContext::new(db, position, config)?;
|
||||
let mut acc = Completions::default();
|
||||
completions::attribute::complete_attribute(&mut acc, &ctx);
|
||||
completions::attribute::complete_derive(&mut acc, &ctx);
|
||||
completions::attribute::complete_known_attribute_input(&mut acc, &ctx);
|
||||
completions::dot::complete_dot(&mut acc, &ctx);
|
||||
completions::extern_abi::complete_extern_abi(&mut acc, &ctx);
|
||||
completions::flyimport::import_on_the_fly(&mut acc, &ctx);
|
||||
completions::fn_param::complete_fn_param(&mut acc, &ctx);
|
||||
completions::format_string::format_string(&mut acc, &ctx);
|
||||
completions::item_list::complete_item_list(&mut acc, &ctx);
|
||||
completions::inferred_type(&mut acc, &ctx);
|
||||
completions::keyword::complete_expr_keyword(&mut acc, &ctx);
|
||||
completions::lifetime::complete_label(&mut acc, &ctx);
|
||||
completions::lifetime::complete_lifetime(&mut acc, &ctx);
|
||||
completions::mod_::complete_mod(&mut acc, &ctx);
|
||||
completions::pattern::complete_pattern(&mut acc, &ctx);
|
||||
completions::postfix::complete_postfix(&mut acc, &ctx);
|
||||
completions::qualified_path::complete_qualified_path(&mut acc, &ctx);
|
||||
completions::record::complete_record_literal(&mut acc, &ctx);
|
||||
completions::record::complete_record(&mut acc, &ctx);
|
||||
completions::snippet::complete_expr_snippet(&mut acc, &ctx);
|
||||
completions::snippet::complete_item_snippet(&mut acc, &ctx);
|
||||
completions::trait_impl::complete_trait_impl(&mut acc, &ctx);
|
||||
completions::unqualified_path::complete_unqualified_path(&mut acc, &ctx);
|
||||
completions::use_::complete_use_tree(&mut acc, &ctx);
|
||||
completions::vis::complete_vis(&mut acc, &ctx);
|
||||
|
||||
{
|
||||
let acc = &mut acc;
|
||||
completions::attribute::complete_attribute(acc, ctx);
|
||||
completions::attribute::complete_derive(acc, ctx);
|
||||
completions::attribute::complete_known_attribute_input(acc, ctx);
|
||||
completions::dot::complete_dot(acc, ctx);
|
||||
completions::expr::complete_expr_path(acc, ctx);
|
||||
completions::extern_abi::complete_extern_abi(acc, ctx);
|
||||
completions::flyimport::import_on_the_fly(acc, ctx);
|
||||
completions::fn_param::complete_fn_param(acc, ctx);
|
||||
completions::format_string::format_string(acc, ctx);
|
||||
completions::item_list::complete_item_list(acc, ctx);
|
||||
completions::inferred_type(acc, ctx);
|
||||
completions::keyword::complete_expr_keyword(acc, ctx);
|
||||
completions::lifetime::complete_label(acc, ctx);
|
||||
completions::lifetime::complete_lifetime(acc, ctx);
|
||||
completions::mod_::complete_mod(acc, ctx);
|
||||
completions::pattern::complete_pattern(acc, ctx);
|
||||
completions::postfix::complete_postfix(acc, ctx);
|
||||
completions::qualified_path::complete_qualified_path(acc, ctx);
|
||||
completions::record::complete_record_literal(acc, ctx);
|
||||
completions::record::complete_record(acc, ctx);
|
||||
completions::snippet::complete_expr_snippet(acc, ctx);
|
||||
completions::snippet::complete_item_snippet(acc, ctx);
|
||||
completions::trait_impl::complete_trait_impl(acc, ctx);
|
||||
completions::r#type::complete_type_path(acc, ctx);
|
||||
completions::use_::complete_use_tree(acc, ctx);
|
||||
completions::vis::complete_vis(acc, ctx);
|
||||
}
|
||||
|
||||
Some(acc)
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
mod attribute;
|
||||
mod expression;
|
||||
mod flyimport;
|
||||
mod fn_param;
|
||||
mod item_list;
|
||||
mod item;
|
||||
|
@ -17,10 +18,10 @@ mod pattern;
|
|||
mod predicate;
|
||||
mod proc_macros;
|
||||
mod record;
|
||||
mod special;
|
||||
mod type_pos;
|
||||
mod use_tree;
|
||||
mod visibility;
|
||||
mod flyimport;
|
||||
|
||||
use std::mem;
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ fn baz() {
|
|||
un Union
|
||||
ev TupleV(…) TupleV(u32)
|
||||
bt u32
|
||||
kw crate
|
||||
kw crate::
|
||||
kw false
|
||||
kw for
|
||||
kw if
|
||||
|
@ -57,8 +57,8 @@ fn baz() {
|
|||
kw match
|
||||
kw mut
|
||||
kw return
|
||||
kw self
|
||||
kw super
|
||||
kw self::
|
||||
kw super::
|
||||
kw true
|
||||
kw unsafe
|
||||
kw while
|
||||
|
@ -91,7 +91,7 @@ fn func(param0 @ (param1, param2): (i32, i32)) {
|
|||
lc param1 i32
|
||||
lc param2 i32
|
||||
bt u32
|
||||
kw crate
|
||||
kw crate::
|
||||
kw false
|
||||
kw for
|
||||
kw if
|
||||
|
@ -99,8 +99,8 @@ fn func(param0 @ (param1, param2): (i32, i32)) {
|
|||
kw loop
|
||||
kw match
|
||||
kw return
|
||||
kw self
|
||||
kw super
|
||||
kw self::
|
||||
kw super::
|
||||
kw true
|
||||
kw unsafe
|
||||
kw while
|
||||
|
@ -111,7 +111,6 @@ fn func(param0 @ (param1, param2): (i32, i32)) {
|
|||
|
||||
#[test]
|
||||
fn completes_all_the_things_in_fn_body() {
|
||||
cov_mark::check!(unqualified_skip_lifetime_completion);
|
||||
check(
|
||||
r#"
|
||||
use non_existant::Unresolved;
|
||||
|
@ -146,7 +145,7 @@ impl Unit {
|
|||
ev TupleV(…) TupleV(u32)
|
||||
bt u32
|
||||
kw const
|
||||
kw crate
|
||||
kw crate::
|
||||
kw enum
|
||||
kw extern
|
||||
kw false
|
||||
|
@ -160,10 +159,10 @@ impl Unit {
|
|||
kw match
|
||||
kw mod
|
||||
kw return
|
||||
kw self
|
||||
kw self::
|
||||
kw static
|
||||
kw struct
|
||||
kw super
|
||||
kw super::
|
||||
kw trait
|
||||
kw true
|
||||
kw type
|
||||
|
@ -224,7 +223,7 @@ fn complete_in_block() {
|
|||
fn foo() fn()
|
||||
bt u32
|
||||
kw const
|
||||
kw crate
|
||||
kw crate::
|
||||
kw enum
|
||||
kw extern
|
||||
kw false
|
||||
|
@ -238,10 +237,10 @@ fn complete_in_block() {
|
|||
kw match
|
||||
kw mod
|
||||
kw return
|
||||
kw self
|
||||
kw self::
|
||||
kw static
|
||||
kw struct
|
||||
kw super
|
||||
kw super::
|
||||
kw trait
|
||||
kw true
|
||||
kw type
|
||||
|
@ -270,7 +269,7 @@ fn complete_after_if_expr() {
|
|||
fn foo() fn()
|
||||
bt u32
|
||||
kw const
|
||||
kw crate
|
||||
kw crate::
|
||||
kw else
|
||||
kw else if
|
||||
kw enum
|
||||
|
@ -286,10 +285,10 @@ fn complete_after_if_expr() {
|
|||
kw match
|
||||
kw mod
|
||||
kw return
|
||||
kw self
|
||||
kw self::
|
||||
kw static
|
||||
kw struct
|
||||
kw super
|
||||
kw super::
|
||||
kw trait
|
||||
kw true
|
||||
kw type
|
||||
|
@ -318,7 +317,7 @@ fn complete_in_match_arm() {
|
|||
expect![[r#"
|
||||
fn foo() fn()
|
||||
bt u32
|
||||
kw crate
|
||||
kw crate::
|
||||
kw false
|
||||
kw for
|
||||
kw if
|
||||
|
@ -326,8 +325,8 @@ fn complete_in_match_arm() {
|
|||
kw loop
|
||||
kw match
|
||||
kw return
|
||||
kw self
|
||||
kw super
|
||||
kw self::
|
||||
kw super::
|
||||
kw true
|
||||
kw unsafe
|
||||
kw while
|
||||
|
@ -346,7 +345,7 @@ fn completes_in_loop_ctx() {
|
|||
kw break
|
||||
kw const
|
||||
kw continue
|
||||
kw crate
|
||||
kw crate::
|
||||
kw enum
|
||||
kw extern
|
||||
kw false
|
||||
|
@ -360,10 +359,10 @@ fn completes_in_loop_ctx() {
|
|||
kw match
|
||||
kw mod
|
||||
kw return
|
||||
kw self
|
||||
kw self::
|
||||
kw static
|
||||
kw struct
|
||||
kw super
|
||||
kw super::
|
||||
kw trait
|
||||
kw true
|
||||
kw type
|
||||
|
@ -386,7 +385,7 @@ fn completes_in_let_initializer() {
|
|||
expect![[r#"
|
||||
fn main() fn()
|
||||
bt u32
|
||||
kw crate
|
||||
kw crate::
|
||||
kw false
|
||||
kw for
|
||||
kw if
|
||||
|
@ -394,8 +393,8 @@ fn completes_in_let_initializer() {
|
|||
kw loop
|
||||
kw match
|
||||
kw return
|
||||
kw self
|
||||
kw super
|
||||
kw self::
|
||||
kw super::
|
||||
kw true
|
||||
kw unsafe
|
||||
kw while
|
||||
|
@ -421,7 +420,7 @@ fn foo() {
|
|||
fn foo() fn()
|
||||
st Foo
|
||||
bt u32
|
||||
kw crate
|
||||
kw crate::
|
||||
kw false
|
||||
kw for
|
||||
kw if
|
||||
|
@ -429,8 +428,8 @@ fn foo() {
|
|||
kw loop
|
||||
kw match
|
||||
kw return
|
||||
kw self
|
||||
kw super
|
||||
kw self::
|
||||
kw super::
|
||||
kw true
|
||||
kw unsafe
|
||||
kw while
|
||||
|
@ -457,7 +456,7 @@ fn foo() {
|
|||
fn foo() fn()
|
||||
lc bar i32
|
||||
bt u32
|
||||
kw crate
|
||||
kw crate::
|
||||
kw false
|
||||
kw for
|
||||
kw if
|
||||
|
@ -465,8 +464,8 @@ fn foo() {
|
|||
kw loop
|
||||
kw match
|
||||
kw return
|
||||
kw self
|
||||
kw super
|
||||
kw self::
|
||||
kw super::
|
||||
kw true
|
||||
kw unsafe
|
||||
kw while
|
||||
|
@ -489,7 +488,7 @@ fn quux(x: i32) {
|
|||
lc x i32
|
||||
ma m!(…) macro_rules! m
|
||||
bt u32
|
||||
kw crate
|
||||
kw crate::
|
||||
kw false
|
||||
kw for
|
||||
kw if
|
||||
|
@ -497,8 +496,8 @@ fn quux(x: i32) {
|
|||
kw loop
|
||||
kw match
|
||||
kw return
|
||||
kw self
|
||||
kw super
|
||||
kw self::
|
||||
kw super::
|
||||
kw true
|
||||
kw unsafe
|
||||
kw while
|
||||
|
@ -517,7 +516,7 @@ fn quux(x: i32) {
|
|||
lc x i32
|
||||
ma m!(…) macro_rules! m
|
||||
bt u32
|
||||
kw crate
|
||||
kw crate::
|
||||
kw false
|
||||
kw for
|
||||
kw if
|
||||
|
@ -525,8 +524,8 @@ fn quux(x: i32) {
|
|||
kw loop
|
||||
kw match
|
||||
kw return
|
||||
kw self
|
||||
kw super
|
||||
kw self::
|
||||
kw super::
|
||||
kw true
|
||||
kw unsafe
|
||||
kw while
|
||||
|
|
|
@ -27,9 +27,9 @@ impl Tra$0
|
|||
tt Trait
|
||||
un Union
|
||||
bt u32
|
||||
kw crate
|
||||
kw self
|
||||
kw super
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
@ -50,9 +50,9 @@ impl Trait for Str$0
|
|||
tt Trait
|
||||
un Union
|
||||
bt u32
|
||||
kw crate
|
||||
kw self
|
||||
kw super
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
|
|
@ -26,9 +26,9 @@ struct Foo<'lt, T, const C: usize> where $0 {}
|
|||
tt Trait
|
||||
un Union
|
||||
bt u32
|
||||
kw crate
|
||||
kw self
|
||||
kw super
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -43,9 +43,9 @@ struct Foo<'lt, T, const C: usize> where T: $0 {}
|
|||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
tt Trait
|
||||
kw crate
|
||||
kw self
|
||||
kw super
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -62,9 +62,9 @@ struct Foo<'lt, T, const C: usize> where 'lt: $0 {}
|
|||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
tt Trait
|
||||
kw crate
|
||||
kw self
|
||||
kw super
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -79,9 +79,9 @@ struct Foo<'lt, T, const C: usize> where for<'a> T: $0 {}
|
|||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
tt Trait
|
||||
kw crate
|
||||
kw self
|
||||
kw super
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -103,9 +103,9 @@ struct Foo<'lt, T, const C: usize> where for<'a> $0 {}
|
|||
tt Trait
|
||||
un Union
|
||||
bt u32
|
||||
kw crate
|
||||
kw self
|
||||
kw super
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -129,9 +129,9 @@ impl Record {
|
|||
tt Trait
|
||||
un Union
|
||||
bt u32
|
||||
kw crate
|
||||
kw self
|
||||
kw super
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -167,7 +167,7 @@ fn main() {
|
|||
tt Default
|
||||
tt Sized
|
||||
bt u32
|
||||
kw crate
|
||||
kw crate::
|
||||
kw false
|
||||
kw for
|
||||
kw if
|
||||
|
@ -175,8 +175,8 @@ fn main() {
|
|||
kw loop
|
||||
kw match
|
||||
kw return
|
||||
kw self
|
||||
kw super
|
||||
kw self::
|
||||
kw super::
|
||||
kw true
|
||||
kw unsafe
|
||||
kw while
|
||||
|
|
183
crates/ide-completion/src/tests/special.rs
Normal file
183
crates/ide-completion/src/tests/special.rs
Normal file
|
@ -0,0 +1,183 @@
|
|||
use expect_test::{expect, Expect};
|
||||
|
||||
use crate::tests::{check_edit, completion_list_no_kw};
|
||||
|
||||
fn check(ra_fixture: &str, expect: Expect) {
|
||||
let actual = completion_list_no_kw(ra_fixture);
|
||||
expect.assert_eq(&actual)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn completes_if_prefix_is_keyword() {
|
||||
check_edit(
|
||||
"wherewolf",
|
||||
r#"
|
||||
fn main() {
|
||||
let wherewolf = 92;
|
||||
drop(where$0)
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
fn main() {
|
||||
let wherewolf = 92;
|
||||
drop(wherewolf)
|
||||
}
|
||||
"#,
|
||||
)
|
||||
}
|
||||
|
||||
/// Regression test for issue #6091.
|
||||
#[test]
|
||||
fn correctly_completes_module_items_prefixed_with_underscore() {
|
||||
check_edit(
|
||||
"_alpha",
|
||||
r#"
|
||||
fn main() {
|
||||
_$0
|
||||
}
|
||||
fn _alpha() {}
|
||||
"#,
|
||||
r#"
|
||||
fn main() {
|
||||
_alpha()$0
|
||||
}
|
||||
fn _alpha() {}
|
||||
"#,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn completes_prelude() {
|
||||
check(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:std
|
||||
fn foo() { let x: $0 }
|
||||
|
||||
//- /std/lib.rs crate:std
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
pub struct Option;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
md std
|
||||
st Option
|
||||
bt u32
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn completes_prelude_macros() {
|
||||
check(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:std
|
||||
fn f() {$0}
|
||||
|
||||
//- /std/lib.rs crate:std
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
pub use crate::concat;
|
||||
}
|
||||
}
|
||||
|
||||
mod macros {
|
||||
#[rustc_builtin_macro]
|
||||
#[macro_export]
|
||||
macro_rules! concat { }
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
fn f() fn()
|
||||
ma concat!(…) macro_rules! concat
|
||||
md std
|
||||
bt u32
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn completes_std_prelude_if_core_is_defined() {
|
||||
check(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:core,std
|
||||
fn foo() { let x: $0 }
|
||||
|
||||
//- /core/lib.rs crate:core
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
pub struct Option;
|
||||
}
|
||||
}
|
||||
|
||||
//- /std/lib.rs crate:std deps:core
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
pub struct String;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
md core
|
||||
md std
|
||||
st String
|
||||
bt u32
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn respects_doc_hidden() {
|
||||
check(
|
||||
r#"
|
||||
//- /lib.rs crate:lib deps:std
|
||||
fn f() {
|
||||
format_$0
|
||||
}
|
||||
|
||||
//- /std.rs crate:std
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! format_args_nl {
|
||||
() => {}
|
||||
}
|
||||
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
fn f() fn()
|
||||
md std
|
||||
bt u32
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn respects_doc_hidden_in_assoc_item_list() {
|
||||
check(
|
||||
r#"
|
||||
//- /lib.rs crate:lib deps:std
|
||||
struct S;
|
||||
impl S {
|
||||
format_$0
|
||||
}
|
||||
|
||||
//- /std.rs crate:std
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! format_args_nl {
|
||||
() => {}
|
||||
}
|
||||
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
md std
|
||||
"#]],
|
||||
);
|
||||
}
|
|
@ -29,9 +29,9 @@ struct Foo<'lt, T, const C: usize> {
|
|||
tp T
|
||||
un Union
|
||||
bt u32
|
||||
kw crate
|
||||
kw self
|
||||
kw super
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
@ -55,12 +55,12 @@ struct Foo<'lt, T, const C: usize>(f$0);
|
|||
tp T
|
||||
un Union
|
||||
bt u32
|
||||
kw crate
|
||||
kw crate::
|
||||
kw pub
|
||||
kw pub(crate)
|
||||
kw pub(super)
|
||||
kw self
|
||||
kw super
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
@ -82,9 +82,9 @@ fn x<'lt, T, const C: usize>() -> $0
|
|||
tp T
|
||||
un Union
|
||||
bt u32
|
||||
kw crate
|
||||
kw self
|
||||
kw super
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -108,9 +108,9 @@ const FOO: $0 = Foo(2);
|
|||
un Union
|
||||
bt u32
|
||||
it Foo<i32>
|
||||
kw crate
|
||||
kw self
|
||||
kw super
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -135,9 +135,9 @@ fn f2() {
|
|||
un Union
|
||||
bt u32
|
||||
it i32
|
||||
kw crate
|
||||
kw self
|
||||
kw super
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -164,9 +164,9 @@ fn f2() {
|
|||
un Union
|
||||
bt u32
|
||||
it u64
|
||||
kw crate
|
||||
kw self
|
||||
kw super
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -190,9 +190,9 @@ fn f2(x: u64) -> $0 {
|
|||
un Union
|
||||
bt u32
|
||||
it u64
|
||||
kw crate
|
||||
kw self
|
||||
kw super
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -217,9 +217,9 @@ fn f2(x: $0) {
|
|||
un Union
|
||||
bt u32
|
||||
it i32
|
||||
kw crate
|
||||
kw self
|
||||
kw super
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -252,9 +252,9 @@ fn foo<'lt, T, const C: usize>() {
|
|||
un Union
|
||||
bt u32
|
||||
it a::Foo<a::Foo<i32>>
|
||||
kw crate
|
||||
kw self
|
||||
kw super
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -282,9 +282,9 @@ fn foo<'lt, T, const C: usize>() {
|
|||
un Union
|
||||
bt u32
|
||||
it Foo<i32>
|
||||
kw crate
|
||||
kw self
|
||||
kw super
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -309,9 +309,9 @@ fn foo<'lt, T, const C: usize>() {
|
|||
tp T
|
||||
un Union
|
||||
bt u32
|
||||
kw crate
|
||||
kw self
|
||||
kw super
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
|
@ -359,9 +359,9 @@ fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {}
|
|||
tp T
|
||||
un Union
|
||||
bt u32
|
||||
kw crate
|
||||
kw self
|
||||
kw super
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
|
|
Loading…
Reference in a new issue