]> git.lizzy.rs Git - rust.git/blob - src/tools/unstable-book-gen/src/main.rs
Support configurable deny-warnings for all in-tree crates.
[rust.git] / src / tools / unstable-book-gen / src / main.rs
1 //! Auto-generate stub docs for the unstable book
2
3 use std::collections::BTreeSet;
4 use std::env;
5 use std::fs::{self, File};
6 use std::io::Write;
7 use std::path::Path;
8 use tidy::features::{collect_lang_features, collect_lib_features, Features};
9 use tidy::unstable_book::{
10     collect_unstable_book_section_file_names, collect_unstable_feature_names, LANG_FEATURES_DIR,
11     LIB_FEATURES_DIR, PATH_STR,
12 };
13
14 /// A helper macro to `unwrap` a result except also print out details like:
15 ///
16 /// * The file/line of the panic
17 /// * The expression that failed
18 /// * The error itself
19 macro_rules! t {
20     ($e:expr) => {
21         match $e {
22             Ok(e) => e,
23             Err(e) => panic!("{} failed with {}", stringify!($e), e),
24         }
25     };
26 }
27
28 fn generate_stub_issue(path: &Path, name: &str, issue: u32) {
29     let mut file = t!(File::create(path));
30     t!(file.write_fmt(format_args!(include_str!("stub-issue.md"), name = name, issue = issue)));
31 }
32
33 fn generate_stub_no_issue(path: &Path, name: &str) {
34     let mut file = t!(File::create(path));
35     t!(file.write_fmt(format_args!(include_str!("stub-no-issue.md"), name = name)));
36 }
37
38 fn set_to_summary_str(set: &BTreeSet<String>, dir: &str) -> String {
39     set.iter()
40         .map(|ref n| format!("    - [{}]({}/{}.md)", n.replace('-', "_"), dir, n))
41         .fold("".to_owned(), |s, a| s + &a + "\n")
42 }
43
44 fn generate_summary(path: &Path, lang_features: &Features, lib_features: &Features) {
45     let compiler_flags = collect_unstable_book_section_file_names(&path.join("src/compiler-flags"));
46
47     let compiler_flags_str = set_to_summary_str(&compiler_flags, "compiler-flags");
48
49     let unstable_lang_features = collect_unstable_feature_names(&lang_features);
50     let unstable_lib_features = collect_unstable_feature_names(&lib_features);
51
52     let lang_features_str = set_to_summary_str(&unstable_lang_features, "language-features");
53     let lib_features_str = set_to_summary_str(&unstable_lib_features, "library-features");
54
55     let mut file = t!(File::create(&path.join("src/SUMMARY.md")));
56     t!(file.write_fmt(format_args!(
57         include_str!("SUMMARY.md"),
58         compiler_flags = compiler_flags_str,
59         language_features = lang_features_str,
60         library_features = lib_features_str
61     )));
62 }
63
64 fn generate_unstable_book_files(src: &Path, out: &Path, features: &Features) {
65     let unstable_features = collect_unstable_feature_names(features);
66     let unstable_section_file_names = collect_unstable_book_section_file_names(src);
67     t!(fs::create_dir_all(&out));
68     for feature_name in &unstable_features - &unstable_section_file_names {
69         let feature_name_underscore = feature_name.replace('-', "_");
70         let file_name = format!("{}.md", feature_name);
71         let out_file_path = out.join(&file_name);
72         let feature = &features[&feature_name_underscore];
73
74         if let Some(issue) = feature.tracking_issue {
75             generate_stub_issue(&out_file_path, &feature_name_underscore, issue.get());
76         } else {
77             generate_stub_no_issue(&out_file_path, &feature_name_underscore);
78         }
79     }
80 }
81
82 fn copy_recursive(from: &Path, to: &Path) {
83     for entry in t!(fs::read_dir(from)) {
84         let e = t!(entry);
85         let t = t!(e.metadata());
86         let dest = &to.join(e.file_name());
87         if t.is_file() {
88             t!(fs::copy(&e.path(), dest));
89         } else if t.is_dir() {
90             t!(fs::create_dir_all(dest));
91             copy_recursive(&e.path(), dest);
92         }
93     }
94 }
95
96 fn main() {
97     let src_path_str = env::args_os().skip(1).next().expect("source path required");
98     let dest_path_str = env::args_os().skip(2).next().expect("destination path required");
99     let src_path = Path::new(&src_path_str);
100     let dest_path = Path::new(&dest_path_str);
101
102     let lang_features = collect_lang_features(src_path, &mut false);
103     let lib_features = collect_lib_features(src_path)
104         .into_iter()
105         .filter(|&(ref name, _)| !lang_features.contains_key(name))
106         .collect();
107
108     let doc_src_path = src_path.join(PATH_STR);
109
110     t!(fs::create_dir_all(&dest_path));
111
112     generate_unstable_book_files(
113         &doc_src_path.join(LANG_FEATURES_DIR),
114         &dest_path.join(LANG_FEATURES_DIR),
115         &lang_features,
116     );
117     generate_unstable_book_files(
118         &doc_src_path.join(LIB_FEATURES_DIR),
119         &dest_path.join(LIB_FEATURES_DIR),
120         &lib_features,
121     );
122
123     copy_recursive(&doc_src_path, &dest_path);
124
125     generate_summary(&dest_path, &lang_features, &lib_features);
126 }