mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 06:11:35 +00:00
Complete associated types in dyn and impl trait
This commit is contained in:
parent
863e23f00f
commit
ec9ef9c283
4 changed files with 64 additions and 10 deletions
|
@ -29,7 +29,7 @@ use crate::{
|
||||||
macro_::render_macro,
|
macro_::render_macro,
|
||||||
pattern::{render_struct_pat, render_variant_pat},
|
pattern::{render_struct_pat, render_variant_pat},
|
||||||
render_field, render_resolution, render_tuple_field,
|
render_field, render_resolution, render_tuple_field,
|
||||||
type_alias::render_type_alias,
|
type_alias::{render_type_alias, render_type_alias_with_eq},
|
||||||
RenderContext,
|
RenderContext,
|
||||||
},
|
},
|
||||||
CompletionContext, CompletionItem, CompletionItemKind,
|
CompletionContext, CompletionItem, CompletionItemKind,
|
||||||
|
@ -188,6 +188,14 @@ impl Completions {
|
||||||
self.add_opt(render_type_alias(RenderContext::new(ctx), type_alias));
|
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(
|
pub(crate) fn add_qualified_enum_variant(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
//! Completion of names from the current scope, e.g. locals and imported items.
|
//! Completion of names from the current scope, e.g. locals and imported items.
|
||||||
|
|
||||||
use hir::ScopeDef;
|
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) {
|
pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
if ctx.is_path_disallowed() || !ctx.is_trivial_path() {
|
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| {
|
ctx.scope.process_all_names(&mut |name, res| {
|
||||||
if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res {
|
if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res {
|
||||||
cov_mark::hit!(skip_lifetime_completion);
|
cov_mark::hit!(skip_lifetime_completion);
|
||||||
|
@ -777,4 +792,21 @@ $0
|
||||||
"#]],
|
"#]],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,9 @@ pub(crate) enum ImmediateLocation {
|
||||||
receiver_is_ambiguous_float_literal: bool,
|
receiver_is_ambiguous_float_literal: bool,
|
||||||
},
|
},
|
||||||
// Original file ast node
|
// 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
|
/// The record expr of the field name we are completing
|
||||||
RecordExpr(ast::RecordExpr),
|
RecordExpr(ast::RecordExpr),
|
||||||
// Original file ast node
|
// Original file ast node
|
||||||
|
@ -159,7 +162,6 @@ pub(crate) fn determine_location(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let res = match_ast! {
|
let res = match_ast! {
|
||||||
match parent {
|
match parent {
|
||||||
ast::IdentPat(_it) => ImmediateLocation::IdentPat,
|
ast::IdentPat(_it) => ImmediateLocation::IdentPat,
|
||||||
|
@ -174,6 +176,9 @@ pub(crate) fn determine_location(
|
||||||
Some(TRAIT) => ImmediateLocation::Trait,
|
Some(TRAIT) => ImmediateLocation::Trait,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
},
|
},
|
||||||
|
ast::GenericArgList(_it) => sema
|
||||||
|
.find_node_at_offset_with_macros(original_file, offset)
|
||||||
|
.map(ImmediateLocation::GenericArgList)?,
|
||||||
ast::Module(it) => {
|
ast::Module(it) => {
|
||||||
if it.item_list().is_none() {
|
if it.item_list().is_none() {
|
||||||
ImmediateLocation::ModDeclaration(it)
|
ImmediateLocation::ModDeclaration(it)
|
||||||
|
|
|
@ -16,7 +16,14 @@ pub(crate) fn render_type_alias<'a>(
|
||||||
ctx: RenderContext<'a>,
|
ctx: RenderContext<'a>,
|
||||||
type_alias: hir::TypeAlias,
|
type_alias: hir::TypeAlias,
|
||||||
) -> Option<CompletionItem> {
|
) -> 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)]
|
#[derive(Debug)]
|
||||||
|
@ -32,8 +39,14 @@ impl<'a> TypeAliasRender<'a> {
|
||||||
Some(TypeAliasRender { ctx, type_alias, ast_node })
|
Some(TypeAliasRender { ctx, type_alias, ast_node })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(self) -> Option<CompletionItem> {
|
fn render(self, with_eq: bool) -> Option<CompletionItem> {
|
||||||
let name = self.name()?;
|
let name = self.ast_node.name().map(|name| {
|
||||||
|
if with_eq {
|
||||||
|
format!("{} = ", name.text())
|
||||||
|
} else {
|
||||||
|
name.text().to_string()
|
||||||
|
}
|
||||||
|
})?;
|
||||||
let detail = self.detail();
|
let detail = self.detail();
|
||||||
|
|
||||||
let mut item =
|
let mut item =
|
||||||
|
@ -49,10 +62,6 @@ impl<'a> TypeAliasRender<'a> {
|
||||||
Some(item.build())
|
Some(item.build())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn name(&self) -> Option<String> {
|
|
||||||
self.ast_node.name().map(|name| name.text().to_string())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn detail(&self) -> String {
|
fn detail(&self) -> String {
|
||||||
type_label(&self.ast_node)
|
type_label(&self.ast_node)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue