From 367487fe88dca78cffad5138673d5259f7f7ba6b Mon Sep 17 00:00:00 2001 From: robojumper Date: Thu, 28 May 2020 21:42:22 +0200 Subject: Support raw_ref_op's raw reference operator --- xtask/src/ast_src.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'xtask/src') diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs index 394a7bc88..d4621930e 100644 --- a/xtask/src/ast_src.rs +++ b/xtask/src/ast_src.rs @@ -1153,10 +1153,12 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { /// ``` /// ❰ &foo ❱; /// ❰ &mut bar ❱; + /// ❰ &raw const bar ❱; + /// ❰ &raw mut bar ❱; /// ``` /// /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#borrow-operators) - struct RefExpr: AttrsOwner { T![&], T![raw], T![mut], Expr } + struct RefExpr: AttrsOwner { T![&], T![raw], T![mut], T![const], Expr } /// Prefix operator call. This is either `!` or `*` or `-`. /// -- cgit v1.2.3 From e1829d8959d9f48302fec42d64216c158db13744 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 30 May 2020 23:57:16 +0200 Subject: minor --- xtask/src/codegen/gen_assists_docs.rs | 144 +++++++++++++++++----------------- 1 file changed, 73 insertions(+), 71 deletions(-) (limited to 'xtask/src') diff --git a/xtask/src/codegen/gen_assists_docs.rs b/xtask/src/codegen/gen_assists_docs.rs index 4bd6b5f0c..20dcde820 100644 --- a/xtask/src/codegen/gen_assists_docs.rs +++ b/xtask/src/codegen/gen_assists_docs.rs @@ -8,7 +8,7 @@ use crate::{ }; pub fn generate_assists_docs(mode: Mode) -> Result<()> { - let assists = collect_assists()?; + let assists = Assist::collect()?; generate_tests(&assists, mode)?; generate_docs(&assists, mode)?; Ok(()) @@ -22,81 +22,61 @@ struct Assist { after: String, } -fn hide_hash_comments(text: &str) -> String { - text.split('\n') // want final newline - .filter(|&it| !(it.starts_with("# ") || it == "#")) - .map(|it| format!("{}\n", it)) - .collect() -} - -fn reveal_hash_comments(text: &str) -> String { - text.split('\n') // want final newline - .map(|it| { - if it.starts_with("# ") { - &it[2..] - } else if it == "#" { - "" - } else { - it - } - }) - .map(|it| format!("{}\n", it)) - .collect() -} - -fn collect_assists() -> Result> { - let mut res = Vec::new(); - for path in rust_files(&project_root().join(codegen::ASSISTS_DIR)) { - collect_file(&mut res, path.as_path())?; - } - res.sort_by(|lhs, rhs| lhs.id.cmp(&rhs.id)); - return Ok(res); - - fn collect_file(acc: &mut Vec, path: &Path) -> Result<()> { - let text = fs::read_to_string(path)?; - let comment_blocks = extract_comment_blocks_with_empty_lines(&text); - - for block in comment_blocks { - // FIXME: doesn't support blank lines yet, need to tweak - // `extract_comment_blocks` for that. - let mut lines = block.iter(); - let first_line = lines.next().unwrap(); - if !first_line.starts_with("Assist: ") { - continue; - } - let id = first_line["Assist: ".len()..].to_string(); - assert!( - id.chars().all(|it| it.is_ascii_lowercase() || it == '_'), - "invalid assist id: {:?}", - id - ); - - let doc = take_until(lines.by_ref(), "```").trim().to_string(); - assert!( - doc.chars().next().unwrap().is_ascii_uppercase() && doc.ends_with('.'), - "\n\n{}: assist docs should be proper sentences, with capitalization and a full stop at the end.\n\n{}\n\n", - id, doc, - ); - - let before = take_until(lines.by_ref(), "```"); - - assert_eq!(lines.next().unwrap().as_str(), "->"); - assert_eq!(lines.next().unwrap().as_str(), "```"); - let after = take_until(lines.by_ref(), "```"); - acc.push(Assist { id, doc, before, after }) +impl Assist { + fn collect() -> Result> { + let mut res = Vec::new(); + for path in rust_files(&project_root().join(codegen::ASSISTS_DIR)) { + collect_file(&mut res, path.as_path())?; } + res.sort_by(|lhs, rhs| lhs.id.cmp(&rhs.id)); + return Ok(res); + + fn collect_file(acc: &mut Vec, path: &Path) -> Result<()> { + let text = fs::read_to_string(path)?; + let comment_blocks = extract_comment_blocks_with_empty_lines(&text); + + for block in comment_blocks { + // FIXME: doesn't support blank lines yet, need to tweak + // `extract_comment_blocks` for that. + let mut lines = block.iter(); + let first_line = lines.next().unwrap(); + if !first_line.starts_with("Assist: ") { + continue; + } + let id = first_line["Assist: ".len()..].to_string(); + assert!( + id.chars().all(|it| it.is_ascii_lowercase() || it == '_'), + "invalid assist id: {:?}", + id + ); + + let doc = take_until(lines.by_ref(), "```").trim().to_string(); + assert!( + doc.chars().next().unwrap().is_ascii_uppercase() && doc.ends_with('.'), + "\n\n{}: assist docs should be proper sentences, with capitalization and a full stop at the end.\n\n{}\n\n", + id, doc, + ); + + let before = take_until(lines.by_ref(), "```"); + + assert_eq!(lines.next().unwrap().as_str(), "->"); + assert_eq!(lines.next().unwrap().as_str(), "```"); + let after = take_until(lines.by_ref(), "```"); + acc.push(Assist { id, doc, before, after }) + } - fn take_until<'a>(lines: impl Iterator, marker: &str) -> String { - let mut buf = Vec::new(); - for line in lines { - if line == marker { - break; + fn take_until<'a>(lines: impl Iterator, marker: &str) -> String { + let mut buf = Vec::new(); + for line in lines { + if line == marker { + break; + } + buf.push(line.clone()); } - buf.push(line.clone()); + buf.join("\n") } - buf.join("\n") + Ok(()) } - Ok(()) } } @@ -157,3 +137,25 @@ fn generate_docs(assists: &[Assist], mode: Mode) -> Result<()> { codegen::update(&project_root().join(codegen::ASSISTS_DOCS), &buf, mode) } + +fn hide_hash_comments(text: &str) -> String { + text.split('\n') // want final newline + .filter(|&it| !(it.starts_with("# ") || it == "#")) + .map(|it| format!("{}\n", it)) + .collect() +} + +fn reveal_hash_comments(text: &str) -> String { + text.split('\n') // want final newline + .map(|it| { + if it.starts_with("# ") { + &it[2..] + } else if it == "#" { + "" + } else { + it + } + }) + .map(|it| format!("{}\n", it)) + .collect() +} -- cgit v1.2.3 From 383247a9ae8202f20ce6f01d1429c1cd2a11d516 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 31 May 2020 00:33:37 +0200 Subject: Generalize --- xtask/src/codegen.rs | 20 ++++++++++++++++++-- xtask/src/codegen/gen_assists_docs.rs | 10 +++------- 2 files changed, 21 insertions(+), 9 deletions(-) (limited to 'xtask/src') diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index b4907f4b2..2e8fd3494 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs @@ -61,8 +61,24 @@ fn extract_comment_blocks(text: &str) -> Vec> { do_extract_comment_blocks(text, false) } -fn extract_comment_blocks_with_empty_lines(text: &str) -> Vec> { - do_extract_comment_blocks(text, true) +fn extract_comment_blocks_with_empty_lines(tag: &str, text: &str) -> Vec { + assert!(tag.starts_with(char::is_uppercase)); + let tag = format!("{}:", tag); + let mut res = Vec::new(); + for mut block in do_extract_comment_blocks(text, true) { + let first = block.remove(0); + if first.starts_with(&tag) { + let id = first[tag.len()..].trim().to_string(); + let block = CommentBlock { id, contents: block }; + res.push(block); + } + } + res +} + +struct CommentBlock { + id: String, + contents: Vec, } fn do_extract_comment_blocks(text: &str, allow_blocks_with_empty_lines: bool) -> Vec> { diff --git a/xtask/src/codegen/gen_assists_docs.rs b/xtask/src/codegen/gen_assists_docs.rs index 20dcde820..6ebeb8aea 100644 --- a/xtask/src/codegen/gen_assists_docs.rs +++ b/xtask/src/codegen/gen_assists_docs.rs @@ -33,22 +33,18 @@ impl Assist { fn collect_file(acc: &mut Vec, path: &Path) -> Result<()> { let text = fs::read_to_string(path)?; - let comment_blocks = extract_comment_blocks_with_empty_lines(&text); + let comment_blocks = extract_comment_blocks_with_empty_lines("Assist", &text); for block in comment_blocks { // FIXME: doesn't support blank lines yet, need to tweak // `extract_comment_blocks` for that. - let mut lines = block.iter(); - let first_line = lines.next().unwrap(); - if !first_line.starts_with("Assist: ") { - continue; - } - let id = first_line["Assist: ".len()..].to_string(); + let id = block.id; assert!( id.chars().all(|it| it.is_ascii_lowercase() || it == '_'), "invalid assist id: {:?}", id ); + let mut lines = block.contents.iter(); let doc = take_until(lines.by_ref(), "```").trim().to_string(); assert!( -- cgit v1.2.3 From c8f27a4a886413a15a2a6af4a87b39b901c873a8 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 31 May 2020 01:54:54 +0200 Subject: Generate features docs from source --- xtask/src/codegen.rs | 5 ++- xtask/src/codegen/gen_feature_docs.rs | 72 +++++++++++++++++++++++++++++++++++ xtask/src/main.rs | 1 + 3 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 xtask/src/codegen/gen_feature_docs.rs (limited to 'xtask/src') diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index 2e8fd3494..3e2a66979 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs @@ -8,14 +8,15 @@ mod gen_syntax; mod gen_parser_tests; mod gen_assists_docs; +mod gen_feature_docs; use std::{mem, path::Path}; use crate::{not_bash::fs2, Result}; pub use self::{ - gen_assists_docs::generate_assists_docs, gen_parser_tests::generate_parser_tests, - gen_syntax::generate_syntax, + gen_assists_docs::generate_assists_docs, gen_feature_docs::generate_feature_docs, + gen_parser_tests::generate_parser_tests, gen_syntax::generate_syntax, }; const GRAMMAR_DIR: &str = "crates/ra_parser/src/grammar"; diff --git a/xtask/src/codegen/gen_feature_docs.rs b/xtask/src/codegen/gen_feature_docs.rs new file mode 100644 index 000000000..583185648 --- /dev/null +++ b/xtask/src/codegen/gen_feature_docs.rs @@ -0,0 +1,72 @@ +//! 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::>().join("\n\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> { + 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, 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!( + id.split_ascii_whitespace().all(|it| it.starts_with(char::is_uppercase)), + "bad feature: {}", + id + ); + let doc = block.contents.join("\n"); + acc.push(Feature { id, path: path.clone(), doc }) + } + + Ok(()) + } + } +} + +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(); + 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.display(), + name.to_str().unwrap(), + )?; + + writeln!(f, "\n{}", self.doc)?; + Ok(()) + } +} diff --git a/xtask/src/main.rs b/xtask/src/main.rs index dff3ce4a1..9d7cdd114 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -75,6 +75,7 @@ FLAGS: codegen::generate_syntax(Mode::Overwrite)?; codegen::generate_parser_tests(Mode::Overwrite)?; codegen::generate_assists_docs(Mode::Overwrite)?; + codegen::generate_feature_docs(Mode::Overwrite)?; Ok(()) } "format" => { -- cgit v1.2.3 From 5dd65495699fb3d9c6e4b3c4f27b78a64d23e567 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 31 May 2020 09:28:53 +0200 Subject: Simplify --- xtask/src/codegen.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'xtask/src') diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index 3e2a66979..f47d54125 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs @@ -41,7 +41,7 @@ pub enum Mode { /// With verify = false, fn update(path: &Path, contents: &str, mode: Mode) -> Result<()> { match fs2::read_to_string(path) { - Ok(ref old_contents) if normalize(old_contents) == normalize(contents) => { + Ok(old_contents) if normalize(&old_contents) == normalize(contents) => { return Ok(()); } _ => (), -- cgit v1.2.3 From f593393ebb9bfa515caf168a9f037324eeb6edfe Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 31 May 2020 09:45:41 +0200 Subject: Specify actions --- xtask/src/codegen/gen_feature_docs.rs | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'xtask/src') diff --git a/xtask/src/codegen/gen_feature_docs.rs b/xtask/src/codegen/gen_feature_docs.rs index 583185648..170a3e889 100644 --- a/xtask/src/codegen/gen_feature_docs.rs +++ b/xtask/src/codegen/gen_feature_docs.rs @@ -38,11 +38,7 @@ impl Feature { for block in comment_blocks { let id = block.id; - assert!( - id.split_ascii_whitespace().all(|it| it.starts_with(char::is_uppercase)), - "bad feature: {}", - 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 }) } @@ -52,6 +48,25 @@ impl Feature { } } +fn is_valid_feature_name(feature: &str) -> bool { + 'word: for word in feature.split_whitespace() { + for &short in ["to"].iter() { + if word == short { + continue 'word; + } + } + for &short in ["To"].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)?; -- cgit v1.2.3 From 1c6a2eb14a84c3a66972d1a6da429cca1aa8b40a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 31 May 2020 11:29:19 +0200 Subject: Move the rest of the features to generated docs --- xtask/src/codegen/gen_feature_docs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'xtask/src') diff --git a/xtask/src/codegen/gen_feature_docs.rs b/xtask/src/codegen/gen_feature_docs.rs index 170a3e889..a0c2ffef9 100644 --- a/xtask/src/codegen/gen_feature_docs.rs +++ b/xtask/src/codegen/gen_feature_docs.rs @@ -50,12 +50,12 @@ impl Feature { fn is_valid_feature_name(feature: &str) -> bool { 'word: for word in feature.split_whitespace() { - for &short in ["to"].iter() { + for &short in ["to", "and"].iter() { if word == short { continue 'word; } } - for &short in ["To"].iter() { + for &short in ["To", "And"].iter() { if word == short { return false; } -- cgit v1.2.3 From 1cd78a3355ea70d3070cabb00c80a5d195499752 Mon Sep 17 00:00:00 2001 From: robojumper Date: Sun, 31 May 2020 10:59:40 +0200 Subject: correctly infer labelled breaks --- xtask/src/ast_src.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'xtask/src') diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs index d4621930e..f60f0fb16 100644 --- a/xtask/src/ast_src.rs +++ b/xtask/src/ast_src.rs @@ -1058,7 +1058,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { /// [Reference](https://doc.rust-lang.org/reference/expressions/block-expr.html) /// [Labels for blocks RFC](https://github.com/rust-lang/rfcs/blob/master/text/2046-label-break-value.md) struct BlockExpr: AttrsOwner, ModuleItemOwner { - T!['{'], statements: [Stmt], Expr, T!['}'], + Label, T!['{'], statements: [Stmt], Expr, T!['}'], } /// Return expression. -- cgit v1.2.3 From 7e3ee77c83dc4e9af470491046206bf46d2a9a7e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 31 May 2020 12:12:41 +0200 Subject: Tweak whitespace --- xtask/src/codegen/gen_feature_docs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'xtask/src') diff --git a/xtask/src/codegen/gen_feature_docs.rs b/xtask/src/codegen/gen_feature_docs.rs index a0c2ffef9..a6f339e7b 100644 --- a/xtask/src/codegen/gen_feature_docs.rs +++ b/xtask/src/codegen/gen_feature_docs.rs @@ -10,7 +10,7 @@ use crate::{ pub fn generate_feature_docs(mode: Mode) -> Result<()> { let features = Feature::collect()?; let contents = features.into_iter().map(|it| it.to_string()).collect::>().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(()) @@ -81,7 +81,7 @@ impl fmt::Display for Feature { name.to_str().unwrap(), )?; - writeln!(f, "\n{}", self.doc)?; + writeln!(f, "{}", self.doc)?; Ok(()) } } -- cgit v1.2.3 From 13a996f3b68c175f6e6ad8d89081e45850dc5583 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 31 May 2020 12:49:06 +0200 Subject: Force / slashes on windows --- xtask/src/codegen/gen_feature_docs.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'xtask/src') diff --git a/xtask/src/codegen/gen_feature_docs.rs b/xtask/src/codegen/gen_feature_docs.rs index a6f339e7b..dbe583e8e 100644 --- a/xtask/src/codegen/gen_feature_docs.rs +++ b/xtask/src/codegen/gen_feature_docs.rs @@ -70,14 +70,15 @@ fn is_valid_feature_name(feature: &str) -> bool { 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(); + 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.display(), + path, name.to_str().unwrap(), )?; -- cgit v1.2.3 From 5a2f4548e59981871fe4db2b9ee591b9bf39a46e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 31 May 2020 13:22:02 +0200 Subject: Rename user/readme.adoc -> user/manual.adoc --- xtask/src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'xtask/src') diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index 2b7a461e5..06043d19f 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -191,7 +191,11 @@ Release: release:{}[] let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n)); fs2::write(&path, &contents)?; - fs2::copy(project_root().join("./docs/user/readme.adoc"), website_root.join("manual.adoc"))?; + for &adoc in ["manual.adoc", "generated_features.adoc"].iter() { + let src = project_root().join("./docs/user/").join(adoc); + let dst = website_root.join(adoc); + fs2::copy(src, dst)?; + } let tags = run!("git tag --list"; echo = false)?; let prev_tag = tags.lines().filter(|line| is_release_tag(line)).last().unwrap(); -- cgit v1.2.3 From 46292c7cecb0bd957aee48f72b5c1e931ce47b79 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 31 May 2020 15:02:12 +0200 Subject: Move assists documentation into the manual --- xtask/src/codegen.rs | 33 ++++++++++++++-- xtask/src/codegen/gen_assists_docs.rs | 71 ++++++++++++++++++----------------- xtask/src/codegen/gen_feature_docs.rs | 22 ++--------- xtask/src/lib.rs | 2 +- 4 files changed, 71 insertions(+), 57 deletions(-) (limited to 'xtask/src') diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index f47d54125..f3917a244 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs @@ -10,9 +10,12 @@ mod gen_parser_tests; mod gen_assists_docs; mod gen_feature_docs; -use std::{mem, path::Path}; +use std::{ + fmt, mem, + path::{Path, PathBuf}, +}; -use crate::{not_bash::fs2, Result}; +use crate::{not_bash::fs2, project_root, Result}; pub use self::{ gen_assists_docs::generate_assists_docs, gen_feature_docs::generate_feature_docs, @@ -29,7 +32,6 @@ const AST_TOKENS: &str = "crates/ra_syntax/src/ast/generated/tokens.rs"; const ASSISTS_DIR: &str = "crates/ra_assists/src/handlers"; const ASSISTS_TESTS: &str = "crates/ra_assists/src/tests/generated.rs"; -const ASSISTS_DOCS: &str = "docs/user/assists.md"; #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum Mode { @@ -107,3 +109,28 @@ fn do_extract_comment_blocks(text: &str, allow_blocks_with_empty_lines: bool) -> } res } + +#[derive(Debug)] +struct Location { + file: PathBuf, +} + +impl Location { + fn new(file: PathBuf) -> Self { + Self { file } + } +} + +impl fmt::Display for Location { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let path = self.file.strip_prefix(&project_root()).unwrap().display().to_string(); + let path = path.replace('\\', "/"); + let name = self.file.file_name().unwrap(); + write!( + f, + "https://github.com/rust-analyzer/rust-analyzer/blob/master/{}[{}]", + path, + name.to_str().unwrap() + ) + } +} diff --git a/xtask/src/codegen/gen_assists_docs.rs b/xtask/src/codegen/gen_assists_docs.rs index 6ebeb8aea..15a02d317 100644 --- a/xtask/src/codegen/gen_assists_docs.rs +++ b/xtask/src/codegen/gen_assists_docs.rs @@ -1,22 +1,28 @@ //! Generates `assists.md` documentation. -use std::{fs, path::Path}; +use std::{fmt, fs, path::Path}; use crate::{ - codegen::{self, extract_comment_blocks_with_empty_lines, Mode}, + codegen::{self, extract_comment_blocks_with_empty_lines, Location, Mode}, project_root, rust_files, Result, }; pub fn generate_assists_docs(mode: Mode) -> Result<()> { let assists = Assist::collect()?; generate_tests(&assists, mode)?; - generate_docs(&assists, mode)?; + + let contents = assists.into_iter().map(|it| it.to_string()).collect::>().join("\n\n"); + let contents = contents.trim().to_string() + "\n"; + let dst = project_root().join("docs/user/generated_assists.adoc"); + codegen::update(&dst, &contents, mode)?; + Ok(()) } #[derive(Debug)] struct Assist { id: String, + location: Location, doc: String, before: String, after: String, @@ -58,7 +64,8 @@ impl Assist { assert_eq!(lines.next().unwrap().as_str(), "->"); assert_eq!(lines.next().unwrap().as_str(), "```"); let after = take_until(lines.by_ref(), "```"); - acc.push(Assist { id, doc, before, after }) + let location = Location::new(path.to_path_buf()); + acc.push(Assist { id, location, doc, before, after }) } fn take_until<'a>(lines: impl Iterator, marker: &str) -> String { @@ -76,6 +83,31 @@ impl Assist { } } +impl fmt::Display for Assist { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let before = self.before.replace("<|>", "┃"); // Unicode pseudo-graphics bar + let after = self.after.replace("<|>", "┃"); + writeln!( + f, + "[discrete]\n=== `{}` + +{} + +.Before +```rust +{}``` + +.After +```rust +{}```", + self.id, + self.doc, + hide_hash_comments(&before), + hide_hash_comments(&after) + ) + } +} + fn generate_tests(assists: &[Assist], mode: Mode) -> Result<()> { let mut buf = String::from("use super::check_doc_test;\n"); @@ -103,37 +135,6 @@ r#####" codegen::update(&project_root().join(codegen::ASSISTS_TESTS), &buf, mode) } -fn generate_docs(assists: &[Assist], mode: Mode) -> Result<()> { - let mut buf = String::from( - "# Assists\n\nCursor position or selection is signified by `┃` character.\n\n", - ); - - for assist in assists { - let before = assist.before.replace("<|>", "┃"); // Unicode pseudo-graphics bar - let after = assist.after.replace("<|>", "┃"); - let docs = format!( - " -## `{}` - -{} - -```rust -// BEFORE -{} -// AFTER -{}``` -", - assist.id, - assist.doc, - hide_hash_comments(&before), - hide_hash_comments(&after) - ); - buf.push_str(&docs); - } - - codegen::update(&project_root().join(codegen::ASSISTS_DOCS), &buf, mode) -} - fn hide_hash_comments(text: &str) -> String { text.split('\n') // want final newline .filter(|&it| !(it.starts_with("# ") || it == "#")) diff --git a/xtask/src/codegen/gen_feature_docs.rs b/xtask/src/codegen/gen_feature_docs.rs index dbe583e8e..731e7ecf2 100644 --- a/xtask/src/codegen/gen_feature_docs.rs +++ b/xtask/src/codegen/gen_feature_docs.rs @@ -3,7 +3,7 @@ use std::{fmt, fs, path::PathBuf}; use crate::{ - codegen::{self, extract_comment_blocks_with_empty_lines, Mode}, + codegen::{self, extract_comment_blocks_with_empty_lines, Location, Mode}, project_root, rust_files, Result, }; @@ -19,7 +19,7 @@ pub fn generate_feature_docs(mode: Mode) -> Result<()> { #[derive(Debug)] struct Feature { id: String, - path: PathBuf, + location: Location, doc: String, } @@ -40,7 +40,7 @@ impl Feature { 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 }) + acc.push(Feature { id, location: Location::new(path.clone()), doc }) } Ok(()) @@ -69,20 +69,6 @@ fn is_valid_feature_name(feature: &str) -> bool { 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(()) + writeln!(f, "=== {}\n**Source:** {}\n{}", self.id, self.location, self.doc) } } diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index 06043d19f..874957885 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -191,7 +191,7 @@ Release: release:{}[] let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n)); fs2::write(&path, &contents)?; - for &adoc in ["manual.adoc", "generated_features.adoc"].iter() { + for &adoc in ["manual.adoc", "generated_features.adoc", "generated_assists.adoc"].iter() { let src = project_root().join("./docs/user/").join(adoc); let dst = website_root.join(adoc); fs2::copy(src, dst)?; -- cgit v1.2.3 From 899570ad7abbc644e87d8379862c1b9f940eaf07 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 31 May 2020 15:36:20 +0200 Subject: Link to the specific source line --- xtask/src/codegen.rs | 39 +++++++++++++++++++++-------------- xtask/src/codegen/gen_assists_docs.rs | 4 +++- xtask/src/codegen/gen_feature_docs.rs | 3 ++- 3 files changed, 29 insertions(+), 17 deletions(-) (limited to 'xtask/src') diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index f3917a244..5511c01d5 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs @@ -61,18 +61,18 @@ fn update(path: &Path, contents: &str, mode: Mode) -> Result<()> { } fn extract_comment_blocks(text: &str) -> Vec> { - do_extract_comment_blocks(text, false) + do_extract_comment_blocks(text, false).into_iter().map(|(_line, block)| block).collect() } fn extract_comment_blocks_with_empty_lines(tag: &str, text: &str) -> Vec { assert!(tag.starts_with(char::is_uppercase)); let tag = format!("{}:", tag); let mut res = Vec::new(); - for mut block in do_extract_comment_blocks(text, true) { + for (line, mut block) in do_extract_comment_blocks(text, true) { let first = block.remove(0); if first.starts_with(&tag) { let id = first[tag.len()..].trim().to_string(); - let block = CommentBlock { id, contents: block }; + let block = CommentBlock { id, line, contents: block }; res.push(block); } } @@ -81,31 +81,38 @@ fn extract_comment_blocks_with_empty_lines(tag: &str, text: &str) -> Vec, } -fn do_extract_comment_blocks(text: &str, allow_blocks_with_empty_lines: bool) -> Vec> { +fn do_extract_comment_blocks( + text: &str, + allow_blocks_with_empty_lines: bool, +) -> Vec<(usize, Vec)> { let mut res = Vec::new(); let prefix = "// "; let lines = text.lines().map(str::trim_start); - let mut block = vec![]; - for line in lines { + let mut block = (0, vec![]); + for (line_num, line) in lines.enumerate() { if line == "//" && allow_blocks_with_empty_lines { - block.push(String::new()); + block.1.push(String::new()); continue; } let is_comment = line.starts_with(prefix); if is_comment { - block.push(line[prefix.len()..].to_string()); - } else if !block.is_empty() { - res.push(mem::replace(&mut block, Vec::new())); + block.1.push(line[prefix.len()..].to_string()); + } else { + if !block.1.is_empty() { + res.push(mem::take(&mut block)); + } + block.0 = line_num + 2; } } - if !block.is_empty() { - res.push(mem::replace(&mut block, Vec::new())) + if !block.1.is_empty() { + res.push(block) } res } @@ -113,11 +120,12 @@ fn do_extract_comment_blocks(text: &str, allow_blocks_with_empty_lines: bool) -> #[derive(Debug)] struct Location { file: PathBuf, + line: usize, } impl Location { - fn new(file: PathBuf) -> Self { - Self { file } + fn new(file: PathBuf, line: usize) -> Self { + Self { file, line } } } @@ -128,8 +136,9 @@ impl fmt::Display for Location { let name = self.file.file_name().unwrap(); write!( f, - "https://github.com/rust-analyzer/rust-analyzer/blob/master/{}[{}]", + "https://github.com/rust-analyzer/rust-analyzer/blob/master/{}#L{}[{}]", path, + self.line, name.to_str().unwrap() ) } diff --git a/xtask/src/codegen/gen_assists_docs.rs b/xtask/src/codegen/gen_assists_docs.rs index 15a02d317..6c1be5350 100644 --- a/xtask/src/codegen/gen_assists_docs.rs +++ b/xtask/src/codegen/gen_assists_docs.rs @@ -64,7 +64,7 @@ impl Assist { assert_eq!(lines.next().unwrap().as_str(), "->"); assert_eq!(lines.next().unwrap().as_str(), "```"); let after = take_until(lines.by_ref(), "```"); - let location = Location::new(path.to_path_buf()); + let location = Location::new(path.to_path_buf(), block.line); acc.push(Assist { id, location, doc, before, after }) } @@ -90,6 +90,7 @@ impl fmt::Display for Assist { writeln!( f, "[discrete]\n=== `{}` +**Source:** {} {} @@ -101,6 +102,7 @@ impl fmt::Display for Assist { ```rust {}```", self.id, + self.location, self.doc, hide_hash_comments(&before), hide_hash_comments(&after) diff --git a/xtask/src/codegen/gen_feature_docs.rs b/xtask/src/codegen/gen_feature_docs.rs index 731e7ecf2..31bc3839d 100644 --- a/xtask/src/codegen/gen_feature_docs.rs +++ b/xtask/src/codegen/gen_feature_docs.rs @@ -40,7 +40,8 @@ impl Feature { let id = block.id; assert!(is_valid_feature_name(&id), "invalid feature name: {:?}", id); let doc = block.contents.join("\n"); - acc.push(Feature { id, location: Location::new(path.clone()), doc }) + let location = Location::new(path.clone(), block.line); + acc.push(Feature { id, location, doc }) } Ok(()) -- cgit v1.2.3 From 5315934d888797432d62ec4a55303aeacb8cd286 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 3 Jun 2020 18:22:05 +0200 Subject: Don't store generated docs in the repo --- xtask/src/codegen.rs | 6 ++++-- xtask/src/codegen/gen_assists_docs.rs | 11 ++++++----- xtask/src/lib.rs | 2 ++ xtask/src/main.rs | 1 + 4 files changed, 13 insertions(+), 7 deletions(-) (limited to 'xtask/src') diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index 5511c01d5..f5f4b964a 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs @@ -18,8 +18,10 @@ use std::{ use crate::{not_bash::fs2, project_root, Result}; pub use self::{ - gen_assists_docs::generate_assists_docs, gen_feature_docs::generate_feature_docs, - gen_parser_tests::generate_parser_tests, gen_syntax::generate_syntax, + gen_assists_docs::{generate_assists_docs, generate_assists_tests}, + gen_feature_docs::generate_feature_docs, + gen_parser_tests::generate_parser_tests, + gen_syntax::generate_syntax, }; const GRAMMAR_DIR: &str = "crates/ra_parser/src/grammar"; diff --git a/xtask/src/codegen/gen_assists_docs.rs b/xtask/src/codegen/gen_assists_docs.rs index 6c1be5350..526941f73 100644 --- a/xtask/src/codegen/gen_assists_docs.rs +++ b/xtask/src/codegen/gen_assists_docs.rs @@ -7,16 +7,17 @@ use crate::{ project_root, rust_files, Result, }; -pub fn generate_assists_docs(mode: Mode) -> Result<()> { +pub fn generate_assists_tests(mode: Mode) -> Result<()> { let assists = Assist::collect()?; - generate_tests(&assists, mode)?; + generate_tests(&assists, mode) +} +pub fn generate_assists_docs(mode: Mode) -> Result<()> { + let assists = Assist::collect()?; let contents = assists.into_iter().map(|it| it.to_string()).collect::>().join("\n\n"); let contents = contents.trim().to_string() + "\n"; let dst = project_root().join("docs/user/generated_assists.adoc"); - codegen::update(&dst, &contents, mode)?; - - Ok(()) + codegen::update(&dst, &contents, mode) } #[derive(Debug)] diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index 874957885..739f49f7b 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -160,6 +160,8 @@ pub fn run_release(dry_run: bool) -> Result<()> { run!("git reset --hard tags/nightly")?; run!("git push")?; } + codegen::generate_assists_docs(Mode::Overwrite)?; + codegen::generate_feature_docs(Mode::Overwrite)?; let website_root = project_root().join("../rust-analyzer.github.io"); let changelog_dir = website_root.join("./thisweek/_posts"); diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 9d7cdd114..81bb3a33f 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -74,6 +74,7 @@ FLAGS: args.finish()?; codegen::generate_syntax(Mode::Overwrite)?; codegen::generate_parser_tests(Mode::Overwrite)?; + codegen::generate_assists_tests(Mode::Overwrite)?; codegen::generate_assists_docs(Mode::Overwrite)?; codegen::generate_feature_docs(Mode::Overwrite)?; Ok(()) -- cgit v1.2.3