1use std::collections::BTreeSet;
2use std::fs;
3use std::path::{Path, PathBuf};
4
5use crate::features::{CollectedFeatures, Features, Status};
6
7pub const PATH_STR: &str = "doc/unstable-book";
8
9pub const COMPILER_FLAGS_DIR: &str = "src/compiler-flags";
10
11pub const LANG_FEATURES_DIR: &str = "src/language-features";
12
13pub const LIB_FEATURES_DIR: &str = "src/library-features";
14
15pub fn unstable_book_path(base_src_path: &Path) -> PathBuf {
17 base_src_path.join(PATH_STR)
18}
19
20pub fn unstable_book_lang_features_path(base_src_path: &Path) -> PathBuf {
23 unstable_book_path(base_src_path).join(LANG_FEATURES_DIR)
24}
25
26pub fn unstable_book_lib_features_path(base_src_path: &Path) -> PathBuf {
29 unstable_book_path(base_src_path).join(LIB_FEATURES_DIR)
30}
31
32fn dir_entry_is_file(dir_entry: &fs::DirEntry) -> bool {
34 dir_entry.file_type().expect("could not determine file type of directory entry").is_file()
35}
36
37pub fn collect_unstable_feature_names(features: &Features) -> BTreeSet<String> {
39 features
40 .iter()
41 .filter(|&(_, ref f)| f.level == Status::Unstable)
42 .map(|(name, _)| name.replace('_', "-"))
43 .collect()
44}
45
46pub fn collect_unstable_book_section_file_names(dir: &Path) -> BTreeSet<String> {
47 fs::read_dir(dir)
48 .expect("could not read directory")
49 .map(|entry| entry.expect("could not read directory entry"))
50 .filter(dir_entry_is_file)
51 .map(|entry| entry.path())
52 .filter(|path| path.extension().map(|e| e.to_str().unwrap()) == Some("md"))
53 .map(|path| path.file_stem().unwrap().to_str().unwrap().into())
54 .collect()
55}
56
57fn collect_unstable_book_lang_features_section_file_names(
62 base_src_path: &Path,
63) -> BTreeSet<String> {
64 collect_unstable_book_section_file_names(&unstable_book_lang_features_path(base_src_path))
65}
66
67fn collect_unstable_book_lib_features_section_file_names(base_src_path: &Path) -> BTreeSet<String> {
72 collect_unstable_book_section_file_names(&unstable_book_lib_features_path(base_src_path))
73}
74
75fn maybe_suggest_dashes(names: &BTreeSet<String>, feature_name: &str, bad: &mut bool) {
77 let with_dashes = feature_name.replace('_', "-");
78 if names.contains(&with_dashes) {
79 tidy_error!(
80 bad,
81 "the file `{}.md` contains underscores; use dashes instead: `{}.md`",
82 feature_name,
83 with_dashes,
84 );
85 }
86}
87
88pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) {
89 let lang_features = features.lang;
90 let lib_features = features
91 .lib
92 .into_iter()
93 .filter(|&(ref name, _)| !lang_features.contains_key(name))
94 .collect::<Features>();
95
96 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 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 for feature_name in &unstable_book_lib_features_section_file_names - &unstable_lib_feature_names
108 {
109 tidy_error!(
110 bad,
111 "The Unstable Book has a 'library feature' section '{}' which doesn't \
112 correspond to an unstable library feature",
113 feature_name
114 );
115 maybe_suggest_dashes(&unstable_lib_feature_names, &feature_name, bad);
116 }
117
118 for feature_name in
120 &unstable_book_lang_features_section_file_names - &unstable_lang_feature_names
121 {
122 tidy_error!(
123 bad,
124 "The Unstable Book has a 'language feature' section '{}' which doesn't \
125 correspond to an unstable language feature",
126 feature_name
127 );
128 maybe_suggest_dashes(&unstable_lang_feature_names, &feature_name, bad);
129 }
130
131 }