about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/test/rustdoc-json/nested.rs20
-rw-r--r--src/tools/jsondocck/src/main.rs18
2 files changed, 27 insertions, 11 deletions
diff --git a/src/test/rustdoc-json/nested.rs b/src/test/rustdoc-json/nested.rs
index 7e705255d98..f32692b70cd 100644
--- a/src/test/rustdoc-json/nested.rs
+++ b/src/test/rustdoc-json/nested.rs
@@ -1,24 +1,24 @@
 // edition:2018
 
-// @has nested.json "$.index[*][?(@.name=='nested')].kind" \"module\"
-// @has - "$.index[*][?(@.name=='nested')].inner.is_crate" true
+// @is nested.json "$.index[*][?(@.name=='nested')].kind" \"module\"
+// @is - "$.index[*][?(@.name=='nested')].inner.is_crate" true
 // @count - "$.index[*][?(@.name=='nested')].inner.items[*]" 1
 
-// @has nested.json "$.index[*][?(@.name=='l1')].kind" \"module\"
-// @has - "$.index[*][?(@.name=='l1')].inner.is_crate" false
+// @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 {
 
-    // @has nested.json "$.index[*][?(@.name=='l3')].kind" \"module\"
-    // @has - "$.index[*][?(@.name=='l3')].inner.is_crate" false
+    // @is nested.json "$.index[*][?(@.name=='l3')].kind" \"module\"
+    // @is - "$.index[*][?(@.name=='l3')].inner.is_crate" false
     // @count - "$.index[*][?(@.name=='l3')].inner.items[*]" 1
     pub mod l3 {
 
-        // @has nested.json "$.index[*][?(@.name=='L4')].kind" \"struct\"
-        // @has - "$.index[*][?(@.name=='L4')].inner.struct_type" \"unit\"
+        // @is nested.json "$.index[*][?(@.name=='L4')].kind" \"struct\"
+        // @is - "$.index[*][?(@.name=='L4')].inner.struct_type" \"unit\"
         pub struct L4;
     }
-    // @has nested.json "$.index[*][?(@.inner.span=='l3::L4')].kind" \"import\"
-    // @has - "$.index[*][?(@.inner.span=='l3::L4')].inner.glob" false
+    // @is nested.json "$.index[*][?(@.inner.span=='l3::L4')].kind" \"import\"
+    // @is - "$.index[*][?(@.inner.span=='l3::L4')].inner.glob" false
     pub use l3::L4;
 }
diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs
index 6ec292aba64..2afb66b9696 100644
--- a/src/tools/jsondocck/src/main.rs
+++ b/src/tools/jsondocck/src/main.rs
@@ -48,13 +48,14 @@ pub struct Command {
 pub enum CommandKind {
     Has,
     Count,
+    Is,
 }
 
 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::Count => 3 == args.len(),
+            CommandKind::Count | CommandKind::Is => 3 == args.len(),
         };
 
         if !count {
@@ -83,6 +84,7 @@ impl fmt::Display for CommandKind {
         let text = match self {
             CommandKind::Has => "has",
             CommandKind::Count => "count",
+            CommandKind::Is => "is",
         };
         write!(f, "{}", text)
     }
@@ -127,6 +129,7 @@ fn get_commands(template: &str) -> Result<Vec<Command>, ()> {
         let cmd = match cmd {
             "has" => CommandKind::Has,
             "count" => CommandKind::Count,
+            "is" => CommandKind::Is,
             _ => {
                 print_err(&format!("Unrecognized command name `@{}`", cmd), lineno);
                 errors = true;
@@ -180,6 +183,7 @@ fn get_commands(template: &str) -> Result<Vec<Command>, ()> {
 /// Performs the actual work of ensuring a command passes. Generally assumes the command
 /// is syntactically valid.
 fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
+    // FIXME: Be more granular about why, (eg syntax error, count not equal)
     let result = match command.kind {
         CommandKind::Has => {
             match command.args.len() {
@@ -220,6 +224,18 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
                 Err(_) => false,
             }
         }
+        CommandKind::Is => {
+            // @has <path> <jsonpath> <value> = check *exactly one* item matched by path, and it equals value
+            assert_eq!(command.args.len(), 3);
+            let val = cache.get_value(&command.args[0])?;
+            match select(&val, &command.args[1]) {
+                Ok(results) => {
+                    let pat: Value = serde_json::from_str(&command.args[2]).unwrap();
+                    results.len() == 1 && *results[0] == pat
+                }
+                Err(_) => false,
+            }
+        }
     };
 
     if result == command.negated {