1 //! Auto-generate stub docs for the unstable book
5 use std::collections::BTreeSet;
7 use std::fs::{self, File};
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,
16 /// A helper macro to `unwrap` a result except also print out details like:
18 /// * The file/line of the panic
19 /// * The expression that failed
20 /// * The error itself
25 Err(e) => panic!("{} failed with {}", stringify!($e), e),
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)));
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)));
40 fn set_to_summary_str(set: &BTreeSet<String>, dir: &str) -> String {
42 .map(|ref n| format!(" - [{}]({}/{}.md)", n.replace('-', "_"), dir, n))
43 .fold("".to_owned(), |s, a| s + &a + "\n")
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"));
49 let compiler_flags_str = set_to_summary_str(&compiler_flags, "compiler-flags");
51 let unstable_lang_features = collect_unstable_feature_names(&lang_features);
52 let unstable_lib_features = collect_unstable_feature_names(&lib_features);
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");
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
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];
76 if let Some(issue) = feature.tracking_issue {
77 generate_stub_issue(&out_file_path, &feature_name_underscore, issue.get());
79 generate_stub_no_issue(&out_file_path, &feature_name_underscore);
84 fn copy_recursive(from: &Path, to: &Path) {
85 for entry in t!(fs::read_dir(from)) {
87 let t = t!(e.metadata());
88 let dest = &to.join(e.file_name());
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);
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);
104 let lang_features = collect_lang_features(src_path, &mut false);
105 let lib_features = collect_lib_features(src_path)
107 .filter(|&(ref name, _)| !lang_features.contains_key(name))
110 let doc_src_path = src_path.join(PATH_STR);
112 t!(fs::create_dir_all(&dest_path));
114 generate_unstable_book_files(
115 &doc_src_path.join(LANG_FEATURES_DIR),
116 &dest_path.join(LANG_FEATURES_DIR),
119 generate_unstable_book_files(
120 &doc_src_path.join(LIB_FEATURES_DIR),
121 &dest_path.join(LIB_FEATURES_DIR),
125 copy_recursive(&doc_src_path, &dest_path);
127 generate_summary(&dest_path, &lang_features, &lib_features);