1 use std::collections::HashSet;
4 use rustdoc_json_types::{
5 Constant, Crate, DynTrait, Enum, FnDecl, Function, FunctionPointer, GenericArg, GenericArgs,
6 GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, Module, OpaqueTy, Path,
7 Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type, TypeBinding,
8 TypeBindingKind, Typedef, Union, Variant, VariantKind, WherePredicate,
10 use serde_json::Value;
12 use crate::{item_kind::Kind, json_find, Error, ErrorKind};
14 /// The Validator walks over the JSON tree, and ensures it is well formed.
15 /// It is made of several parts.
17 /// - `check_*`: These take a type from [`rustdoc_json_types`], and check that
18 /// it is well formed. This involves calling `check_*` functions on
19 /// fields of that item, and `add_*` functions on [`Id`]s.
20 /// - `add_*`: These add an [`Id`] to the worklist, after validating it to check if
21 /// the `Id` is a kind expected in this suituation.
23 pub struct Validator<'a> {
24 pub(crate) errs: Vec<Error>,
27 /// Worklist of Ids to check.
28 todo: HashSet<&'a Id>,
29 /// Ids that have already been visited, so don't need to be checked again.
30 seen_ids: HashSet<&'a Id>,
31 /// Ids that have already been reported missing.
32 missing_ids: HashSet<&'a Id>,
37 /// Structs, Enums, Unions and Typedefs.
39 /// This doesn't include trait's because traits are not types.
43 impl<'a> Validator<'a> {
44 pub fn new(krate: &'a Crate, krate_json: Value) -> Self {
49 seen_ids: HashSet::new(),
51 missing_ids: HashSet::new(),
55 pub fn check_crate(&mut self) {
56 let root = &self.krate.root;
57 self.add_mod_id(root);
58 while let Some(id) = set_remove(&mut self.todo) {
59 self.seen_ids.insert(id);
64 fn check_item(&mut self, id: &'a Id) {
65 if let Some(item) = &self.krate.index.get(id) {
66 item.links.values().for_each(|id| self.add_any_id(id));
69 ItemEnum::Import(x) => self.check_import(x),
70 ItemEnum::Union(x) => self.check_union(x),
71 ItemEnum::Struct(x) => self.check_struct(x),
72 ItemEnum::StructField(x) => self.check_struct_field(x),
73 ItemEnum::Enum(x) => self.check_enum(x),
74 ItemEnum::Variant(x) => self.check_variant(x, id),
75 ItemEnum::Function(x) => self.check_function(x),
76 ItemEnum::Trait(x) => self.check_trait(x),
77 ItemEnum::TraitAlias(x) => self.check_trait_alias(x),
78 ItemEnum::Impl(x) => self.check_impl(x),
79 ItemEnum::Typedef(x) => self.check_typedef(x),
80 ItemEnum::OpaqueTy(x) => self.check_opaque_ty(x),
81 ItemEnum::Constant(x) => self.check_constant(x),
82 ItemEnum::Static(x) => self.check_static(x),
83 ItemEnum::ForeignType => {} // nop
84 ItemEnum::Macro(x) => self.check_macro(x),
85 ItemEnum::ProcMacro(x) => self.check_proc_macro(x),
86 ItemEnum::Primitive(x) => self.check_primitive_type(x),
87 ItemEnum::Module(x) => self.check_module(x),
88 // FIXME: Why don't these have their own structs?
89 ItemEnum::ExternCrate { .. } => {}
90 ItemEnum::AssocConst { type_, default: _ } => self.check_type(type_),
91 ItemEnum::AssocType { generics, bounds, default } => {
92 self.check_generics(generics);
93 bounds.iter().for_each(|b| self.check_generic_bound(b));
94 if let Some(ty) = default {
100 assert!(self.krate.paths.contains_key(id));
105 fn check_module(&mut self, module: &'a Module) {
106 module.items.iter().for_each(|i| self.add_mod_item_id(i));
109 fn check_import(&mut self, x: &'a Import) {
111 self.add_glob_import_item_id(x.id.as_ref().unwrap());
112 } else if let Some(id) = &x.id {
113 self.add_import_item_id(id);
117 fn check_union(&mut self, x: &'a Union) {
118 self.check_generics(&x.generics);
119 x.fields.iter().for_each(|i| self.add_field_id(i));
120 x.impls.iter().for_each(|i| self.add_impl_id(i));
123 fn check_struct(&mut self, x: &'a Struct) {
124 self.check_generics(&x.generics);
126 StructKind::Unit => {}
127 StructKind::Tuple(fields) => fields.iter().flatten().for_each(|f| self.add_field_id(f)),
128 StructKind::Plain { fields, fields_stripped: _ } => {
129 fields.iter().for_each(|f| self.add_field_id(f))
132 x.impls.iter().for_each(|i| self.add_impl_id(i));
135 fn check_struct_field(&mut self, x: &'a Type) {
139 fn check_enum(&mut self, x: &'a Enum) {
140 self.check_generics(&x.generics);
141 x.variants.iter().for_each(|i| self.add_variant_id(i));
142 x.impls.iter().for_each(|i| self.add_impl_id(i));
145 fn check_variant(&mut self, x: &'a Variant, id: &'a Id) {
146 let Variant { kind, discriminant } = x;
148 if let Some(discr) = discriminant {
149 if let (Err(_), Err(_)) = (discr.value.parse::<i128>(), discr.value.parse::<u128>()) {
152 ErrorKind::Custom(format!(
153 "Failed to parse discriminant value `{}`",
161 VariantKind::Plain => {}
162 VariantKind::Tuple(tys) => tys.iter().flatten().for_each(|t| self.add_field_id(t)),
163 VariantKind::Struct { fields, fields_stripped: _ } => {
164 fields.iter().for_each(|f| self.add_field_id(f))
169 fn check_function(&mut self, x: &'a Function) {
170 self.check_generics(&x.generics);
171 self.check_fn_decl(&x.decl);
174 fn check_trait(&mut self, x: &'a Trait) {
175 self.check_generics(&x.generics);
176 x.items.iter().for_each(|i| self.add_trait_item_id(i));
177 x.bounds.iter().for_each(|i| self.check_generic_bound(i));
178 x.implementations.iter().for_each(|i| self.add_impl_id(i));
181 fn check_trait_alias(&mut self, x: &'a TraitAlias) {
182 self.check_generics(&x.generics);
183 x.params.iter().for_each(|i| self.check_generic_bound(i));
186 fn check_impl(&mut self, x: &'a Impl) {
187 self.check_generics(&x.generics);
188 if let Some(path) = &x.trait_ {
189 self.check_path(path, PathKind::Trait);
191 self.check_type(&x.for_);
192 x.items.iter().for_each(|i| self.add_trait_item_id(i));
193 if let Some(blanket_impl) = &x.blanket_impl {
194 self.check_type(blanket_impl)
198 fn check_typedef(&mut self, x: &'a Typedef) {
199 self.check_generics(&x.generics);
200 self.check_type(&x.type_);
203 fn check_opaque_ty(&mut self, x: &'a OpaqueTy) {
204 x.bounds.iter().for_each(|b| self.check_generic_bound(b));
205 self.check_generics(&x.generics);
208 fn check_constant(&mut self, x: &'a Constant) {
209 self.check_type(&x.type_);
212 fn check_static(&mut self, x: &'a Static) {
213 self.check_type(&x.type_);
216 fn check_macro(&mut self, _: &'a str) {
220 fn check_proc_macro(&mut self, _: &'a ProcMacro) {
224 fn check_primitive_type(&mut self, x: &'a Primitive) {
225 x.impls.iter().for_each(|i| self.add_impl_id(i));
228 fn check_generics(&mut self, x: &'a Generics) {
229 x.params.iter().for_each(|p| self.check_generic_param_def(p));
230 x.where_predicates.iter().for_each(|w| self.check_where_predicate(w));
233 fn check_type(&mut self, x: &'a Type) {
235 Type::ResolvedPath(path) => self.check_path(path, PathKind::Type),
236 Type::DynTrait(dyn_trait) => self.check_dyn_trait(dyn_trait),
237 Type::Generic(_) => {}
238 Type::Primitive(_) => {}
239 Type::FunctionPointer(fp) => self.check_function_pointer(&**fp),
240 Type::Tuple(tys) => tys.iter().for_each(|ty| self.check_type(ty)),
241 Type::Slice(inner) => self.check_type(&**inner),
242 Type::Array { type_, len: _ } => self.check_type(&**type_),
243 Type::ImplTrait(bounds) => bounds.iter().for_each(|b| self.check_generic_bound(b)),
245 Type::RawPointer { mutable: _, type_ } => self.check_type(&**type_),
246 Type::BorrowedRef { lifetime: _, mutable: _, type_ } => self.check_type(&**type_),
247 Type::QualifiedPath { name: _, args, self_type, trait_ } => {
248 self.check_generic_args(&**args);
249 self.check_type(&**self_type);
250 self.check_path(trait_, PathKind::Trait);
255 fn check_fn_decl(&mut self, x: &'a FnDecl) {
256 x.inputs.iter().for_each(|(_name, ty)| self.check_type(ty));
257 if let Some(output) = &x.output {
258 self.check_type(output);
262 fn check_generic_bound(&mut self, x: &'a GenericBound) {
264 GenericBound::TraitBound { trait_, generic_params, modifier: _ } => {
265 self.check_path(trait_, PathKind::Trait);
266 generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd));
268 GenericBound::Outlives(_) => {}
272 fn check_path(&mut self, x: &'a Path, kind: PathKind) {
274 PathKind::Trait => self.add_trait_or_alias_id(&x.id),
275 PathKind::Type => self.add_type_id(&x.id),
277 if let Some(args) = &x.args {
278 self.check_generic_args(&**args);
282 fn check_generic_args(&mut self, x: &'a GenericArgs) {
284 GenericArgs::AngleBracketed { args, bindings } => {
285 args.iter().for_each(|arg| self.check_generic_arg(arg));
286 bindings.iter().for_each(|bind| self.check_type_binding(bind));
288 GenericArgs::Parenthesized { inputs, output } => {
289 inputs.iter().for_each(|ty| self.check_type(ty));
290 if let Some(o) = output {
297 fn check_generic_param_def(&mut self, gpd: &'a GenericParamDef) {
299 rustdoc_json_types::GenericParamDefKind::Lifetime { outlives: _ } => {}
300 rustdoc_json_types::GenericParamDefKind::Type { bounds, default, synthetic: _ } => {
301 bounds.iter().for_each(|b| self.check_generic_bound(b));
302 if let Some(ty) = default {
306 rustdoc_json_types::GenericParamDefKind::Const { type_, default: _ } => {
307 self.check_type(type_)
312 fn check_generic_arg(&mut self, arg: &'a GenericArg) {
314 GenericArg::Lifetime(_) => {}
315 GenericArg::Type(ty) => self.check_type(ty),
316 GenericArg::Const(c) => self.check_constant(c),
317 GenericArg::Infer => {}
321 fn check_type_binding(&mut self, bind: &'a TypeBinding) {
322 self.check_generic_args(&bind.args);
323 match &bind.binding {
324 TypeBindingKind::Equality(term) => self.check_term(term),
325 TypeBindingKind::Constraint(bounds) => {
326 bounds.iter().for_each(|b| self.check_generic_bound(b))
331 fn check_term(&mut self, term: &'a Term) {
333 Term::Type(ty) => self.check_type(ty),
334 Term::Constant(con) => self.check_constant(con),
338 fn check_where_predicate(&mut self, w: &'a WherePredicate) {
340 WherePredicate::BoundPredicate { type_, bounds, generic_params } => {
341 self.check_type(type_);
342 bounds.iter().for_each(|b| self.check_generic_bound(b));
343 generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd));
345 WherePredicate::RegionPredicate { lifetime: _, bounds } => {
346 bounds.iter().for_each(|b| self.check_generic_bound(b));
348 WherePredicate::EqPredicate { lhs, rhs } => {
349 self.check_type(lhs);
350 self.check_term(rhs);
355 fn check_dyn_trait(&mut self, dyn_trait: &'a DynTrait) {
356 for pt in &dyn_trait.traits {
357 self.check_path(&pt.trait_, PathKind::Trait);
358 pt.generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd));
362 fn check_function_pointer(&mut self, fp: &'a FunctionPointer) {
363 self.check_fn_decl(&fp.decl);
364 fp.generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd));
367 fn add_id_checked(&mut self, id: &'a Id, valid: fn(Kind) -> bool, expected: &str) {
368 if let Some(kind) = self.kind_of(id) {
370 if !self.seen_ids.contains(id) {
371 self.todo.insert(id);
374 self.fail_expecting(id, expected);
377 if !self.missing_ids.contains(id) {
378 self.missing_ids.insert(id);
380 let sels = json_find::find_selector(&self.krate_json, &Value::String(id.0.clone()));
381 assert_ne!(sels.len(), 0);
383 self.fail(id, ErrorKind::NotFound(sels))
388 fn add_any_id(&mut self, id: &'a Id) {
389 self.add_id_checked(id, |_| true, "any kind of item");
392 fn add_field_id(&mut self, id: &'a Id) {
393 self.add_id_checked(id, Kind::is_struct_field, "StructField");
396 fn add_mod_id(&mut self, id: &'a Id) {
397 self.add_id_checked(id, Kind::is_module, "Module");
399 fn add_impl_id(&mut self, id: &'a Id) {
400 self.add_id_checked(id, Kind::is_impl, "Impl");
403 fn add_variant_id(&mut self, id: &'a Id) {
404 self.add_id_checked(id, Kind::is_variant, "Variant");
407 fn add_trait_or_alias_id(&mut self, id: &'a Id) {
408 self.add_id_checked(id, Kind::is_trait_or_alias, "Trait (or TraitAlias)");
411 fn add_type_id(&mut self, id: &'a Id) {
412 self.add_id_checked(id, Kind::is_type, "Type (Struct, Enum, Union or Typedef)");
415 /// Add an Id that appeared in a trait
416 fn add_trait_item_id(&mut self, id: &'a Id) {
417 self.add_id_checked(id, Kind::can_appear_in_trait, "Trait inner item");
420 /// Add an Id that can be `use`d
421 fn add_import_item_id(&mut self, id: &'a Id) {
422 self.add_id_checked(id, Kind::can_appear_in_import, "Import inner item");
425 fn add_glob_import_item_id(&mut self, id: &'a Id) {
426 self.add_id_checked(id, Kind::can_appear_in_glob_import, "Glob import inner item");
429 /// Add an Id that appeared in a mod
430 fn add_mod_item_id(&mut self, id: &'a Id) {
431 self.add_id_checked(id, Kind::can_appear_in_mod, "Module inner item")
434 fn fail_expecting(&mut self, id: &Id, expected: &str) {
435 let kind = self.kind_of(id).unwrap(); // We know it has a kind, as it's wrong.
436 self.fail(id, ErrorKind::Custom(format!("Expected {expected} but found {kind:?}")));
439 fn fail(&mut self, id: &Id, kind: ErrorKind) {
440 self.errs.push(Error { id: id.clone(), kind });
443 fn kind_of(&mut self, id: &Id) -> Option<Kind> {
444 if let Some(item) = self.krate.index.get(id) {
445 Some(Kind::from_item(item))
446 } else if let Some(summary) = self.krate.paths.get(id) {
447 Some(Kind::from_summary(summary))
454 fn set_remove<T: Hash + Eq + Clone>(set: &mut HashSet<T>) -> Option<T> {
455 if let Some(id) = set.iter().next() {