aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2021-04-19 12:20:37 +0100
committerLukas Wirth <[email protected]>2021-04-19 12:32:52 +0100
commit2f62c0117a1d59a531f9c84fbdb2f70ff87d22e0 (patch)
treeb5d6941cad6a68b786dd8993bfb8a9bb8997aa80
parent8a959497b1fab35294d8ccfa5e51c80a3551a224 (diff)
Check for rust doc code attributes like rustdoc does
-rw-r--r--crates/ide/src/syntax_highlighting/inject.rs24
-rw-r--r--crates/ide/src/syntax_highlighting/tests.rs2
-rw-r--r--crates/ide_db/src/helpers.rs1
-rw-r--r--crates/ide_db/src/helpers/rust_doc.rs34
-rw-r--r--crates/rust-analyzer/src/markdown.rs24
5 files changed, 40 insertions, 45 deletions
diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs
index 6b1037870..bc221d599 100644
--- a/crates/ide/src/syntax_highlighting/inject.rs
+++ b/crates/ide/src/syntax_highlighting/inject.rs
@@ -4,7 +4,7 @@ use std::mem;
4 4
5use either::Either; 5use either::Either;
6use hir::{InFile, Semantics}; 6use hir::{InFile, Semantics};
7use ide_db::{call_info::ActiveParameter, SymbolKind}; 7use ide_db::{call_info::ActiveParameter, helpers::rust_doc::is_rust_fence, SymbolKind};
8use syntax::{ 8use syntax::{
9 ast::{self, AstNode}, 9 ast::{self, AstNode},
10 AstToken, NodeOrToken, SyntaxNode, SyntaxToken, TextRange, TextSize, 10 AstToken, NodeOrToken, SyntaxNode, SyntaxToken, TextRange, TextSize,
@@ -78,26 +78,6 @@ pub(super) fn ra_fixture(
78} 78}
79 79
80const RUSTDOC_FENCE: &'static str = "```"; 80const RUSTDOC_FENCE: &'static str = "```";
81const RUSTDOC_FENCE_TOKENS: &[&'static str] = &[
82 "",
83 "rust",
84 "should_panic",
85 "ignore",
86 "no_run",
87 "compile_fail",
88 "allow_fail",
89 "test_harness",
90 "edition2015",
91 "edition2018",
92 "edition2021",
93];
94
95fn is_rustdoc_fence_token(token: &str) -> bool {
96 if RUSTDOC_FENCE_TOKENS.contains(&token) {
97 return true;
98 }
99 token.starts_with('E') && token.len() == 5 && token[1..].parse::<u32>().is_ok()
100}
101 81
102/// Injection of syntax highlighting of doctests. 82/// Injection of syntax highlighting of doctests.
103pub(super) fn doc_comment( 83pub(super) fn doc_comment(
@@ -183,7 +163,7 @@ pub(super) fn doc_comment(
183 is_codeblock = !is_codeblock; 163 is_codeblock = !is_codeblock;
184 // Check whether code is rust by inspecting fence guards 164 // Check whether code is rust by inspecting fence guards
185 let guards = &line[idx + RUSTDOC_FENCE.len()..]; 165 let guards = &line[idx + RUSTDOC_FENCE.len()..];
186 let is_rust = guards.split(',').any(|sub| is_rustdoc_fence_token(sub.trim())); 166 let is_rust = is_rust_fence(guards);
187 is_doctest = is_codeblock && is_rust; 167 is_doctest = is_codeblock && is_rust;
188 continue; 168 continue;
189 } 169 }
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index 933cfa6f3..17cc6334b 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -307,7 +307,7 @@ fn benchmark_syntax_highlighting_parser() {
307 .filter(|it| it.highlight.tag == HlTag::Symbol(SymbolKind::Function)) 307 .filter(|it| it.highlight.tag == HlTag::Symbol(SymbolKind::Function))
308 .count() 308 .count()
309 }; 309 };
310 assert_eq!(hash, 1629); 310 assert_eq!(hash, 1632);
311} 311}
312 312
313#[test] 313#[test]
diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs
index 83a665b37..720de0d1f 100644
--- a/crates/ide_db/src/helpers.rs
+++ b/crates/ide_db/src/helpers.rs
@@ -1,6 +1,7 @@
1//! A module with ide helpers for high-level ide features. 1//! A module with ide helpers for high-level ide features.
2pub mod insert_use; 2pub mod insert_use;
3pub mod import_assets; 3pub mod import_assets;
4pub mod rust_doc;
4 5
5use std::collections::VecDeque; 6use std::collections::VecDeque;
6 7
diff --git a/crates/ide_db/src/helpers/rust_doc.rs b/crates/ide_db/src/helpers/rust_doc.rs
new file mode 100644
index 000000000..e27e23867
--- /dev/null
+++ b/crates/ide_db/src/helpers/rust_doc.rs
@@ -0,0 +1,34 @@
1//! Rustdoc specific doc comment handling
2
3// stripped down version of https://github.com/rust-lang/rust/blob/392ba2ba1a7d6c542d2459fb8133bebf62a4a423/src/librustdoc/html/markdown.rs#L810-L933
4pub fn is_rust_fence(s: &str) -> bool {
5 let mut seen_rust_tags = false;
6 let mut seen_other_tags = false;
7
8 let tokens = s
9 .trim()
10 .split(|c| c == ',' || c == ' ' || c == '\t')
11 .map(str::trim)
12 .filter(|t| !t.is_empty());
13
14 for token in tokens {
15 match token {
16 "should_panic" | "no_run" | "ignore" | "allow_fail" => {
17 seen_rust_tags = !seen_other_tags
18 }
19 "rust" => seen_rust_tags = true,
20 "test_harness" | "compile_fail" => seen_rust_tags = !seen_other_tags || seen_rust_tags,
21 x if x.starts_with("edition") => {}
22 x if x.starts_with('E') && x.len() == 5 => {
23 if x[1..].parse::<u32>().is_ok() {
24 seen_rust_tags = !seen_other_tags || seen_rust_tags;
25 } else {
26 seen_other_tags = true;
27 }
28 }
29 _ => seen_other_tags = true,
30 }
31 }
32
33 !seen_other_tags || seen_rust_tags
34}
diff --git a/crates/rust-analyzer/src/markdown.rs b/crates/rust-analyzer/src/markdown.rs
index 8932faaa8..35eaffba8 100644
--- a/crates/rust-analyzer/src/markdown.rs
+++ b/crates/rust-analyzer/src/markdown.rs
@@ -1,19 +1,7 @@
1//! Transforms markdown 1//! Transforms markdown
2use ide_db::helpers::rust_doc::is_rust_fence;
2 3
3const RUSTDOC_FENCE: &str = "```"; 4const RUSTDOC_FENCE: &str = "```";
4const RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUST_SPECIFIC: &[&str] = &[
5 "",
6 "rust",
7 "should_panic",
8 "ignore",
9 "no_run",
10 "compile_fail",
11 "allow_fail",
12 "test_harness",
13 "edition2015",
14 "edition2018",
15 "edition2021",
16];
17 5
18pub(crate) fn format_docs(src: &str) -> String { 6pub(crate) fn format_docs(src: &str) -> String {
19 let mut processed_lines = Vec::new(); 7 let mut processed_lines = Vec::new();
@@ -29,8 +17,7 @@ pub(crate) fn format_docs(src: &str) -> String {
29 in_code_block ^= true; 17 in_code_block ^= true;
30 18
31 if in_code_block { 19 if in_code_block {
32 is_rust = 20 is_rust = is_rust_fence(header);
33 header.split(',').any(|sub| is_rust_specific_code_block_attribute(sub.trim()));
34 21
35 if is_rust { 22 if is_rust {
36 line = "```rust"; 23 line = "```rust";
@@ -43,13 +30,6 @@ pub(crate) fn format_docs(src: &str) -> String {
43 processed_lines.join("\n") 30 processed_lines.join("\n")
44} 31}
45 32
46fn is_rust_specific_code_block_attribute(attr: &str) -> bool {
47 if RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUST_SPECIFIC.contains(&attr) {
48 return true;
49 }
50 attr.starts_with('E') && attr.len() == 5 && attr[1..].parse::<u32>().is_ok()
51}
52
53fn code_line_ignored_by_rustdoc(line: &str) -> bool { 33fn code_line_ignored_by_rustdoc(line: &str) -> bool {
54 let trimmed = line.trim(); 34 let trimmed = line.trim();
55 trimmed == "#" || trimmed.starts_with("# ") || trimmed.starts_with("#\t") 35 trimmed == "#" || trimmed.starts_with("# ") || trimmed.starts_with("#\t")