9223: Complete associated types in dyn and impl trait r=Veykril a=Veykril

Fixes #9222
bors r+

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
bors[bot] 2021-06-11 21:13:28 +00:00 committed by GitHub
commit 72ea02869b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 10 deletions

View File

@ -29,7 +29,7 @@
macro_::render_macro,
pattern::{render_struct_pat, render_variant_pat},
render_field, render_resolution, render_tuple_field,
type_alias::render_type_alias,
type_alias::{render_type_alias, render_type_alias_with_eq},
RenderContext,
},
CompletionContext, CompletionItem, CompletionItemKind,
@ -188,6 +188,14 @@ pub(crate) fn add_type_alias(&mut self, ctx: &CompletionContext, type_alias: hir
self.add_opt(render_type_alias(RenderContext::new(ctx), type_alias));
}
pub(crate) fn add_type_alias_with_eq(
&mut self,
ctx: &CompletionContext,
type_alias: hir::TypeAlias,
) {
self.add_opt(render_type_alias_with_eq(RenderContext::new(ctx), type_alias));
}
pub(crate) fn add_qualified_enum_variant(
&mut self,
ctx: &CompletionContext,

View File

@ -1,8 +1,9 @@
//! Completion of names from the current scope, e.g. locals and imported items.
use hir::ScopeDef;
use syntax::{ast, AstNode};
use crate::{CompletionContext, Completions};
use crate::{patterns::ImmediateLocation, CompletionContext, Completions};
pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) {
if ctx.is_path_disallowed() || !ctx.is_trivial_path() {
@ -43,6 +44,20 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
});
}
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.scope.process_all_names(&mut |name, res| {
if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res {
cov_mark::hit!(skip_lifetime_completion);
@ -777,4 +792,21 @@ mod bar {}
"#]],
)
}
#[test]
fn completes_assoc_types_in_dynimpl_trait() {
check(
r#"
trait Foo {
type Bar;
}
fn foo(_: impl Foo<B$0>) {}
"#,
expect![[r#"
ta Bar = type Bar;
tt Foo
"#]],
);
}
}

View File

@ -47,6 +47,9 @@ pub(crate) enum ImmediateLocation {
receiver_is_ambiguous_float_literal: bool,
},
// Original file ast node
// Only set from a type arg
GenericArgList(ast::GenericArgList),
// Original file ast node
/// The record expr of the field name we are completing
RecordExpr(ast::RecordExpr),
// Original file ast node
@ -159,7 +162,6 @@ pub(crate) fn determine_location(
}
}
};
let res = match_ast! {
match parent {
ast::IdentPat(_it) => ImmediateLocation::IdentPat,
@ -174,6 +176,9 @@ pub(crate) fn determine_location(
Some(TRAIT) => ImmediateLocation::Trait,
_ => return None,
},
ast::GenericArgList(_it) => sema
.find_node_at_offset_with_macros(original_file, offset)
.map(ImmediateLocation::GenericArgList)?,
ast::Module(it) => {
if it.item_list().is_none() {
ImmediateLocation::ModDeclaration(it)

View File

@ -16,7 +16,14 @@ pub(crate) fn render_type_alias<'a>(
ctx: RenderContext<'a>,
type_alias: hir::TypeAlias,
) -> Option<CompletionItem> {
TypeAliasRender::new(ctx, type_alias)?.render()
TypeAliasRender::new(ctx, type_alias)?.render(false)
}
pub(crate) fn render_type_alias_with_eq<'a>(
ctx: RenderContext<'a>,
type_alias: hir::TypeAlias,
) -> Option<CompletionItem> {
TypeAliasRender::new(ctx, type_alias)?.render(true)
}
#[derive(Debug)]
@ -32,8 +39,14 @@ fn new(ctx: RenderContext<'a>, type_alias: hir::TypeAlias) -> Option<TypeAliasRe
Some(TypeAliasRender { ctx, type_alias, ast_node })
}
fn render(self) -> Option<CompletionItem> {
let name = self.name()?;
fn render(self, with_eq: bool) -> Option<CompletionItem> {
let name = self.ast_node.name().map(|name| {
if with_eq {
format!("{} = ", name.text())
} else {
name.text().to_string()
}
})?;
let detail = self.detail();
let mut item =
@ -49,10 +62,6 @@ fn render(self) -> Option<CompletionItem> {
Some(item.build())
}
fn name(&self) -> Option<String> {
self.ast_node.name().map(|name| name.text().to_string())
}
fn detail(&self) -> String {
type_label(&self.ast_node)
}