]> git.lizzy.rs Git - rust.git/commitdiff
Check for rust doc code attributes like rustdoc does
authorLukas Wirth <lukastw97@gmail.com>
Mon, 19 Apr 2021 11:20:37 +0000 (13:20 +0200)
committerLukas Wirth <lukastw97@gmail.com>
Mon, 19 Apr 2021 11:32:52 +0000 (13:32 +0200)
crates/ide/src/syntax_highlighting/inject.rs
crates/ide/src/syntax_highlighting/tests.rs
crates/ide_db/src/helpers.rs
crates/ide_db/src/helpers/rust_doc.rs [new file with mode: 0644]
crates/rust-analyzer/src/markdown.rs

index 6b10378701fae465713763bff5dac16bf4ee4c9b..bc221d59966fc422e9fa092dc66347b1a2d1e9c1 100644 (file)
@@ -4,7 +4,7 @@
 
 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::<u32>().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;
                 }
index 933cfa6f314267f2ea5bd1aa6954b351d8a969c2..17cc6334b9e07cc68f440ce6ee3a7f18100033f0 100644 (file)
@@ -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]
index 83a665b376069417714727a7f64c76dfc3559537..720de0d1fba82d9cd55ad484e560a31666bd2439 100644 (file)
@@ -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 (file)
index 0000000..e27e238
--- /dev/null
@@ -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::<u32>().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
+}
index 8932faaa8735d73836e25f8728a7b9618d5bda69..35eaffba8ca99a4e88ca5f0d20f13c946820a7b1 100644 (file)
@@ -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::<u32>().is_ok()
-}
-
 fn code_line_ignored_by_rustdoc(line: &str) -> bool {
     let trimmed = line.trim();
     trimmed == "#" || trimmed.starts_with("# ") || trimmed.starts_with("#\t")