aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-04-19 12:39:45 +0100
committerGitHub <[email protected]>2021-04-19 12:39:45 +0100
commit3f1a220f32220cd4a664ca1adac5eb36e9eb33b2 (patch)
treee59269946584d6c70c00dcc25f49ccb0f88a2235 /crates
parent65dd942fa1199361f2f7327bee71ae7ac5f4239d (diff)
parent2f62c0117a1d59a531f9c84fbdb2f70ff87d22e0 (diff)
Merge #8574
8574: Check for rust doc code attributes like rustdoc does r=Veykril a=Veykril bors r+ Co-authored-by: Lukas Wirth <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r--crates/ide/src/syntax_highlighting/inject.rs22
-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.rs22
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
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,24 +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 "edition2015",
89 "edition2018",
90 "edition2021",
91];
92
93fn 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.
101pub(super) fn doc_comment( 83pub(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.
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 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
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 "edition2015",
12 "edition2018",
13 "edition2021",
14];
15 5
16pub(crate) fn format_docs(src: &str) -> String { 6pub(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
44fn 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
51fn code_line_ignored_by_rustdoc(line: &str) -> bool { 33fn 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")