diff --git a/Cargo.lock b/Cargo.lock index 0483d50fc2a..bb438f288f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2115,6 +2115,7 @@ dependencies = [ "clap 4.0.15", "fs-err", "rustdoc-json-types", + "serde", "serde_json", ] diff --git a/src/tools/jsondoclint/Cargo.toml b/src/tools/jsondoclint/Cargo.toml index 0dda3935ed8..8990310a4f4 100644 --- a/src/tools/jsondoclint/Cargo.toml +++ b/src/tools/jsondoclint/Cargo.toml @@ -10,4 +10,5 @@ anyhow = "1.0.62" clap = { version = "4.0.15", features = ["derive"] } fs-err = "2.8.1" rustdoc-json-types = { version = "0.1.0", path = "../../rustdoc-json-types" } +serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.85" diff --git a/src/tools/jsondoclint/src/json_find.rs b/src/tools/jsondoclint/src/json_find.rs index 70e7440f730..a183c4068ce 100644 --- a/src/tools/jsondoclint/src/json_find.rs +++ b/src/tools/jsondoclint/src/json_find.rs @@ -1,8 +1,9 @@ use std::fmt::Write; +use serde::Serialize; use serde_json::Value; -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize)] pub enum SelectorPart { Field(String), Index(usize), diff --git a/src/tools/jsondoclint/src/main.rs b/src/tools/jsondoclint/src/main.rs index 266900ea3a2..05e938f4f7d 100644 --- a/src/tools/jsondoclint/src/main.rs +++ b/src/tools/jsondoclint/src/main.rs @@ -1,25 +1,34 @@ +use std::io::{BufWriter, Write}; + use anyhow::{bail, Result}; use clap::Parser; use fs_err as fs; use rustdoc_json_types::{Crate, Id, FORMAT_VERSION}; +use serde::Serialize; use serde_json::Value; pub(crate) mod item_kind; mod json_find; mod validator; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Serialize, Clone)] struct Error { kind: ErrorKind, id: Id, } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Serialize, Clone)] enum ErrorKind { NotFound(Vec), Custom(String), } +#[derive(Debug, Serialize)] +struct JsonOutput { + path: String, + errors: Vec, +} + #[derive(Parser)] struct Cli { /// The path to the json file to be linted @@ -28,10 +37,13 @@ struct Cli { /// Show verbose output #[arg(long)] verbose: bool, + + #[arg(long)] + json_output: Option, } fn main() -> Result<()> { - let Cli { path, verbose } = Cli::parse(); + let Cli { path, verbose, json_output } = Cli::parse(); let contents = fs::read_to_string(&path)?; let krate: Crate = serde_json::from_str(&contents)?; @@ -42,6 +54,13 @@ fn main() -> Result<()> { let mut validator = validator::Validator::new(&krate, krate_json); validator.check_crate(); + if let Some(json_output) = json_output { + let output = JsonOutput { path: path.clone(), errors: validator.errs.clone() }; + let mut f = BufWriter::new(fs::File::create(json_output)?); + serde_json::to_writer(&mut f, &output)?; + f.flush()?; + } + if !validator.errs.is_empty() { for err in validator.errs { match err.kind {