diff options
-rw-r--r-- | crates/ide/src/syntax_highlighting/inject.rs | 22 | ||||
-rw-r--r-- | crates/ide/src/syntax_highlighting/tests.rs | 2 | ||||
-rw-r--r-- | crates/ide_db/src/helpers.rs | 1 | ||||
-rw-r--r-- | crates/ide_db/src/helpers/rust_doc.rs | 34 | ||||
-rw-r--r-- | crates/rust-analyzer/src/markdown.rs | 22 |
5 files changed, 40 insertions, 41 deletions
diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs index 855c7fba8..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 | ||
5 | use either::Either; | 5 | use either::Either; |
6 | use hir::{InFile, Semantics}; | 6 | use hir::{InFile, Semantics}; |
7 | use ide_db::{call_info::ActiveParameter, SymbolKind}; | 7 | use ide_db::{call_info::ActiveParameter, helpers::rust_doc::is_rust_fence, SymbolKind}; |
8 | use syntax::{ | 8 | use syntax::{ |
9 | ast::{self, AstNode}, | 9 | ast::{self, AstNode}, |
10 | AstToken, NodeOrToken, SyntaxNode, SyntaxToken, TextRange, TextSize, | 10 | AstToken, NodeOrToken, SyntaxNode, SyntaxToken, TextRange, TextSize, |
@@ -78,24 +78,6 @@ pub(super) fn ra_fixture( | |||
78 | } | 78 | } |
79 | 79 | ||
80 | const RUSTDOC_FENCE: &'static str = "```"; | 80 | const RUSTDOC_FENCE: &'static str = "```"; |
81 | const RUSTDOC_FENCE_TOKENS: &[&'static str] = &[ | ||
82 | "", | ||
83 | "rust", | ||
84 | "should_panic", | ||
85 | "ignore", | ||
86 | "no_run", | ||
87 | "compile_fail", | ||
88 | "edition2015", | ||
89 | "edition2018", | ||
90 | "edition2021", | ||
91 | ]; | ||
92 | |||
93 | fn is_rustdoc_fence_token(token: &str) -> bool { | ||
94 | if RUSTDOC_FENCE_TOKENS.contains(&token) { | ||
95 | return true; | ||
96 | } | ||
97 | token.starts_with('E') && token.len() == 5 && token[1..].parse::<u32>().is_ok() | ||
98 | } | ||
99 | 81 | ||
100 | /// Injection of syntax highlighting of doctests. | 82 | /// Injection of syntax highlighting of doctests. |
101 | pub(super) fn doc_comment( | 83 | pub(super) fn doc_comment( |
@@ -181,7 +163,7 @@ pub(super) fn doc_comment( | |||
181 | is_codeblock = !is_codeblock; | 163 | is_codeblock = !is_codeblock; |
182 | // Check whether code is rust by inspecting fence guards | 164 | // Check whether code is rust by inspecting fence guards |
183 | let guards = &line[idx + RUSTDOC_FENCE.len()..]; | 165 | let guards = &line[idx + RUSTDOC_FENCE.len()..]; |
184 | let is_rust = guards.split(',').all(|sub| is_rustdoc_fence_token(sub.trim())); | 166 | let is_rust = is_rust_fence(guards); |
185 | is_doctest = is_codeblock && is_rust; | 167 | is_doctest = is_codeblock && is_rust; |
186 | continue; | 168 | continue; |
187 | } | 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. |
2 | pub mod insert_use; | 2 | pub mod insert_use; |
3 | pub mod import_assets; | 3 | pub mod import_assets; |
4 | pub mod rust_doc; | ||
4 | 5 | ||
5 | use std::collections::VecDeque; | 6 | use 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 | ||
4 | pub 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 a51ff89e4..35eaffba8 100644 --- a/crates/rust-analyzer/src/markdown.rs +++ b/crates/rust-analyzer/src/markdown.rs | |||
@@ -1,17 +1,7 @@ | |||
1 | //! Transforms markdown | 1 | //! Transforms markdown |
2 | use ide_db::helpers::rust_doc::is_rust_fence; | ||
2 | 3 | ||
3 | const RUSTDOC_FENCE: &str = "```"; | 4 | const RUSTDOC_FENCE: &str = "```"; |
4 | const RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUST_SPECIFIC: &[&str] = &[ | ||
5 | "", | ||
6 | "rust", | ||
7 | "should_panic", | ||
8 | "ignore", | ||
9 | "no_run", | ||
10 | "compile_fail", | ||
11 | "edition2015", | ||
12 | "edition2018", | ||
13 | "edition2021", | ||
14 | ]; | ||
15 | 5 | ||
16 | pub(crate) fn format_docs(src: &str) -> String { | 6 | pub(crate) fn format_docs(src: &str) -> String { |
17 | let mut processed_lines = Vec::new(); | 7 | let mut processed_lines = Vec::new(); |
@@ -27,8 +17,7 @@ pub(crate) fn format_docs(src: &str) -> String { | |||
27 | in_code_block ^= true; | 17 | in_code_block ^= true; |
28 | 18 | ||
29 | if in_code_block { | 19 | if in_code_block { |
30 | is_rust = | 20 | is_rust = is_rust_fence(header); |
31 | header.split(',').all(|sub| is_rust_specific_code_block_attribute(sub.trim())); | ||
32 | 21 | ||
33 | if is_rust { | 22 | if is_rust { |
34 | line = "```rust"; | 23 | line = "```rust"; |
@@ -41,13 +30,6 @@ pub(crate) fn format_docs(src: &str) -> String { | |||
41 | processed_lines.join("\n") | 30 | processed_lines.join("\n") |
42 | } | 31 | } |
43 | 32 | ||
44 | fn is_rust_specific_code_block_attribute(attr: &str) -> bool { | ||
45 | if RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUST_SPECIFIC.contains(&attr) { | ||
46 | return true; | ||
47 | } | ||
48 | attr.starts_with('E') && attr.len() == 5 && attr[1..].parse::<u32>().is_ok() | ||
49 | } | ||
50 | |||
51 | fn code_line_ignored_by_rustdoc(line: &str) -> bool { | 33 | fn code_line_ignored_by_rustdoc(line: &str) -> bool { |
52 | let trimmed = line.trim(); | 34 | let trimmed = line.trim(); |
53 | trimmed == "#" || trimmed.starts_with("# ") || trimmed.starts_with("#\t") | 35 | trimmed == "#" || trimmed.starts_with("# ") || trimmed.starts_with("#\t") |