]> git.lizzy.rs Git - rust.git/blob - src/tools/jsondoclint/src/validator.rs
Auto merge of #101030 - woppopo:const_location, r=scottmcm
[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, Method, Module, OpaqueTy,
7     Path, Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type,
8     TypeBinding, TypeBindingKind, Typedef, Union, Variant, WherePredicate,
9 };
10
11 use crate::{item_kind::Kind, Error, ErrorKind};
12
13 /// The Validator walks over the JSON tree, and ensures it is well formed.
14 /// It is made of several parts.
15 ///
16 /// - `check_*`: These take a type from [`rustdoc_json_types`], and check that
17 ///              it is well formed. This involves calling `check_*` functions on
18 ///              fields of that item, and `add_*` functions on [`Id`]s.
19 /// - `add_*`: These add an [`Id`] to the worklist, after validating it to check if
20 ///            the `Id` is a kind expected in this suituation.
21 #[derive(Debug)]
22 pub struct Validator<'a> {
23     pub(crate) errs: Vec<Error>,
24     krate: &'a Crate,
25     /// Worklist of Ids to check.
26     todo: HashSet<&'a Id>,
27     /// Ids that have already been visited, so don't need to be checked again.
28     seen_ids: HashSet<&'a Id>,
29     /// Ids that have already been reported missing.
30     missing_ids: HashSet<&'a Id>,
31 }
32
33 enum PathKind {
34     Trait,
35     StructEnumUnion,
36 }
37
38 impl<'a> Validator<'a> {
39     pub fn new(krate: &'a Crate) -> Self {
40         Self {
41             krate,
42             errs: Vec::new(),
43             seen_ids: HashSet::new(),
44             todo: HashSet::new(),
45             missing_ids: HashSet::new(),
46         }
47     }
48
49     pub fn check_crate(&mut self) {
50         let root = &self.krate.root;
51         self.add_mod_id(root);
52         while let Some(id) = set_remove(&mut self.todo) {
53             self.seen_ids.insert(id);
54             self.check_item(id);
55         }
56     }
57
58     fn check_item(&mut self, id: &'a Id) {
59         if let Some(item) = &self.krate.index.get(id) {
60             match &item.inner {
61                 ItemEnum::Import(x) => self.check_import(x),
62                 ItemEnum::Union(x) => self.check_union(x),
63                 ItemEnum::Struct(x) => self.check_struct(x),
64                 ItemEnum::StructField(x) => self.check_struct_field(x),
65                 ItemEnum::Enum(x) => self.check_enum(x),
66                 ItemEnum::Variant(x) => self.check_variant(x, id),
67                 ItemEnum::Function(x) => self.check_function(x),
68                 ItemEnum::Trait(x) => self.check_trait(x),
69                 ItemEnum::TraitAlias(x) => self.check_trait_alias(x),
70                 ItemEnum::Method(x) => self.check_method(x),
71                 ItemEnum::Impl(x) => self.check_impl(x),
72                 ItemEnum::Typedef(x) => self.check_typedef(x),
73                 ItemEnum::OpaqueTy(x) => self.check_opaque_ty(x),
74                 ItemEnum::Constant(x) => self.check_constant(x),
75                 ItemEnum::Static(x) => self.check_static(x),
76                 ItemEnum::ForeignType => {} // nop
77                 ItemEnum::Macro(x) => self.check_macro(x),
78                 ItemEnum::ProcMacro(x) => self.check_proc_macro(x),
79                 ItemEnum::Primitive(x) => self.check_primitive_type(x),
80                 ItemEnum::Module(x) => self.check_module(x),
81                 // FIXME: Why don't these have their own structs?
82                 ItemEnum::ExternCrate { .. } => {}
83                 ItemEnum::AssocConst { type_, default: _ } => self.check_type(type_),
84                 ItemEnum::AssocType { generics, bounds, default } => {
85                     self.check_generics(generics);
86                     bounds.iter().for_each(|b| self.check_generic_bound(b));
87                     if let Some(ty) = default {
88                         self.check_type(ty);
89                     }
90                 }
91             }
92         } else {
93             assert!(self.krate.paths.contains_key(id));
94         }
95     }
96
97     // Core checkers
98     fn check_module(&mut self, module: &'a Module) {
99         module.items.iter().for_each(|i| self.add_mod_item_id(i));
100     }
101
102     fn check_import(&mut self, x: &'a Import) {
103         if x.glob {
104             self.add_mod_id(x.id.as_ref().unwrap());
105         } else if let Some(id) = &x.id {
106             self.add_mod_item_id(id);
107         }
108     }
109
110     fn check_union(&mut self, x: &'a Union) {
111         self.check_generics(&x.generics);
112         x.fields.iter().for_each(|i| self.add_field_id(i));
113         x.impls.iter().for_each(|i| self.add_impl_id(i));
114     }
115
116     fn check_struct(&mut self, x: &'a Struct) {
117         self.check_generics(&x.generics);
118         match &x.kind {
119             StructKind::Unit => {}
120             StructKind::Tuple(fields) => fields.iter().flatten().for_each(|f| self.add_field_id(f)),
121             StructKind::Plain { fields, fields_stripped: _ } => {
122                 fields.iter().for_each(|f| self.add_field_id(f))
123             }
124         }
125         x.impls.iter().for_each(|i| self.add_impl_id(i));
126     }
127
128     fn check_struct_field(&mut self, x: &'a Type) {
129         self.check_type(x);
130     }
131
132     fn check_enum(&mut self, x: &'a Enum) {
133         self.check_generics(&x.generics);
134         x.variants.iter().for_each(|i| self.add_variant_id(i));
135         x.impls.iter().for_each(|i| self.add_impl_id(i));
136     }
137
138     fn check_variant(&mut self, x: &'a Variant, id: &'a Id) {
139         match x {
140             Variant::Plain(discr) => {
141                 if let Some(discr) = discr {
142                     if let (Err(_), Err(_)) =
143                         (discr.value.parse::<i128>(), discr.value.parse::<u128>())
144                     {
145                         self.fail(
146                             id,
147                             ErrorKind::Custom(format!(
148                                 "Failed to parse discriminant value `{}`",
149                                 discr.value
150                             )),
151                         );
152                     }
153                 }
154             }
155             Variant::Tuple(tys) => tys.iter().flatten().for_each(|t| self.add_field_id(t)),
156             Variant::Struct { fields, fields_stripped: _ } => {
157                 fields.iter().for_each(|f| self.add_field_id(f))
158             }
159         }
160     }
161
162     fn check_function(&mut self, x: &'a Function) {
163         self.check_generics(&x.generics);
164         self.check_fn_decl(&x.decl);
165     }
166
167     fn check_trait(&mut self, x: &'a Trait) {
168         self.check_generics(&x.generics);
169         x.items.iter().for_each(|i| self.add_trait_item_id(i));
170         x.bounds.iter().for_each(|i| self.check_generic_bound(i));
171         x.implementations.iter().for_each(|i| self.add_impl_id(i));
172     }
173
174     fn check_trait_alias(&mut self, x: &'a TraitAlias) {
175         self.check_generics(&x.generics);
176         x.params.iter().for_each(|i| self.check_generic_bound(i));
177     }
178
179     fn check_method(&mut self, x: &'a Method) {
180         self.check_fn_decl(&x.decl);
181         self.check_generics(&x.generics);
182     }
183
184     fn check_impl(&mut self, x: &'a Impl) {
185         self.check_generics(&x.generics);
186         if let Some(path) = &x.trait_ {
187             self.check_path(path, PathKind::Trait);
188         }
189         self.check_type(&x.for_);
190         x.items.iter().for_each(|i| self.add_trait_item_id(i));
191         if let Some(blanket_impl) = &x.blanket_impl {
192             self.check_type(blanket_impl)
193         }
194     }
195
196     fn check_typedef(&mut self, x: &'a Typedef) {
197         self.check_generics(&x.generics);
198         self.check_type(&x.type_);
199     }
200
201     fn check_opaque_ty(&mut self, x: &'a OpaqueTy) {
202         x.bounds.iter().for_each(|b| self.check_generic_bound(b));
203         self.check_generics(&x.generics);
204     }
205
206     fn check_constant(&mut self, x: &'a Constant) {
207         self.check_type(&x.type_);
208     }
209
210     fn check_static(&mut self, x: &'a Static) {
211         self.check_type(&x.type_);
212     }
213
214     fn check_macro(&mut self, _: &'a str) {
215         // nop
216     }
217
218     fn check_proc_macro(&mut self, _: &'a ProcMacro) {
219         // nop
220     }
221
222     fn check_primitive_type(&mut self, x: &'a Primitive) {
223         x.impls.iter().for_each(|i| self.add_impl_id(i));
224     }
225
226     fn check_generics(&mut self, x: &'a Generics) {
227         x.params.iter().for_each(|p| self.check_generic_param_def(p));
228         x.where_predicates.iter().for_each(|w| self.check_where_predicate(w));
229     }
230
231     fn check_type(&mut self, x: &'a Type) {
232         match x {
233             Type::ResolvedPath(path) => self.check_path(path, PathKind::StructEnumUnion),
234             Type::DynTrait(dyn_trait) => self.check_dyn_trait(dyn_trait),
235             Type::Generic(_) => {}
236             Type::Primitive(_) => {}
237             Type::FunctionPointer(fp) => self.check_function_pointer(&**fp),
238             Type::Tuple(tys) => tys.iter().for_each(|ty| self.check_type(ty)),
239             Type::Slice(inner) => self.check_type(&**inner),
240             Type::Array { type_, len: _ } => self.check_type(&**type_),
241             Type::ImplTrait(bounds) => bounds.iter().for_each(|b| self.check_generic_bound(b)),
242             Type::Infer => {}
243             Type::RawPointer { mutable: _, type_ } => self.check_type(&**type_),
244             Type::BorrowedRef { lifetime: _, mutable: _, type_ } => self.check_type(&**type_),
245             Type::QualifiedPath { name: _, args, self_type, trait_ } => {
246                 self.check_generic_args(&**args);
247                 self.check_type(&**self_type);
248                 self.check_path(trait_, PathKind::Trait);
249             }
250         }
251     }
252
253     fn check_fn_decl(&mut self, x: &'a FnDecl) {
254         x.inputs.iter().for_each(|(_name, ty)| self.check_type(ty));
255         if let Some(output) = &x.output {
256             self.check_type(output);
257         }
258     }
259
260     fn check_generic_bound(&mut self, x: &'a GenericBound) {
261         match x {
262             GenericBound::TraitBound { trait_, generic_params, modifier: _ } => {
263                 self.check_path(trait_, PathKind::Trait);
264                 generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd));
265             }
266             GenericBound::Outlives(_) => {}
267         }
268     }
269
270     fn check_path(&mut self, x: &'a Path, kind: PathKind) {
271         match kind {
272             PathKind::Trait => self.add_trait_id(&x.id),
273             PathKind::StructEnumUnion => self.add_struct_enum_union_id(&x.id),
274         }
275         if let Some(args) = &x.args {
276             self.check_generic_args(&**args);
277         }
278     }
279
280     fn check_generic_args(&mut self, x: &'a GenericArgs) {
281         match x {
282             GenericArgs::AngleBracketed { args, bindings } => {
283                 args.iter().for_each(|arg| self.check_generic_arg(arg));
284                 bindings.iter().for_each(|bind| self.check_type_binding(bind));
285             }
286             GenericArgs::Parenthesized { inputs, output } => {
287                 inputs.iter().for_each(|ty| self.check_type(ty));
288                 if let Some(o) = output {
289                     self.check_type(o);
290                 }
291             }
292         }
293     }
294
295     fn check_generic_param_def(&mut self, gpd: &'a GenericParamDef) {
296         match &gpd.kind {
297             rustdoc_json_types::GenericParamDefKind::Lifetime { outlives: _ } => {}
298             rustdoc_json_types::GenericParamDefKind::Type { bounds, default, synthetic: _ } => {
299                 bounds.iter().for_each(|b| self.check_generic_bound(b));
300                 if let Some(ty) = default {
301                     self.check_type(ty);
302                 }
303             }
304             rustdoc_json_types::GenericParamDefKind::Const { type_, default: _ } => {
305                 self.check_type(type_)
306             }
307         }
308     }
309
310     fn check_generic_arg(&mut self, arg: &'a GenericArg) {
311         match arg {
312             GenericArg::Lifetime(_) => {}
313             GenericArg::Type(ty) => self.check_type(ty),
314             GenericArg::Const(c) => self.check_constant(c),
315             GenericArg::Infer => {}
316         }
317     }
318
319     fn check_type_binding(&mut self, bind: &'a TypeBinding) {
320         self.check_generic_args(&bind.args);
321         match &bind.binding {
322             TypeBindingKind::Equality(term) => self.check_term(term),
323             TypeBindingKind::Constraint(bounds) => {
324                 bounds.iter().for_each(|b| self.check_generic_bound(b))
325             }
326         }
327     }
328
329     fn check_term(&mut self, term: &'a Term) {
330         match term {
331             Term::Type(ty) => self.check_type(ty),
332             Term::Constant(con) => self.check_constant(con),
333         }
334     }
335
336     fn check_where_predicate(&mut self, w: &'a WherePredicate) {
337         match w {
338             WherePredicate::BoundPredicate { type_, bounds, generic_params } => {
339                 self.check_type(type_);
340                 bounds.iter().for_each(|b| self.check_generic_bound(b));
341                 generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd));
342             }
343             WherePredicate::RegionPredicate { lifetime: _, bounds } => {
344                 bounds.iter().for_each(|b| self.check_generic_bound(b));
345             }
346             WherePredicate::EqPredicate { lhs, rhs } => {
347                 self.check_type(lhs);
348                 self.check_term(rhs);
349             }
350         }
351     }
352
353     fn check_dyn_trait(&mut self, dyn_trait: &'a DynTrait) {
354         for pt in &dyn_trait.traits {
355             self.check_path(&pt.trait_, PathKind::Trait);
356             pt.generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd));
357         }
358     }
359
360     fn check_function_pointer(&mut self, fp: &'a FunctionPointer) {
361         self.check_fn_decl(&fp.decl);
362         fp.generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd));
363     }
364
365     fn add_id_checked(&mut self, id: &'a Id, valid: fn(Kind) -> bool, expected: &str) {
366         if let Some(kind) = self.kind_of(id) {
367             if valid(kind) {
368                 if !self.seen_ids.contains(id) {
369                     self.todo.insert(id);
370                 }
371             } else {
372                 self.fail_expecting(id, expected);
373             }
374         } else {
375             if !self.missing_ids.contains(id) {
376                 self.missing_ids.insert(id);
377                 self.fail(id, ErrorKind::NotFound)
378             }
379         }
380     }
381
382     fn add_field_id(&mut self, id: &'a Id) {
383         self.add_id_checked(id, Kind::is_struct_field, "StructField");
384     }
385
386     fn add_mod_id(&mut self, id: &'a Id) {
387         self.add_id_checked(id, Kind::is_module, "Module");
388     }
389     fn add_impl_id(&mut self, id: &'a Id) {
390         self.add_id_checked(id, Kind::is_impl, "Impl");
391     }
392
393     fn add_variant_id(&mut self, id: &'a Id) {
394         self.add_id_checked(id, Kind::is_variant, "Variant");
395     }
396
397     fn add_trait_id(&mut self, id: &'a Id) {
398         self.add_id_checked(id, Kind::is_trait, "Trait");
399     }
400
401     fn add_struct_enum_union_id(&mut self, id: &'a Id) {
402         self.add_id_checked(id, Kind::is_struct_enum_union, "Struct or Enum or Union");
403     }
404
405     /// Add an Id that appeared in a trait
406     fn add_trait_item_id(&mut self, id: &'a Id) {
407         self.add_id_checked(id, Kind::can_appear_in_trait, "Trait inner item");
408     }
409
410     /// Add an Id that appeared in a mod
411     fn add_mod_item_id(&mut self, id: &'a Id) {
412         self.add_id_checked(id, Kind::can_appear_in_mod, "Module inner item")
413     }
414
415     fn fail_expecting(&mut self, id: &Id, expected: &str) {
416         let kind = self.kind_of(id).unwrap(); // We know it has a kind, as it's wrong.
417         self.fail(id, ErrorKind::Custom(format!("Expected {expected} but found {kind:?}")));
418     }
419
420     fn fail(&mut self, id: &Id, kind: ErrorKind) {
421         self.errs.push(Error { id: id.clone(), kind });
422     }
423
424     fn kind_of(&mut self, id: &Id) -> Option<Kind> {
425         if let Some(item) = self.krate.index.get(id) {
426             Some(Kind::from_item(item))
427         } else if let Some(summary) = self.krate.paths.get(id) {
428             Some(Kind::from_summary(summary))
429         } else {
430             None
431         }
432     }
433 }
434
435 fn set_remove<T: Hash + Eq + Clone>(set: &mut HashSet<T>) -> Option<T> {
436     if let Some(id) = set.iter().next() {
437         let id = id.clone();
438         set.take(&id)
439     } else {
440         None
441     }
442 }