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