Skip to content

Commit 1662c34

Browse files
Merge #9715
9715: feat: Make most completions respect `#[doc(hidden)]` r=jonas-schievink a=jonas-schievink Closes #2003 This continues #9681 and makes most other completion sources respect `#[doc(hidden)]`. After this, only flyimport is missing support for this. bors r+ Co-authored-by: Jonas Schievink <[email protected]>
2 parents 33dcc89 + 0fbf396 commit 1662c34

File tree

6 files changed

+165
-10
lines changed

6 files changed

+165
-10
lines changed

crates/hir/src/lib.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,20 @@ impl ModuleDef {
351351
}
352352
acc
353353
}
354+
355+
pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
356+
Some(match self {
357+
ModuleDef::Module(it) => it.attrs(db),
358+
ModuleDef::Function(it) => it.attrs(db),
359+
ModuleDef::Adt(it) => it.attrs(db),
360+
ModuleDef::Variant(it) => it.attrs(db),
361+
ModuleDef::Const(it) => it.attrs(db),
362+
ModuleDef::Static(it) => it.attrs(db),
363+
ModuleDef::Trait(it) => it.attrs(db),
364+
ModuleDef::TypeAlias(it) => it.attrs(db),
365+
ModuleDef::BuiltinType(_) => return None,
366+
})
367+
}
354368
}
355369

356370
impl HasVisibility for ModuleDef {
@@ -2725,6 +2739,32 @@ impl ScopeDef {
27252739

27262740
items
27272741
}
2742+
2743+
pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
2744+
match self {
2745+
ScopeDef::ModuleDef(it) => it.attrs(db),
2746+
ScopeDef::MacroDef(it) => Some(it.attrs(db)),
2747+
ScopeDef::GenericParam(it) => Some(it.attrs(db)),
2748+
ScopeDef::ImplSelfType(_)
2749+
| ScopeDef::AdtSelfType(_)
2750+
| ScopeDef::Local(_)
2751+
| ScopeDef::Label(_)
2752+
| ScopeDef::Unknown => None,
2753+
}
2754+
}
2755+
2756+
pub fn krate(&self, db: &dyn HirDatabase) -> Option<Crate> {
2757+
match self {
2758+
ScopeDef::ModuleDef(it) => it.module(db).map(|m| m.krate()),
2759+
ScopeDef::MacroDef(it) => it.module(db).map(|m| m.krate()),
2760+
ScopeDef::GenericParam(it) => Some(it.module(db).krate()),
2761+
ScopeDef::ImplSelfType(_) => None,
2762+
ScopeDef::AdtSelfType(it) => Some(it.module(db).krate()),
2763+
ScopeDef::Local(it) => Some(it.module(db).krate()),
2764+
ScopeDef::Label(it) => Some(it.module(db).krate()),
2765+
ScopeDef::Unknown => None,
2766+
}
2767+
}
27282768
}
27292769

27302770
impl From<ItemInNs> for ScopeDef {

crates/ide_completion/src/completions/attribute/derive.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ fn get_derive_names_in_scope(
5454
ctx: &CompletionContext,
5555
) -> FxHashMap<String, Option<hir::Documentation>> {
5656
let mut result = FxHashMap::default();
57-
ctx.scope.process_all_names(&mut |name, scope_def| {
57+
ctx.process_all_names(&mut |name, scope_def| {
5858
if let hir::ScopeDef::MacroDef(mac) = scope_def {
5959
if mac.kind() == hir::MacroKind::Derive {
6060
result.insert(name.to_string(), mac.docs(ctx.db));

crates/ide_completion/src/completions/pattern.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
2222

2323
// FIXME: ideally, we should look at the type we are matching against and
2424
// suggest variants + auto-imports
25-
ctx.scope.process_all_names(&mut |name, res| {
25+
ctx.process_all_names(&mut |name, res| {
2626
let add_resolution = match &res {
2727
hir::ScopeDef::ModuleDef(def) => match def {
2828
hir::ModuleDef::Adt(hir::Adt::Struct(strukt)) => {

crates/ide_completion/src/completions/qualified_path.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
102102
}
103103
}
104104

105+
if ctx.is_scope_def_hidden(&def) {
106+
cov_mark::hit!(qualified_path_doc_hidden);
107+
continue;
108+
}
109+
105110
let add_resolution = match def {
106111
// Don't suggest attribute macros and derives.
107112
hir::ScopeDef::MacroDef(mac) => mac.is_fn_like(),
@@ -119,7 +124,6 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
119124
_ => true,
120125
};
121126

122-
// FIXME: respect #[doc(hidden)] (see `CompletionContext::is_visible`)
123127
if add_resolution {
124128
acc.add_resolution(ctx, name, &def);
125129
}
@@ -666,4 +670,34 @@ fn main() {
666670
"#]],
667671
);
668672
}
673+
674+
#[test]
675+
fn respects_doc_hidden() {
676+
cov_mark::check!(qualified_path_doc_hidden);
677+
check(
678+
r#"
679+
//- /lib.rs crate:lib deps:dep
680+
fn f() {
681+
dep::$0
682+
}
683+
684+
//- /dep.rs crate:dep
685+
#[doc(hidden)]
686+
#[macro_export]
687+
macro_rules! m {
688+
() => {}
689+
}
690+
691+
#[doc(hidden)]
692+
pub fn f() {}
693+
694+
#[doc(hidden)]
695+
pub struct S;
696+
697+
#[doc(hidden)]
698+
pub mod m {}
699+
"#,
700+
expect![[r#""#]],
701+
)
702+
}
669703
}

crates/ide_completion/src/completions/unqualified_path.rs

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
1313
if ctx.in_use_tree() {
1414
// only show modules in a fresh UseTree
1515
cov_mark::hit!(unqualified_path_only_modules_in_import);
16-
ctx.scope.process_all_names(&mut |name, res| {
16+
ctx.process_all_names(&mut |name, res| {
1717
if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
1818
acc.add_resolution(ctx, name, &res);
1919
}
@@ -29,7 +29,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
2929
Some(ImmediateLocation::Visibility(_)) => return,
3030
Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
3131
// only show macros in {Assoc}ItemList
32-
ctx.scope.process_all_names(&mut |name, res| {
32+
ctx.process_all_names(&mut |name, res| {
3333
if let hir::ScopeDef::MacroDef(mac) = res {
3434
if mac.is_fn_like() {
3535
acc.add_macro(ctx, Some(name.clone()), mac);
@@ -42,7 +42,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
4242
return;
4343
}
4444
Some(ImmediateLocation::TypeBound) => {
45-
ctx.scope.process_all_names(&mut |name, res| {
45+
ctx.process_all_names(&mut |name, res| {
4646
let add_resolution = match res {
4747
ScopeDef::MacroDef(mac) => mac.is_fn_like(),
4848
ScopeDef::ModuleDef(hir::ModuleDef::Trait(_) | hir::ModuleDef::Module(_)) => {
@@ -83,7 +83,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
8383
}
8484
}
8585

86-
ctx.scope.process_all_names(&mut |name, res| {
86+
ctx.process_all_names(&mut |name, res| {
8787
if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) | ScopeDef::Label(_) =
8888
res
8989
{
@@ -252,4 +252,58 @@ pub mod prelude {
252252
"#]],
253253
);
254254
}
255+
256+
#[test]
257+
fn respects_doc_hidden() {
258+
check(
259+
r#"
260+
//- /lib.rs crate:lib deps:std
261+
fn f() {
262+
format_$0
263+
}
264+
265+
//- /std.rs crate:std
266+
#[doc(hidden)]
267+
#[macro_export]
268+
macro_rules! format_args_nl {
269+
() => {}
270+
}
271+
272+
pub mod prelude {
273+
pub mod rust_2018 {}
274+
}
275+
"#,
276+
expect![[r#"
277+
fn f() fn()
278+
md std
279+
"#]],
280+
);
281+
}
282+
283+
#[test]
284+
fn respects_doc_hidden_in_assoc_item_list() {
285+
check(
286+
r#"
287+
//- /lib.rs crate:lib deps:std
288+
struct S;
289+
impl S {
290+
format_$0
291+
}
292+
293+
//- /std.rs crate:std
294+
#[doc(hidden)]
295+
#[macro_export]
296+
macro_rules! format_args_nl {
297+
() => {}
298+
}
299+
300+
pub mod prelude {
301+
pub mod rust_2018 {}
302+
}
303+
"#,
304+
expect![[r#"
305+
md std
306+
"#]],
307+
);
308+
}
255309
}

crates/ide_completion/src/context.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! See `CompletionContext` structure.
22
33
use base_db::SourceDatabaseExt;
4-
use hir::{Local, ScopeDef, Semantics, SemanticsScope, Type};
4+
use hir::{Local, Name, ScopeDef, Semantics, SemanticsScope, Type};
55
use ide_db::{
66
base_db::{FilePosition, SourceDatabase},
77
call_info::ActiveParameter,
@@ -370,6 +370,25 @@ impl<'a> CompletionContext<'a> {
370370
self.is_visible_impl(&item.visibility(self.db), &item.attrs(self.db), item.krate(self.db))
371371
}
372372

373+
pub(crate) fn is_scope_def_hidden(&self, scope_def: &ScopeDef) -> bool {
374+
if let (Some(attrs), Some(krate)) = (scope_def.attrs(self.db), scope_def.krate(self.db)) {
375+
return self.is_doc_hidden(&attrs, krate);
376+
}
377+
378+
false
379+
}
380+
381+
/// A version of [`SemanticsScope::process_all_names`] that filters out `#[doc(hidden)]` items.
382+
pub(crate) fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef)) {
383+
self.scope.process_all_names(&mut |name, def| {
384+
if self.is_scope_def_hidden(&def) {
385+
return;
386+
}
387+
388+
f(name, def);
389+
})
390+
}
391+
373392
fn is_visible_impl(
374393
&self,
375394
vis: &hir::Visibility,
@@ -388,12 +407,20 @@ impl<'a> CompletionContext<'a> {
388407
return is_editable;
389408
}
390409

410+
!self.is_doc_hidden(attrs, defining_crate)
411+
}
412+
413+
fn is_doc_hidden(&self, attrs: &hir::Attrs, defining_crate: hir::Crate) -> bool {
414+
let module = match self.scope.module() {
415+
Some(it) => it,
416+
None => return true,
417+
};
391418
if module.krate() != defining_crate && attrs.has_doc_hidden() {
392419
// `doc(hidden)` items are only completed within the defining crate.
393-
return false;
420+
return true;
394421
}
395422

396-
true
423+
false
397424
}
398425

399426
fn fill_impl_def(&mut self) {

0 commit comments

Comments
 (0)