Skip to content

Commit c2d5906

Browse files
committed
Autogenerate stubs and the summary of the unstable book
1 parent d810898 commit c2d5906

File tree

15 files changed

+308
-45
lines changed

15 files changed

+308
-45
lines changed

src/Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ members = [
99
"tools/error_index_generator",
1010
"tools/linkchecker",
1111
"tools/rustbook",
12+
"tools/unstable-book-gen",
1213
"tools/tidy",
1314
"tools/build-manifest",
1415
"tools/remote-test-client",

src/bootstrap/doc.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,26 @@ use {Build, Compiler, Mode};
2727
use util::{cp_r, symlink_dir};
2828
use build_helper::up_to_date;
2929

30-
/// Invoke `rustbook` as compiled in `stage` for `target` for the doc book
31-
/// `name` into the `out` path.
30+
/// Invoke `rustbook` for `target` for the doc book `name`.
3231
///
3332
/// This will not actually generate any documentation if the documentation has
3433
/// already been generated.
3534
pub fn rustbook(build: &Build, target: &str, name: &str) {
35+
let src = build.src.join("src/doc");
36+
rustbook_src(build, target, name, &src);
37+
}
38+
39+
/// Invoke `rustbook` for `target` for the doc book `name` from the `src` path.
40+
///
41+
/// This will not actually generate any documentation if the documentation has
42+
/// already been generated.
43+
pub fn rustbook_src(build: &Build, target: &str, name: &str, src: &Path) {
3644
let out = build.doc_out(target);
3745
t!(fs::create_dir_all(&out));
3846

3947
let out = out.join(name);
4048
let compiler = Compiler::new(0, &build.config.build);
41-
let src = build.src.join("src/doc").join(name);
49+
let src = src.join(name);
4250
let index = out.join("index.html");
4351
let rustbook = build.tool(&compiler, "rustbook");
4452
if up_to_date(&src, &index) && up_to_date(&rustbook, &index) {
@@ -354,6 +362,19 @@ pub fn error_index(build: &Build, target: &str) {
354362
build.run(&mut index);
355363
}
356364

365+
pub fn unstable_book_gen(build: &Build, target: &str) {
366+
println!("Generating unstable book md files ({})", target);
367+
let out = build.md_doc_out(target).join("unstable-book");
368+
t!(fs::create_dir_all(&out));
369+
t!(fs::remove_dir_all(&out));
370+
let compiler = Compiler::new(0, &build.config.build);
371+
let mut cmd = build.tool_cmd(&compiler, "unstable-book-gen");
372+
cmd.arg(build.src.join("src"));
373+
cmd.arg(out);
374+
375+
build.run(&mut cmd);
376+
}
377+
357378
fn symlink_dir_force(src: &Path, dst: &Path) -> io::Result<()> {
358379
if let Ok(m) = fs::symlink_metadata(dst) {
359380
if m.file_type().is_dir() {

src/bootstrap/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,11 @@ impl Build {
677677
self.out.join(target).join("doc")
678678
}
679679

680+
/// Output directory for some generated md crate documentation for a target (temporary)
681+
fn md_doc_out(&self, target: &str) -> PathBuf {
682+
self.out.join(target).join("md-doc")
683+
}
684+
680685
/// Output directory for all crate documentation for a target (temporary)
681686
///
682687
/// The artifacts here are then copied into `doc_out` above.

src/bootstrap/step.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,10 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
548548
.dep(|s| s.name("maybe-clean-tools"))
549549
.dep(|s| s.name("librustc-tool"))
550550
.run(move |s| compile::tool(build, s.stage, s.target, "error_index_generator"));
551+
rules.build("tool-unstable-book-gen", "src/tools/unstable-book-gen")
552+
.dep(|s| s.name("maybe-clean-tools"))
553+
.dep(|s| s.name("libstd-tool"))
554+
.run(move |s| compile::tool(build, s.stage, s.target, "unstable-book-gen"));
551555
rules.build("tool-tidy", "src/tools/tidy")
552556
.dep(|s| s.name("maybe-clean-tools"))
553557
.dep(|s| s.name("libstd-tool"))
@@ -662,8 +666,17 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
662666
.target(&build.config.build)
663667
.stage(0)
664668
})
669+
.dep(move |s| {
670+
s.name("doc-unstable-book-gen")
671+
.host(&build.config.build)
672+
.target(&build.config.build)
673+
.stage(0)
674+
})
665675
.default(build.config.docs)
666-
.run(move |s| doc::rustbook(build, s.target, "unstable-book"));
676+
.run(move |s| doc::rustbook_src(build,
677+
s.target,
678+
"unstable-book",
679+
&build.md_doc_out(s.target)));
667680
rules.doc("doc-standalone", "src/doc")
668681
.dep(move |s| {
669682
s.name("rustc")
@@ -679,6 +692,12 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
679692
.default(build.config.docs)
680693
.host(true)
681694
.run(move |s| doc::error_index(build, s.target));
695+
rules.doc("doc-unstable-book-gen", "src/tools/unstable-book-gen")
696+
.dep(move |s| s.name("tool-unstable-book-gen").target(&build.config.build).stage(0))
697+
.dep(move |s| s.name("librustc-link"))
698+
.default(build.config.docs)
699+
.host(true)
700+
.run(move |s| doc::unstable_book_gen(build, s.target));
682701
for (krate, path, default) in krates("std") {
683702
rules.doc(&krate.doc_step, path)
684703
.dep(|s| s.name("libstd-link"))

src/doc/unstable-book/src/language-features/asm.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,4 +190,4 @@ constraints, etc.
190190
[llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions
191191

192192
If you need more power and don't mind losing some of the niceties of
193-
`asm!`, check out [global_asm](language-features/global_asm.html).
193+
`asm!`, check out [global_asm](language-features/global-asm.html).

src/tools/tidy/src/features.rs

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use std::fs::File;
2424
use std::io::prelude::*;
2525
use std::path::Path;
2626

27-
#[derive(Debug, PartialEq)]
27+
#[derive(Debug, PartialEq, Clone)]
2828
pub enum Status {
2929
Stable,
3030
Removed,
@@ -42,13 +42,16 @@ impl fmt::Display for Status {
4242
}
4343
}
4444

45-
#[derive(Debug)]
45+
#[derive(Debug, Clone)]
4646
pub struct Feature {
4747
pub level: Status,
4848
pub since: String,
4949
pub has_gate_test: bool,
50+
pub tracking_issue: Option<u32>,
5051
}
5152

53+
pub type Features = HashMap<String, Feature>;
54+
5255
pub fn check(path: &Path, bad: &mut bool, quiet: bool) {
5356
let mut features = collect_lang_features(path);
5457
assert!(!features.is_empty());
@@ -168,8 +171,7 @@ fn find_attr_val<'a>(line: &'a str, attr: &str) -> Option<&'a str> {
168171
.map(|(i, j)| &line[i..j])
169172
}
170173

171-
fn test_filen_gate(filen_underscore: &str,
172-
features: &mut HashMap<String, Feature>) -> bool {
174+
fn test_filen_gate(filen_underscore: &str, features: &mut Features) -> bool {
173175
if filen_underscore.starts_with("feature_gate") {
174176
for (n, f) in features.iter_mut() {
175177
if filen_underscore == format!("feature_gate_{}", n) {
@@ -181,7 +183,7 @@ fn test_filen_gate(filen_underscore: &str,
181183
return false;
182184
}
183185

184-
pub fn collect_lang_features(base_src_path: &Path) -> HashMap<String, Feature> {
186+
pub fn collect_lang_features(base_src_path: &Path) -> Features {
185187
let mut contents = String::new();
186188
let path = base_src_path.join("libsyntax/feature_gate.rs");
187189
t!(t!(File::open(path)).read_to_string(&mut contents));
@@ -197,20 +199,28 @@ pub fn collect_lang_features(base_src_path: &Path) -> HashMap<String, Feature> {
197199
};
198200
let name = parts.next().unwrap().trim();
199201
let since = parts.next().unwrap().trim().trim_matches('"');
202+
let issue_str = parts.next().unwrap().trim();
203+
let tracking_issue = if issue_str.starts_with("None") {
204+
None
205+
} else {
206+
let s = issue_str.split("(").nth(1).unwrap().split(")").nth(0).unwrap();
207+
Some(s.parse().unwrap())
208+
};
200209
Some((name.to_owned(),
201210
Feature {
202-
level: level,
211+
level,
203212
since: since.to_owned(),
204213
has_gate_test: false,
214+
tracking_issue,
205215
}))
206216
})
207217
.collect()
208218
}
209219

210220
pub fn collect_lib_features(base_src_path: &Path,
211221
bad: &mut bool,
212-
features: &HashMap<String, Feature>) -> HashMap<String, Feature> {
213-
let mut lib_features = HashMap::<String, Feature>::new();
222+
features: &Features) -> Features {
223+
let mut lib_features = Features::new();
214224
let mut contents = String::new();
215225
super::walk(base_src_path,
216226
&mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
@@ -224,10 +234,32 @@ pub fn collect_lib_features(base_src_path: &Path,
224234
contents.truncate(0);
225235
t!(t!(File::open(&file), &file).read_to_string(&mut contents));
226236

237+
let mut becoming_feature: Option<(String, Feature)> = None;
227238
for (i, line) in contents.lines().enumerate() {
228239
let mut err = |msg: &str| {
229240
tidy_error!(bad, "{}:{}: {}", file.display(), i + 1, msg);
230241
};
242+
if let Some((ref name, ref mut f)) = becoming_feature {
243+
if f.tracking_issue.is_none() {
244+
f.tracking_issue = find_attr_val(line, "issue")
245+
.map(|s| s.parse().unwrap());
246+
}
247+
if line.ends_with("]") {
248+
lib_features.insert(name.to_owned(), f.clone());
249+
} else if !line.ends_with(",") && !line.ends_with("\\") {
250+
// We need to bail here because we might have missed the
251+
// end of a stability attribute above because the "]"
252+
// might not have been at the end of the line.
253+
// We could then get into the very unfortunate situation that
254+
// we continue parsing the file assuming the current stability
255+
// attribute has not ended, and ignoring possible feature
256+
// attributes in the process.
257+
err("malformed stability attribute");
258+
} else {
259+
continue;
260+
}
261+
}
262+
becoming_feature = None;
231263
let level = if line.contains("[unstable(") {
232264
Status::Unstable
233265
} else if line.contains("[stable(") {
@@ -250,6 +282,7 @@ pub fn collect_lib_features(base_src_path: &Path,
250282
}
251283
None => "None",
252284
};
285+
let tracking_issue = find_attr_val(line, "issue").map(|s| s.parse().unwrap());
253286

254287
if features.contains_key(feature_name) {
255288
err("duplicating a lang feature");
@@ -263,12 +296,17 @@ pub fn collect_lib_features(base_src_path: &Path,
263296
}
264297
continue;
265298
}
266-
lib_features.insert(feature_name.to_owned(),
267-
Feature {
268-
level: level,
269-
since: since.to_owned(),
270-
has_gate_test: false,
271-
});
299+
let feature = Feature {
300+
level,
301+
since: since.to_owned(),
302+
has_gate_test: false,
303+
tracking_issue,
304+
};
305+
if line.contains("]") {
306+
lib_features.insert(feature_name.to_owned(), feature);
307+
} else {
308+
becoming_feature = Some((feature_name.to_owned(), feature));
309+
}
272310
}
273311
});
274312
lib_features

src/tools/tidy/src/unstable_book.rs

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,28 @@
1111
use std::collections::HashSet;
1212
use std::fs;
1313
use std::path;
14-
use features::{collect_lang_features, collect_lib_features, Status};
14+
use features::{collect_lang_features, collect_lib_features, Features, Status};
1515

16-
const PATH_STR: &'static str = "doc/unstable-book/src";
16+
pub const PATH_STR: &str = "doc/unstable-book/src";
1717

18-
const LANG_FEATURES_DIR: &'static str = "language-features";
18+
pub const COMPILER_FLAGS_DIR: &str = "compiler-flags";
1919

20-
const LIB_FEATURES_DIR: &'static str = "library-features";
20+
pub const LANG_FEATURES_DIR: &str = "language-features";
21+
22+
pub const LIB_FEATURES_DIR: &str = "library-features";
2123

2224
/// Build the path to the Unstable Book source directory from the Rust 'src' directory
23-
fn unstable_book_path(base_src_path: &path::Path) -> path::PathBuf {
25+
pub fn unstable_book_path(base_src_path: &path::Path) -> path::PathBuf {
2426
base_src_path.join(PATH_STR)
2527
}
2628

2729
/// Directory where the features are documented within the Unstable Book source directory
28-
fn unstable_book_lang_features_path(base_src_path: &path::Path) -> path::PathBuf {
30+
pub fn unstable_book_lang_features_path(base_src_path: &path::Path) -> path::PathBuf {
2931
unstable_book_path(base_src_path).join(LANG_FEATURES_DIR)
3032
}
3133

3234
/// Directory where the features are documented within the Unstable Book source directory
33-
fn unstable_book_lib_features_path(base_src_path: &path::Path) -> path::PathBuf {
35+
pub fn unstable_book_lib_features_path(base_src_path: &path::Path) -> path::PathBuf {
3436
unstable_book_path(base_src_path).join(LIB_FEATURES_DIR)
3537
}
3638

@@ -42,27 +44,16 @@ fn dir_entry_is_file(dir_entry: &fs::DirEntry) -> bool {
4244
.is_file()
4345
}
4446

45-
/// Retrieve names of all lang-related unstable features
46-
fn collect_unstable_lang_feature_names(base_src_path: &path::Path) -> HashSet<String> {
47-
collect_lang_features(base_src_path)
48-
.into_iter()
49-
.filter(|&(_, ref f)| f.level == Status::Unstable)
50-
.map(|(ref name, _)| name.to_owned())
51-
.collect()
52-
}
53-
54-
/// Retrieve names of all lib-related unstable features
55-
fn collect_unstable_lib_feature_names(base_src_path: &path::Path) -> HashSet<String> {
56-
let mut bad = true;
57-
let lang_features = collect_lang_features(base_src_path);
58-
collect_lib_features(base_src_path, &mut bad, &lang_features)
59-
.into_iter()
47+
/// Retrieve names of all unstable features
48+
pub fn collect_unstable_feature_names(features: &Features) -> HashSet<String> {
49+
features
50+
.iter()
6051
.filter(|&(_, ref f)| f.level == Status::Unstable)
61-
.map(|(ref name, _)| name.to_owned())
52+
.map(|(name, _)| name.to_owned())
6253
.collect()
6354
}
6455

65-
fn collect_unstable_book_section_file_names(dir: &path::Path) -> HashSet<String> {
56+
pub fn collect_unstable_book_section_file_names(dir: &path::Path) -> HashSet<String> {
6657
fs::read_dir(dir)
6758
.expect("could not read directory")
6859
.into_iter()
@@ -95,7 +86,10 @@ pub fn check(path: &path::Path, bad: &mut bool) {
9586

9687
// Library features
9788

98-
let unstable_lib_feature_names = collect_unstable_lib_feature_names(path);
89+
let lang_features = collect_lang_features(path);
90+
let lib_features = collect_lib_features(path, bad, &lang_features);
91+
92+
let unstable_lib_feature_names = collect_unstable_feature_names(&lib_features);
9993
let unstable_book_lib_features_section_file_names =
10094
collect_unstable_book_lib_features_section_file_names(path);
10195

@@ -119,7 +113,7 @@ pub fn check(path: &path::Path, bad: &mut bool) {
119113

120114
// Language features
121115

122-
let unstable_lang_feature_names = collect_unstable_lang_feature_names(path);
116+
let unstable_lang_feature_names = collect_unstable_feature_names(&lang_features);
123117
let unstable_book_lang_features_section_file_names =
124118
collect_unstable_book_lang_features_section_file_names(path);
125119

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
authors = ["est31 <MTest31@outlook.com>",
3+
"The Rust Project Developers"]
4+
name = "unstable-book-gen"
5+
version = "0.1.0"
6+
license = "MIT/Apache-2.0"
7+
8+
[dependencies]
9+
tidy = { path = "../tidy" }
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[The Unstable Book](the-unstable-book.md)
2+
3+
- [Compiler flags](compiler-flags.md)
4+
{compiler_flags}
5+
- [Language features](language-features.md)
6+
{language_features}
7+
- [Library Features](library-features.md)
8+
{library_features}

0 commit comments

Comments
 (0)