Skip to content

Commit 44cf174

Browse files
committed
Auto merge of #15473 - Veykril:doc-hidden-imports, r=Veykril
fix: Fix auto-import (and completions) importing `#[doc(hidden)]` items Fixes #9197 and #9911 Turns out while #15472 didn't give access to the import stuff to the IDE layer, these can be fixed already since they use the import map which works in the hir-def crate 🎉
2 parents 49716e6 + 637f496 commit 44cf174

File tree

7 files changed

+155
-16
lines changed

7 files changed

+155
-16
lines changed

crates/hir-def/src/find_path.rs

+49
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ fn find_path_for_module(
224224
)
225225
}
226226

227+
// FIXME: Do we still need this now that we record import origins, and hence aliases?
227228
fn find_in_scope(
228229
db: &dyn DefDatabase,
229230
def_map: &DefMap,
@@ -346,6 +347,11 @@ fn calculate_best_path(
346347
let extern_paths = crate_graph[from.krate].dependencies.iter().filter_map(|dep| {
347348
let import_map = db.import_map(dep.crate_id);
348349
import_map.import_info_for(item).and_then(|info| {
350+
if info.is_doc_hidden {
351+
// the item or import is `#[doc(hidden)]`, so skip it as it is in an external crate
352+
return None;
353+
}
354+
349355
// Determine best path for containing module and append last segment from `info`.
350356
// FIXME: we should guide this to look up the path locally, or from the same crate again?
351357
let mut path = find_path_for_module(
@@ -1311,4 +1317,47 @@ pub struct S;
13111317
"intermediate::std_renamed::S",
13121318
);
13131319
}
1320+
1321+
#[test]
1322+
fn different_crate_doc_hidden() {
1323+
check_found_path(
1324+
r#"
1325+
//- /main.rs crate:main deps:intermediate
1326+
$0
1327+
//- /intermediate.rs crate:intermediate deps:std
1328+
#[doc(hidden)]
1329+
pub extern crate std;
1330+
pub extern crate std as longer;
1331+
//- /std.rs crate:std
1332+
pub struct S;
1333+
"#,
1334+
"intermediate::longer::S",
1335+
"intermediate::longer::S",
1336+
"intermediate::longer::S",
1337+
"intermediate::longer::S",
1338+
);
1339+
}
1340+
1341+
#[test]
1342+
fn respect_doc_hidden() {
1343+
check_found_path(
1344+
r#"
1345+
//- /main.rs crate:main deps:std,lazy_static
1346+
$0
1347+
//- /lazy_static.rs crate:lazy_static deps:core
1348+
#[doc(hidden)]
1349+
pub use core::ops::Deref as __Deref;
1350+
//- /std.rs crate:std deps:core
1351+
pub use core::ops;
1352+
//- /core.rs crate:core
1353+
pub mod ops {
1354+
pub trait Deref {}
1355+
}
1356+
"#,
1357+
"std::ops::Deref",
1358+
"std::ops::Deref",
1359+
"std::ops::Deref",
1360+
"std::ops::Deref",
1361+
);
1362+
}
13141363
}

crates/hir-def/src/import_map.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use itertools::Itertools;
1111
use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
1212
use triomphe::Arc;
1313

14+
use crate::item_scope::ImportOrExternCrate;
1415
use crate::{
1516
db::DefDatabase, item_scope::ItemInNs, nameres::DefMap, visibility::Visibility, AssocItemId,
1617
ModuleDefId, ModuleId, TraitId,
@@ -29,6 +30,8 @@ pub struct ImportInfo {
2930
pub container: ModuleId,
3031
/// Whether the import is a trait associated item or not.
3132
pub is_trait_assoc_item: bool,
33+
/// Whether this item is annotated with `#[doc(hidden)]`.
34+
pub is_doc_hidden: bool,
3235
}
3336

3437
/// A map from publicly exported items to its name.
@@ -113,14 +116,27 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> FxIndexMap<ItemIn
113116
});
114117

115118
for (name, per_ns) in visible_items {
116-
for item in per_ns.iter_items() {
119+
for (item, import) in per_ns.iter_items() {
117120
// FIXME: Not yet used, but will be once we handle doc(hidden) import sources
118-
let is_doc_hidden = false;
121+
let attr_id = if let Some(import) = import {
122+
match import {
123+
ImportOrExternCrate::ExternCrate(id) => Some(id.into()),
124+
ImportOrExternCrate::Import(id) => Some(id.import.into()),
125+
}
126+
} else {
127+
match item {
128+
ItemInNs::Types(id) | ItemInNs::Values(id) => id.try_into().ok(),
129+
ItemInNs::Macros(id) => Some(id.into()),
130+
}
131+
};
132+
let is_doc_hidden =
133+
attr_id.map_or(false, |attr_id| db.attrs(attr_id).has_doc_hidden());
119134

120135
let import_info = ImportInfo {
121136
name: name.clone(),
122137
container: module,
123138
is_trait_assoc_item: false,
139+
is_doc_hidden,
124140
};
125141

126142
match depth_map.entry(item) {
@@ -171,10 +187,10 @@ fn collect_trait_assoc_items(
171187
trait_import_info: &ImportInfo,
172188
) {
173189
let _p = profile::span("collect_trait_assoc_items");
174-
for (assoc_item_name, item) in &db.trait_data(tr).items {
190+
for &(ref assoc_item_name, item) in &db.trait_data(tr).items {
175191
let module_def_id = match item {
176-
AssocItemId::FunctionId(f) => ModuleDefId::from(*f),
177-
AssocItemId::ConstId(c) => ModuleDefId::from(*c),
192+
AssocItemId::FunctionId(f) => ModuleDefId::from(f),
193+
AssocItemId::ConstId(c) => ModuleDefId::from(c),
178194
// cannot use associated type aliases directly: need a `<Struct as Trait>::TypeAlias`
179195
// qualifier, ergo no need to store it for imports in import_map
180196
AssocItemId::TypeAliasId(_) => {
@@ -192,6 +208,7 @@ fn collect_trait_assoc_items(
192208
container: trait_import_info.container,
193209
name: assoc_item_name.clone(),
194210
is_trait_assoc_item: true,
211+
is_doc_hidden: db.attrs(item.into()).has_doc_hidden(),
195212
};
196213
map.insert(assoc_item, assoc_item_info);
197214
}

crates/hir-def/src/item_scope.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ pub struct ItemScope {
6666
_c: Count<Self>,
6767

6868
/// Defs visible in this scope. This includes `declarations`, but also
69-
/// imports.
69+
/// imports. The imports belong to this module and can be resolved by using them on
70+
/// the `use_imports_*` fields.
7071
types: FxHashMap<Name, (ModuleDefId, Visibility, Option<ImportOrExternCrate>)>,
7172
values: FxHashMap<Name, (ModuleDefId, Visibility, Option<ImportId>)>,
7273
macros: FxHashMap<Name, (MacroId, Visibility, Option<ImportId>)>,
@@ -375,8 +376,8 @@ impl ItemScope {
375376
None | Some(ImportType::Glob(_)) => None,
376377
};
377378
let prev = std::mem::replace(&mut fld.2, import);
378-
if let Some(ImportOrExternCrate::Import(import)) = import {
379-
self.use_imports_values.insert(
379+
if let Some(import) = import {
380+
self.use_imports_types.insert(
380381
import,
381382
match prev {
382383
Some(ImportOrExternCrate::Import(import)) => {
@@ -404,8 +405,8 @@ impl ItemScope {
404405
None | Some(ImportType::Glob(_)) => None,
405406
};
406407
let prev = std::mem::replace(&mut fld.2, import);
407-
if let Some(ImportOrExternCrate::Import(import)) = import {
408-
self.use_imports_values.insert(
408+
if let Some(import) = import {
409+
self.use_imports_types.insert(
409410
import,
410411
match prev {
411412
Some(ImportOrExternCrate::Import(import)) => {

crates/hir-def/src/lib.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -870,7 +870,8 @@ impl_from!(
870870
MacroId(Macro2Id, MacroRulesId, ProcMacroId),
871871
ImplId,
872872
GenericParamId,
873-
ExternCrateId
873+
ExternCrateId,
874+
UseId
874875
for AttrDefId
875876
);
876877

@@ -904,6 +905,15 @@ impl From<ItemContainerId> for AttrDefId {
904905
}
905906
}
906907
}
908+
impl From<AssocItemId> for AttrDefId {
909+
fn from(assoc: AssocItemId) -> Self {
910+
match assoc {
911+
AssocItemId::FunctionId(it) => AttrDefId::FunctionId(it),
912+
AssocItemId::ConstId(it) => AttrDefId::ConstId(it),
913+
AssocItemId::TypeAliasId(it) => AttrDefId::TypeAliasId(it),
914+
}
915+
}
916+
}
907917

908918
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
909919
pub enum VariantId {

crates/hir-def/src/per_ns.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,20 @@ impl PerNs {
117117
}
118118
}
119119

120-
pub fn iter_items(self) -> impl Iterator<Item = ItemInNs> {
120+
pub fn iter_items(self) -> impl Iterator<Item = (ItemInNs, Option<ImportOrExternCrate>)> {
121121
let _p = profile::span("PerNs::iter_items");
122122
self.types
123-
.map(|it| ItemInNs::Types(it.0))
123+
.map(|it| (ItemInNs::Types(it.0), it.2))
124124
.into_iter()
125-
.chain(self.values.map(|it| ItemInNs::Values(it.0)).into_iter())
126-
.chain(self.macros.map(|it| ItemInNs::Macros(it.0)).into_iter())
125+
.chain(
126+
self.values
127+
.map(|it| (ItemInNs::Values(it.0), it.2.map(ImportOrExternCrate::Import)))
128+
.into_iter(),
129+
)
130+
.chain(
131+
self.macros
132+
.map(|it| (ItemInNs::Macros(it.0), it.2.map(ImportOrExternCrate::Import)))
133+
.into_iter(),
134+
)
127135
}
128136
}

crates/hir/src/attrs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ fn resolve_doc_path(
212212
Some(Namespace::Types) => resolved.take_types(),
213213
Some(Namespace::Values) => resolved.take_values(),
214214
Some(Namespace::Macros) => resolved.take_macros().map(ModuleDefId::MacroId),
215-
None => resolved.iter_items().next().map(|it| match it {
215+
None => resolved.iter_items().next().map(|(it, _)| match it {
216216
ItemInNs::Types(it) => it,
217217
ItemInNs::Values(it) => it,
218218
ItemInNs::Macros(it) => ModuleDefId::MacroId(it),

crates/ide-completion/src/tests/flyimport.rs

+54
Original file line numberDiff line numberDiff line change
@@ -1286,3 +1286,57 @@ macro_rules! println {
12861286
expect![""],
12871287
)
12881288
}
1289+
1290+
#[test]
1291+
fn no_completions_for_external_doc_hidden_in_path() {
1292+
check(
1293+
r#"
1294+
//- /main.rs crate:main deps:dep
1295+
fn main() {
1296+
Span$0
1297+
}
1298+
//- /lib.rs crate:dep
1299+
#[doc(hidden)]
1300+
pub mod bridge {
1301+
pub mod server {
1302+
pub trait Span
1303+
}
1304+
}
1305+
pub mod bridge2 {
1306+
#[doc(hidden)]
1307+
pub mod server2 {
1308+
pub trait Span
1309+
}
1310+
}
1311+
"#,
1312+
expect![""],
1313+
);
1314+
// unless re-exported
1315+
check(
1316+
r#"
1317+
//- /main.rs crate:main deps:dep
1318+
fn main() {
1319+
Span$0
1320+
}
1321+
//- /lib.rs crate:dep
1322+
#[doc(hidden)]
1323+
pub mod bridge {
1324+
pub mod server {
1325+
pub trait Span
1326+
}
1327+
}
1328+
pub use bridge::server::Span;
1329+
pub mod bridge2 {
1330+
#[doc(hidden)]
1331+
pub mod server2 {
1332+
pub trait Span2
1333+
}
1334+
}
1335+
pub use bridge2::server2::Span2;
1336+
"#,
1337+
expect![[r#"
1338+
tt Span (use dep::Span)
1339+
tt Span2 (use dep::Span2)
1340+
"#]],
1341+
);
1342+
}

0 commit comments

Comments
 (0)