Skip to content

Commit efc5a81

Browse files
committed
Auto merge of rust-lang#15050 - alibektas:14957, r=Veykril
bugfix : skip doc(hidden) default members fixes rust-lang#14957 . I have two questions : 1. I am definitely looking for a more idiomatic way for the things I added in `crates/ide-assists/src/utils.rs`. See `FIXME` in that file. 2. Would it be actually better to change `DefaultMethods` to something like ```rust enum DefaultMethods { Only( IgnoreHidden ( bool ) ) , None } ``` instead of adding a boolean to every function that calls `crates/ide-assists/src/utils.rs::filter_assoc_items`
2 parents 8202b5a + 915ddb0 commit efc5a81

File tree

3 files changed

+208
-5
lines changed

3 files changed

+208
-5
lines changed

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

+183-1
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,6 +46,7 @@ pub(crate) fn add_missing_impl_members(acc: &mut Assists, ctx: &AssistContext<'_
4346
acc,
4447
ctx,
4548
DefaultMethods::No,
49+
IgnoreAssocItems::DocHiddenAttrPresent,
4650
"add_impl_missing_members",
4751
"Implement missing members",
4852
)
@@ -87,6 +91,7 @@ pub(crate) fn add_missing_default_members(
8791
acc,
8892
ctx,
8993
DefaultMethods::Only,
94+
IgnoreAssocItems::DocHiddenAttrPresent,
9095
"add_impl_default_members",
9196
"Implement default members",
9297
)
@@ -96,6 +101,7 @@ fn add_missing_impl_members_inner(
96101
acc: &mut Assists,
97102
ctx: &AssistContext<'_>,
98103
mode: DefaultMethods,
104+
ignore_items: IgnoreAssocItems,
99105
assist_id: &'static str,
100106
label: &'static str,
101107
) -> Option<()> {
@@ -115,10 +121,21 @@ fn add_missing_impl_members_inner(
115121
let trait_ref = impl_.trait_ref(ctx.db())?;
116122
let trait_ = trait_ref.trait_();
117123

124+
let mut ign_item = ignore_items;
125+
126+
if let IgnoreAssocItems::DocHiddenAttrPresent = ignore_items {
127+
// Relax condition for local crates.
128+
let db = ctx.db();
129+
if trait_.module(db).krate().origin(db).is_local() {
130+
ign_item = IgnoreAssocItems::No;
131+
}
132+
}
133+
118134
let missing_items = filter_assoc_items(
119135
&ctx.sema,
120136
&ide_db::traits::get_missing_assoc_items(&ctx.sema, &impl_def),
121137
mode,
138+
ign_item,
122139
);
123140

124141
if missing_items.is_empty() {
@@ -1966,4 +1983,169 @@ impl AnotherTrait<i32> for () {
19661983
"#,
19671984
);
19681985
}
1986+
1987+
#[test]
1988+
fn doc_hidden_default_impls_ignored() {
1989+
// doc(hidden) attr is ignored trait and impl both belong to the local crate.
1990+
check_assist(
1991+
add_missing_default_members,
1992+
r#"
1993+
struct Foo;
1994+
trait Trait {
1995+
#[doc(hidden)]
1996+
fn func_with_default_impl() -> u32 {
1997+
42
1998+
}
1999+
fn another_default_impl() -> u32 {
2000+
43
2001+
}
2002+
}
2003+
impl Tra$0it for Foo {}"#,
2004+
r#"
2005+
struct Foo;
2006+
trait Trait {
2007+
#[doc(hidden)]
2008+
fn func_with_default_impl() -> u32 {
2009+
42
2010+
}
2011+
fn another_default_impl() -> u32 {
2012+
43
2013+
}
2014+
}
2015+
impl Trait for Foo {
2016+
$0fn func_with_default_impl() -> u32 {
2017+
42
2018+
}
2019+
2020+
fn another_default_impl() -> u32 {
2021+
43
2022+
}
2023+
}"#,
2024+
)
2025+
}
2026+
2027+
#[test]
2028+
fn doc_hidden_default_impls_lang_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+
}
2040+
2041+
#[test]
2042+
fn doc_hidden_default_impls_lib_crates() {
2043+
check_assist(
2044+
add_missing_default_members,
2045+
r#"
2046+
//- /main.rs crate:a deps:b
2047+
struct B;
2048+
impl b::Exte$0rnTrait for B {}
2049+
//- /lib.rs crate:b new_source_root:library
2050+
pub trait ExternTrait {
2051+
#[doc(hidden)]
2052+
fn hidden_default() -> Option<()> {
2053+
todo!()
2054+
}
2055+
2056+
fn unhidden_default() -> Option<()> {
2057+
todo!()
2058+
}
2059+
2060+
fn unhidden_nondefault() -> Option<()>;
2061+
}
2062+
"#,
2063+
r#"
2064+
struct B;
2065+
impl b::ExternTrait for B {
2066+
$0fn unhidden_default() -> Option<()> {
2067+
todo!()
2068+
}
2069+
}
2070+
"#,
2071+
)
2072+
}
2073+
2074+
#[test]
2075+
fn doc_hidden_default_impls_local_crates() {
2076+
check_assist(
2077+
add_missing_default_members,
2078+
r#"
2079+
trait LocalTrait {
2080+
#[doc(hidden)]
2081+
fn no_skip_default() -> Option<()> {
2082+
todo!()
2083+
}
2084+
fn no_skip_default_2() -> Option<()> {
2085+
todo!()
2086+
}
2087+
}
2088+
2089+
struct B;
2090+
impl Loc$0alTrait for B {}
2091+
"#,
2092+
r#"
2093+
trait LocalTrait {
2094+
#[doc(hidden)]
2095+
fn no_skip_default() -> Option<()> {
2096+
todo!()
2097+
}
2098+
fn no_skip_default_2() -> Option<()> {
2099+
todo!()
2100+
}
2101+
}
2102+
2103+
struct B;
2104+
impl LocalTrait for B {
2105+
$0fn no_skip_default() -> Option<()> {
2106+
todo!()
2107+
}
2108+
2109+
fn no_skip_default_2() -> Option<()> {
2110+
todo!()
2111+
}
2112+
}
2113+
"#,
2114+
)
2115+
}
2116+
2117+
#[test]
2118+
fn doc_hidden_default_impls_workspace_crates() {
2119+
check_assist(
2120+
add_missing_default_members,
2121+
r#"
2122+
//- /lib.rs crate:b new_source_root:local
2123+
trait LocalTrait {
2124+
#[doc(hidden)]
2125+
fn no_skip_default() -> Option<()> {
2126+
todo!()
2127+
}
2128+
fn no_skip_default_2() -> Option<()> {
2129+
todo!()
2130+
}
2131+
}
2132+
2133+
//- /main.rs crate:a deps:b
2134+
struct B;
2135+
impl b::Loc$0alTrait for B {}
2136+
"#,
2137+
r#"
2138+
struct B;
2139+
impl b::LocalTrait for B {
2140+
$0fn no_skip_default() -> Option<()> {
2141+
todo!()
2142+
}
2143+
2144+
fn no_skip_default_2() -> Option<()> {
2145+
todo!()
2146+
}
2147+
}
2148+
"#,
2149+
)
2150+
}
19692151
}

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);
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::DocHiddenAttrPresent
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

+13-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use std::ops;
44

55
pub(crate) use gen_trait_fn_body::gen_trait_fn_body;
6-
use hir::{db::HirDatabase, HirDisplay, InFile, Semantics};
6+
use hir::{db::HirDatabase, HasAttrs as HirHasAttrs, HirDisplay, InFile, Semantics};
77
use ide_db::{
88
famous_defs::FamousDefs, path_transform::PathTransform,
99
syntax_helpers::insert_whitespace_into_node::insert_ws_into, RootDatabase, SnippetCap,
@@ -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+
DocHiddenAttrPresent,
90+
No,
91+
}
92+
8793
#[derive(Copy, Clone, PartialEq)]
8894
pub enum DefaultMethods {
8995
Only,
@@ -94,11 +100,16 @@ pub fn filter_assoc_items(
94100
sema: &Semantics<'_, RootDatabase>,
95101
items: &[hir::AssocItem],
96102
default_methods: DefaultMethods,
103+
ignore_items: IgnoreAssocItems,
97104
) -> Vec<InFile<ast::AssocItem>> {
98105
return items
99106
.iter()
100-
// Note: This throws away items with no source.
101107
.copied()
108+
.filter(|assoc_item| {
109+
!(ignore_items == IgnoreAssocItems::DocHiddenAttrPresent
110+
&& assoc_item.attrs(sema.db).has_doc_hidden())
111+
})
112+
// Note: This throws away items with no source.
102113
.filter_map(|assoc_item| {
103114
let item = match assoc_item {
104115
hir::AssocItem::Function(it) => sema.source(it)?.map(ast::AssocItem::Fn),

0 commit comments

Comments
 (0)