From 5f1bc6fc5e362c5955f6a06a7cf21e62b97c86c7 Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Wed, 24 Aug 2022 20:09:37 +0100 Subject: [PATCH] jsondocck: Better errors --- src/tools/jsondoclint/src/item_kind.rs | 19 +++--- src/tools/jsondoclint/src/main.rs | 13 +++- src/tools/jsondoclint/src/validator.rs | 83 ++++++++++++++++---------- 3 files changed, 70 insertions(+), 45 deletions(-) diff --git a/src/tools/jsondoclint/src/item_kind.rs b/src/tools/jsondoclint/src/item_kind.rs index 15866ab6950..f4153245e0b 100644 --- a/src/tools/jsondoclint/src/item_kind.rs +++ b/src/tools/jsondoclint/src/item_kind.rs @@ -31,7 +31,6 @@ pub(crate) enum Kind { Keyword, // Not in ItemKind ProcMacro, - PrimitiveType, } impl Kind { @@ -54,13 +53,13 @@ impl Kind { Macro => true, ProcMacro => true, - ForeignType => todo!("IDK"), - Keyword => todo!("IDK"), - OpaqueTy => todo!("IDK"), - Primitive => todo!("IDK"), - PrimitiveType => todo!("IDK"), - ProcAttribute => todo!("IDK"), - ProcDerive => todo!("IDK"), + // FIXME(adotinthevoid): I'm not sure if these are corrent + ForeignType => false, + Keyword => false, + OpaqueTy => false, + Primitive => false, + ProcAttribute => false, + ProcDerive => false, // Only in traits AssocConst => false, @@ -101,7 +100,6 @@ impl Kind { Kind::Primitive => false, Kind::Keyword => false, Kind::ProcMacro => false, - Kind::PrimitiveType => false, } } @@ -139,7 +137,8 @@ impl Kind { ItemEnum::Static(_) => Static, ItemEnum::Macro(_) => Macro, ItemEnum::ProcMacro(_) => ProcMacro, - ItemEnum::PrimitiveType(_) => PrimitiveType, + // https://github.com/rust-lang/rust/issues/100961 + ItemEnum::PrimitiveType(_) => Primitive, ItemEnum::ForeignType => ForeignType, ItemEnum::ExternCrate { .. } => ExternCrate, ItemEnum::AssocConst { .. } => AssocConst, diff --git a/src/tools/jsondoclint/src/main.rs b/src/tools/jsondoclint/src/main.rs index b98601f7d89..4df8fbc29a2 100644 --- a/src/tools/jsondoclint/src/main.rs +++ b/src/tools/jsondoclint/src/main.rs @@ -9,10 +9,16 @@ mod validator; #[derive(Debug)] struct Error { - message: String, + kind: ErrorKind, id: Id, } +#[derive(Debug)] +enum ErrorKind { + NotFound, + Custom(String), +} + fn main() -> Result<()> { let path = env::args().nth(1).ok_or_else(|| anyhow!("no path given"))?; let contents = fs::read_to_string(path)?; @@ -24,7 +30,10 @@ fn main() -> Result<()> { if !validator.errs.is_empty() { for err in validator.errs { - eprintln!("`{}`: `{}`", err.id.0, err.message); + match err.kind { + ErrorKind::NotFound => eprintln!("{}: Not Found", err.id.0), + ErrorKind::Custom(msg) => eprintln!("{}: {}", err.id.0, msg), + } } bail!("Errors validating json"); } diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs index b0e12479f92..06b114f6c2f 100644 --- a/src/tools/jsondoclint/src/validator.rs +++ b/src/tools/jsondoclint/src/validator.rs @@ -8,13 +8,14 @@ use rustdoc_json_types::{ TypeBindingKind, Typedef, Union, Variant, WherePredicate, }; -use crate::{item_kind::Kind, Error}; +use crate::{item_kind::Kind, Error, ErrorKind}; #[derive(Debug)] pub struct Validator<'a> { pub(crate) errs: Vec, krate: &'a Crate, seen_ids: HashSet<&'a Id>, + missing_ids: HashSet<&'a Id>, todo: HashSet<&'a Id>, } @@ -29,7 +30,13 @@ fn set_remove(set: &mut HashSet) -> Option { impl<'a> Validator<'a> { pub fn new(krate: &'a Crate) -> Self { - Self { krate, errs: Vec::new(), seen_ids: HashSet::new(), todo: HashSet::new() } + Self { + krate, + errs: Vec::new(), + seen_ids: HashSet::new(), + todo: HashSet::new(), + missing_ids: HashSet::new(), + } } pub fn check_crate(&mut self) { @@ -42,32 +49,39 @@ impl<'a> Validator<'a> { } fn check_item(&mut self, id: &'a Id) { - let item = &self.krate.index[id]; - match &item.inner { - ItemEnum::Import(x) => self.check_import(x), - ItemEnum::Union(x) => self.check_union(x), - ItemEnum::Struct(x) => self.check_struct(x), - ItemEnum::StructField(x) => self.check_struct_field(x), - ItemEnum::Enum(x) => self.check_enum(x), - ItemEnum::Variant(x) => self.check_variant(x), - ItemEnum::Function(x) => self.check_function(x), - ItemEnum::Trait(x) => self.check_trait(x), - ItemEnum::TraitAlias(x) => self.check_trait_alias(x), - ItemEnum::Method(x) => self.check_method(x), - ItemEnum::Impl(x) => self.check_impl(x), - ItemEnum::Typedef(x) => self.check_typedef(x), - ItemEnum::OpaqueTy(x) => self.check_opaque_ty(x), - ItemEnum::Constant(x) => self.check_constant(x), - ItemEnum::Static(x) => self.check_static(x), - ItemEnum::ForeignType => todo!(), - ItemEnum::Macro(x) => self.check_macro(x), - ItemEnum::ProcMacro(x) => self.check_proc_macro(x), - ItemEnum::PrimitiveType(x) => self.check_primitive_type(x), - ItemEnum::Module(x) => self.check_module(x), - - ItemEnum::ExternCrate { .. } => todo!(), - ItemEnum::AssocConst { .. } => todo!(), - ItemEnum::AssocType { .. } => todo!(), + if let Some(item) = &self.krate.index.get(id) { + match &item.inner { + ItemEnum::Import(x) => self.check_import(x), + ItemEnum::Union(x) => self.check_union(x), + ItemEnum::Struct(x) => self.check_struct(x), + ItemEnum::StructField(x) => self.check_struct_field(x), + ItemEnum::Enum(x) => self.check_enum(x), + ItemEnum::Variant(x) => self.check_variant(x), + ItemEnum::Function(x) => self.check_function(x), + ItemEnum::Trait(x) => self.check_trait(x), + ItemEnum::TraitAlias(x) => self.check_trait_alias(x), + ItemEnum::Method(x) => self.check_method(x), + ItemEnum::Impl(x) => self.check_impl(x), + ItemEnum::Typedef(x) => self.check_typedef(x), + ItemEnum::OpaqueTy(x) => self.check_opaque_ty(x), + ItemEnum::Constant(x) => self.check_constant(x), + ItemEnum::Static(x) => self.check_static(x), + ItemEnum::ForeignType => todo!(), + ItemEnum::Macro(x) => self.check_macro(x), + ItemEnum::ProcMacro(x) => self.check_proc_macro(x), + ItemEnum::PrimitiveType(x) => self.check_primitive_type(x), + ItemEnum::Module(x) => self.check_module(x), + // FIXME: Why don't these have their own structs? + ItemEnum::ExternCrate { .. } => {} + ItemEnum::AssocConst { type_, default: _ } => self.check_type(type_), + ItemEnum::AssocType { generics, bounds, default } => { + self.check_generics(generics); + bounds.iter().for_each(|b| self.check_generic_bound(b)); + if let Some(ty) = default { + self.check_type(ty); + } + } + } } } @@ -226,7 +240,7 @@ impl<'a> Validator<'a> { self.check_path(trait_); generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd)); } - GenericBound::Outlives(_) => todo!(), + GenericBound::Outlives(_) => {} } } @@ -337,7 +351,10 @@ impl<'a> Validator<'a> { self.fail_expecting(id, expected); } } else { - self.fail(id, "Not found") + if !self.missing_ids.contains(id) { + self.missing_ids.insert(id); + self.fail(id, ErrorKind::NotFound) + } } } @@ -368,11 +385,11 @@ impl<'a> Validator<'a> { fn fail_expecting(&mut self, id: &Id, expected: &str) { let kind = self.kind_of(id).unwrap(); // We know it has a kind, as it's wrong. - self.fail(id, format!("Expected {expected} but found {kind:?}")); + self.fail(id, ErrorKind::Custom(format!("Expected {expected} but found {kind:?}"))); } - fn fail(&mut self, id: &Id, message: impl Into) { - self.errs.push(Error { id: id.clone(), message: message.into() }); + fn fail(&mut self, id: &Id, kind: ErrorKind) { + self.errs.push(Error { id: id.clone(), kind }); } fn kind_of(&mut self, id: &Id) -> Option {