Skip to content

Commit 9d3ae11

Browse files
Rollup merge of #135348 - aDotInTheVoid:pathspathspaths, r=GuillaumeGomez
rustdoc-json: Include items in stripped modules in `Crate::paths`. Closes #135309 When we're running rustdoc-json, we should err on the side of adding more items to `Cache::paths`, as that directly becomes `Crate::paths` in the output. r? ``@GuillaumeGomez.`` Best reviewed commit-by-commit.
2 parents 627513a + 2a2b090 commit 9d3ae11

File tree

6 files changed

+151
-13
lines changed

6 files changed

+151
-13
lines changed

src/librustdoc/formats/cache.rs

+15-8
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ struct CacheBuilder<'a, 'tcx> {
140140
/// This field is used to prevent duplicated impl blocks.
141141
impl_ids: DefIdMap<DefIdSet>,
142142
tcx: TyCtxt<'tcx>,
143+
is_json_output: bool,
143144
}
144145

145146
impl Cache {
@@ -184,8 +185,13 @@ impl Cache {
184185
}
185186

186187
let (krate, mut impl_ids) = {
187-
let mut cache_builder =
188-
CacheBuilder { tcx, cache: &mut cx.cache, impl_ids: Default::default() };
188+
let is_json_output = cx.is_json_output();
189+
let mut cache_builder = CacheBuilder {
190+
tcx,
191+
cache: &mut cx.cache,
192+
impl_ids: Default::default(),
193+
is_json_output,
194+
};
189195
krate = cache_builder.fold_crate(krate);
190196
(krate, cache_builder.impl_ids)
191197
};
@@ -307,12 +313,13 @@ impl DocFolder for CacheBuilder<'_, '_> {
307313
| clean::ProcMacroItem(..)
308314
| clean::VariantItem(..) => {
309315
use rustc_data_structures::fx::IndexEntry as Entry;
310-
if !self.cache.stripped_mod
311-
&& !matches!(
312-
item.stability.map(|stab| stab.level),
313-
Some(StabilityLevel::Stable { allowed_through_unstable_modules: true, .. })
314-
)
315-
{
316+
317+
let skip_because_unstable = matches!(
318+
item.stability.map(|stab| stab.level),
319+
Some(StabilityLevel::Stable { allowed_through_unstable_modules: true, .. })
320+
);
321+
322+
if (!self.cache.stripped_mod && !skip_because_unstable) || self.is_json_output {
316323
// Re-exported items mean that the same id can show up twice
317324
// in the rustdoc ast that we're looking at. We know,
318325
// however, that a re-exported item doesn't show up in the

src/tools/jsondocck/src/main.rs

+23-4
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ enum CommandKind {
6565
/// Checks the path doesn't exist.
6666
HasNotPath,
6767

68+
/// `//@ !has <path> <value>`
69+
///
70+
/// Checks the path exists, but doesn't have the given value.
71+
HasNotValue { value: String },
72+
6873
/// `//@ is <path> <value>`
6974
///
7075
/// Check the path is the given value.
@@ -128,10 +133,11 @@ impl CommandKind {
128133
[_path, value] => Self::HasValue { value: value.clone() },
129134
_ => panic!("`//@ has` must have 2 or 3 arguments, but got {args:?}"),
130135
},
131-
("has", true) => {
132-
assert_eq!(args.len(), 1, "args={args:?}");
133-
Self::HasNotPath
134-
}
136+
("has", true) => match args {
137+
[_path] => Self::HasNotPath,
138+
[_path, value] => Self::HasNotValue { value: value.clone() },
139+
_ => panic!("`//@ !has` must have 2 or 3 arguments, but got {args:?}"),
140+
},
135141

136142
(_, false) if KNOWN_DIRECTIVE_NAMES.contains(&command_name) => {
137143
return None;
@@ -223,6 +229,19 @@ fn check_command(command: &Command, cache: &mut Cache) -> Result<(), String> {
223229
return Err(format!("matched to {matches:?}, which didn't contain {want_value:?}"));
224230
}
225231
}
232+
CommandKind::HasNotValue { value } => {
233+
let wantnt_value = string_to_value(value, cache);
234+
if matches.contains(&wantnt_value.as_ref()) {
235+
return Err(format!(
236+
"matched to {matches:?}, which contains unwanted {wantnt_value:?}"
237+
));
238+
} else if matches.is_empty() {
239+
return Err(format!(
240+
"got no matches, but expected some matched (not containing {wantnt_value:?}"
241+
));
242+
}
243+
}
244+
226245
CommandKind::Is { value } => {
227246
let want_value = string_to_value(value, cache);
228247
let matched = get_one(&matches)?;

src/tools/jsondoclint/src/validator.rs

+6
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,12 @@ impl<'a> Validator<'a> {
303303
PathKind::Trait => self.add_trait_or_alias_id(&x.id),
304304
PathKind::Type => self.add_type_id(&x.id),
305305
}
306+
307+
// FIXME: More robust support for checking things in $.index also exist in $.paths
308+
if !self.krate.paths.contains_key(&x.id) {
309+
self.fail(&x.id, ErrorKind::Custom(format!("No entry in '$.paths' for {x:?}")));
310+
}
311+
306312
if let Some(args) = &x.args {
307313
self.check_generic_args(&**args);
308314
}

src/tools/jsondoclint/src/validator/tests.rs

+96-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use rustc_hash::FxHashMap;
2-
use rustdoc_json_types::{FORMAT_VERSION, Item, ItemKind, Visibility};
2+
use rustdoc_json_types::{Abi, FORMAT_VERSION, FunctionHeader, Item, ItemKind, Visibility};
33

44
use super::*;
55
use crate::json_find::SelectorPart;
@@ -102,6 +102,101 @@ fn errors_on_local_in_paths_and_not_index() {
102102
}]);
103103
}
104104

105+
#[test]
106+
fn errors_on_missing_path() {
107+
// crate-name=foo
108+
// ```
109+
// pub struct Bar;
110+
// pub fn mk_bar() -> Bar { ... }
111+
// ```
112+
113+
let generics = Generics { params: vec![], where_predicates: vec![] };
114+
115+
let krate = Crate {
116+
root: Id(0),
117+
crate_version: None,
118+
includes_private: false,
119+
index: FxHashMap::from_iter([
120+
(Id(0), Item {
121+
id: Id(0),
122+
crate_id: 0,
123+
name: Some("foo".to_owned()),
124+
span: None,
125+
visibility: Visibility::Public,
126+
docs: None,
127+
links: FxHashMap::default(),
128+
attrs: Vec::new(),
129+
deprecation: None,
130+
inner: ItemEnum::Module(Module {
131+
is_crate: true,
132+
items: vec![Id(1), Id(2)],
133+
is_stripped: false,
134+
}),
135+
}),
136+
(Id(1), Item {
137+
id: Id(0),
138+
crate_id: 0,
139+
name: Some("Bar".to_owned()),
140+
span: None,
141+
visibility: Visibility::Public,
142+
docs: None,
143+
links: FxHashMap::default(),
144+
attrs: Vec::new(),
145+
deprecation: None,
146+
inner: ItemEnum::Struct(Struct {
147+
kind: StructKind::Unit,
148+
generics: generics.clone(),
149+
impls: vec![],
150+
}),
151+
}),
152+
(Id(2), Item {
153+
id: Id(0),
154+
crate_id: 0,
155+
name: Some("mk_bar".to_owned()),
156+
span: None,
157+
visibility: Visibility::Public,
158+
docs: None,
159+
links: FxHashMap::default(),
160+
attrs: Vec::new(),
161+
deprecation: None,
162+
inner: ItemEnum::Function(Function {
163+
sig: FunctionSignature {
164+
inputs: vec![],
165+
output: Some(Type::ResolvedPath(Path {
166+
name: "Bar".to_owned(),
167+
id: Id(1),
168+
args: None,
169+
})),
170+
is_c_variadic: false,
171+
},
172+
generics,
173+
header: FunctionHeader {
174+
is_const: false,
175+
is_unsafe: false,
176+
is_async: false,
177+
abi: Abi::Rust,
178+
},
179+
has_body: true,
180+
}),
181+
}),
182+
]),
183+
paths: FxHashMap::from_iter([(Id(0), ItemSummary {
184+
crate_id: 0,
185+
path: vec!["foo".to_owned()],
186+
kind: ItemKind::Module,
187+
})]),
188+
external_crates: FxHashMap::default(),
189+
format_version: rustdoc_json_types::FORMAT_VERSION,
190+
};
191+
192+
check(&krate, &[Error {
193+
kind: ErrorKind::Custom(
194+
r#"No entry in '$.paths' for Path { name: "Bar", id: Id(1), args: None }"#.to_owned(),
195+
),
196+
id: Id(1),
197+
}]);
198+
}
199+
105200
#[test]
106201
#[should_panic = "LOCAL_CRATE_ID is wrong"]
107202
fn checks_local_crate_id_is_correct() {

tests/rustdoc-json/reexport/simple_private.rs

+6
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,9 @@ mod inner {
1212
pub use inner::Public;
1313

1414
//@ ismany "$.index[*][?(@.name=='simple_private')].inner.module.items[*]" $use_id
15+
16+
// Test for https://github.com/rust-lang/rust/issues/135309
17+
//@ has "$.paths[*][?(@.kind=='module')].path" '["simple_private"]'
18+
//@ !has "$.paths[*].path" '["simple_private", "inner"]'
19+
//@ has "$.paths[*][?(@.kind=='struct')].path" '["simple_private", "inner", "Public"]'
20+
//@ !has "$.paths[*].path" '["simple_private", "Public"]'

tests/rustdoc-json/reexport/simple_public.rs

+5
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,8 @@ pub mod inner {
1414
pub use inner::Public;
1515

1616
//@ ismany "$.index[*][?(@.name=='simple_public')].inner.module.items[*]" $import_id $inner_id
17+
18+
//@ has "$.paths[*][?(@.kind=='module')].path" '["simple_public"]'
19+
//@ has "$.paths[*][?(@.kind=='module')].path" '["simple_public", "inner"]'
20+
//@ has "$.paths[*][?(@.kind=='struct')].path" '["simple_public", "inner", "Public"]'
21+
//@ !has "$.paths[*].path" '["simple_public", "Public"]'

0 commit comments

Comments
 (0)