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