Complete crate
, super
and self
in non-usetree paths
This commit is contained in:
parent
2b6770c936
commit
9f9cc72ee5
@ -74,6 +74,12 @@ pub(crate) fn add_all<I>(&mut self, items: I)
|
||||
items.into_iter().for_each(|item| self.add(item.into()))
|
||||
}
|
||||
|
||||
pub(crate) fn add_keyword(&mut self, ctx: &CompletionContext, keyword: &'static str) {
|
||||
let mut item = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), keyword);
|
||||
item.kind(CompletionItemKind::Keyword);
|
||||
item.add_to(self);
|
||||
}
|
||||
|
||||
pub(crate) fn add_resolution(
|
||||
&mut self,
|
||||
ctx: &CompletionContext,
|
||||
|
@ -1,7 +1,5 @@
|
||||
//! Completes keywords.
|
||||
|
||||
use std::iter;
|
||||
|
||||
use syntax::{SyntaxKind, T};
|
||||
|
||||
use crate::{
|
||||
@ -9,36 +7,6 @@
|
||||
CompletionItemKind, CompletionKind, Completions,
|
||||
};
|
||||
|
||||
pub(crate) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionContext) {
|
||||
// complete keyword "crate" in use stmt
|
||||
let source_range = ctx.source_range();
|
||||
let kw_completion = move |text: &str| {
|
||||
let mut item = CompletionItem::new(CompletionKind::Keyword, source_range, text);
|
||||
item.kind(CompletionItemKind::Keyword).insert_text(text);
|
||||
item
|
||||
};
|
||||
|
||||
if ctx.in_use_tree() {
|
||||
match &ctx.path_context {
|
||||
Some(PathCompletionContext { qualifier: Some(qual), use_tree_parent, .. }) => {
|
||||
if iter::successors(Some(qual.clone()), |p| p.qualifier())
|
||||
.all(|p| p.segment().and_then(|s| s.super_token()).is_some())
|
||||
{
|
||||
kw_completion("super::").add_to(acc);
|
||||
}
|
||||
if *use_tree_parent {
|
||||
kw_completion("self").add_to(acc);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
kw_completion("crate::").add_to(acc);
|
||||
kw_completion("self::").add_to(acc);
|
||||
kw_completion("super::").add_to(acc);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
|
||||
if ctx.token.kind() == SyntaxKind::COMMENT {
|
||||
cov_mark::hit!(no_keyword_completion_in_comments);
|
||||
@ -243,6 +211,9 @@ fn test_keywords_in_function() {
|
||||
kw for
|
||||
kw let
|
||||
kw return
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
@ -271,6 +242,9 @@ fn test_keywords_inside_block() {
|
||||
kw for
|
||||
kw let
|
||||
kw return
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
@ -301,6 +275,9 @@ fn test_keywords_after_if() {
|
||||
kw else
|
||||
kw else if
|
||||
kw return
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
"#]],
|
||||
);
|
||||
check_edit(
|
||||
@ -330,6 +307,9 @@ fn quux() -> i32 {
|
||||
kw if let
|
||||
kw for
|
||||
kw return
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
@ -360,6 +340,9 @@ fn test_keywords_in_loop() {
|
||||
kw continue
|
||||
kw break
|
||||
kw return
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
@ -448,6 +431,9 @@ fn after_let() {
|
||||
kw if let
|
||||
kw for
|
||||
kw return
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
@ -493,6 +479,9 @@ fn foo() {
|
||||
kw if let
|
||||
kw for
|
||||
kw return
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -1,18 +1,22 @@
|
||||
//! Completion of paths, i.e. `some::prefix::$0`.
|
||||
|
||||
use std::iter;
|
||||
|
||||
use hir::HasVisibility;
|
||||
use rustc_hash::FxHashSet;
|
||||
use syntax::AstNode;
|
||||
use syntax::{ast, AstNode};
|
||||
|
||||
use crate::{CompletionContext, Completions};
|
||||
use crate::{context::PathCompletionContext, CompletionContext, Completions};
|
||||
|
||||
pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) {
|
||||
if ctx.is_path_disallowed() {
|
||||
return;
|
||||
}
|
||||
let path = match ctx.path_qual() {
|
||||
Some(path) => path,
|
||||
None => return,
|
||||
let (path, use_tree_parent) = match &ctx.path_context {
|
||||
Some(PathCompletionContext { qualifier: Some(qualifier), use_tree_parent, .. }) => {
|
||||
(qualifier, *use_tree_parent)
|
||||
}
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let resolution = match ctx.sema.resolve_path(path) {
|
||||
@ -39,6 +43,23 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
||||
return;
|
||||
}
|
||||
|
||||
if ctx.in_use_tree() {
|
||||
if iter::successors(Some(path.clone()), |p| p.qualifier())
|
||||
.all(|p| p.segment().and_then(|s| s.super_token()).is_some())
|
||||
{
|
||||
acc.add_keyword(ctx, "super::");
|
||||
}
|
||||
// only show `self` in a new use-tree when the qualifier doesn't end in self
|
||||
if use_tree_parent
|
||||
&& !matches!(
|
||||
path.segment().and_then(|it| it.kind()),
|
||||
Some(ast::PathSegmentKind::SelfKw)
|
||||
)
|
||||
{
|
||||
acc.add_keyword(ctx, "self");
|
||||
}
|
||||
}
|
||||
|
||||
// Add associated types on type parameters and `Self`.
|
||||
resolution.assoc_type_shorthand_candidates(ctx.db, |_, alias| {
|
||||
acc.add_type_alias(ctx, alias);
|
||||
|
@ -10,6 +10,21 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
|
||||
return;
|
||||
}
|
||||
|
||||
if ctx.in_use_tree() {
|
||||
// only show modules in a fresh UseTree
|
||||
cov_mark::hit!(only_completes_modules_in_import);
|
||||
ctx.scope.process_all_names(&mut |name, res| {
|
||||
if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
|
||||
acc.add_resolution(ctx, name, &res);
|
||||
}
|
||||
});
|
||||
|
||||
std::array::IntoIter::new(["self::", "super::", "crate::"])
|
||||
.for_each(|kw| acc.add_keyword(ctx, kw));
|
||||
return;
|
||||
}
|
||||
std::array::IntoIter::new(["self", "super", "crate"]).for_each(|kw| acc.add_keyword(ctx, kw));
|
||||
|
||||
if ctx.expects_item() || ctx.expects_assoc_item() {
|
||||
// only show macros in {Assoc}ItemList
|
||||
ctx.scope.process_all_names(&mut |name, res| {
|
||||
@ -25,17 +40,6 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
|
||||
return;
|
||||
}
|
||||
|
||||
if ctx.in_use_tree() {
|
||||
// only show modules in a fresh UseTree
|
||||
cov_mark::hit!(only_completes_modules_in_import);
|
||||
ctx.scope.process_all_names(&mut |name, res| {
|
||||
if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
|
||||
acc.add_resolution(ctx, name, &res);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if matches!(&ctx.completion_location, Some(ImmediateLocation::TypeBound)) {
|
||||
ctx.scope.process_all_names(&mut |name, res| {
|
||||
let add_resolution = match res {
|
||||
|
@ -150,7 +150,6 @@ pub fn completions(
|
||||
completions::attribute::complete_attribute(&mut acc, &ctx);
|
||||
completions::fn_param::complete_fn_param(&mut acc, &ctx);
|
||||
completions::keyword::complete_expr_keyword(&mut acc, &ctx);
|
||||
completions::keyword::complete_use_tree_keyword(&mut acc, &ctx);
|
||||
completions::snippet::complete_expr_snippet(&mut acc, &ctx);
|
||||
completions::snippet::complete_item_snippet(&mut acc, &ctx);
|
||||
completions::qualified_path::complete_qualified_path(&mut acc, &ctx);
|
||||
|
@ -30,6 +30,9 @@ fn in_mod_item_list() {
|
||||
sn tmod (Test module)
|
||||
sn tfn (Test function)
|
||||
sn macro_rules
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
ma makro!(…) #[macro_export] macro_rules! makro
|
||||
"##]],
|
||||
)
|
||||
@ -58,6 +61,9 @@ fn in_source_file_item_list() {
|
||||
sn tmod (Test module)
|
||||
sn tfn (Test function)
|
||||
sn macro_rules
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
ma makro!(…) #[macro_export] macro_rules! makro
|
||||
md module
|
||||
ma makro!(…) #[macro_export] macro_rules! makro
|
||||
@ -174,6 +180,9 @@ fn in_impl_assoc_item_list() {
|
||||
kw fn
|
||||
kw const
|
||||
kw type
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
ma makro!(…) #[macro_export] macro_rules! makro
|
||||
md module
|
||||
ma makro!(…) #[macro_export] macro_rules! makro
|
||||
@ -205,6 +214,9 @@ fn in_trait_assoc_item_list() {
|
||||
kw fn
|
||||
kw const
|
||||
kw type
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
md module
|
||||
ma makro!(…) #[macro_export] macro_rules! makro
|
||||
ma makro!(…) #[macro_export] macro_rules! makro
|
||||
|
@ -18,6 +18,9 @@ fn target_type_or_trait_in_impl_block() {
|
||||
impl Tra$0
|
||||
"#,
|
||||
expect![[r##"
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
tt Trait
|
||||
en Enum
|
||||
st Record
|
||||
@ -38,6 +41,9 @@ fn target_type_in_trait_impl_block() {
|
||||
impl Trait for Str$0
|
||||
"#,
|
||||
expect![[r##"
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
tt Trait
|
||||
en Enum
|
||||
st Record
|
||||
|
@ -16,6 +16,9 @@ fn predicate_start() {
|
||||
struct Foo<'lt, T, const C: usize> where $0 {}
|
||||
"#,
|
||||
expect![[r##"
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
tt Trait
|
||||
en Enum
|
||||
st Record
|
||||
@ -38,6 +41,9 @@ fn bound_for_type_pred() {
|
||||
struct Foo<'lt, T, const C: usize> where T: $0 {}
|
||||
"#,
|
||||
expect![[r##"
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
tt Trait
|
||||
md module
|
||||
ma makro!(…) #[macro_export] macro_rules! makro
|
||||
@ -54,6 +60,9 @@ fn bound_for_lifetime_pred() {
|
||||
struct Foo<'lt, T, const C: usize> where 'lt: $0 {}
|
||||
"#,
|
||||
expect![[r##"
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
tt Trait
|
||||
md module
|
||||
ma makro!(…) #[macro_export] macro_rules! makro
|
||||
@ -69,6 +78,9 @@ fn bound_for_for_pred() {
|
||||
struct Foo<'lt, T, const C: usize> where for<'a> T: $0 {}
|
||||
"#,
|
||||
expect![[r##"
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
tt Trait
|
||||
md module
|
||||
ma makro!(…) #[macro_export] macro_rules! makro
|
||||
@ -84,6 +96,9 @@ fn param_list_for_for_pred() {
|
||||
struct Foo<'lt, T, const C: usize> where for<'a> $0 {}
|
||||
"#,
|
||||
expect![[r##"
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
tt Trait
|
||||
en Enum
|
||||
st Record
|
||||
@ -107,6 +122,9 @@ fn method(self) where $0 {}
|
||||
}
|
||||
"#,
|
||||
expect![[r##"
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
sp Self
|
||||
tt Trait
|
||||
en Enum
|
||||
|
@ -30,6 +30,9 @@ struct Foo<'lt, T, const C: usize> {
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
sp Self
|
||||
tp T
|
||||
tt Trait
|
||||
@ -54,6 +57,9 @@ fn tuple_struct_field() {
|
||||
expect![[r#"
|
||||
kw pub(crate)
|
||||
kw pub
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
sp Self
|
||||
tp T
|
||||
tt Trait
|
||||
@ -76,6 +82,9 @@ fn fn_return_type() {
|
||||
fn x<'lt, T, const C: usize>() -> $0
|
||||
"#,
|
||||
expect![[r#"
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
tp T
|
||||
tt Trait
|
||||
en Enum
|
||||
@ -99,6 +108,9 @@ fn foo<'lt, T, const C: usize>() {
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
tp T
|
||||
tt Trait
|
||||
en Enum
|
||||
@ -140,6 +152,9 @@ trait Trait2 {
|
||||
fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {}
|
||||
"#,
|
||||
expect![[r#"
|
||||
kw self
|
||||
kw super
|
||||
kw crate
|
||||
ta Foo = (as Trait2) type Foo;
|
||||
tp T
|
||||
cp CONST_PARAM
|
||||
|
@ -22,11 +22,11 @@ mod foo {}
|
||||
// nothing here
|
||||
"#,
|
||||
expect![[r#"
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
md foo
|
||||
md other_crate
|
||||
kw self::
|
||||
kw super::
|
||||
kw crate::
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
@ -41,7 +41,6 @@ fn dont_complete_current_use() {
|
||||
use self::{foo::*, bar$0};
|
||||
"#,
|
||||
expect![[r#"
|
||||
kw self
|
||||
st S
|
||||
md foo
|
||||
"#]],
|
||||
@ -230,10 +229,10 @@ pub mod bar {}
|
||||
pub use $0;
|
||||
"#,
|
||||
expect![[r#"
|
||||
kw crate::
|
||||
md bar
|
||||
kw self::
|
||||
kw super::
|
||||
md bar
|
||||
kw crate::
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
@ -247,10 +246,10 @@ mod bar {}
|
||||
use {$0};
|
||||
"#,
|
||||
expect![[r#"
|
||||
kw crate::
|
||||
md bar
|
||||
kw self::
|
||||
kw super::
|
||||
md bar
|
||||
kw crate::
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user