From 2f62c0117a1d59a531f9c84fbdb2f70ff87d22e0 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 19 Apr 2021 13:20:37 +0200 Subject: Check for rust doc code attributes like rustdoc does --- crates/ide/src/syntax_highlighting/inject.rs | 24 ++------------------ crates/ide/src/syntax_highlighting/tests.rs | 2 +- crates/ide_db/src/helpers.rs | 1 + crates/ide_db/src/helpers/rust_doc.rs | 34 ++++++++++++++++++++++++++++ crates/rust-analyzer/src/markdown.rs | 24 ++------------------ 5 files changed, 40 insertions(+), 45 deletions(-) create mode 100644 crates/ide_db/src/helpers/rust_doc.rs 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; use either::Either; use hir::{InFile, Semantics}; -use ide_db::{call_info::ActiveParameter, SymbolKind}; +use ide_db::{call_info::ActiveParameter, helpers::rust_doc::is_rust_fence, SymbolKind}; use syntax::{ ast::{self, AstNode}, AstToken, NodeOrToken, SyntaxNode, SyntaxToken, TextRange, TextSize, @@ -78,26 +78,6 @@ pub(super) fn ra_fixture( } const RUSTDOC_FENCE: &'static str = "```"; -const RUSTDOC_FENCE_TOKENS: &[&'static str] = &[ - "", - "rust", - "should_panic", - "ignore", - "no_run", - "compile_fail", - "allow_fail", - "test_harness", - "edition2015", - "edition2018", - "edition2021", -]; - -fn is_rustdoc_fence_token(token: &str) -> bool { - if RUSTDOC_FENCE_TOKENS.contains(&token) { - return true; - } - token.starts_with('E') && token.len() == 5 && token[1..].parse::().is_ok() -} /// Injection of syntax highlighting of doctests. pub(super) fn doc_comment( @@ -183,7 +163,7 @@ pub(super) fn doc_comment( is_codeblock = !is_codeblock; // Check whether code is rust by inspecting fence guards let guards = &line[idx + RUSTDOC_FENCE.len()..]; - let is_rust = guards.split(',').any(|sub| is_rustdoc_fence_token(sub.trim())); + let is_rust = is_rust_fence(guards); is_doctest = is_codeblock && is_rust; continue; } 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() { .filter(|it| it.highlight.tag == HlTag::Symbol(SymbolKind::Function)) .count() }; - assert_eq!(hash, 1629); + assert_eq!(hash, 1632); } #[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 @@ //! A module with ide helpers for high-level ide features. pub mod insert_use; pub mod import_assets; +pub mod rust_doc; use std::collections::VecDeque; 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 @@ +//! Rustdoc specific doc comment handling + +// stripped down version of https://github.com/rust-lang/rust/blob/392ba2ba1a7d6c542d2459fb8133bebf62a4a423/src/librustdoc/html/markdown.rs#L810-L933 +pub fn is_rust_fence(s: &str) -> bool { + let mut seen_rust_tags = false; + let mut seen_other_tags = false; + + let tokens = s + .trim() + .split(|c| c == ',' || c == ' ' || c == '\t') + .map(str::trim) + .filter(|t| !t.is_empty()); + + for token in tokens { + match token { + "should_panic" | "no_run" | "ignore" | "allow_fail" => { + seen_rust_tags = !seen_other_tags + } + "rust" => seen_rust_tags = true, + "test_harness" | "compile_fail" => seen_rust_tags = !seen_other_tags || seen_rust_tags, + x if x.starts_with("edition") => {} + x if x.starts_with('E') && x.len() == 5 => { + if x[1..].parse::().is_ok() { + seen_rust_tags = !seen_other_tags || seen_rust_tags; + } else { + seen_other_tags = true; + } + } + _ => seen_other_tags = true, + } + } + + !seen_other_tags || seen_rust_tags +} 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 @@ //! Transforms markdown +use ide_db::helpers::rust_doc::is_rust_fence; const RUSTDOC_FENCE: &str = "```"; -const RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUST_SPECIFIC: &[&str] = &[ - "", - "rust", - "should_panic", - "ignore", - "no_run", - "compile_fail", - "allow_fail", - "test_harness", - "edition2015", - "edition2018", - "edition2021", -]; pub(crate) fn format_docs(src: &str) -> String { let mut processed_lines = Vec::new(); @@ -29,8 +17,7 @@ pub(crate) fn format_docs(src: &str) -> String { in_code_block ^= true; if in_code_block { - is_rust = - header.split(',').any(|sub| is_rust_specific_code_block_attribute(sub.trim())); + is_rust = is_rust_fence(header); if is_rust { line = "```rust"; @@ -43,13 +30,6 @@ pub(crate) fn format_docs(src: &str) -> String { processed_lines.join("\n") } -fn is_rust_specific_code_block_attribute(attr: &str) -> bool { - if RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUST_SPECIFIC.contains(&attr) { - return true; - } - attr.starts_with('E') && attr.len() == 5 && attr[1..].parse::().is_ok() -} - fn code_line_ignored_by_rustdoc(line: &str) -> bool { let trimmed = line.trim(); trimmed == "#" || trimmed.starts_with("# ") || trimmed.starts_with("#\t") -- cgit v1.2.3