jsondoclint: Add Kind
abstraction
This commit is contained in:
parent
a7a4fe9ffa
commit
bb1911db39
@ -1,29 +1,180 @@
|
||||
use rustdoc_json_types::ItemEnum;
|
||||
use rustdoc_json_types::{Item, ItemEnum, ItemKind, ItemSummary};
|
||||
|
||||
pub(crate) fn can_appear_in_mod(kind: &ItemEnum) -> bool {
|
||||
match kind {
|
||||
ItemEnum::Module(_) => true,
|
||||
ItemEnum::ExternCrate { .. } => true,
|
||||
ItemEnum::Import(_) => true,
|
||||
ItemEnum::Union(_) => true,
|
||||
ItemEnum::Struct(_) => true,
|
||||
ItemEnum::StructField(_) => false, // Only in structs or variants
|
||||
ItemEnum::Enum(_) => true,
|
||||
ItemEnum::Variant(_) => false, // Only in enums
|
||||
ItemEnum::Function(_) => true,
|
||||
ItemEnum::Trait(_) => true,
|
||||
ItemEnum::TraitAlias(_) => true,
|
||||
ItemEnum::Method(_) => false, // Only in traits
|
||||
ItemEnum::Impl(_) => true,
|
||||
ItemEnum::Typedef(_) => true,
|
||||
ItemEnum::OpaqueTy(_) => todo!("IDK"), // On
|
||||
ItemEnum::Constant(_) => true,
|
||||
ItemEnum::Static(_) => true,
|
||||
ItemEnum::ForeignType => todo!("IDK"),
|
||||
ItemEnum::Macro(_) => true,
|
||||
ItemEnum::ProcMacro(_) => true,
|
||||
ItemEnum::PrimitiveType(_) => todo!("IDK"),
|
||||
ItemEnum::AssocConst { .. } => false, // Trait Only
|
||||
ItemEnum::AssocType { .. } => false, // Trait only
|
||||
// We want a univeral way to represent an `ItemEnum` or `ItemKind`
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum Kind {
|
||||
Module,
|
||||
ExternCrate,
|
||||
Import,
|
||||
Struct,
|
||||
StructField,
|
||||
Union,
|
||||
Enum,
|
||||
Variant,
|
||||
Function,
|
||||
Typedef,
|
||||
OpaqueTy,
|
||||
Constant,
|
||||
Trait,
|
||||
TraitAlias,
|
||||
Method,
|
||||
Impl,
|
||||
Static,
|
||||
ForeignType,
|
||||
Macro,
|
||||
ProcAttribute,
|
||||
ProcDerive,
|
||||
AssocConst,
|
||||
AssocType,
|
||||
Primitive,
|
||||
Keyword,
|
||||
// Not in ItemKind
|
||||
ProcMacro,
|
||||
PrimitiveType,
|
||||
}
|
||||
|
||||
impl Kind {
|
||||
pub fn can_appear_in_mod(self) -> bool {
|
||||
use Kind::*;
|
||||
match self {
|
||||
Module => true,
|
||||
ExternCrate => true,
|
||||
Import => true,
|
||||
Union => true,
|
||||
Struct => true,
|
||||
Enum => true,
|
||||
Function => true,
|
||||
Trait => true,
|
||||
TraitAlias => true,
|
||||
Impl => true,
|
||||
Typedef => true,
|
||||
Constant => true,
|
||||
Static => true,
|
||||
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"),
|
||||
|
||||
// Only in traits
|
||||
AssocConst => false,
|
||||
AssocType => false,
|
||||
Method => false,
|
||||
|
||||
StructField => false, // Only in structs or variants
|
||||
Variant => false, // Only in enums
|
||||
}
|
||||
}
|
||||
|
||||
pub fn can_appear_in_trait(self) -> bool {
|
||||
match self {
|
||||
Kind::AssocConst => true,
|
||||
Kind::AssocType => true,
|
||||
Kind::Method => true,
|
||||
|
||||
Kind::Module => false,
|
||||
Kind::ExternCrate => false,
|
||||
Kind::Import => false,
|
||||
Kind::Struct => false,
|
||||
Kind::StructField => false,
|
||||
Kind::Union => false,
|
||||
Kind::Enum => false,
|
||||
Kind::Variant => false,
|
||||
Kind::Function => false,
|
||||
Kind::Typedef => false,
|
||||
Kind::OpaqueTy => false,
|
||||
Kind::Constant => false,
|
||||
Kind::Trait => false,
|
||||
Kind::TraitAlias => false,
|
||||
Kind::Impl => false,
|
||||
Kind::Static => false,
|
||||
Kind::ForeignType => false,
|
||||
Kind::Macro => false,
|
||||
Kind::ProcAttribute => false,
|
||||
Kind::ProcDerive => false,
|
||||
Kind::Primitive => false,
|
||||
Kind::Keyword => false,
|
||||
Kind::ProcMacro => false,
|
||||
Kind::PrimitiveType => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_struct_field(self) -> bool {
|
||||
matches!(self, Kind::StructField)
|
||||
}
|
||||
pub fn is_module(self) -> bool {
|
||||
matches!(self, Kind::Module)
|
||||
}
|
||||
pub fn is_impl(self) -> bool {
|
||||
matches!(self, Kind::Impl)
|
||||
}
|
||||
pub fn is_variant(self) -> bool {
|
||||
matches!(self, Kind::Variant)
|
||||
}
|
||||
|
||||
pub fn from_item(i: &Item) -> Self {
|
||||
use Kind::*;
|
||||
match i.inner {
|
||||
ItemEnum::Module(_) => Module,
|
||||
ItemEnum::Import(_) => Import,
|
||||
ItemEnum::Union(_) => Union,
|
||||
ItemEnum::Struct(_) => Struct,
|
||||
ItemEnum::StructField(_) => StructField,
|
||||
ItemEnum::Enum(_) => Enum,
|
||||
ItemEnum::Variant(_) => Variant,
|
||||
ItemEnum::Function(_) => Function,
|
||||
ItemEnum::Trait(_) => Trait,
|
||||
ItemEnum::TraitAlias(_) => TraitAlias,
|
||||
ItemEnum::Method(_) => Method,
|
||||
ItemEnum::Impl(_) => Impl,
|
||||
ItemEnum::Typedef(_) => Typedef,
|
||||
ItemEnum::OpaqueTy(_) => OpaqueTy,
|
||||
ItemEnum::Constant(_) => Constant,
|
||||
ItemEnum::Static(_) => Static,
|
||||
ItemEnum::Macro(_) => Macro,
|
||||
ItemEnum::ProcMacro(_) => ProcMacro,
|
||||
ItemEnum::PrimitiveType(_) => PrimitiveType,
|
||||
ItemEnum::ForeignType => ForeignType,
|
||||
ItemEnum::ExternCrate { .. } => ExternCrate,
|
||||
ItemEnum::AssocConst { .. } => AssocConst,
|
||||
ItemEnum::AssocType { .. } => AssocType,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_summary(s: &ItemSummary) -> Self {
|
||||
use Kind::*;
|
||||
match s.kind {
|
||||
ItemKind::AssocConst => AssocConst,
|
||||
ItemKind::AssocType => AssocType,
|
||||
ItemKind::Constant => Constant,
|
||||
ItemKind::Enum => Enum,
|
||||
ItemKind::ExternCrate => ExternCrate,
|
||||
ItemKind::ForeignType => ForeignType,
|
||||
ItemKind::Function => Function,
|
||||
ItemKind::Impl => Impl,
|
||||
ItemKind::Import => Import,
|
||||
ItemKind::Keyword => Keyword,
|
||||
ItemKind::Macro => Macro,
|
||||
ItemKind::Method => Method,
|
||||
ItemKind::Module => Module,
|
||||
ItemKind::OpaqueTy => OpaqueTy,
|
||||
ItemKind::Primitive => Primitive,
|
||||
ItemKind::ProcAttribute => ProcAttribute,
|
||||
ItemKind::ProcDerive => ProcDerive,
|
||||
ItemKind::Static => Static,
|
||||
ItemKind::Struct => Struct,
|
||||
ItemKind::StructField => StructField,
|
||||
ItemKind::Trait => Trait,
|
||||
ItemKind::TraitAlias => TraitAlias,
|
||||
ItemKind::Typedef => Typedef,
|
||||
ItemKind::Union => Union,
|
||||
ItemKind::Variant => Variant,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
TypeBindingKind, Typedef, Union, Variant, WherePredicate,
|
||||
};
|
||||
|
||||
use crate::{item_kind::can_appear_in_mod, Error};
|
||||
use crate::{item_kind::Kind, Error};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Validator<'a> {
|
||||
@ -329,63 +329,59 @@ fn add_id(&mut self, id: &'a Id) {
|
||||
}
|
||||
}
|
||||
|
||||
fn add_field_id(&mut self, id: &'a Id) {
|
||||
let item = &self.krate.index[id];
|
||||
if let ItemEnum::StructField(_) = item.inner {
|
||||
self.add_id(id);
|
||||
fn add_id_checked(&mut self, id: &'a Id, valid: fn(Kind) -> bool, expected: &str) {
|
||||
if let Some(kind) = self.kind_of(id) {
|
||||
if valid(kind) {
|
||||
self.add_id(id);
|
||||
} else {
|
||||
self.fail_expecting(id, expected);
|
||||
}
|
||||
} else {
|
||||
self.fail(id, "Expecting field");
|
||||
self.fail(id, "Not found")
|
||||
}
|
||||
}
|
||||
|
||||
fn add_field_id(&mut self, id: &'a Id) {
|
||||
self.add_id_checked(id, Kind::is_struct_field, "StructField");
|
||||
}
|
||||
|
||||
fn add_mod_id(&mut self, id: &'a Id) {
|
||||
let item = &self.krate.index[id];
|
||||
if let ItemEnum::Module(_) = item.inner {
|
||||
self.add_id(id);
|
||||
} else {
|
||||
self.fail(id, "Expecting module");
|
||||
}
|
||||
self.add_id_checked(id, Kind::is_module, "Module");
|
||||
}
|
||||
|
||||
fn add_impl_id(&mut self, id: &'a Id) {
|
||||
let item = &self.krate.index[id];
|
||||
if let ItemEnum::StructField(_) = item.inner {
|
||||
self.add_id(id);
|
||||
} else {
|
||||
self.fail(id, "Expecting impl");
|
||||
}
|
||||
self.add_id_checked(id, Kind::is_impl, "Impl");
|
||||
}
|
||||
|
||||
fn add_variant_id(&mut self, id: &'a Id) {
|
||||
let item = &self.krate.index[id];
|
||||
if let ItemEnum::StructField(_) = item.inner {
|
||||
self.add_id(id);
|
||||
} else {
|
||||
self.fail(id, "Expecting variant");
|
||||
}
|
||||
self.add_id_checked(id, Kind::is_variant, "Variant");
|
||||
}
|
||||
|
||||
/// Add an Id that appeared in a trait
|
||||
fn add_trait_item_id(&mut self, id: &'a Id) {
|
||||
let item = &self.krate.index[id];
|
||||
if !can_appear_in_mod(&item.inner) {
|
||||
self.fail(id, "Expecting item that can appear in trait");
|
||||
} else {
|
||||
self.add_id(id);
|
||||
}
|
||||
self.add_id_checked(id, Kind::can_appear_in_trait, "Trait inner item");
|
||||
}
|
||||
|
||||
/// Add an Id that appeared in a mod
|
||||
fn add_mod_item_id(&mut self, id: &'a Id) {
|
||||
let item = &self.krate.index[id];
|
||||
if can_appear_in_mod(&item.inner) {
|
||||
self.add_id(id);
|
||||
} else {
|
||||
self.fail(id, "Expecting item that can appear in trait");
|
||||
}
|
||||
self.add_id_checked(id, Kind::can_appear_in_mod, "Module inner item")
|
||||
}
|
||||
|
||||
fn fail(&mut self, id: &Id, msg: &str) {
|
||||
self.errs.push(Error { id: id.clone(), message: msg.to_string() });
|
||||
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:?}"));
|
||||
}
|
||||
|
||||
fn fail(&mut self, id: &Id, message: impl Into<String>) {
|
||||
self.errs.push(Error { id: id.clone(), message: message.into() });
|
||||
}
|
||||
|
||||
fn kind_of(&mut self, id: &Id) -> Option<Kind> {
|
||||
if let Some(item) = self.krate.index.get(id) {
|
||||
Some(Kind::from_item(item))
|
||||
} else if let Some(summary) = self.krate.paths.get(id) {
|
||||
Some(Kind::from_summary(summary))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user