jsondoclint: Find selector for missing ID when error is created, not reported.

This is needed for json output, but even without that, it increases
performance massivly. On my machine, in reduces the time to check
core.json from 40.190s to 11.333s.
This commit is contained in:
Nixon Enraght-Moony 2023-01-02 19:54:08 +00:00
parent 855b7e8cf3
commit 95329080d3
3 changed files with 64 additions and 42 deletions

View File

@ -16,7 +16,7 @@ struct Error {
#[derive(Debug, PartialEq, Eq)]
enum ErrorKind {
NotFound,
NotFound(Vec<json_find::Selector>),
Custom(String),
}
@ -37,49 +37,48 @@ fn main() -> Result<()> {
let krate: Crate = serde_json::from_str(&contents)?;
assert_eq!(krate.format_version, FORMAT_VERSION);
let mut validator = validator::Validator::new(&krate);
let krate_json: Value = serde_json::from_str(&contents)?;
let mut validator = validator::Validator::new(&krate, krate_json);
validator.check_crate();
if !validator.errs.is_empty() {
for err in validator.errs {
match err.kind {
ErrorKind::NotFound => {
let krate_json: Value = serde_json::from_str(&contents)?;
let sels =
json_find::find_selector(&krate_json, &Value::String(err.id.0.clone()));
match &sels[..] {
[] => unreachable!(
"id must be in crate, or it wouldn't be reported as not found"
),
[sel] => eprintln!(
"{} not in index or paths, but refered to at '{}'",
err.id.0,
json_find::to_jsonpath(&sel)
),
[sel, ..] => {
if verbose {
let sels = sels
.iter()
.map(json_find::to_jsonpath)
.map(|i| format!("'{i}'"))
.collect::<Vec<_>>()
.join(", ");
eprintln!(
"{} not in index or paths, but refered to at {sels}",
err.id.0
);
} else {
eprintln!(
"{} not in index or paths, but refered to at '{}' and {} more",
err.id.0,
json_find::to_jsonpath(&sel),
sels.len() - 1,
)
}
ErrorKind::NotFound(sels) => match &sels[..] {
[] => {
unreachable!(
"id {:?} must be in crate, or it wouldn't be reported as not found",
err.id
)
}
[sel] => eprintln!(
"{} not in index or paths, but refered to at '{}'",
err.id.0,
json_find::to_jsonpath(&sel)
),
[sel, ..] => {
if verbose {
let sels = sels
.iter()
.map(json_find::to_jsonpath)
.map(|i| format!("'{i}'"))
.collect::<Vec<_>>()
.join(", ");
eprintln!(
"{} not in index or paths, but refered to at {sels}",
err.id.0
);
} else {
eprintln!(
"{} not in index or paths, but refered to at '{}' and {} more",
err.id.0,
json_find::to_jsonpath(&sel),
sels.len() - 1,
)
}
}
}
},
ErrorKind::Custom(msg) => eprintln!("{}: {}", err.id.0, msg),
}
}

View File

@ -7,8 +7,9 @@ use rustdoc_json_types::{
Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type, TypeBinding,
TypeBindingKind, Typedef, Union, Variant, VariantKind, WherePredicate,
};
use serde_json::Value;
use crate::{item_kind::Kind, Error, ErrorKind};
use crate::{item_kind::Kind, json_find, Error, ErrorKind};
/// The Validator walks over the JSON tree, and ensures it is well formed.
/// It is made of several parts.
@ -22,6 +23,7 @@ use crate::{item_kind::Kind, Error, ErrorKind};
pub struct Validator<'a> {
pub(crate) errs: Vec<Error>,
krate: &'a Crate,
krate_json: Value,
/// Worklist of Ids to check.
todo: HashSet<&'a Id>,
/// Ids that have already been visited, so don't need to be checked again.
@ -39,9 +41,10 @@ enum PathKind {
}
impl<'a> Validator<'a> {
pub fn new(krate: &'a Crate) -> Self {
pub fn new(krate: &'a Crate, krate_json: Value) -> Self {
Self {
krate,
krate_json,
errs: Vec::new(),
seen_ids: HashSet::new(),
todo: HashSet::new(),
@ -373,7 +376,11 @@ impl<'a> Validator<'a> {
} else {
if !self.missing_ids.contains(id) {
self.missing_ids.insert(id);
self.fail(id, ErrorKind::NotFound)
let sels = json_find::find_selector(&self.krate_json, &Value::String(id.0.clone()));
assert_ne!(sels.len(), 0);
self.fail(id, ErrorKind::NotFound(sels))
}
}
}

View File

@ -2,11 +2,16 @@ use std::collections::HashMap;
use rustdoc_json_types::{Crate, Item, Visibility};
use crate::json_find::SelectorPart;
use super::*;
#[track_caller]
fn check(krate: &Crate, errs: &[Error]) {
let mut validator = Validator::new(krate);
let krate_string = serde_json::to_string(krate).unwrap();
let krate_json = serde_json::from_str(&krate_string).unwrap();
let mut validator = Validator::new(krate, krate_json);
validator.check_crate();
assert_eq!(errs, &validator.errs[..]);
@ -46,5 +51,16 @@ fn errors_on_missing_links() {
format_version: rustdoc_json_types::FORMAT_VERSION,
};
check(&k, &[Error { kind: ErrorKind::NotFound, id: id("1") }]);
check(
&k,
&[Error {
kind: ErrorKind::NotFound(vec![vec![
SelectorPart::Field("index".to_owned()),
SelectorPart::Field("0".to_owned()),
SelectorPart::Field("links".to_owned()),
SelectorPart::Field("Not Found".to_owned()),
]]),
id: id("1"),
}],
);
}