diff options
| author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-05-31 10:50:11 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-05-31 10:50:11 +0000 |
| commit | 09df51dab89340bcf4b8ede95c02c32b0c8eb2bc (patch) | |
| tree | 0240c629fe96243e1a1c91ccd679947bfb1ecb03 /xtask/src/codegen/gen_feature_docs.rs | |
| parent | 5f7225446e75509ae0d971a6f3e2b9d3e37d6f2a (diff) | |
| parent | 13a996f3b68c175f6e6ad8d89081e45850dc5583 (diff) | |
| download | rust-09df51dab89340bcf4b8ede95c02c32b0c8eb2bc.tar.gz rust-09df51dab89340bcf4b8ede95c02c32b0c8eb2bc.zip | |
Merge #4664
4664: Generate feature documentation from code r=matklad a=matklad Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
Diffstat (limited to 'xtask/src/codegen/gen_feature_docs.rs')
| -rw-r--r-- | xtask/src/codegen/gen_feature_docs.rs | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/xtask/src/codegen/gen_feature_docs.rs b/xtask/src/codegen/gen_feature_docs.rs new file mode 100644 index 00000000000..dbe583e8e4f --- /dev/null +++ b/xtask/src/codegen/gen_feature_docs.rs @@ -0,0 +1,88 @@ +//! Generates `assists.md` documentation. + +use std::{fmt, fs, path::PathBuf}; + +use crate::{ + codegen::{self, extract_comment_blocks_with_empty_lines, Mode}, + project_root, rust_files, Result, +}; + +pub fn generate_feature_docs(mode: Mode) -> Result<()> { + let features = Feature::collect()?; + let contents = features.into_iter().map(|it| it.to_string()).collect::<Vec<_>>().join("\n\n"); + let contents = contents.trim().to_string() + "\n"; + let dst = project_root().join("docs/user/generated_features.adoc"); + codegen::update(&dst, &contents, mode)?; + Ok(()) +} + +#[derive(Debug)] +struct Feature { + id: String, + path: PathBuf, + doc: String, +} + +impl Feature { + fn collect() -> Result<Vec<Feature>> { + let mut res = Vec::new(); + for path in rust_files(&project_root()) { + collect_file(&mut res, path)?; + } + res.sort_by(|lhs, rhs| lhs.id.cmp(&rhs.id)); + return Ok(res); + + fn collect_file(acc: &mut Vec<Feature>, path: PathBuf) -> Result<()> { + let text = fs::read_to_string(&path)?; + let comment_blocks = extract_comment_blocks_with_empty_lines("Feature", &text); + + for block in comment_blocks { + let id = block.id; + assert!(is_valid_feature_name(&id), "invalid feature name: {:?}", id); + let doc = block.contents.join("\n"); + acc.push(Feature { id, path: path.clone(), doc }) + } + + Ok(()) + } + } +} + +fn is_valid_feature_name(feature: &str) -> bool { + 'word: for word in feature.split_whitespace() { + for &short in ["to", "and"].iter() { + if word == short { + continue 'word; + } + } + for &short in ["To", "And"].iter() { + if word == short { + return false; + } + } + if !word.starts_with(char::is_uppercase) { + return false; + } + } + true +} + +impl fmt::Display for Feature { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!(f, "=== {}", self.id)?; + let path = self.path.strip_prefix(&project_root()).unwrap().display().to_string(); + let path = path.replace('\\', "/"); + let name = self.path.file_name().unwrap(); + + //FIXME: generate line number as well + writeln!( + f, + "**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/{}[{}]", + path, + name.to_str().unwrap(), + )?; + + writeln!(f, "{}", self.doc)?; + Ok(()) + } +} |
