mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-03 15:15:24 +00:00
Merge #9715
9715: feat: Make most completions respect `#[doc(hidden)]` r=jonas-schievink a=jonas-schievink Closes https://github.com/rust-analyzer/rust-analyzer/issues/2003 This continues https://github.com/rust-analyzer/rust-analyzer/pull/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 <jonasschievink@gmail.com>
This commit is contained in:
commit
1662c3470d
6 changed files with 165 additions and 10 deletions
|
@ -351,6 +351,20 @@ impl ModuleDef {
|
||||||
}
|
}
|
||||||
acc
|
acc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
|
||||||
|
Some(match self {
|
||||||
|
ModuleDef::Module(it) => it.attrs(db),
|
||||||
|
ModuleDef::Function(it) => it.attrs(db),
|
||||||
|
ModuleDef::Adt(it) => it.attrs(db),
|
||||||
|
ModuleDef::Variant(it) => it.attrs(db),
|
||||||
|
ModuleDef::Const(it) => it.attrs(db),
|
||||||
|
ModuleDef::Static(it) => it.attrs(db),
|
||||||
|
ModuleDef::Trait(it) => it.attrs(db),
|
||||||
|
ModuleDef::TypeAlias(it) => it.attrs(db),
|
||||||
|
ModuleDef::BuiltinType(_) => return None,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasVisibility for ModuleDef {
|
impl HasVisibility for ModuleDef {
|
||||||
|
@ -2725,6 +2739,32 @@ impl ScopeDef {
|
||||||
|
|
||||||
items
|
items
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
|
||||||
|
match self {
|
||||||
|
ScopeDef::ModuleDef(it) => it.attrs(db),
|
||||||
|
ScopeDef::MacroDef(it) => Some(it.attrs(db)),
|
||||||
|
ScopeDef::GenericParam(it) => Some(it.attrs(db)),
|
||||||
|
ScopeDef::ImplSelfType(_)
|
||||||
|
| ScopeDef::AdtSelfType(_)
|
||||||
|
| ScopeDef::Local(_)
|
||||||
|
| ScopeDef::Label(_)
|
||||||
|
| ScopeDef::Unknown => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn krate(&self, db: &dyn HirDatabase) -> Option<Crate> {
|
||||||
|
match self {
|
||||||
|
ScopeDef::ModuleDef(it) => it.module(db).map(|m| m.krate()),
|
||||||
|
ScopeDef::MacroDef(it) => it.module(db).map(|m| m.krate()),
|
||||||
|
ScopeDef::GenericParam(it) => Some(it.module(db).krate()),
|
||||||
|
ScopeDef::ImplSelfType(_) => None,
|
||||||
|
ScopeDef::AdtSelfType(it) => Some(it.module(db).krate()),
|
||||||
|
ScopeDef::Local(it) => Some(it.module(db).krate()),
|
||||||
|
ScopeDef::Label(it) => Some(it.module(db).krate()),
|
||||||
|
ScopeDef::Unknown => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ItemInNs> for ScopeDef {
|
impl From<ItemInNs> for ScopeDef {
|
||||||
|
|
|
@ -54,7 +54,7 @@ fn get_derive_names_in_scope(
|
||||||
ctx: &CompletionContext,
|
ctx: &CompletionContext,
|
||||||
) -> FxHashMap<String, Option<hir::Documentation>> {
|
) -> FxHashMap<String, Option<hir::Documentation>> {
|
||||||
let mut result = FxHashMap::default();
|
let mut result = FxHashMap::default();
|
||||||
ctx.scope.process_all_names(&mut |name, scope_def| {
|
ctx.process_all_names(&mut |name, scope_def| {
|
||||||
if let hir::ScopeDef::MacroDef(mac) = scope_def {
|
if let hir::ScopeDef::MacroDef(mac) = scope_def {
|
||||||
if mac.kind() == hir::MacroKind::Derive {
|
if mac.kind() == hir::MacroKind::Derive {
|
||||||
result.insert(name.to_string(), mac.docs(ctx.db));
|
result.insert(name.to_string(), mac.docs(ctx.db));
|
||||||
|
|
|
@ -22,7 +22,7 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
|
|
||||||
// FIXME: ideally, we should look at the type we are matching against and
|
// FIXME: ideally, we should look at the type we are matching against and
|
||||||
// suggest variants + auto-imports
|
// suggest variants + auto-imports
|
||||||
ctx.scope.process_all_names(&mut |name, res| {
|
ctx.process_all_names(&mut |name, res| {
|
||||||
let add_resolution = match &res {
|
let add_resolution = match &res {
|
||||||
hir::ScopeDef::ModuleDef(def) => match def {
|
hir::ScopeDef::ModuleDef(def) => match def {
|
||||||
hir::ModuleDef::Adt(hir::Adt::Struct(strukt)) => {
|
hir::ModuleDef::Adt(hir::Adt::Struct(strukt)) => {
|
||||||
|
|
|
@ -102,6 +102,11 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ctx.is_scope_def_hidden(&def) {
|
||||||
|
cov_mark::hit!(qualified_path_doc_hidden);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let add_resolution = match def {
|
let add_resolution = match def {
|
||||||
// Don't suggest attribute macros and derives.
|
// Don't suggest attribute macros and derives.
|
||||||
hir::ScopeDef::MacroDef(mac) => mac.is_fn_like(),
|
hir::ScopeDef::MacroDef(mac) => mac.is_fn_like(),
|
||||||
|
@ -119,7 +124,6 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
||||||
_ => true,
|
_ => true,
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: respect #[doc(hidden)] (see `CompletionContext::is_visible`)
|
|
||||||
if add_resolution {
|
if add_resolution {
|
||||||
acc.add_resolution(ctx, name, &def);
|
acc.add_resolution(ctx, name, &def);
|
||||||
}
|
}
|
||||||
|
@ -666,4 +670,34 @@ fn main() {
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn respects_doc_hidden() {
|
||||||
|
cov_mark::check!(qualified_path_doc_hidden);
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
//- /lib.rs crate:lib deps:dep
|
||||||
|
fn f() {
|
||||||
|
dep::$0
|
||||||
|
}
|
||||||
|
|
||||||
|
//- /dep.rs crate:dep
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! m {
|
||||||
|
() => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn f() {}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub struct S;
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub mod m {}
|
||||||
|
"#,
|
||||||
|
expect![[r#""#]],
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
|
||||||
if ctx.in_use_tree() {
|
if ctx.in_use_tree() {
|
||||||
// only show modules in a fresh UseTree
|
// only show modules in a fresh UseTree
|
||||||
cov_mark::hit!(unqualified_path_only_modules_in_import);
|
cov_mark::hit!(unqualified_path_only_modules_in_import);
|
||||||
ctx.scope.process_all_names(&mut |name, res| {
|
ctx.process_all_names(&mut |name, res| {
|
||||||
if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
|
if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
|
||||||
acc.add_resolution(ctx, name, &res);
|
acc.add_resolution(ctx, name, &res);
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
|
||||||
Some(ImmediateLocation::Visibility(_)) => return,
|
Some(ImmediateLocation::Visibility(_)) => return,
|
||||||
Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
|
Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
|
||||||
// only show macros in {Assoc}ItemList
|
// only show macros in {Assoc}ItemList
|
||||||
ctx.scope.process_all_names(&mut |name, res| {
|
ctx.process_all_names(&mut |name, res| {
|
||||||
if let hir::ScopeDef::MacroDef(mac) = res {
|
if let hir::ScopeDef::MacroDef(mac) = res {
|
||||||
if mac.is_fn_like() {
|
if mac.is_fn_like() {
|
||||||
acc.add_macro(ctx, Some(name.clone()), mac);
|
acc.add_macro(ctx, Some(name.clone()), mac);
|
||||||
|
@ -42,7 +42,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Some(ImmediateLocation::TypeBound) => {
|
Some(ImmediateLocation::TypeBound) => {
|
||||||
ctx.scope.process_all_names(&mut |name, res| {
|
ctx.process_all_names(&mut |name, res| {
|
||||||
let add_resolution = match res {
|
let add_resolution = match res {
|
||||||
ScopeDef::MacroDef(mac) => mac.is_fn_like(),
|
ScopeDef::MacroDef(mac) => mac.is_fn_like(),
|
||||||
ScopeDef::ModuleDef(hir::ModuleDef::Trait(_) | hir::ModuleDef::Module(_)) => {
|
ScopeDef::ModuleDef(hir::ModuleDef::Trait(_) | hir::ModuleDef::Module(_)) => {
|
||||||
|
@ -83,7 +83,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.scope.process_all_names(&mut |name, res| {
|
ctx.process_all_names(&mut |name, res| {
|
||||||
if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) | ScopeDef::Label(_) =
|
if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) | ScopeDef::Label(_) =
|
||||||
res
|
res
|
||||||
{
|
{
|
||||||
|
@ -252,4 +252,58 @@ pub mod prelude {
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn respects_doc_hidden() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
//- /lib.rs crate:lib deps:std
|
||||||
|
fn f() {
|
||||||
|
format_$0
|
||||||
|
}
|
||||||
|
|
||||||
|
//- /std.rs crate:std
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! format_args_nl {
|
||||||
|
() => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod prelude {
|
||||||
|
pub mod rust_2018 {}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
fn f() fn()
|
||||||
|
md std
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn respects_doc_hidden_in_assoc_item_list() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
//- /lib.rs crate:lib deps:std
|
||||||
|
struct S;
|
||||||
|
impl S {
|
||||||
|
format_$0
|
||||||
|
}
|
||||||
|
|
||||||
|
//- /std.rs crate:std
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! format_args_nl {
|
||||||
|
() => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod prelude {
|
||||||
|
pub mod rust_2018 {}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
md std
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! See `CompletionContext` structure.
|
//! See `CompletionContext` structure.
|
||||||
|
|
||||||
use base_db::SourceDatabaseExt;
|
use base_db::SourceDatabaseExt;
|
||||||
use hir::{Local, ScopeDef, Semantics, SemanticsScope, Type};
|
use hir::{Local, Name, ScopeDef, Semantics, SemanticsScope, Type};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
base_db::{FilePosition, SourceDatabase},
|
base_db::{FilePosition, SourceDatabase},
|
||||||
call_info::ActiveParameter,
|
call_info::ActiveParameter,
|
||||||
|
@ -370,6 +370,25 @@ impl<'a> CompletionContext<'a> {
|
||||||
self.is_visible_impl(&item.visibility(self.db), &item.attrs(self.db), item.krate(self.db))
|
self.is_visible_impl(&item.visibility(self.db), &item.attrs(self.db), item.krate(self.db))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn is_scope_def_hidden(&self, scope_def: &ScopeDef) -> bool {
|
||||||
|
if let (Some(attrs), Some(krate)) = (scope_def.attrs(self.db), scope_def.krate(self.db)) {
|
||||||
|
return self.is_doc_hidden(&attrs, krate);
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A version of [`SemanticsScope::process_all_names`] that filters out `#[doc(hidden)]` items.
|
||||||
|
pub(crate) fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef)) {
|
||||||
|
self.scope.process_all_names(&mut |name, def| {
|
||||||
|
if self.is_scope_def_hidden(&def) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
f(name, def);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn is_visible_impl(
|
fn is_visible_impl(
|
||||||
&self,
|
&self,
|
||||||
vis: &hir::Visibility,
|
vis: &hir::Visibility,
|
||||||
|
@ -388,12 +407,20 @@ impl<'a> CompletionContext<'a> {
|
||||||
return is_editable;
|
return is_editable;
|
||||||
}
|
}
|
||||||
|
|
||||||
if module.krate() != defining_crate && attrs.has_doc_hidden() {
|
!self.is_doc_hidden(attrs, defining_crate)
|
||||||
// `doc(hidden)` items are only completed within the defining crate.
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
fn is_doc_hidden(&self, attrs: &hir::Attrs, defining_crate: hir::Crate) -> bool {
|
||||||
|
let module = match self.scope.module() {
|
||||||
|
Some(it) => it,
|
||||||
|
None => return true,
|
||||||
|
};
|
||||||
|
if module.krate() != defining_crate && attrs.has_doc_hidden() {
|
||||||
|
// `doc(hidden)` items are only completed within the defining crate.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill_impl_def(&mut self) {
|
fn fill_impl_def(&mut self) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue