diff --git a/src/test/rustdoc-json/nested.rs b/src/test/rustdoc-json/nested.rs index b0e717d8a86..9ff1f60c0d5 100644 --- a/src/test/rustdoc-json/nested.rs +++ b/src/test/rustdoc-json/nested.rs @@ -4,27 +4,28 @@ // @is nested.json "$.crate_version" \"1.0.0\" // @is - "$.index[*][?(@.name=='nested')].kind" \"module\" // @is - "$.index[*][?(@.name=='nested')].inner.is_crate" true -// @count - "$.index[*][?(@.name=='nested')].inner.items[*]" 1 + +// @set l1_id = - "$.index[*][?(@.name=='l1')].id" +// @ismany - "$.index[*][?(@.name=='nested')].inner.items[*]" $l1_id // @is nested.json "$.index[*][?(@.name=='l1')].kind" \"module\" // @is - "$.index[*][?(@.name=='l1')].inner.is_crate" false -// @count - "$.index[*][?(@.name=='l1')].inner.items[*]" 2 pub mod l1 { - // @is nested.json "$.index[*][?(@.name=='l3')].kind" \"module\" // @is - "$.index[*][?(@.name=='l3')].inner.is_crate" false - // @count - "$.index[*][?(@.name=='l3')].inner.items[*]" 1 // @set l3_id = - "$.index[*][?(@.name=='l3')].id" - // @has - "$.index[*][?(@.name=='l1')].inner.items[*]" $l3_id pub mod l3 { // @is nested.json "$.index[*][?(@.name=='L4')].kind" \"struct\" // @is - "$.index[*][?(@.name=='L4')].inner.struct_type" \"unit\" // @set l4_id = - "$.index[*][?(@.name=='L4')].id" - // @has - "$.index[*][?(@.name=='l3')].inner.items[*]" $l4_id + // @ismany - "$.index[*][?(@.name=='l3')].inner.items[*]" $l4_id pub struct L4; } // @is nested.json "$.index[*][?(@.inner.source=='l3::L4')].kind" \"import\" // @is - "$.index[*][?(@.inner.source=='l3::L4')].inner.glob" false + // @is - "$.index[*][?(@.inner.source=='l3::L4')].inner.id" $l4_id + // @set l4_use_id = - "$.index[*][?(@.inner.source=='l3::L4')].id" pub use l3::L4; } +// @ismany - "$.index[*][?(@.name=='l1')].inner.items[*]" $l3_id $l4_use_id diff --git a/src/test/rustdoc-json/reexport/glob_extern.rs b/src/test/rustdoc-json/reexport/glob_extern.rs index ba1cfd8a0b5..4fe25904423 100644 --- a/src/test/rustdoc-json/reexport/glob_extern.rs +++ b/src/test/rustdoc-json/reexport/glob_extern.rs @@ -4,15 +4,20 @@ #![feature(no_core)] // @is glob_extern.json "$.index[*][?(@.name=='mod1')].kind" \"module\" -// @is glob_extern.json "$.index[*][?(@.name=='mod1')].inner.is_stripped" "true" +// @is - "$.index[*][?(@.name=='mod1')].inner.is_stripped" "true" mod mod1 { extern "C" { - // @has - "$.index[*][?(@.name=='public_fn')].id" + // @set public_fn_id = - "$.index[*][?(@.name=='public_fn')].id" pub fn public_fn(); // @!has - "$.index[*][?(@.name=='private_fn')]" fn private_fn(); } + // @ismany - "$.index[*][?(@.name=='mod1')].inner.items[*]" $public_fn_id + // @set mod1_id = - "$.index[*][?(@.name=='mod1')].id" } // @is - "$.index[*][?(@.kind=='import')].inner.glob" true +// @is - "$.index[*][?(@.kind=='import')].inner.id" $mod1_id +// @set use_id = - "$.index[*][?(@.kind=='import')].id" +// @ismany - "$.index[*][?(@.name=='glob_extern')].inner.items[*]" $use_id pub use mod1::*; diff --git a/src/test/rustdoc-json/reexport/glob_private.rs b/src/test/rustdoc-json/reexport/glob_private.rs index e6a44748c25..04460a817f1 100644 --- a/src/test/rustdoc-json/reexport/glob_private.rs +++ b/src/test/rustdoc-json/reexport/glob_private.rs @@ -16,7 +16,7 @@ mod mod1 { struct Mod2Private; } - // @has - "$.index[*][?(@.kind=='import' && @.inner.name=='mod2')]" + // @set mod2_use_id = - "$.index[*][?(@.kind=='import' && @.inner.name=='mod2')].id" pub use self::mod2::*; // @set m1pub_id = - "$.index[*][?(@.name=='Mod1Public')].id" @@ -25,8 +25,9 @@ mod mod1 { struct Mod1Private; } -// @has - "$.index[*][?(@.kind=='import' && @.inner.name=='mod1')]" +// @set mod1_use_id = - "$.index[*][?(@.kind=='import' && @.inner.name=='mod1')].id" pub use mod1::*; -// @has - "$.index[*][?(@.name=='mod2')].inner.items[*]" $m2pub_id -// @has - "$.index[*][?(@.name=='mod1')].inner.items[*]" $m1pub_id +// @ismany - "$.index[*][?(@.name=='mod2')].inner.items[*]" $m2pub_id +// @ismany - "$.index[*][?(@.name=='mod1')].inner.items[*]" $m1pub_id $mod2_use_id +// @ismany - "$.index[*][?(@.name=='glob_private')].inner.items[*]" $mod1_use_id diff --git a/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs b/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs index 2daadf7620c..09302ee3acb 100644 --- a/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs +++ b/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs @@ -3,7 +3,7 @@ pub mod foo { // @set bar_id = in_root_and_mod_pub.json "$.index[*][?(@.name=='Bar')].id" - // @has - "$.index[*][?(@.name=='foo')].inner.items[*]" $bar_id + // @ismany - "$.index[*][?(@.name=='foo')].inner.items[*]" $bar_id pub struct Bar; } @@ -15,6 +15,6 @@ pub use foo::Bar; pub mod baz { // @set baz_import_id = - "$.index[*][?(@.inner.source=='crate::foo::Bar')].id" // @is - "$.index[*][?(@.inner.source=='crate::foo::Bar')].inner.id" $bar_id - // @has - "$.index[*][?(@.name=='baz')].inner.items[*]" $baz_import_id + // @ismany - "$.index[*][?(@.name=='baz')].inner.items[*]" $baz_import_id pub use crate::foo::Bar; } diff --git a/src/test/rustdoc-json/reexport/macro.rs b/src/test/rustdoc-json/reexport/macro.rs index b86614ffbad..0959736f309 100644 --- a/src/test/rustdoc-json/reexport/macro.rs +++ b/src/test/rustdoc-json/reexport/macro.rs @@ -3,15 +3,13 @@ #![no_core] #![feature(no_core)] -// @count macro.json "$.index[*][?(@.name=='macro')].inner.items[*]" 2 - // @set repro_id = macro.json "$.index[*][?(@.name=='repro')].id" -// @has - "$.index[*][?(@.name=='macro')].inner.items[*]" $repro_id #[macro_export] macro_rules! repro { () => {}; } // @set repro2_id = macro.json "$.index[*][?(@.inner.name=='repro2')].id" -// @has - "$.index[*][?(@.name=='macro')].inner.items[*]" $repro2_id pub use crate::repro as repro2; + +// @ismany macro.json "$.index[*][?(@.name=='macro')].inner.items[*]" $repro_id $repro2_id diff --git a/src/test/rustdoc-json/reexport/private_twice_one_inline.rs b/src/test/rustdoc-json/reexport/private_twice_one_inline.rs index 327b0f45fdd..a76d352b28b 100644 --- a/src/test/rustdoc-json/reexport/private_twice_one_inline.rs +++ b/src/test/rustdoc-json/reexport/private_twice_one_inline.rs @@ -1,18 +1,28 @@ // aux-build:pub-struct.rs +// ignore-tidy-linelength -// Test for the ICE in rust/83057 -// Am external type re-exported with different attributes shouldn't cause an error +// Test for the ICE in https://github.com/rust-lang/rust/issues/83057 +// An external type re-exported with different attributes shouldn't cause an error #![no_core] #![feature(no_core)] extern crate pub_struct as foo; - #[doc(inline)] + +// @set crate_use_id = private_twice_one_inline.json "$.index[*][?(@.docs=='Hack A')].id" +// @set foo_id = - "$.index[*][?(@.docs=='Hack A')].inner.id" +/// Hack A pub use foo::Foo; +// @set bar_id = - "$.index[*][?(@.name=='bar')].id" pub mod bar { + // @is - "$.index[*][?(@.docs=='Hack B')].inner.id" $foo_id + // @set bar_use_id = - "$.index[*][?(@.docs=='Hack B')].id" + // @ismany - "$.index[*][?(@.name=='bar')].inner.items[*]" $bar_use_id + /// Hack B pub use foo::Foo; } -// @count private_twice_one_inline.json "$.index[*][?(@.kind=='import')]" 2 +// @ismany - "$.index[*][?(@.kind=='import')].id" $crate_use_id $bar_use_id +// @ismany - "$.index[*][?(@.name=='private_twice_one_inline')].inner.items[*]" $bar_id $crate_use_id diff --git a/src/test/rustdoc-json/reexport/private_two_names.rs b/src/test/rustdoc-json/reexport/private_two_names.rs index 36d6a50d385..cd8212cf344 100644 --- a/src/test/rustdoc-json/reexport/private_two_names.rs +++ b/src/test/rustdoc-json/reexport/private_two_names.rs @@ -1,4 +1,6 @@ -// Test for the ICE in rust/83720 +// ignore-tidy-linelength + +// Test for the ICE in https://github.com/rust-lang/rust/issues/83720 // A pub-in-private type re-exported under two different names shouldn't cause an error #![no_core] @@ -7,11 +9,15 @@ // @is private_two_names.json "$.index[*][?(@.name=='style')].kind" \"module\" // @is private_two_names.json "$.index[*][?(@.name=='style')].inner.is_stripped" "true" mod style { - // @has - "$.index[*](?(@.name=='Color'))" + // @set color_struct_id = - "$.index[*][?(@.kind=='struct' && @.name=='Color')].id" pub struct Color; } -// @has - "$.index[*][?(@.kind=='import' && @.inner.name=='Color')]" +// @is - "$.index[*][?(@.kind=='import' && @.inner.name=='Color')].inner.id" $color_struct_id +// @set color_export_id = - "$.index[*][?(@.kind=='import' && @.inner.name=='Color')].id" pub use style::Color; -// @has - "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')]" +// @is - "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')].inner.id" $color_struct_id +// @set colour_export_id = - "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')].id" pub use style::Color as Colour; + +// @ismany - "$.index[*][?(@.name=='private_two_names')].inner.items[*]" $color_export_id $colour_export_id diff --git a/src/test/rustdoc-json/reexport/rename_public.rs b/src/test/rustdoc-json/reexport/rename_public.rs index 2dd438d2230..d41556974b4 100644 --- a/src/test/rustdoc-json/reexport/rename_public.rs +++ b/src/test/rustdoc-json/reexport/rename_public.rs @@ -4,14 +4,14 @@ #![feature(no_core)] // @set inner_id = rename_public.json "$.index[*][?(@.name=='inner')].id" -// @has - "$.index[*][?(@.name=='rename_public')].inner.items[*]" $inner_id pub mod inner { // @set public_id = - "$.index[*][?(@.name=='Public')].id" - // @has - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id + // @ismany - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id pub struct Public; } // @set import_id = - "$.index[*][?(@.inner.name=='NewName')].id" // @!has - "$.index[*][?(@.inner.name=='Public')]" -// @has - "$.index[*][?(@.name=='rename_public')].inner.items[*]" $import_id // @is - "$.index[*][?(@.inner.name=='NewName')].inner.source" \"inner::Public\" pub use inner::Public as NewName; + +// @ismany - "$.index[*][?(@.name=='rename_public')].inner.items[*]" $inner_id $import_id diff --git a/src/test/rustdoc-json/reexport/same_type_reexported_more_than_once.rs b/src/test/rustdoc-json/reexport/same_type_reexported_more_than_once.rs index eedddd6a7bb..1d76c7e139b 100644 --- a/src/test/rustdoc-json/reexport/same_type_reexported_more_than_once.rs +++ b/src/test/rustdoc-json/reexport/same_type_reexported_more_than_once.rs @@ -1,3 +1,5 @@ +// ignore-tidy-linelength + // Regression test for . #![feature(no_core)] @@ -5,11 +7,17 @@ #![no_core] // @has same_type_reexported_more_than_once.json -// @has - "$.index[*][?(@.name=='Trait')]" -pub use inner::Trait; -// @has - "$.index[*].inner[?(@.name=='Reexport')].id" -pub use inner::Trait as Reexport; mod inner { + // @set trait_id = - "$.index[*][?(@.name=='Trait')].id" pub trait Trait {} } + +// @set export_id = - "$.index[*][?(@.inner.name=='Trait')].id" +// @is - "$.index[*][?(@.inner.name=='Trait')].inner.id" $trait_id +pub use inner::Trait; +// @set reexport_id = - "$.index[*][?(@.inner.name=='Reexport')].id" +// @is - "$.index[*][?(@.inner.name=='Reexport')].inner.id" $trait_id +pub use inner::Trait as Reexport; + +// @ismany - "$.index[*][?(@.name=='same_type_reexported_more_than_once')].inner.items[*]" $reexport_id $export_id diff --git a/src/test/rustdoc-json/reexport/simple_private.rs b/src/test/rustdoc-json/reexport/simple_private.rs index 5ec13e403ae..55523bcd1de 100644 --- a/src/test/rustdoc-json/reexport/simple_private.rs +++ b/src/test/rustdoc-json/reexport/simple_private.rs @@ -10,6 +10,8 @@ mod inner { } // @is - "$.index[*][?(@.kind=='import')].inner.name" \"Public\" +// @set use_id = - "$.index[*][?(@.kind=='import')].id" pub use inner::Public; -// @has - "$.index[*][?(@.name=='inner')].inner.items[*]" $pub_id +// @ismany - "$.index[*][?(@.name=='inner')].inner.items[*]" $pub_id +// @ismany - "$.index[*][?(@.name=='simple_private')].inner.items[*]" $use_id diff --git a/src/test/rustdoc-json/reexport/simple_public.rs b/src/test/rustdoc-json/reexport/simple_public.rs index 2e4de301f6f..a3156a2b33a 100644 --- a/src/test/rustdoc-json/reexport/simple_public.rs +++ b/src/test/rustdoc-json/reexport/simple_public.rs @@ -4,15 +4,15 @@ #![feature(no_core)] // @set inner_id = simple_public.json "$.index[*][?(@.name=='inner')].id" -// @has - "$.index[*][?(@.name=='simple_public')].inner.items[*]" $inner_id pub mod inner { // @set public_id = - "$.index[*][?(@.name=='Public')].id" - // @has - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id + // @ismany - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id pub struct Public; } // @set import_id = - "$.index[*][?(@.inner.name=='Public')].id" -// @has - "$.index[*][?(@.name=='simple_public')].inner.items[*]" $import_id // @is - "$.index[*][?(@.inner.name=='Public')].inner.source" \"inner::Public\" pub use inner::Public; + +// @ismany - "$.index[*][?(@.name=='simple_public')].inner.items[*]" $import_id $inner_id diff --git a/src/test/rustdoc-json/type/fn_lifetime.rs b/src/test/rustdoc-json/type/fn_lifetime.rs index e0d1e9649a0..fd49a0890c0 100644 --- a/src/test/rustdoc-json/type/fn_lifetime.rs +++ b/src/test/rustdoc-json/type/fn_lifetime.rs @@ -2,8 +2,7 @@ // @is fn_lifetime.json "$.index[*][?(@.name=='GenericFn')].kind" \"typedef\" -// @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*]" 1 -// @is - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].name" \"\'a\" +// @ismany - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].name" \"\'a\" // @has - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime" // @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime.outlives[*]" 0 // @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.where_predicates[*]" 0 diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs index c4462466646..022f7eb8e02 100644 --- a/src/tools/jsondocck/src/main.rs +++ b/src/tools/jsondocck/src/main.rs @@ -50,6 +50,7 @@ pub enum CommandKind { Has, Count, Is, + IsMany, Set, } @@ -57,6 +58,7 @@ impl CommandKind { fn validate(&self, args: &[String], command_num: usize, lineno: usize) -> bool { let count = match self { CommandKind::Has => (1..=3).contains(&args.len()), + CommandKind::IsMany => args.len() >= 3, CommandKind::Count | CommandKind::Is => 3 == args.len(), CommandKind::Set => 4 == args.len(), }; @@ -89,6 +91,7 @@ impl fmt::Display for CommandKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let text = match self { CommandKind::Has => "has", + CommandKind::IsMany => "ismany", CommandKind::Count => "count", CommandKind::Is => "is", CommandKind::Set => "set", @@ -137,6 +140,7 @@ fn get_commands(template: &str) -> Result, ()> { "has" => CommandKind::Has, "count" => CommandKind::Count, "is" => CommandKind::Is, + "ismany" => CommandKind::IsMany, "set" => CommandKind::Set, _ => { print_err(&format!("Unrecognized command name `@{}`", cmd), lineno); @@ -227,6 +231,44 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> { _ => unreachable!(), } } + CommandKind::IsMany => { + // @ismany ... + let (path, query, values) = if let [path, query, values @ ..] = &command.args[..] { + (path, query, values) + } else { + unreachable!("Checked in CommandKind::validate") + }; + let val = cache.get_value(path)?; + let got_values = select(&val, &query).unwrap(); + assert!(!command.negated, "`@!ismany` is not supported"); + + // Serde json doesn't implement Ord or Hash for Value, so we must + // use a Vec here. While in theory that makes setwize equality + // O(n^2), in practice n will never be large enought to matter. + let expected_values = + values.iter().map(|v| string_to_value(v, cache)).collect::>(); + if expected_values.len() != got_values.len() { + return Err(CkError::FailedCheck( + format!( + "Expected {} values, but `{}` matched to {} values ({:?})", + expected_values.len(), + query, + got_values.len(), + got_values + ), + command, + )); + }; + for got_value in got_values { + if !expected_values.iter().any(|exp| &**exp == got_value) { + return Err(CkError::FailedCheck( + format!("`{}` has match {:?}, which was not expected", query, got_value), + command, + )); + } + } + true + } CommandKind::Count => { // @count = Check that the jsonpath matches exactly [count] times assert_eq!(command.args.len(), 3);