Skip to content

Commit a9dba83

Browse files
Add check to ensure there are no duplicates in rustdoc JSON output format in items fields
1 parent bd4a96a commit a9dba83

File tree

1 file changed

+22
-6
lines changed

1 file changed

+22
-6
lines changed

src/tools/jsondoclint/src/validator.rs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,19 @@ impl<'a> Validator<'a> {
7171
}
7272
}
7373

74+
fn check_items(&mut self, id: &Id, items: &[Id]) {
75+
let mut visited_ids = HashSet::with_capacity(items.len());
76+
77+
for item in items {
78+
if !visited_ids.insert(item) {
79+
self.fail(
80+
id,
81+
ErrorKind::Custom(format!("Duplicated entry in `items` field: `{item:?}`")),
82+
);
83+
}
84+
}
85+
}
86+
7487
fn check_item(&mut self, id: &'a Id) {
7588
if let Some(item) = &self.krate.index.get(id) {
7689
item.links.values().for_each(|id| self.add_any_id(id));
@@ -83,9 +96,9 @@ impl<'a> Validator<'a> {
8396
ItemEnum::Enum(x) => self.check_enum(x),
8497
ItemEnum::Variant(x) => self.check_variant(x, id),
8598
ItemEnum::Function(x) => self.check_function(x),
86-
ItemEnum::Trait(x) => self.check_trait(x),
99+
ItemEnum::Trait(x) => self.check_trait(x, id),
87100
ItemEnum::TraitAlias(x) => self.check_trait_alias(x),
88-
ItemEnum::Impl(x) => self.check_impl(x),
101+
ItemEnum::Impl(x) => self.check_impl(x, id),
89102
ItemEnum::Typedef(x) => self.check_typedef(x),
90103
ItemEnum::OpaqueTy(x) => self.check_opaque_ty(x),
91104
ItemEnum::Constant(x) => self.check_constant(x),
@@ -94,7 +107,7 @@ impl<'a> Validator<'a> {
94107
ItemEnum::Macro(x) => self.check_macro(x),
95108
ItemEnum::ProcMacro(x) => self.check_proc_macro(x),
96109
ItemEnum::Primitive(x) => self.check_primitive_type(x),
97-
ItemEnum::Module(x) => self.check_module(x),
110+
ItemEnum::Module(x) => self.check_module(x, id),
98111
// FIXME: Why don't these have their own structs?
99112
ItemEnum::ExternCrate { .. } => {}
100113
ItemEnum::AssocConst { type_, default: _ } => self.check_type(type_),
@@ -112,7 +125,8 @@ impl<'a> Validator<'a> {
112125
}
113126

114127
// Core checkers
115-
fn check_module(&mut self, module: &'a Module) {
128+
fn check_module(&mut self, module: &'a Module, id: &Id) {
129+
self.check_items(id, &module.items);
116130
module.items.iter().for_each(|i| self.add_mod_item_id(i));
117131
}
118132

@@ -181,7 +195,8 @@ impl<'a> Validator<'a> {
181195
self.check_fn_decl(&x.decl);
182196
}
183197

184-
fn check_trait(&mut self, x: &'a Trait) {
198+
fn check_trait(&mut self, x: &'a Trait, id: &Id) {
199+
self.check_items(id, &x.items);
185200
self.check_generics(&x.generics);
186201
x.items.iter().for_each(|i| self.add_trait_item_id(i));
187202
x.bounds.iter().for_each(|i| self.check_generic_bound(i));
@@ -193,7 +208,8 @@ impl<'a> Validator<'a> {
193208
x.params.iter().for_each(|i| self.check_generic_bound(i));
194209
}
195210

196-
fn check_impl(&mut self, x: &'a Impl) {
211+
fn check_impl(&mut self, x: &'a Impl, id: &Id) {
212+
self.check_items(id, &x.items);
197213
self.check_generics(&x.generics);
198214
if let Some(path) = &x.trait_ {
199215
self.check_path(path, PathKind::Trait);

0 commit comments

Comments
 (0)