]> git.lizzy.rs Git - rust.git/blob - src/tools/jsondoclint/src/validator.rs
Rollup merge of #106341 - Ezrashaw:refactor-error-code-tidy-check, r=mejrs,klensy...
[rust.git] / src / tools / jsondoclint / src / validator.rs
1 use std::collections::HashSet;
2 use std::hash::Hash;
3
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,
9 };
10 use serde_json::Value;
11
12 use crate::{item_kind::Kind, json_find, Error, ErrorKind};
13
14 /// The Validator walks over the JSON tree, and ensures it is well formed.
15 /// It is made of several parts.
16 ///
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.
22 #[derive(Debug)]
23 pub struct Validator<'a> {
24     pub(crate) errs: Vec<Error>,
25     krate: &'a Crate,
26     krate_json: Value,
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>,
33 }
34
35 enum PathKind {
36     Trait,
37     /// Structs, Enums, Unions and Typedefs.
38     ///
39     /// This doesn't include trait's because traits are not types.
40     Type,
41 }
42
43 impl<'a> Validator<'a> {
44     pub fn new(krate: &'a Crate, krate_json: Value) -> Self {
45         Self {
46             krate,
47             krate_json,
48             errs: Vec::new(),
49             seen_ids: HashSet::new(),
50             todo: HashSet::new(),
51             missing_ids: HashSet::new(),
52         }
53     }
54
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);
60             self.check_item(id);
61         }
62     }
63
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));
67
68             match &item.inner {
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 {
95                         self.check_type(ty);
96                     }
97                 }
98             }
99         } else {
100             assert!(self.krate.paths.contains_key(id));
101         }
102     }
103
104     // Core checkers
105     fn check_module(&mut self, module: &'a Module) {
106         module.items.iter().for_each(|i| self.add_mod_item_id(i));
107     }
108
109     fn check_import(&mut self, x: &'a Import) {
110         if x.glob {
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);
114         }
115     }
116
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));
121     }
122
123     fn check_struct(&mut self, x: &'a Struct) {
124         self.check_generics(&x.generics);
125         match &x.kind {
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))
130             }
131         }
132         x.impls.iter().for_each(|i| self.add_impl_id(i));
133     }
134
135     fn check_struct_field(&mut self, x: &'a Type) {
136         self.check_type(x);
137     }
138
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));
143     }
144
145     fn check_variant(&mut self, x: &'a Variant, id: &'a Id) {
146         let Variant { kind, discriminant } = x;
147
148         if let Some(discr) = discriminant {
149             if let (Err(_), Err(_)) = (discr.value.parse::<i128>(), discr.value.parse::<u128>()) {
150                 self.fail(
151                     id,
152                     ErrorKind::Custom(format!(
153                         "Failed to parse discriminant value `{}`",
154                         discr.value
155                     )),
156                 );
157             }
158         }
159
160         match kind {
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))
165             }
166         }
167     }
168
169     fn check_function(&mut self, x: &'a Function) {
170         self.check_generics(&x.generics);
171         self.check_fn_decl(&x.decl);
172     }
173
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));
179     }
180
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));
184     }
185
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);
190         }
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)
195         }
196     }
197
198     fn check_typedef(&mut self, x: &'a Typedef) {
199         self.check_generics(&x.generics);
200         self.check_type(&x.type_);
201     }
202
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);
206     }
207
208     fn check_constant(&mut self, x: &'a Constant) {
209         self.check_type(&x.type_);
210     }
211
212     fn check_static(&mut self, x: &'a Static) {
213         self.check_type(&x.type_);
214     }
215
216     fn check_macro(&mut self, _: &'a str) {
217         // nop
218     }
219
220     fn check_proc_macro(&mut self, _: &'a ProcMacro) {
221         // nop
222     }
223
224     fn check_primitive_type(&mut self, x: &'a Primitive) {
225         x.impls.iter().for_each(|i| self.add_impl_id(i));
226     }
227
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));
231     }
232
233     fn check_type(&mut self, x: &'a Type) {
234         match x {
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)),
244             Type::Infer => {}
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);
251             }
252         }
253     }
254
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);
259         }
260     }
261
262     fn check_generic_bound(&mut self, x: &'a GenericBound) {
263         match x {
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));
267             }
268             GenericBound::Outlives(_) => {}
269         }
270     }
271
272     fn check_path(&mut self, x: &'a Path, kind: PathKind) {
273         match kind {
274             PathKind::Trait => self.add_trait_or_alias_id(&x.id),
275             PathKind::Type => self.add_type_id(&x.id),
276         }
277         if let Some(args) = &x.args {
278             self.check_generic_args(&**args);
279         }
280     }
281
282     fn check_generic_args(&mut self, x: &'a GenericArgs) {
283         match x {
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));
287             }
288             GenericArgs::Parenthesized { inputs, output } => {
289                 inputs.iter().for_each(|ty| self.check_type(ty));
290                 if let Some(o) = output {
291                     self.check_type(o);
292                 }
293             }
294         }
295     }
296
297     fn check_generic_param_def(&mut self, gpd: &'a GenericParamDef) {
298         match &gpd.kind {
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 {
303                     self.check_type(ty);
304                 }
305             }
306             rustdoc_json_types::GenericParamDefKind::Const { type_, default: _ } => {
307                 self.check_type(type_)
308             }
309         }
310     }
311
312     fn check_generic_arg(&mut self, arg: &'a GenericArg) {
313         match arg {
314             GenericArg::Lifetime(_) => {}
315             GenericArg::Type(ty) => self.check_type(ty),
316             GenericArg::Const(c) => self.check_constant(c),
317             GenericArg::Infer => {}
318         }
319     }
320
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))
327             }
328         }
329     }
330
331     fn check_term(&mut self, term: &'a Term) {
332         match term {
333             Term::Type(ty) => self.check_type(ty),
334             Term::Constant(con) => self.check_constant(con),
335         }
336     }
337
338     fn check_where_predicate(&mut self, w: &'a WherePredicate) {
339         match w {
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));
344             }
345             WherePredicate::RegionPredicate { lifetime: _, bounds } => {
346                 bounds.iter().for_each(|b| self.check_generic_bound(b));
347             }
348             WherePredicate::EqPredicate { lhs, rhs } => {
349                 self.check_type(lhs);
350                 self.check_term(rhs);
351             }
352         }
353     }
354
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));
359         }
360     }
361
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));
365     }
366
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) {
369             if valid(kind) {
370                 if !self.seen_ids.contains(id) {
371                     self.todo.insert(id);
372                 }
373             } else {
374                 self.fail_expecting(id, expected);
375             }
376         } else {
377             if !self.missing_ids.contains(id) {
378                 self.missing_ids.insert(id);
379
380                 let sels = json_find::find_selector(&self.krate_json, &Value::String(id.0.clone()));
381                 assert_ne!(sels.len(), 0);
382
383                 self.fail(id, ErrorKind::NotFound(sels))
384             }
385         }
386     }
387
388     fn add_any_id(&mut self, id: &'a Id) {
389         self.add_id_checked(id, |_| true, "any kind of item");
390     }
391
392     fn add_field_id(&mut self, id: &'a Id) {
393         self.add_id_checked(id, Kind::is_struct_field, "StructField");
394     }
395
396     fn add_mod_id(&mut self, id: &'a Id) {
397         self.add_id_checked(id, Kind::is_module, "Module");
398     }
399     fn add_impl_id(&mut self, id: &'a Id) {
400         self.add_id_checked(id, Kind::is_impl, "Impl");
401     }
402
403     fn add_variant_id(&mut self, id: &'a Id) {
404         self.add_id_checked(id, Kind::is_variant, "Variant");
405     }
406
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)");
409     }
410
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)");
413     }
414
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");
418     }
419
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");
423     }
424
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");
427     }
428
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")
432     }
433
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:?}")));
437     }
438
439     fn fail(&mut self, id: &Id, kind: ErrorKind) {
440         self.errs.push(Error { id: id.clone(), kind });
441     }
442
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))
448         } else {
449             None
450         }
451     }
452 }
453
454 fn set_remove<T: Hash + Eq + Clone>(set: &mut HashSet<T>) -> Option<T> {
455     if let Some(id) = set.iter().next() {
456         let id = id.clone();
457         set.take(&id)
458     } else {
459         None
460     }
461 }
462
463 #[cfg(test)]
464 mod tests;