mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 05:15:04 +00:00
Implement completion for associated items
This commit is contained in:
parent
37148000dc
commit
7e8527f748
7 changed files with 265 additions and 1 deletions
|
@ -174,4 +174,24 @@ impl Ty {
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This would be nicer if it just returned an iterator, but that runs into
|
||||||
|
// lifetime problems, because we need to borrow temp `CrateImplBlocks`.
|
||||||
|
pub fn iterate_impl_items<T>(
|
||||||
|
self,
|
||||||
|
db: &impl HirDatabase,
|
||||||
|
mut callback: impl FnMut(ImplItem) -> Option<T>,
|
||||||
|
) -> Option<T> {
|
||||||
|
let krate = def_crate(db, &self)?;
|
||||||
|
let impls = db.impls_in_crate(krate);
|
||||||
|
|
||||||
|
for (_, impl_block) in impls.lookup_impl_blocks(db, &self) {
|
||||||
|
for item in impl_block.items() {
|
||||||
|
if let Some(result) = callback(*item) {
|
||||||
|
return Some(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,3 +80,25 @@ pub fn function_label(node: &ast::FnDef) -> Option<String> {
|
||||||
|
|
||||||
Some(label.trim().to_owned())
|
Some(label.trim().to_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn const_label(node: &ast::ConstDef) -> String {
|
||||||
|
let label: String = node
|
||||||
|
.syntax()
|
||||||
|
.children()
|
||||||
|
.filter(|child| ast::Comment::cast(child).is_none())
|
||||||
|
.map(|node| node.text().to_string())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
label.trim().to_owned()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_label(node: &ast::TypeDef) -> String {
|
||||||
|
let label: String = node
|
||||||
|
.syntax()
|
||||||
|
.children()
|
||||||
|
.filter(|child| ast::Comment::cast(child).is_none())
|
||||||
|
.map(|node| node.text().to_string())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
label.trim().to_owned()
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use join_to_string::join;
|
use join_to_string::join;
|
||||||
use hir::{Docs, Resolution};
|
use hir::{Docs, Resolution};
|
||||||
use ra_syntax::AstNode;
|
use ra_syntax::{AstNode, ast::NameOwner};
|
||||||
use test_utils::tested_by;
|
use test_utils::tested_by;
|
||||||
|
|
||||||
use crate::completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext};
|
use crate::completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext};
|
||||||
|
@ -58,6 +58,51 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
hir::ModuleDef::Struct(s) => {
|
||||||
|
let ty = s.ty(ctx.db);
|
||||||
|
ty.iterate_impl_items(ctx.db, |item| match item {
|
||||||
|
hir::ImplItem::Method(func) => {
|
||||||
|
let sig = func.signature(ctx.db);
|
||||||
|
if !sig.has_self_param() {
|
||||||
|
CompletionItem::new(
|
||||||
|
CompletionKind::Reference,
|
||||||
|
ctx.source_range(),
|
||||||
|
sig.name().to_string(),
|
||||||
|
)
|
||||||
|
.from_function(ctx, func)
|
||||||
|
.kind(CompletionItemKind::Method)
|
||||||
|
.add_to(acc);
|
||||||
|
}
|
||||||
|
None::<()>
|
||||||
|
}
|
||||||
|
hir::ImplItem::Const(ct) => {
|
||||||
|
let source = ct.source(ctx.db);
|
||||||
|
if let Some(name) = source.1.name() {
|
||||||
|
CompletionItem::new(
|
||||||
|
CompletionKind::Reference,
|
||||||
|
ctx.source_range(),
|
||||||
|
name.text().to_string(),
|
||||||
|
)
|
||||||
|
.from_const(ctx, ct)
|
||||||
|
.add_to(acc);
|
||||||
|
}
|
||||||
|
None::<()>
|
||||||
|
}
|
||||||
|
hir::ImplItem::Type(ty) => {
|
||||||
|
let source = ty.source(ctx.db);
|
||||||
|
if let Some(name) = source.1.name() {
|
||||||
|
CompletionItem::new(
|
||||||
|
CompletionKind::Reference,
|
||||||
|
ctx.source_range(),
|
||||||
|
name.text().to_string(),
|
||||||
|
)
|
||||||
|
.from_type(ctx, ty)
|
||||||
|
.add_to(acc);
|
||||||
|
}
|
||||||
|
None::<()>
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -197,6 +242,63 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn completes_struct_associated_method() {
|
||||||
|
check_reference_completion(
|
||||||
|
"struct_associated_method",
|
||||||
|
"
|
||||||
|
//- /lib.rs
|
||||||
|
/// A Struct
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
impl S {
|
||||||
|
/// An associated method
|
||||||
|
fn m() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo() { let _ = S::<|> }
|
||||||
|
",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn completes_struct_associated_const() {
|
||||||
|
check_reference_completion(
|
||||||
|
"struct_associated_const",
|
||||||
|
"
|
||||||
|
//- /lib.rs
|
||||||
|
/// A Struct
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
impl S {
|
||||||
|
/// An associated const
|
||||||
|
const C: i32 = 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo() { let _ = S::<|> }
|
||||||
|
",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn completes_struct_associated_type() {
|
||||||
|
check_reference_completion(
|
||||||
|
"struct_associated_type",
|
||||||
|
"
|
||||||
|
//- /lib.rs
|
||||||
|
/// A Struct
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
impl S {
|
||||||
|
/// An associated type
|
||||||
|
type T = i32;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo() { let _ = S::<|> }
|
||||||
|
",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn completes_use_paths_across_crates() {
|
fn completes_use_paths_across_crates() {
|
||||||
check_reference_completion(
|
check_reference_completion(
|
||||||
|
|
|
@ -8,6 +8,8 @@ use test_utils::tested_by;
|
||||||
use crate::completion::{
|
use crate::completion::{
|
||||||
completion_context::CompletionContext,
|
completion_context::CompletionContext,
|
||||||
function_label,
|
function_label,
|
||||||
|
const_label,
|
||||||
|
type_label
|
||||||
};
|
};
|
||||||
|
|
||||||
/// `CompletionItem` describes a single completion variant in the editor pop-up.
|
/// `CompletionItem` describes a single completion variant in the editor pop-up.
|
||||||
|
@ -267,6 +269,28 @@ impl Builder {
|
||||||
self.kind = Some(CompletionItemKind::Function);
|
self.kind = Some(CompletionItemKind::Function);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn from_const(mut self, ctx: &CompletionContext, ct: hir::Const) -> Builder {
|
||||||
|
if let Some(docs) = ct.docs(ctx.db) {
|
||||||
|
self.documentation = Some(docs);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.detail = Some(const_item_label(ctx, ct));
|
||||||
|
self.kind = Some(CompletionItemKind::Const);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn from_type(mut self, ctx: &CompletionContext, ty: hir::Type) -> Builder {
|
||||||
|
if let Some(docs) = ty.docs(ctx.db) {
|
||||||
|
self.documentation = Some(docs);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.detail = Some(type_item_label(ctx, ty));
|
||||||
|
self.kind = Some(CompletionItemKind::TypeAlias);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Into<CompletionItem> for Builder {
|
impl<'a> Into<CompletionItem> for Builder {
|
||||||
|
@ -305,6 +329,16 @@ fn function_item_label(ctx: &CompletionContext, function: hir::Function) -> Opti
|
||||||
function_label(&node)
|
function_label(&node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn const_item_label(ctx: &CompletionContext, ct: hir::Const) -> String {
|
||||||
|
let node = ct.source(ctx.db).1;
|
||||||
|
const_label(&node)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn type_item_label(ctx: &CompletionContext, ty: hir::Type) -> String {
|
||||||
|
let node = ty.source(ctx.db).1;
|
||||||
|
type_label(&node)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> {
|
pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> {
|
||||||
use crate::mock_analysis::{single_file_with_position, analysis_and_position};
|
use crate::mock_analysis::{single_file_with_position, analysis_and_position};
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
---
|
||||||
|
created: "2019-02-12T09:57:51.107816726Z"
|
||||||
|
creator: insta@0.6.2
|
||||||
|
source: crates/ra_ide_api/src/completion/completion_item.rs
|
||||||
|
expression: kind_completions
|
||||||
|
---
|
||||||
|
[
|
||||||
|
CompletionItem {
|
||||||
|
completion_kind: Reference,
|
||||||
|
label: "C",
|
||||||
|
kind: Some(
|
||||||
|
Const
|
||||||
|
),
|
||||||
|
detail: Some(
|
||||||
|
"const C: i32 = 42;"
|
||||||
|
),
|
||||||
|
documentation: Some(
|
||||||
|
Documentation(
|
||||||
|
"An associated const"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
lookup: None,
|
||||||
|
insert_text: None,
|
||||||
|
insert_text_format: PlainText,
|
||||||
|
source_range: [107; 107),
|
||||||
|
text_edit: None
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,30 @@
|
||||||
|
---
|
||||||
|
created: "2019-02-12T09:57:51.106389138Z"
|
||||||
|
creator: insta@0.6.2
|
||||||
|
source: crates/ra_ide_api/src/completion/completion_item.rs
|
||||||
|
expression: kind_completions
|
||||||
|
---
|
||||||
|
[
|
||||||
|
CompletionItem {
|
||||||
|
completion_kind: Reference,
|
||||||
|
label: "m",
|
||||||
|
kind: Some(
|
||||||
|
Method
|
||||||
|
),
|
||||||
|
detail: Some(
|
||||||
|
"fn m()"
|
||||||
|
),
|
||||||
|
documentation: Some(
|
||||||
|
Documentation(
|
||||||
|
"An associated method"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
lookup: None,
|
||||||
|
insert_text: Some(
|
||||||
|
"m()$0"
|
||||||
|
),
|
||||||
|
insert_text_format: Snippet,
|
||||||
|
source_range: [100; 100),
|
||||||
|
text_edit: None
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,28 @@
|
||||||
|
---
|
||||||
|
created: "2019-02-12T09:33:54.719956203Z"
|
||||||
|
creator: insta@0.6.2
|
||||||
|
source: crates/ra_ide_api/src/completion/completion_item.rs
|
||||||
|
expression: kind_completions
|
||||||
|
---
|
||||||
|
[
|
||||||
|
CompletionItem {
|
||||||
|
completion_kind: Reference,
|
||||||
|
label: "T",
|
||||||
|
kind: Some(
|
||||||
|
TypeAlias
|
||||||
|
),
|
||||||
|
detail: Some(
|
||||||
|
"type T = i32;"
|
||||||
|
),
|
||||||
|
documentation: Some(
|
||||||
|
Documentation(
|
||||||
|
"An associated type"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
lookup: None,
|
||||||
|
insert_text: None,
|
||||||
|
insert_text_format: PlainText,
|
||||||
|
source_range: [101; 101),
|
||||||
|
text_edit: None
|
||||||
|
}
|
||||||
|
]
|
Loading…
Add table
Add a link
Reference in a new issue