Merge pull request #3506 from slyngbaek/3183

Next steps in assoc item completion #3183
This commit is contained in:
Aleksey Kladov 2020-03-10 17:45:57 +01:00 committed by GitHub
commit 34bc0f4f55
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -34,7 +34,7 @@
use hir::{self, Docs, HasSource};
use ra_assists::utils::get_missing_impl_items;
use ra_syntax::{
ast::{self, edit},
ast::{self, edit, ImplDef},
AstNode, SyntaxKind, SyntaxNode, TextRange,
};
use ra_text_edit::TextEdit;
@ -47,22 +47,22 @@ use crate::{
};
pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {
let trigger = ctx.token.ancestors().find(|p| match p.kind() {
SyntaxKind::FN_DEF
| SyntaxKind::TYPE_ALIAS_DEF
| SyntaxKind::CONST_DEF
| SyntaxKind::BLOCK_EXPR => true,
_ => false,
});
let impl_def = trigger
.as_ref()
.and_then(|node| node.parent())
.and_then(|node| node.parent())
.and_then(ast::ImplDef::cast);
if let (Some(trigger), Some(impl_def)) = (trigger, impl_def) {
if let Some((trigger, impl_def)) = completion_match(ctx) {
match trigger.kind() {
SyntaxKind::NAME_REF => {
get_missing_impl_items(&ctx.sema, &impl_def).iter().for_each(|item| match item {
hir::AssocItem::Function(fn_item) => {
add_function_impl(&trigger, acc, ctx, &fn_item)
}
hir::AssocItem::TypeAlias(type_item) => {
add_type_alias_impl(&trigger, acc, ctx, &type_item)
}
hir::AssocItem::Const(const_item) => {
add_const_impl(&trigger, acc, ctx, &const_item)
}
})
}
SyntaxKind::FN_DEF => {
for missing_fn in get_missing_impl_items(&ctx.sema, &impl_def).iter().filter_map(
|item| match item {
@ -101,6 +101,21 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext
}
}
fn completion_match(ctx: &CompletionContext) -> Option<(SyntaxNode, ImplDef)> {
let (trigger, impl_def_offset) = ctx.token.ancestors().find_map(|p| match p.kind() {
SyntaxKind::FN_DEF
| SyntaxKind::TYPE_ALIAS_DEF
| SyntaxKind::CONST_DEF
| SyntaxKind::BLOCK_EXPR => Some((p, 2)),
SyntaxKind::NAME_REF => Some((p, 5)),
_ => None,
})?;
let impl_def = (0..impl_def_offset - 1)
.try_fold(trigger.parent()?, |t, _| t.parent())
.and_then(ast::ImplDef::cast)?;
Some((trigger, impl_def))
}
fn add_function_impl(
fn_def_node: &SyntaxNode,
acc: &mut Completions,
@ -209,6 +224,103 @@ mod tests {
do_completion(code, CompletionKind::Magic)
}
#[test]
fn name_ref_function_type_const() {
let completions = complete(
r"
trait Test {
type TestType;
const TEST_CONST: u16;
fn test();
}
struct T1;
impl Test for T1 {
t<|>
}
",
);
assert_debug_snapshot!(completions, @r###"
[
CompletionItem {
label: "const TEST_CONST: u16 = ",
source_range: [209; 210),
delete: [209; 210),
insert: "const TEST_CONST: u16 = ",
kind: Const,
lookup: "TEST_CONST",
},
CompletionItem {
label: "fn test()",
source_range: [209; 210),
delete: [209; 210),
insert: "fn test() {}",
kind: Function,
lookup: "test",
},
CompletionItem {
label: "type TestType = ",
source_range: [209; 210),
delete: [209; 210),
insert: "type TestType = ",
kind: TypeAlias,
lookup: "TestType",
},
]
"###);
}
#[test]
fn no_nested_fn_completions() {
let completions = complete(
r"
trait Test {
fn test();
fn test2();
}
struct T1;
impl Test for T1 {
fn test() {
t<|>
}
}
",
);
assert_debug_snapshot!(completions, @r###"[]"###);
}
#[test]
fn name_ref_single_function() {
let completions = complete(
r"
trait Test {
fn test();
}
struct T1;
impl Test for T1 {
t<|>
}
",
);
assert_debug_snapshot!(completions, @r###"
[
CompletionItem {
label: "fn test()",
source_range: [139; 140),
delete: [139; 140),
insert: "fn test() {}",
kind: Function,
lookup: "test",
},
]
"###);
}
#[test]
fn single_function() {
let completions = complete(