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, Method, Module, OpaqueTy,
7 Path, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type, TypeBinding,
8 TypeBindingKind, Typedef, Union, Variant, WherePredicate,
11 use crate::{item_kind::can_appear_in_mod, Error};
14 pub struct Validator<'a> {
15 pub(crate) errs: Vec<Error>,
17 seen_ids: HashSet<&'a Id>,
18 todo: HashSet<&'a Id>,
21 fn set_remove<T: Hash + Eq + Clone>(set: &mut HashSet<T>) -> Option<T> {
22 if let Some(id) = set.iter().next() {
30 impl<'a> Validator<'a> {
31 pub fn new(krate: &'a Crate) -> Self {
32 Self { krate, errs: Vec::new(), seen_ids: HashSet::new(), todo: HashSet::new() }
35 pub fn check_crate(&mut self) {
36 let root = &self.krate.root;
37 self.add_mod_id(root);
38 while let Some(id) = set_remove(&mut self.todo) {
39 self.seen_ids.insert(id);
44 fn check_item(&mut self, id: &'a Id) {
45 let item = &self.krate.index[id];
47 ItemEnum::Import(x) => self.check_import(x),
48 ItemEnum::Union(x) => self.check_union(x),
49 ItemEnum::Struct(x) => self.check_struct(x),
50 ItemEnum::StructField(x) => self.check_struct_field(x),
51 ItemEnum::Enum(x) => self.check_enum(x),
52 ItemEnum::Variant(x) => self.check_variant(x),
53 ItemEnum::Function(x) => self.check_function(x),
54 ItemEnum::Trait(x) => self.check_trait(x),
55 ItemEnum::TraitAlias(x) => self.check_trait_alias(x),
56 ItemEnum::Method(x) => self.check_method(x),
57 ItemEnum::Impl(x) => self.check_impl(x),
58 ItemEnum::Typedef(x) => self.check_typedef(x),
59 ItemEnum::OpaqueTy(x) => self.check_opaque_ty(x),
60 ItemEnum::Constant(x) => self.check_constant(x),
61 ItemEnum::Static(x) => self.check_static(x),
62 ItemEnum::ForeignType => todo!(),
63 ItemEnum::Macro(x) => self.check_macro(x),
64 ItemEnum::ProcMacro(x) => self.check_proc_macro(x),
65 ItemEnum::PrimitiveType(x) => self.check_primitive_type(x),
66 ItemEnum::Module(x) => self.check_module(x),
68 ItemEnum::ExternCrate { .. } => todo!(),
69 ItemEnum::AssocConst { .. } => todo!(),
70 ItemEnum::AssocType { .. } => todo!(),
75 fn check_module(&mut self, module: &'a Module) {
76 module.items.iter().for_each(|i| self.add_mod_item_id(i));
79 fn check_import(&mut self, x: &'a Import) {
81 self.add_mod_id(x.id.as_ref().unwrap());
82 } else if let Some(id) = &x.id {
83 self.add_mod_item_id(id);
87 fn check_union(&mut self, x: &'a Union) {
88 self.check_generics(&x.generics);
89 x.fields.iter().for_each(|i| self.add_field_id(i));
90 x.impls.iter().for_each(|i| self.add_impl_id(i));
93 fn check_struct(&mut self, x: &'a Struct) {
94 self.check_generics(&x.generics);
96 StructKind::Unit => {}
97 StructKind::Tuple(fields) => fields.iter().flatten().for_each(|f| self.add_field_id(f)),
98 StructKind::Plain { fields, fields_stripped: _ } => {
99 fields.iter().for_each(|f| self.add_field_id(f))
102 x.impls.iter().for_each(|i| self.add_impl_id(i));
105 fn check_struct_field(&mut self, x: &'a Type) {
109 fn check_enum(&mut self, x: &'a Enum) {
110 self.check_generics(&x.generics);
111 x.variants.iter().for_each(|i| self.add_variant_id(i));
112 x.impls.iter().for_each(|i| self.add_impl_id(i));
115 fn check_variant(&mut self, x: &'a Variant) {
117 Variant::Plain(_discriminant) => {} // TODO: Check discriminant value parses
118 Variant::Tuple(tys) => tys.iter().flatten().for_each(|t| self.add_field_id(t)),
119 Variant::Struct { fields, fields_stripped: _ } => {
120 fields.iter().for_each(|f| self.add_field_id(f))
125 fn check_function(&mut self, x: &'a Function) {
126 self.check_generics(&x.generics);
127 self.check_fn_decl(&x.decl);
130 fn check_trait(&mut self, x: &'a Trait) {
131 self.check_generics(&x.generics);
132 x.items.iter().for_each(|i| self.add_trait_item_id(i));
133 x.bounds.iter().for_each(|i| self.check_generic_bound(i));
134 x.implementations.iter().for_each(|i| self.add_impl_id(i));
137 fn check_trait_alias(&mut self, x: &'a TraitAlias) {
138 self.check_generics(&x.generics);
139 x.params.iter().for_each(|i| self.check_generic_bound(i));
142 fn check_method(&mut self, x: &'a Method) {
143 self.check_fn_decl(&x.decl);
144 self.check_generics(&x.generics);
147 fn check_impl(&mut self, x: &'a Impl) {
148 self.check_generics(&x.generics);
149 if let Some(path) = &x.trait_ {
150 self.check_path(path); // TODO: Check is trait.
152 self.check_type(&x.for_);
153 x.items.iter().for_each(|i| self.add_trait_item_id(i));
154 if let Some(blanket_impl) = &x.blanket_impl {
155 self.check_type(blanket_impl)
159 fn check_typedef(&mut self, x: &'a Typedef) {
160 self.check_generics(&x.generics);
161 self.check_type(&x.type_);
164 fn check_opaque_ty(&mut self, x: &'a OpaqueTy) {
165 x.bounds.iter().for_each(|b| self.check_generic_bound(b));
166 self.check_generics(&x.generics);
169 fn check_constant(&mut self, x: &'a Constant) {
170 self.check_type(&x.type_);
173 fn check_static(&mut self, x: &'a Static) {
174 self.check_type(&x.type_);
177 fn check_macro(&mut self, _: &'a str) {
181 fn check_proc_macro(&mut self, _: &'a ProcMacro) {
185 fn check_primitive_type(&mut self, _: &'a str) {
189 fn check_generics(&mut self, x: &'a Generics) {
190 x.params.iter().for_each(|p| self.check_generic_param_def(p));
191 x.where_predicates.iter().for_each(|w| self.check_where_predicate(w));
194 fn check_type(&mut self, x: &'a Type) {
196 Type::ResolvedPath(path) => self.check_path(path),
197 Type::DynTrait(dyn_trait) => self.check_dyn_trait(dyn_trait),
198 Type::Generic(_) => {}
199 Type::Primitive(_) => {}
200 Type::FunctionPointer(fp) => self.check_function_pointer(&**fp),
201 Type::Tuple(tys) => tys.iter().for_each(|ty| self.check_type(ty)),
202 Type::Slice(inner) => self.check_type(&**inner),
203 Type::Array { type_, len: _ } => self.check_type(&**type_),
204 Type::ImplTrait(bounds) => bounds.iter().for_each(|b| self.check_generic_bound(b)),
206 Type::RawPointer { mutable: _, type_ } => self.check_type(&**type_),
207 Type::BorrowedRef { lifetime: _, mutable: _, type_ } => self.check_type(&**type_),
208 Type::QualifiedPath { name: _, args, self_type, trait_ } => {
209 self.check_generic_args(&**args);
210 self.check_type(&**self_type);
211 self.check_path(trait_);
216 fn check_fn_decl(&mut self, x: &'a FnDecl) {
217 x.inputs.iter().for_each(|(_name, ty)| self.check_type(ty));
218 if let Some(output) = &x.output {
219 self.check_type(output);
223 fn check_generic_bound(&mut self, x: &'a GenericBound) {
225 GenericBound::TraitBound { trait_, generic_params, modifier: _ } => {
226 self.check_path(trait_);
227 generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd));
229 GenericBound::Outlives(_) => todo!(),
233 fn check_path(&mut self, x: &'a Path) {
234 self.add_id(&x.id); // TODO: What kinds are allowed here.
235 if let Some(args) = &x.args {
236 self.check_generic_args(&**args);
240 fn check_generic_args(&mut self, x: &'a GenericArgs) {
242 GenericArgs::AngleBracketed { args, bindings } => {
243 args.iter().for_each(|arg| self.check_generic_arg(arg));
244 bindings.iter().for_each(|bind| self.check_type_binding(bind));
246 GenericArgs::Parenthesized { inputs, output } => {
247 inputs.iter().for_each(|ty| self.check_type(ty));
248 if let Some(o) = output {
255 fn check_generic_param_def(&mut self, gpd: &'a GenericParamDef) {
257 rustdoc_json_types::GenericParamDefKind::Lifetime { outlives: _ } => {}
258 rustdoc_json_types::GenericParamDefKind::Type { bounds, default, synthetic: _ } => {
259 bounds.iter().for_each(|b| self.check_generic_bound(b));
260 if let Some(ty) = default {
264 rustdoc_json_types::GenericParamDefKind::Const { type_, default: _ } => {
265 self.check_type(type_)
270 fn check_generic_arg(&mut self, arg: &'a GenericArg) {
272 GenericArg::Lifetime(_) => {}
273 GenericArg::Type(ty) => self.check_type(ty),
274 GenericArg::Const(c) => self.check_constant(c),
275 GenericArg::Infer => {}
279 fn check_type_binding(&mut self, bind: &'a TypeBinding) {
280 self.check_generic_args(&bind.args);
281 match &bind.binding {
282 TypeBindingKind::Equality(term) => self.check_term(term),
283 TypeBindingKind::Constraint(bounds) => {
284 bounds.iter().for_each(|b| self.check_generic_bound(b))
289 fn check_term(&mut self, term: &'a Term) {
291 Term::Type(ty) => self.check_type(ty),
292 Term::Constant(con) => self.check_constant(con),
296 fn check_where_predicate(&mut self, w: &'a WherePredicate) {
298 WherePredicate::BoundPredicate { type_, bounds, generic_params } => {
299 self.check_type(type_);
300 bounds.iter().for_each(|b| self.check_generic_bound(b));
301 generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd));
303 WherePredicate::RegionPredicate { lifetime: _, bounds } => {
304 bounds.iter().for_each(|b| self.check_generic_bound(b));
306 WherePredicate::EqPredicate { lhs, rhs } => {
307 self.check_type(lhs);
308 self.check_term(rhs);
313 fn check_dyn_trait(&mut self, dyn_trait: &'a DynTrait) {
314 for pt in &dyn_trait.traits {
315 self.check_path(&pt.trait_);
316 pt.generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd));
320 fn check_function_pointer(&mut self, fp: &'a FunctionPointer) {
321 self.check_fn_decl(&fp.decl);
322 fp.generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd));
326 fn add_id(&mut self, id: &'a Id) {
327 if !self.seen_ids.contains(id) {
328 self.todo.insert(id);
332 fn add_field_id(&mut self, id: &'a Id) {
333 let item = &self.krate.index[id];
334 if let ItemEnum::StructField(_) = item.inner {
337 self.fail(id, "Expecting field");
341 fn add_mod_id(&mut self, id: &'a Id) {
342 let item = &self.krate.index[id];
343 if let ItemEnum::Module(_) = item.inner {
346 self.fail(id, "Expecting module");
350 fn add_impl_id(&mut self, id: &'a Id) {
351 let item = &self.krate.index[id];
352 if let ItemEnum::StructField(_) = item.inner {
355 self.fail(id, "Expecting impl");
359 fn add_variant_id(&mut self, id: &'a Id) {
360 let item = &self.krate.index[id];
361 if let ItemEnum::StructField(_) = item.inner {
364 self.fail(id, "Expecting variant");
368 /// Add an Id that appeared in a trait
369 fn add_trait_item_id(&mut self, id: &'a Id) {
370 let item = &self.krate.index[id];
371 if !can_appear_in_mod(&item.inner) {
372 self.fail(id, "Expecting item that can appear in trait");
378 /// Add an Id that appeared in a mod
379 fn add_mod_item_id(&mut self, id: &'a Id) {
380 let item = &self.krate.index[id];
381 if can_appear_in_mod(&item.inner) {
384 self.fail(id, "Expecting item that can appear in trait");
388 fn fail(&mut self, id: &Id, msg: &str) {
389 self.errs.push(Error { id: id.clone(), message: msg.to_string() });