tidy/
rustdoc_json.rs

1//! Tidy check to ensure that `FORMAT_VERSION` was correctly updated if `rustdoc-json-types` was
2//! updated as well.
3
4use std::path::Path;
5use std::str::FromStr;
6
7const RUSTDOC_JSON_TYPES: &str = "src/rustdoc-json-types";
8
9pub fn check(src_path: &Path, ci_info: &crate::CiInfo, bad: &mut bool) {
10    println!("Checking tidy rustdoc_json...");
11    let Some(base_commit) = &ci_info.base_commit else {
12        eprintln!("No base commit, skipping rustdoc_json check");
13        return;
14    };
15
16    // First we check that `src/rustdoc-json-types` was modified.
17    match crate::git_diff(&base_commit, "--name-status") {
18        Some(output) => {
19            if !output
20                .lines()
21                .any(|line| line.starts_with("M") && line.contains(RUSTDOC_JSON_TYPES))
22            {
23                // `rustdoc-json-types` was not modified so nothing more to check here.
24                println!("`rustdoc-json-types` was not modified.");
25                return;
26            }
27        }
28        None => {
29            *bad = true;
30            eprintln!("error: failed to run `git diff` in rustdoc_json check");
31            return;
32        }
33    }
34    // Then we check that if `FORMAT_VERSION` was updated, the `Latest feature:` was also updated.
35    match crate::git_diff(&base_commit, src_path.join("rustdoc-json-types")) {
36        Some(output) => {
37            let mut format_version_updated = false;
38            let mut latest_feature_comment_updated = false;
39            let mut new_version = None;
40            let mut old_version = None;
41            for line in output.lines() {
42                if line.starts_with("+pub const FORMAT_VERSION: u32 =") {
43                    format_version_updated = true;
44                    new_version = line
45                        .split('=')
46                        .nth(1)
47                        .and_then(|s| s.trim().split(';').next())
48                        .and_then(|s| u32::from_str(s.trim()).ok());
49                } else if line.starts_with("-pub const FORMAT_VERSION: u32 =") {
50                    old_version = line
51                        .split('=')
52                        .nth(1)
53                        .and_then(|s| s.trim().split(';').next())
54                        .and_then(|s| u32::from_str(s.trim()).ok());
55                } else if line.starts_with("+// Latest feature:") {
56                    latest_feature_comment_updated = true;
57                }
58            }
59            if format_version_updated != latest_feature_comment_updated {
60                *bad = true;
61                if latest_feature_comment_updated {
62                    eprintln!(
63                        "error in `rustdoc_json` tidy check: `Latest feature` comment was updated \
64                         whereas `FORMAT_VERSION` wasn't in `{RUSTDOC_JSON_TYPES}/lib.rs`"
65                    );
66                } else {
67                    eprintln!(
68                        "error in `rustdoc_json` tidy check: `Latest feature` comment was not \
69                         updated whereas `FORMAT_VERSION` was in `{RUSTDOC_JSON_TYPES}/lib.rs`"
70                    );
71                }
72            }
73            match (new_version, old_version) {
74                (Some(new_version), Some(old_version)) if new_version != old_version + 1 => {
75                    *bad = true;
76                    eprintln!(
77                        "error in `rustdoc_json` tidy check: invalid `FORMAT_VERSION` increase in \
78                         `{RUSTDOC_JSON_TYPES}/lib.rs`, should be `{}`, found `{new_version}`",
79                        old_version + 1,
80                    );
81                }
82                _ => {}
83            }
84        }
85        None => {
86            *bad = true;
87            eprintln!("error: failed to run `git diff` in rustdoc_json check");
88        }
89    }
90}