mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-22 08:12:04 +00:00
Deduplicate methods in completion by function ID and not by name
Because duplicates can be found with traits. Worse, the inherent methods could be private, and we'll discover that only later. But even if they're not they're different methods, and its seems worthy to present them all to the user.
This commit is contained in:
parent
21614ed2d3
commit
8a2e845e58
2 changed files with 47 additions and 8 deletions
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use hir::{Complete, HasContainer, ItemContainer, MethodCandidateCallback, Name};
|
||||
use hir::{Complete, Function, HasContainer, ItemContainer, MethodCandidateCallback};
|
||||
use ide_db::FxHashSet;
|
||||
use syntax::SmolStr;
|
||||
|
||||
|
@ -237,7 +237,10 @@ fn complete_methods(
|
|||
struct Callback<'a, F> {
|
||||
ctx: &'a CompletionContext<'a>,
|
||||
f: F,
|
||||
seen_methods: FxHashSet<Name>,
|
||||
// We deliberately deduplicate by function ID and not name, because while inherent methods cannot be
|
||||
// duplicated, trait methods can. And it is still useful to show all of them (even when there
|
||||
// is also an inherent method, especially considering that it may be private, and filtered later).
|
||||
seen_methods: FxHashSet<Function>,
|
||||
}
|
||||
|
||||
impl<F> MethodCandidateCallback for Callback<'_, F>
|
||||
|
@ -247,9 +250,7 @@ fn complete_methods(
|
|||
// We don't want to exclude inherent trait methods - that is, methods of traits available from
|
||||
// `where` clauses or `dyn Trait`.
|
||||
fn on_inherent_method(&mut self, func: hir::Function) -> ControlFlow<()> {
|
||||
if func.self_param(self.ctx.db).is_some()
|
||||
&& self.seen_methods.insert(func.name(self.ctx.db))
|
||||
{
|
||||
if func.self_param(self.ctx.db).is_some() && self.seen_methods.insert(func) {
|
||||
(self.f)(func);
|
||||
}
|
||||
ControlFlow::Continue(())
|
||||
|
@ -265,9 +266,7 @@ fn complete_methods(
|
|||
return ControlFlow::Continue(());
|
||||
}
|
||||
|
||||
if func.self_param(self.ctx.db).is_some()
|
||||
&& self.seen_methods.insert(func.name(self.ctx.db))
|
||||
{
|
||||
if func.self_param(self.ctx.db).is_some() && self.seen_methods.insert(func) {
|
||||
(self.f)(func);
|
||||
}
|
||||
|
||||
|
|
|
@ -2632,3 +2632,43 @@ fn let_in_condition() {
|
|||
fn let_in_let_chain() {
|
||||
check_edit("let", r#"fn f() { if true && $0 {} }"#, r#"fn f() { if true && let $1 = $0 {} }"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn private_inherent_and_public_trait() {
|
||||
check(
|
||||
r#"
|
||||
struct Foo;
|
||||
|
||||
mod private {
|
||||
impl super::Foo {
|
||||
fn method(&self) {}
|
||||
}
|
||||
}
|
||||
|
||||
trait Trait {
|
||||
fn method(&self) {}
|
||||
}
|
||||
impl Trait for Foo {}
|
||||
|
||||
fn main() {
|
||||
Foo.$0
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
me method() (as Trait) fn(&self)
|
||||
sn box Box::new(expr)
|
||||
sn call function(expr)
|
||||
sn const const {}
|
||||
sn dbg dbg!(expr)
|
||||
sn dbgr dbg!(&expr)
|
||||
sn deref *expr
|
||||
sn let let
|
||||
sn letm let mut
|
||||
sn match match expr {}
|
||||
sn ref &expr
|
||||
sn refm &mut expr
|
||||
sn return return expr
|
||||
sn unsafe unsafe {}
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue