Skip to content

Commit 52b19c3

Browse files
committed
Create xtask module to generate diagnostics docs
1 parent 378dd90 commit 52b19c3

File tree

3 files changed

+77
-0
lines changed

3 files changed

+77
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ crates/*/target
99
.vscode/settings.json
1010
generated_assists.adoc
1111
generated_features.adoc
12+
generated_diagnostic.adoc

xtask/src/codegen.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ mod gen_parser_tests;
1010
mod gen_assists_docs;
1111
mod gen_feature_docs;
1212
mod gen_features;
13+
mod gen_diagnostic_docs;
1314

1415
use std::{
1516
fmt, mem,
@@ -21,6 +22,7 @@ use crate::{ensure_rustfmt, project_root, Result};
2122

2223
pub use self::{
2324
gen_assists_docs::{generate_assists_docs, generate_assists_tests},
25+
gen_diagnostic_docs::generate_diagnostic_docs,
2426
gen_feature_docs::generate_feature_docs,
2527
gen_features::generate_features,
2628
gen_parser_tests::generate_parser_tests,
@@ -47,6 +49,7 @@ impl CodegenCmd {
4749
generate_assists_tests(Mode::Overwrite)?;
4850
generate_assists_docs(Mode::Overwrite)?;
4951
generate_feature_docs(Mode::Overwrite)?;
52+
generate_diagnostic_docs(Mode::Overwrite)?;
5053
Ok(())
5154
}
5255
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
//! Generates `assists.md` documentation.
2+
3+
use std::{fmt, fs, path::PathBuf};
4+
5+
use crate::{
6+
codegen::{self, extract_comment_blocks_with_empty_lines, Location, Mode, PREAMBLE},
7+
project_root, rust_files, Result,
8+
};
9+
10+
pub fn generate_diagnostic_docs(mode: Mode) -> Result<()> {
11+
let features = Diagnostic::collect()?;
12+
let contents = features.into_iter().map(|it| it.to_string()).collect::<Vec<_>>().join("\n\n");
13+
let contents = format!("//{}\n{}\n", PREAMBLE, contents.trim());
14+
let dst = project_root().join("docs/user/generated_diagnostic.adoc");
15+
codegen::update(&dst, &contents, mode)?;
16+
Ok(())
17+
}
18+
19+
#[derive(Debug)]
20+
struct Diagnostic {
21+
id: String,
22+
location: Location,
23+
doc: String,
24+
}
25+
26+
impl Diagnostic {
27+
fn collect() -> Result<Vec<Diagnostic>> {
28+
let mut res = Vec::new();
29+
for path in rust_files(&project_root()) {
30+
collect_file(&mut res, path)?;
31+
}
32+
res.sort_by(|lhs, rhs| lhs.id.cmp(&rhs.id));
33+
return Ok(res);
34+
35+
fn collect_file(acc: &mut Vec<Diagnostic>, path: PathBuf) -> Result<()> {
36+
let text = fs::read_to_string(&path)?;
37+
let comment_blocks = extract_comment_blocks_with_empty_lines("Diagnostic", &text);
38+
39+
for block in comment_blocks {
40+
let id = block.id;
41+
if let Err(msg) = is_valid_diagnostic_name(&id) {
42+
panic!("invalid diagnostic name: {:?}:\n {}", id, msg)
43+
}
44+
let doc = block.contents.join("\n");
45+
let location = Location::new(path.clone(), block.line);
46+
acc.push(Diagnostic { id, location, doc })
47+
}
48+
49+
Ok(())
50+
}
51+
}
52+
}
53+
54+
fn is_valid_diagnostic_name(diagnostic: &str) -> Result<(), String> {
55+
let diagnostic = diagnostic.trim();
56+
if diagnostic.find(char::is_whitespace).is_some() {
57+
return Err("Diagnostic names can't contain whitespace symbols".into());
58+
}
59+
if diagnostic.chars().any(|c| c.is_ascii_uppercase()) {
60+
return Err("Diagnostic names can't contain uppercase symbols".into());
61+
}
62+
if diagnostic.chars().any(|c| !c.is_ascii()) {
63+
return Err("Diagnostic can't contain non-ASCII symbols".into());
64+
}
65+
66+
Ok(())
67+
}
68+
69+
impl fmt::Display for Diagnostic {
70+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71+
writeln!(f, "=== {}\n**Source:** {}\n{}", self.id, self.location, self.doc)
72+
}
73+
}

0 commit comments

Comments
 (0)