jsondoclint: Check local items in paths
are also in index
.
This commit is contained in:
parent
7bbbaabbb6
commit
d4139b36cf
@ -3,14 +3,17 @@
|
|||||||
|
|
||||||
use rustdoc_json_types::{
|
use rustdoc_json_types::{
|
||||||
Constant, Crate, DynTrait, Enum, FnDecl, Function, FunctionPointer, GenericArg, GenericArgs,
|
Constant, Crate, DynTrait, Enum, FnDecl, Function, FunctionPointer, GenericArg, GenericArgs,
|
||||||
GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, Module, OpaqueTy, Path,
|
GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, ItemSummary, Module,
|
||||||
Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type, TypeBinding,
|
OpaqueTy, Path, Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias,
|
||||||
TypeBindingKind, Typedef, Union, Variant, VariantKind, WherePredicate,
|
Type, TypeBinding, TypeBindingKind, Typedef, Union, Variant, VariantKind, WherePredicate,
|
||||||
};
|
};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::{item_kind::Kind, json_find, Error, ErrorKind};
|
use crate::{item_kind::Kind, json_find, Error, ErrorKind};
|
||||||
|
|
||||||
|
// This is a rustc implementation detail that we rely on here
|
||||||
|
const LOCAL_CRATE_ID: u32 = 0;
|
||||||
|
|
||||||
/// The Validator walks over the JSON tree, and ensures it is well formed.
|
/// The Validator walks over the JSON tree, and ensures it is well formed.
|
||||||
/// It is made of several parts.
|
/// It is made of several parts.
|
||||||
///
|
///
|
||||||
@ -53,12 +56,19 @@ pub fn new(krate: &'a Crate, krate_json: Value) -> Self {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_crate(&mut self) {
|
pub fn check_crate(&mut self) {
|
||||||
|
// Graph traverse the index
|
||||||
let root = &self.krate.root;
|
let root = &self.krate.root;
|
||||||
self.add_mod_id(root);
|
self.add_mod_id(root);
|
||||||
while let Some(id) = set_remove(&mut self.todo) {
|
while let Some(id) = set_remove(&mut self.todo) {
|
||||||
self.seen_ids.insert(id);
|
self.seen_ids.insert(id);
|
||||||
self.check_item(id);
|
self.check_item(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let root_crate_id = self.krate.index[root].crate_id;
|
||||||
|
assert_eq!(root_crate_id, LOCAL_CRATE_ID, "LOCAL_CRATE_ID is wrong");
|
||||||
|
for (id, item_info) in &self.krate.paths {
|
||||||
|
self.check_item_info(id, item_info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_item(&mut self, id: &'a Id) {
|
fn check_item(&mut self, id: &'a Id) {
|
||||||
@ -364,6 +374,19 @@ fn check_function_pointer(&mut self, fp: &'a FunctionPointer) {
|
|||||||
fp.generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd));
|
fp.generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_item_info(&mut self, id: &Id, item_info: &ItemSummary) {
|
||||||
|
// FIXME: Their should be a better way to determine if an item is local, rather than relying on `LOCAL_CRATE_ID`,
|
||||||
|
// which encodes rustc implementation details.
|
||||||
|
if item_info.crate_id == LOCAL_CRATE_ID && !self.krate.index.contains_key(id) {
|
||||||
|
self.errs.push(Error {
|
||||||
|
id: id.clone(),
|
||||||
|
kind: ErrorKind::Custom(
|
||||||
|
"Id for local item in `paths` but not in `index`".to_owned(),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn add_id_checked(&mut self, id: &'a Id, valid: fn(Kind) -> bool, expected: &str) {
|
fn add_id_checked(&mut self, id: &'a Id, valid: fn(Kind) -> bool, expected: &str) {
|
||||||
if let Some(kind) = self.kind_of(id) {
|
if let Some(kind) = self.kind_of(id) {
|
||||||
if valid(kind) {
|
if valid(kind) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use rustdoc_json_types::{Crate, Item, Visibility};
|
use rustdoc_json_types::{Crate, Item, ItemKind, ItemSummary, Visibility, FORMAT_VERSION};
|
||||||
|
|
||||||
use crate::json_find::SelectorPart;
|
use crate::json_find::SelectorPart;
|
||||||
|
|
||||||
@ -64,3 +64,101 @@ fn errors_on_missing_links() {
|
|||||||
}],
|
}],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test we would catch
|
||||||
|
// https://github.com/rust-lang/rust/issues/104064#issuecomment-1368589718
|
||||||
|
#[test]
|
||||||
|
fn errors_on_local_in_paths_and_not_index() {
|
||||||
|
let krate = Crate {
|
||||||
|
root: id("0:0:1572"),
|
||||||
|
crate_version: None,
|
||||||
|
includes_private: false,
|
||||||
|
index: HashMap::from_iter([
|
||||||
|
(
|
||||||
|
id("0:0:1572"),
|
||||||
|
Item {
|
||||||
|
id: id("0:0:1572"),
|
||||||
|
crate_id: 0,
|
||||||
|
name: Some("microcore".to_owned()),
|
||||||
|
span: None,
|
||||||
|
visibility: Visibility::Public,
|
||||||
|
docs: None,
|
||||||
|
links: HashMap::from_iter([(("prim@i32".to_owned(), id("0:1:1571")))]),
|
||||||
|
attrs: Vec::new(),
|
||||||
|
deprecation: None,
|
||||||
|
inner: ItemEnum::Module(Module {
|
||||||
|
is_crate: true,
|
||||||
|
items: vec![id("0:1:717")],
|
||||||
|
is_stripped: false,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
id("0:1:717"),
|
||||||
|
Item {
|
||||||
|
id: id("0:1:717"),
|
||||||
|
crate_id: 0,
|
||||||
|
name: Some("i32".to_owned()),
|
||||||
|
span: None,
|
||||||
|
visibility: Visibility::Public,
|
||||||
|
docs: None,
|
||||||
|
links: HashMap::default(),
|
||||||
|
attrs: Vec::new(),
|
||||||
|
deprecation: None,
|
||||||
|
inner: ItemEnum::Primitive(Primitive { name: "i32".to_owned(), impls: vec![] }),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
paths: HashMap::from_iter([(
|
||||||
|
id("0:1:1571"),
|
||||||
|
ItemSummary {
|
||||||
|
crate_id: 0,
|
||||||
|
path: vec!["microcore".to_owned(), "i32".to_owned()],
|
||||||
|
kind: ItemKind::Primitive,
|
||||||
|
},
|
||||||
|
)]),
|
||||||
|
external_crates: HashMap::default(),
|
||||||
|
format_version: rustdoc_json_types::FORMAT_VERSION,
|
||||||
|
};
|
||||||
|
|
||||||
|
check(
|
||||||
|
&krate,
|
||||||
|
&[Error {
|
||||||
|
id: id("0:1:1571"),
|
||||||
|
kind: ErrorKind::Custom("Id for local item in `paths` but not in `index`".to_owned()),
|
||||||
|
}],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic = "LOCAL_CRATE_ID is wrong"]
|
||||||
|
fn checks_local_crate_id_is_correct() {
|
||||||
|
let krate = Crate {
|
||||||
|
root: id("root"),
|
||||||
|
crate_version: None,
|
||||||
|
includes_private: false,
|
||||||
|
index: HashMap::from_iter([(
|
||||||
|
id("root"),
|
||||||
|
Item {
|
||||||
|
id: id("root"),
|
||||||
|
crate_id: LOCAL_CRATE_ID.wrapping_add(1),
|
||||||
|
name: Some("irrelavent".to_owned()),
|
||||||
|
span: None,
|
||||||
|
visibility: Visibility::Public,
|
||||||
|
docs: None,
|
||||||
|
links: HashMap::default(),
|
||||||
|
attrs: Vec::new(),
|
||||||
|
deprecation: None,
|
||||||
|
inner: ItemEnum::Module(Module {
|
||||||
|
is_crate: true,
|
||||||
|
items: vec![],
|
||||||
|
is_stripped: false,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
)]),
|
||||||
|
paths: HashMap::default(),
|
||||||
|
external_crates: HashMap::default(),
|
||||||
|
format_version: FORMAT_VERSION,
|
||||||
|
};
|
||||||
|
check(&krate, &[]);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user