Skip to main content

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
7use crate::diagnostics::{CheckId, TidyCtx};
8
9const RUSTDOC_JSON_TYPES: &str = "src/rustdoc-json-types";
10
11pub fn check(src_path: &Path, tidy_ctx: TidyCtx) {
12    let mut check = tidy_ctx.start_check(CheckId::new("rustdoc_json").path(src_path));
13
14    let Some(base_commit) = &tidy_ctx.base_commit else {
15        check.verbose_msg("No base commit, skipping rustdoc_json check");
16        return;
17    };
18
19    // First we check that `src/rustdoc-json-types` was modified.
20    if !crate::files_modified(&tidy_ctx.base_commit, tidy_ctx.is_running_on_ci(), |p| {
21        p.starts_with(RUSTDOC_JSON_TYPES)
22    }) {
23        // `rustdoc-json-types` was not modified so nothing more to check here.
24        return;
25    }
26
27    check.message("`rustdoc-json-types` modified, checking format version");
28
29    // Then we check that if `FORMAT_VERSION` was updated, the `Latest feature:` was also updated.
30    match crate::git_diff(base_commit, src_path.join("rustdoc-json-types")) {
31        Some(output) => {
32            let mut format_version_updated = false;
33            let mut latest_feature_comment_updated = false;
34            let mut new_version = None;
35            let mut old_version = None;
36            for line in output.lines() {
37                if line.starts_with("+pub const FORMAT_VERSION: u32 =") {
38                    format_version_updated = true;
39                    new_version = line
40                        .split('=')
41                        .nth(1)
42                        .and_then(|s| s.trim().split(';').next())
43                        .and_then(|s| u32::from_str(s.trim()).ok());
44                } else if line.starts_with("-pub const FORMAT_VERSION: u32 =") {
45                    old_version = line
46                        .split('=')
47                        .nth(1)
48                        .and_then(|s| s.trim().split(';').next())
49                        .and_then(|s| u32::from_str(s.trim()).ok());
50                } else if line.starts_with("+// Latest feature:") {
51                    latest_feature_comment_updated = true;
52                }
53            }
54            if format_version_updated != latest_feature_comment_updated {
55                let msg = if latest_feature_comment_updated {
56                    format!(
57                        "`Latest feature` comment was updated whereas `FORMAT_VERSION` wasn't in `{RUSTDOC_JSON_TYPES}/lib.rs`"
58                    )
59                } else {
60                    format!(
61                        "`Latest feature` comment was not updated whereas `FORMAT_VERSION` was in `{RUSTDOC_JSON_TYPES}/lib.rs`"
62                    )
63                };
64                check.error(msg);
65            }
66            match (new_version, old_version) {
67                (Some(new_version), Some(old_version)) if new_version != old_version + 1 => {
68                    check.error(format!(
69                        "invalid `FORMAT_VERSION` increase in `{RUSTDOC_JSON_TYPES}/lib.rs`, should be `{}`, found `{new_version}`",
70                        old_version + 1,
71                    ));
72                }
73                _ => {}
74            }
75        }
76        None => {
77            check.error("failed to run `git diff` in rustdoc_json check");
78        }
79    }
80}