1 use crate::features::{CollectedFeatures, Feature, Features, Status};
2 use std::collections::BTreeSet;
4 use std::path::{Path, PathBuf};
6 pub const PATH_STR: &str = "doc/unstable-book";
8 pub const COMPILER_FLAGS_DIR: &str = "src/compiler-flags";
10 pub const LANG_FEATURES_DIR: &str = "src/language-features";
12 pub const LIB_FEATURES_DIR: &str = "src/library-features";
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)
19 /// Builds the path to the directory where the features are documented within the Unstable Book
21 pub fn unstable_book_lang_features_path(base_src_path: &Path) -> PathBuf {
22 unstable_book_path(base_src_path).join(LANG_FEATURES_DIR)
25 /// Builds the path to the directory where the features are documented within the Unstable Book
27 pub fn unstable_book_lib_features_path(base_src_path: &Path) -> PathBuf {
28 unstable_book_path(base_src_path).join(LIB_FEATURES_DIR)
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()
36 /// Retrieves names of all unstable features.
37 pub fn collect_unstable_feature_names(features: &Features) -> BTreeSet<String> {
40 .filter(|&(_, ref f)| f.level == Status::Unstable)
41 .map(|(name, _)| name.replace('_', "-"))
45 pub fn collect_unstable_book_section_file_names(dir: &Path) -> BTreeSet<String> {
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())
56 /// Retrieves file names of all library feature sections in the Unstable Book with:
58 /// * hyphens replaced by underscores,
59 /// * the markdown suffix ('.md') removed.
60 fn collect_unstable_book_lang_features_section_file_names(
62 ) -> BTreeSet<String> {
63 collect_unstable_book_section_file_names(&unstable_book_lang_features_path(base_src_path))
66 /// Retrieves file names of all language feature sections in the Unstable Book with:
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))
74 pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) {
75 let lang_features = features.lang;
76 let mut lib_features = features
79 .filter(|&(ref name, _)| !lang_features.contains_key(name))
80 .collect::<Features>();
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.
87 "compiler_builtins_lib".to_owned(),
89 level: Status::Unstable,
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);
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);
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
109 if !unstable_lang_feature_names.contains(&feature_name) {
112 "The Unstable Book has a 'library feature' section '{}' which doesn't \
113 correspond to an unstable library feature",
119 // Check for Unstable Book sections that don't have a corresponding unstable feature.
121 &unstable_book_lang_features_section_file_names - &unstable_lang_feature_names
125 "The Unstable Book has a 'language feature' section '{}' which doesn't \
126 correspond to an unstable language feature",
131 // List unstable features that don't have Unstable Book sections.
132 // Remove the comment marker if you want the list printed.
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);
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);