]> git.lizzy.rs Git - rust.git/blob - src/tools/tidy/src/unstable_book.rs
Rollup merge of #67531 - RalfJung:tame-promotion, r=nikomatsakis
[rust.git] / src / tools / tidy / src / unstable_book.rs
1 use crate::features::{CollectedFeatures, Feature, Features, Status};
2 use std::collections::BTreeSet;
3 use std::fs;
4 use std::path::{Path, PathBuf};
5
6 pub const PATH_STR: &str = "doc/unstable-book";
7
8 pub const COMPILER_FLAGS_DIR: &str = "src/compiler-flags";
9
10 pub const LANG_FEATURES_DIR: &str = "src/language-features";
11
12 pub const LIB_FEATURES_DIR: &str = "src/library-features";
13
14 /// Builds the path to the Unstable Book source directory from the Rust 'src' directory.
15 pub fn unstable_book_path(base_src_path: &Path) -> PathBuf {
16     base_src_path.join(PATH_STR)
17 }
18
19 /// Builds the path to the directory where the features are documented within the Unstable Book
20 /// source directory.
21 pub fn unstable_book_lang_features_path(base_src_path: &Path) -> PathBuf {
22     unstable_book_path(base_src_path).join(LANG_FEATURES_DIR)
23 }
24
25 /// Builds the path to the directory where the features are documented within the Unstable Book
26 /// source directory.
27 pub fn unstable_book_lib_features_path(base_src_path: &Path) -> PathBuf {
28     unstable_book_path(base_src_path).join(LIB_FEATURES_DIR)
29 }
30
31 /// Tests whether `DirEntry` is a file.
32 fn dir_entry_is_file(dir_entry: &fs::DirEntry) -> bool {
33     dir_entry.file_type().expect("could not determine file type of directory entry").is_file()
34 }
35
36 /// Retrieves names of all unstable features.
37 pub fn collect_unstable_feature_names(features: &Features) -> BTreeSet<String> {
38     features
39         .iter()
40         .filter(|&(_, ref f)| f.level == Status::Unstable)
41         .map(|(name, _)| name.replace('_', "-"))
42         .collect()
43 }
44
45 pub fn collect_unstable_book_section_file_names(dir: &Path) -> BTreeSet<String> {
46     fs::read_dir(dir)
47         .expect("could not read directory")
48         .map(|entry| entry.expect("could not read directory entry"))
49         .filter(dir_entry_is_file)
50         .map(|entry| entry.path())
51         .filter(|path| path.extension().map(|e| e.to_str().unwrap()) == Some("md"))
52         .map(|path| path.file_stem().unwrap().to_str().unwrap().into())
53         .collect()
54 }
55
56 /// Retrieves file names of all library feature sections in the Unstable Book with:
57 ///
58 /// * hyphens replaced by underscores,
59 /// * the markdown suffix ('.md') removed.
60 fn collect_unstable_book_lang_features_section_file_names(
61     base_src_path: &Path,
62 ) -> BTreeSet<String> {
63     collect_unstable_book_section_file_names(&unstable_book_lang_features_path(base_src_path))
64 }
65
66 /// Retrieves file names of all language feature sections in the Unstable Book with:
67 ///
68 /// * hyphens replaced by underscores,
69 /// * the markdown suffix ('.md') removed.
70 fn collect_unstable_book_lib_features_section_file_names(base_src_path: &Path) -> BTreeSet<String> {
71     collect_unstable_book_section_file_names(&unstable_book_lib_features_path(base_src_path))
72 }
73
74 pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) {
75     let lang_features = features.lang;
76     let mut lib_features = features
77         .lib
78         .into_iter()
79         .filter(|&(ref name, _)| !lang_features.contains_key(name))
80         .collect::<Features>();
81
82     // This library feature is defined in the `compiler_builtins` crate, which
83     // has been moved out-of-tree. Now it can no longer be auto-discovered by
84     // `tidy`, because we need to filter out its (submodule) directory. Manually
85     // add it to the set of known library features so we can still generate docs.
86     lib_features.insert(
87         "compiler_builtins_lib".to_owned(),
88         Feature {
89             level: Status::Unstable,
90             since: None,
91             has_gate_test: false,
92             tracking_issue: None,
93         },
94     );
95
96     // Library features
97     let unstable_lib_feature_names = collect_unstable_feature_names(&lib_features);
98     let unstable_book_lib_features_section_file_names =
99         collect_unstable_book_lib_features_section_file_names(path);
100
101     // Language features
102     let unstable_lang_feature_names = collect_unstable_feature_names(&lang_features);
103     let unstable_book_lang_features_section_file_names =
104         collect_unstable_book_lang_features_section_file_names(path);
105
106     // Check for Unstable Book sections that don't have a corresponding unstable feature
107     for feature_name in &unstable_book_lib_features_section_file_names - &unstable_lib_feature_names
108     {
109         if !unstable_lang_feature_names.contains(&feature_name) {
110             tidy_error!(
111                 bad,
112                 "The Unstable Book has a 'library feature' section '{}' which doesn't \
113                          correspond to an unstable library feature",
114                 feature_name
115             );
116         }
117     }
118
119     // Check for Unstable Book sections that don't have a corresponding unstable feature.
120     for feature_name in
121         &unstable_book_lang_features_section_file_names - &unstable_lang_feature_names
122     {
123         tidy_error!(
124             bad,
125             "The Unstable Book has a 'language feature' section '{}' which doesn't \
126                      correspond to an unstable language feature",
127             feature_name
128         )
129     }
130
131     // List unstable features that don't have Unstable Book sections.
132     // Remove the comment marker if you want the list printed.
133     /*
134     println!("Lib features without unstable book sections:");
135     for feature_name in &unstable_lang_feature_names -
136                         &unstable_book_lang_features_section_file_names {
137         println!("    * {} {:?}", feature_name, lib_features[&feature_name].tracking_issue);
138     }
139
140     println!("Lang features without unstable book sections:");
141     for feature_name in &unstable_lib_feature_names-
142                         &unstable_book_lib_features_section_file_names {
143         println!("    * {} {:?}", feature_name, lang_features[&feature_name].tracking_issue);
144     }
145     // */
146 }