Skip to content

Commit 3f1a220

Browse files
bors[bot]Veykril
andauthored
Merge #8574
8574: Check for rust doc code attributes like rustdoc does r=Veykril a=Veykril bors r+ Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
2 parents 65dd942 + 2f62c01 commit 3f1a220

File tree

5 files changed

+40
-41
lines changed

5 files changed

+40
-41
lines changed

crates/ide/src/syntax_highlighting/inject.rs

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::mem;
44

55
use either::Either;
66
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};
88
use syntax::{
99
ast::{self, AstNode},
1010
AstToken, NodeOrToken, SyntaxNode, SyntaxToken, TextRange, TextSize,
@@ -78,24 +78,6 @@ pub(super) fn ra_fixture(
7878
}
7979

8080
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-
}
9981

10082
/// Injection of syntax highlighting of doctests.
10183
pub(super) fn doc_comment(
@@ -181,7 +163,7 @@ pub(super) fn doc_comment(
181163
is_codeblock = !is_codeblock;
182164
// Check whether code is rust by inspecting fence guards
183165
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);
185167
is_doctest = is_codeblock && is_rust;
186168
continue;
187169
}

crates/ide/src/syntax_highlighting/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ fn benchmark_syntax_highlighting_parser() {
307307
.filter(|it| it.highlight.tag == HlTag::Symbol(SymbolKind::Function))
308308
.count()
309309
};
310-
assert_eq!(hash, 1629);
310+
assert_eq!(hash, 1632);
311311
}
312312

313313
#[test]

crates/ide_db/src/helpers.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! A module with ide helpers for high-level ide features.
22
pub mod insert_use;
33
pub mod import_assets;
4+
pub mod rust_doc;
45

56
use std::collections::VecDeque;
67

crates/ide_db/src/helpers/rust_doc.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
}

crates/rust-analyzer/src/markdown.rs

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,7 @@
11
//! Transforms markdown
2+
use ide_db::helpers::rust_doc::is_rust_fence;
23

34
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-
];
155

166
pub(crate) fn format_docs(src: &str) -> String {
177
let mut processed_lines = Vec::new();
@@ -27,8 +17,7 @@ pub(crate) fn format_docs(src: &str) -> String {
2717
in_code_block ^= true;
2818

2919
if in_code_block {
30-
is_rust =
31-
header.split(',').all(|sub| is_rust_specific_code_block_attribute(sub.trim()));
20+
is_rust = is_rust_fence(header);
3221

3322
if is_rust {
3423
line = "```rust";
@@ -41,13 +30,6 @@ pub(crate) fn format_docs(src: &str) -> String {
4130
processed_lines.join("\n")
4231
}
4332

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-
5133
fn code_line_ignored_by_rustdoc(line: &str) -> bool {
5234
let trimmed = line.trim();
5335
trimmed == "#" || trimmed.starts_with("# ") || trimmed.starts_with("#\t")

0 commit comments

Comments
 (0)