Skip to content

Commit 8a2c5d2

Browse files
committed
Still in need of more test cases
1 parent 0df1153 commit 8a2c5d2

File tree

3 files changed

+65
-40
lines changed

3 files changed

+65
-40
lines changed

crates/ide-assists/src/handlers/add_missing_impl_members.rs

+38-6
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ use syntax::ast::{self, make, AstNode};
33

44
use crate::{
55
assist_context::{AssistContext, Assists},
6-
utils::{add_trait_assoc_items_to_impl, filter_assoc_items, gen_trait_fn_body, DefaultMethods},
6+
utils::{
7+
add_trait_assoc_items_to_impl, filter_assoc_items, gen_trait_fn_body, DefaultMethods,
8+
IgnoreAssocItems,
9+
},
710
AssistId, AssistKind,
811
};
912

@@ -43,7 +46,7 @@ pub(crate) fn add_missing_impl_members(acc: &mut Assists, ctx: &AssistContext<'_
4346
acc,
4447
ctx,
4548
DefaultMethods::No,
46-
true,
49+
IgnoreAssocItems::HiddenDocAttrPresent,
4750
"add_impl_missing_members",
4851
"Implement missing members",
4952
)
@@ -88,7 +91,7 @@ pub(crate) fn add_missing_default_members(
8891
acc,
8992
ctx,
9093
DefaultMethods::Only,
91-
true,
94+
IgnoreAssocItems::HiddenDocAttrPresent,
9295
"add_impl_default_members",
9396
"Implement default members",
9497
)
@@ -98,7 +101,7 @@ fn add_missing_impl_members_inner(
98101
acc: &mut Assists,
99102
ctx: &AssistContext<'_>,
100103
mode: DefaultMethods,
101-
ignore_hidden: bool,
104+
ignore_items: IgnoreAssocItems,
102105
assist_id: &'static str,
103106
label: &'static str,
104107
) -> Option<()> {
@@ -118,11 +121,22 @@ fn add_missing_impl_members_inner(
118121
let trait_ref = impl_.trait_ref(ctx.db())?;
119122
let trait_ = trait_ref.trait_();
120123

124+
let mut ign_item = ignore_items;
125+
126+
if let IgnoreAssocItems::HiddenDocAttrPresent = ignore_items {
127+
// Relax condition for local crates.
128+
129+
let db = ctx.db();
130+
if trait_.module(db).krate().origin(db).is_local() {
131+
ign_item = IgnoreAssocItems::No;
132+
}
133+
}
134+
121135
let missing_items = filter_assoc_items(
122136
&ctx.sema,
123137
&ide_db::traits::get_missing_assoc_items(&ctx.sema, &impl_def),
124138
mode,
125-
ignore_hidden,
139+
ign_item,
126140
);
127141

128142
if missing_items.is_empty() {
@@ -1999,10 +2013,28 @@ trait Trait {
19992013
}
20002014
}
20012015
impl Trait for Foo {
2002-
$0fn another_default_impl() -> u32 {
2016+
$0fn func_with_default_impl() -> u32 {
2017+
42
2018+
}
2019+
2020+
fn another_default_impl() -> u32 {
20032021
43
20042022
}
20052023
}"#,
20062024
)
20072025
}
2026+
2027+
#[test]
2028+
fn doc_hidden_default_impls_extern_crates() {
2029+
// Not applicable because Eq has a single method and this has a #[doc(hidden)] attr set.
2030+
check_assist_not_applicable(
2031+
add_missing_default_members,
2032+
r#"
2033+
//- minicore: eq
2034+
use core::cmp::Eq;
2035+
struct Foo;
2036+
impl E$0q for Foo { /* $0 */ }
2037+
"#,
2038+
)
2039+
}
20082040
}

crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{
1010
assist_context::{AssistContext, Assists, SourceChangeBuilder},
1111
utils::{
1212
add_trait_assoc_items_to_impl, filter_assoc_items, gen_trait_fn_body,
13-
generate_trait_impl_text, render_snippet, Cursor, DefaultMethods,
13+
generate_trait_impl_text, render_snippet, Cursor, DefaultMethods, IgnoreAssocItems,
1414
},
1515
AssistId, AssistKind,
1616
};
@@ -172,7 +172,17 @@ fn impl_def_from_trait(
172172
) -> Option<(ast::Impl, ast::AssocItem)> {
173173
let trait_ = trait_?;
174174
let target_scope = sema.scope(annotated_name.syntax())?;
175-
let trait_items = filter_assoc_items(sema, &trait_.items(sema.db), DefaultMethods::No, true);
175+
176+
// Keep assoc items of local crates even if they have #[doc(hidden)] attr.
177+
let ignore_items = if trait_.module(sema.db).krate().origin(sema.db).is_local() {
178+
IgnoreAssocItems::No
179+
} else {
180+
IgnoreAssocItems::HiddenDocAttrPresent
181+
};
182+
183+
let trait_items =
184+
filter_assoc_items(sema, &trait_.items(sema.db), DefaultMethods::No, ignore_items);
185+
176186
if trait_items.is_empty() {
177187
return None;
178188
}

crates/ide-assists/src/utils.rs

+15-32
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ pub fn test_related_attribute(fn_def: &ast::Fn) -> Option<ast::Attr> {
8484
})
8585
}
8686

87+
#[derive(Clone, Copy, PartialEq)]
88+
pub enum IgnoreAssocItems {
89+
HiddenDocAttrPresent,
90+
No,
91+
}
92+
8793
#[derive(Copy, Clone, PartialEq)]
8894
pub enum DefaultMethods {
8995
Only,
@@ -94,48 +100,25 @@ pub fn filter_assoc_items(
94100
sema: &Semantics<'_, RootDatabase>,
95101
items: &[hir::AssocItem],
96102
default_methods: DefaultMethods,
97-
ignore_hidden: bool,
103+
ignore_items: IgnoreAssocItems,
98104
) -> Vec<InFile<ast::AssocItem>> {
99-
// FIXME : How to use the closure below this so I can write sth like
100-
// sema.source(hide(it)?)?...
101-
102-
// let hide = |it: impl HasAttrs| {
103-
// if default_methods == DefaultMethods::IgnoreHidden && it.attrs(sema.db).has_doc_hidden() {
104-
// None;
105-
// }
106-
// Some(it)
107-
// };
108-
109105
return items
110106
.iter()
111-
// Note: This throws away items with no source.
112107
.copied()
108+
.filter(|assoc_item| {
109+
!(ignore_items == IgnoreAssocItems::HiddenDocAttrPresent
110+
&& assoc_item.attrs(sema.db).has_doc_hidden())
111+
})
113112
.filter_map(|assoc_item| {
114113
let item = match assoc_item {
115-
hir::AssocItem::Function(it) => {
116-
if ignore_hidden && it.attrs(sema.db).has_doc_hidden() {
117-
return None;
118-
}
119-
sema.source(it)?.map(ast::AssocItem::Fn)
120-
}
121-
hir::AssocItem::TypeAlias(it) => {
122-
if ignore_hidden && it.attrs(sema.db).has_doc_hidden() {
123-
return None;
124-
}
125-
126-
sema.source(it)?.map(ast::AssocItem::TypeAlias)
127-
}
128-
hir::AssocItem::Const(it) => {
129-
if ignore_hidden && it.attrs(sema.db).has_doc_hidden() {
130-
return None;
131-
}
132-
133-
sema.source(it)?.map(ast::AssocItem::Const)
134-
}
114+
hir::AssocItem::Function(it) => sema.source(it)?.map(ast::AssocItem::Fn),
115+
hir::AssocItem::TypeAlias(it) => sema.source(it)?.map(ast::AssocItem::TypeAlias),
116+
hir::AssocItem::Const(it) => sema.source(it)?.map(ast::AssocItem::Const),
135117
};
136118
Some(item)
137119
})
138120
.filter(has_def_name)
121+
// Note: This throws away items with no source.
139122
.filter(|it| match &it.value {
140123
ast::AssocItem::Fn(def) => matches!(
141124
(default_methods, def.body()),

0 commit comments

Comments
 (0)