]> git.proxmox.com Git - rustc.git/blame - src/tools/jsondoclint/src/main.rs
New upstream version 1.68.2+dfsg1
[rustc.git] / src / tools / jsondoclint / src / main.rs
CommitLineData
f25598a0 1use std::io::{BufWriter, Write};
f2b60f7d 2
f25598a0
FG
3use anyhow::{bail, Result};
4use clap::Parser;
f2b60f7d
FG
5use fs_err as fs;
6use rustdoc_json_types::{Crate, Id, FORMAT_VERSION};
f25598a0 7use serde::Serialize;
f2b60f7d
FG
8use serde_json::Value;
9
10pub(crate) mod item_kind;
11mod json_find;
12mod validator;
13
f25598a0 14#[derive(Debug, PartialEq, Eq, Serialize, Clone)]
f2b60f7d
FG
15struct Error {
16 kind: ErrorKind,
17 id: Id,
18}
19
f25598a0 20#[derive(Debug, PartialEq, Eq, Serialize, Clone)]
f2b60f7d 21enum ErrorKind {
f25598a0 22 NotFound(Vec<json_find::Selector>),
f2b60f7d
FG
23 Custom(String),
24}
25
f25598a0
FG
26#[derive(Debug, Serialize)]
27struct JsonOutput {
28 path: String,
29 errors: Vec<Error>,
30}
31
32#[derive(Parser)]
33struct Cli {
34 /// The path to the json file to be linted
35 path: String,
36
37 /// Show verbose output
38 #[arg(long)]
39 verbose: bool,
40
41 #[arg(long)]
42 json_output: Option<String>,
43}
44
f2b60f7d 45fn main() -> Result<()> {
f25598a0
FG
46 let Cli { path, verbose, json_output } = Cli::parse();
47
f2b60f7d
FG
48 let contents = fs::read_to_string(&path)?;
49 let krate: Crate = serde_json::from_str(&contents)?;
50 assert_eq!(krate.format_version, FORMAT_VERSION);
51
f25598a0
FG
52 let krate_json: Value = serde_json::from_str(&contents)?;
53
54 let mut validator = validator::Validator::new(&krate, krate_json);
f2b60f7d
FG
55 validator.check_crate();
56
f25598a0
FG
57 if let Some(json_output) = json_output {
58 let output = JsonOutput { path: path.clone(), errors: validator.errs.clone() };
59 let mut f = BufWriter::new(fs::File::create(json_output)?);
60 serde_json::to_writer(&mut f, &output)?;
61 f.flush()?;
62 }
63
f2b60f7d
FG
64 if !validator.errs.is_empty() {
65 for err in validator.errs {
66 match err.kind {
f25598a0
FG
67 ErrorKind::NotFound(sels) => match &sels[..] {
68 [] => {
69 unreachable!(
70 "id {:?} must be in crate, or it wouldn't be reported as not found",
71 err.id
72 )
73 }
74 [sel] => eprintln!(
75 "{} not in index or paths, but refered to at '{}'",
76 err.id.0,
77 json_find::to_jsonpath(&sel)
78 ),
79 [sel, ..] => {
80 if verbose {
81 let sels = sels
82 .iter()
83 .map(json_find::to_jsonpath)
84 .map(|i| format!("'{i}'"))
85 .collect::<Vec<_>>()
86 .join(", ");
87 eprintln!(
88 "{} not in index or paths, but refered to at {sels}",
89 err.id.0
90 );
91 } else {
92 eprintln!(
93 "{} not in index or paths, but refered to at '{}' and {} more",
94 err.id.0,
95 json_find::to_jsonpath(&sel),
96 sels.len() - 1,
97 )
98 }
f2b60f7d 99 }
f25598a0 100 },
f2b60f7d
FG
101 ErrorKind::Custom(msg) => eprintln!("{}: {}", err.id.0, msg),
102 }
103 }
104 bail!("Errors validating json {path}");
105 }
106
107 Ok(())
108}