about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2023-09-02 17:20:37 +0200
committerLukas Wirth <lukastw97@gmail.com>2023-09-02 17:27:52 +0200
commit81f0108067fe29c758270c0384a359003f7860de (patch)
treeb8c02ef6d0945832fb5a78af22def4d75d10f2e7
parent8eddc64f862700b16256a1712ff25bf673f02efb (diff)
downloadrust-81f0108067fe29c758270c0384a359003f7860de.tar.gz
rust-81f0108067fe29c758270c0384a359003f7860de.zip
Remove markdown module from rust-analyzer crate
-rw-r--r--crates/hir-def/src/attr.rs4
-rw-r--r--crates/ide-db/src/documentation.rs1
-rw-r--r--crates/ide-db/src/rust_doc.rs169
-rw-r--r--crates/ide/src/signature_help.rs26
-rw-r--r--crates/rust-analyzer/src/lib.rs1
-rw-r--r--crates/rust-analyzer/src/lsp/to_proto.rs7
-rw-r--r--crates/rust-analyzer/src/markdown.rs167
7 files changed, 188 insertions, 187 deletions
diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs
index 07dbafec749..c6454eb9ea0 100644
--- a/crates/hir-def/src/attr.rs
+++ b/crates/hir-def/src/attr.rs
@@ -5,7 +5,7 @@ pub mod builtin;
 #[cfg(test)]
 mod tests;
 
-use std::{hash::Hash, ops};
+use std::{hash::Hash, ops, slice::Iter as SliceIter};
 
 use base_db::CrateId;
 use cfg::{CfgExpr, CfgOptions};
@@ -251,7 +251,6 @@ impl Attrs {
     }
 }
 
-use std::slice::Iter as SliceIter;
 #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
 pub enum DocAtom {
     /// eg. `#[doc(hidden)]`
@@ -265,7 +264,6 @@ pub enum DocAtom {
 
 // Adapted from `CfgExpr` parsing code
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-// #[cfg_attr(test, derive(derive_arbitrary::Arbitrary))]
 pub enum DocExpr {
     Invalid,
     /// eg. `#[doc(hidden)]`, `#[doc(alias = "x")]`
diff --git a/crates/ide-db/src/documentation.rs b/crates/ide-db/src/documentation.rs
index aa8a374218d..26f3cd28a27 100644
--- a/crates/ide-db/src/documentation.rs
+++ b/crates/ide-db/src/documentation.rs
@@ -1,3 +1,4 @@
+//! Documentation attribute related utilties.
 use either::Either;
 use hir::{
     db::{DefDatabase, HirDatabase},
diff --git a/crates/ide-db/src/rust_doc.rs b/crates/ide-db/src/rust_doc.rs
index e27e23867a8..ab2a250289c 100644
--- a/crates/ide-db/src/rust_doc.rs
+++ b/crates/ide-db/src/rust_doc.rs
@@ -1,5 +1,7 @@
 //! Rustdoc specific doc comment handling
 
+use crate::documentation::Documentation;
+
 // 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;
@@ -32,3 +34,170 @@ pub fn is_rust_fence(s: &str) -> bool {
 
     !seen_other_tags || seen_rust_tags
 }
+
+const RUSTDOC_FENCES: [&str; 2] = ["```", "~~~"];
+
+pub fn format_docs(src: &Documentation) -> String {
+    format_docs_(src.as_str())
+}
+
+fn format_docs_(src: &str) -> String {
+    let mut processed_lines = Vec::new();
+    let mut in_code_block = false;
+    let mut is_rust = false;
+
+    for mut line in src.lines() {
+        if in_code_block && is_rust && code_line_ignored_by_rustdoc(line) {
+            continue;
+        }
+
+        if let Some(header) = RUSTDOC_FENCES.into_iter().find_map(|fence| line.strip_prefix(fence))
+        {
+            in_code_block ^= true;
+
+            if in_code_block {
+                is_rust = is_rust_fence(header);
+
+                if is_rust {
+                    line = "```rust";
+                }
+            }
+        }
+
+        if in_code_block {
+            let trimmed = line.trim_start();
+            if is_rust && trimmed.starts_with("##") {
+                line = &trimmed[1..];
+            }
+        }
+
+        processed_lines.push(line);
+    }
+    processed_lines.join("\n")
+}
+
+fn code_line_ignored_by_rustdoc(line: &str) -> bool {
+    let trimmed = line.trim();
+    trimmed == "#" || trimmed.starts_with("# ") || trimmed.starts_with("#\t")
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_format_docs_adds_rust() {
+        let comment = "```\nfn some_rust() {}\n```";
+        assert_eq!(format_docs_(comment), "```rust\nfn some_rust() {}\n```");
+    }
+
+    #[test]
+    fn test_format_docs_handles_plain_text() {
+        let comment = "```text\nthis is plain text\n```";
+        assert_eq!(format_docs_(comment), "```text\nthis is plain text\n```");
+    }
+
+    #[test]
+    fn test_format_docs_handles_non_rust() {
+        let comment = "```sh\nsupposedly shell code\n```";
+        assert_eq!(format_docs_(comment), "```sh\nsupposedly shell code\n```");
+    }
+
+    #[test]
+    fn test_format_docs_handles_rust_alias() {
+        let comment = "```ignore\nlet z = 55;\n```";
+        assert_eq!(format_docs_(comment), "```rust\nlet z = 55;\n```");
+    }
+
+    #[test]
+    fn test_format_docs_handles_complex_code_block_attrs() {
+        let comment = "```rust,no_run\nlet z = 55;\n```";
+        assert_eq!(format_docs_(comment), "```rust\nlet z = 55;\n```");
+    }
+
+    #[test]
+    fn test_format_docs_handles_error_codes() {
+        let comment = "```compile_fail,E0641\nlet b = 0 as *const _;\n```";
+        assert_eq!(format_docs_(comment), "```rust\nlet b = 0 as *const _;\n```");
+    }
+
+    #[test]
+    fn test_format_docs_skips_comments_in_rust_block() {
+        let comment =
+            "```rust\n # skip1\n# skip2\n#stay1\nstay2\n#\n #\n   #    \n #\tskip3\n\t#\t\n```";
+        assert_eq!(format_docs_(comment), "```rust\n#stay1\nstay2\n```");
+    }
+
+    #[test]
+    fn test_format_docs_does_not_skip_lines_if_plain_text() {
+        let comment =
+            "```text\n # stay1\n# stay2\n#stay3\nstay4\n#\n #\n   #    \n #\tstay5\n\t#\t\n```";
+        assert_eq!(
+            format_docs_(comment),
+            "```text\n # stay1\n# stay2\n#stay3\nstay4\n#\n #\n   #    \n #\tstay5\n\t#\t\n```",
+        );
+    }
+
+    #[test]
+    fn test_format_docs_keeps_comments_outside_of_rust_block() {
+        let comment = " # stay1\n# stay2\n#stay3\nstay4\n#\n #\n   #    \n #\tstay5\n\t#\t";
+        assert_eq!(format_docs_(comment), comment);
+    }
+
+    #[test]
+    fn test_format_docs_preserves_newlines() {
+        let comment = "this\nis\nmultiline";
+        assert_eq!(format_docs_(comment), comment);
+    }
+
+    #[test]
+    fn test_code_blocks_in_comments_marked_as_rust() {
+        let comment = r#"```rust
+fn main(){}
+```
+Some comment.
+```
+let a = 1;
+```"#;
+
+        assert_eq!(
+            format_docs_(comment),
+            "```rust\nfn main(){}\n```\nSome comment.\n```rust\nlet a = 1;\n```"
+        );
+    }
+
+    #[test]
+    fn test_code_blocks_in_comments_marked_as_text() {
+        let comment = r#"```text
+filler
+text
+```
+Some comment.
+```
+let a = 1;
+```"#;
+
+        assert_eq!(
+            format_docs_(comment),
+            "```text\nfiller\ntext\n```\nSome comment.\n```rust\nlet a = 1;\n```"
+        );
+    }
+
+    #[test]
+    fn test_format_docs_handles_escape_double_hashes() {
+        let comment = r#"```rust
+let s = "foo
+## bar # baz";
+```"#;
+
+        assert_eq!(format_docs_(comment), "```rust\nlet s = \"foo\n# bar # baz\";\n```");
+    }
+
+    #[test]
+    fn test_format_docs_handles_double_hashes_non_rust() {
+        let comment = r#"```markdown
+## A second-level heading
+```"#;
+        assert_eq!(format_docs_(comment), "```markdown\n## A second-level heading\n```");
+    }
+}
diff --git a/crates/ide/src/signature_help.rs b/crates/ide/src/signature_help.rs
index f57eb2ba3eb..e020b52e171 100644
--- a/crates/ide/src/signature_help.rs
+++ b/crates/ide/src/signature_help.rs
@@ -8,7 +8,7 @@ use hir::{AssocItem, GenericParam, HirDisplay, ModuleDef, PathResolution, Semant
 use ide_db::{
     active_parameter::{callable_for_node, generic_def_for_node},
     base_db::FilePosition,
-    documentation::HasDocs,
+    documentation::{Documentation, HasDocs},
     FxIndexMap,
 };
 use stdx::format_to;
@@ -27,7 +27,7 @@ use crate::RootDatabase;
 /// edited.
 #[derive(Debug)]
 pub struct SignatureHelp {
-    pub doc: Option<String>,
+    pub doc: Option<Documentation>,
     pub signature: String,
     pub active_parameter: Option<usize>,
     parameters: Vec<TextRange>,
@@ -178,7 +178,7 @@ fn signature_help_for_call(
     let mut fn_params = None;
     match callable.kind() {
         hir::CallableKind::Function(func) => {
-            res.doc = func.docs(db).map(|it| it.into());
+            res.doc = func.docs(db);
             format_to!(res.signature, "fn {}", func.name(db).display(db));
             fn_params = Some(match callable.receiver_param(db) {
                 Some(_self) => func.params_without_self(db),
@@ -186,11 +186,11 @@ fn signature_help_for_call(
             });
         }
         hir::CallableKind::TupleStruct(strukt) => {
-            res.doc = strukt.docs(db).map(|it| it.into());
+            res.doc = strukt.docs(db);
             format_to!(res.signature, "struct {}", strukt.name(db).display(db));
         }
         hir::CallableKind::TupleEnumVariant(variant) => {
-            res.doc = variant.docs(db).map(|it| it.into());
+            res.doc = variant.docs(db);
             format_to!(
                 res.signature,
                 "enum {}::{}",
@@ -264,38 +264,38 @@ fn signature_help_for_generics(
     let db = sema.db;
     match generics_def {
         hir::GenericDef::Function(it) => {
-            res.doc = it.docs(db).map(|it| it.into());
+            res.doc = it.docs(db);
             format_to!(res.signature, "fn {}", it.name(db).display(db));
         }
         hir::GenericDef::Adt(hir::Adt::Enum(it)) => {
-            res.doc = it.docs(db).map(|it| it.into());
+            res.doc = it.docs(db);
             format_to!(res.signature, "enum {}", it.name(db).display(db));
         }
         hir::GenericDef::Adt(hir::Adt::Struct(it)) => {
-            res.doc = it.docs(db).map(|it| it.into());
+            res.doc = it.docs(db);
             format_to!(res.signature, "struct {}", it.name(db).display(db));
         }
         hir::GenericDef::Adt(hir::Adt::Union(it)) => {
-            res.doc = it.docs(db).map(|it| it.into());
+            res.doc = it.docs(db);
             format_to!(res.signature, "union {}", it.name(db).display(db));
         }
         hir::GenericDef::Trait(it) => {
-            res.doc = it.docs(db).map(|it| it.into());
+            res.doc = it.docs(db);
             format_to!(res.signature, "trait {}", it.name(db).display(db));
         }
         hir::GenericDef::TraitAlias(it) => {
-            res.doc = it.docs(db).map(|it| it.into());
+            res.doc = it.docs(db);
             format_to!(res.signature, "trait {}", it.name(db).display(db));
         }
         hir::GenericDef::TypeAlias(it) => {
-            res.doc = it.docs(db).map(|it| it.into());
+            res.doc = it.docs(db);
             format_to!(res.signature, "type {}", it.name(db).display(db));
         }
         hir::GenericDef::Variant(it) => {
             // In paths, generics of an enum can be specified *after* one of its variants.
             // eg. `None::<u8>`
             // We'll use the signature of the enum, but include the docs of the variant.
-            res.doc = it.docs(db).map(|it| it.into());
+            res.doc = it.docs(db);
             let enum_ = it.parent_enum(db);
             format_to!(res.signature, "enum {}", enum_.name(db).display(db));
             generics_def = enum_.into();
diff --git a/crates/rust-analyzer/src/lib.rs b/crates/rust-analyzer/src/lib.rs
index 04ac77b1f6c..6c62577f696 100644
--- a/crates/rust-analyzer/src/lib.rs
+++ b/crates/rust-analyzer/src/lib.rs
@@ -26,7 +26,6 @@ mod dispatch;
 mod global_state;
 mod line_index;
 mod main_loop;
-mod markdown;
 mod mem_docs;
 mod op_queue;
 mod reload;
diff --git a/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs
index daa7f5fe19d..57f46022540 100644
--- a/crates/rust-analyzer/src/lsp/to_proto.rs
+++ b/crates/rust-analyzer/src/lsp/to_proto.rs
@@ -13,6 +13,7 @@ use ide::{
     RenameError, Runnable, Severity, SignatureHelp, SnippetEdit, SourceChange, StructureNodeKind,
     SymbolKind, TextEdit, TextRange, TextSize,
 };
+use ide_db::rust_doc::format_docs;
 use itertools::Itertools;
 use serde_json::to_value;
 use vfs::AbsPath;
@@ -105,7 +106,7 @@ pub(crate) fn diagnostic_severity(severity: Severity) -> lsp_types::DiagnosticSe
 }
 
 pub(crate) fn documentation(documentation: Documentation) -> lsp_types::Documentation {
-    let value = crate::markdown::format_docs(documentation.as_str());
+    let value = format_docs(&documentation);
     let markup_content = lsp_types::MarkupContent { kind: lsp_types::MarkupKind::Markdown, value };
     lsp_types::Documentation::MarkupContent(markup_content)
 }
@@ -416,7 +417,7 @@ pub(crate) fn signature_help(
     let documentation = call_info.doc.filter(|_| config.docs).map(|doc| {
         lsp_types::Documentation::MarkupContent(lsp_types::MarkupContent {
             kind: lsp_types::MarkupKind::Markdown,
-            value: crate::markdown::format_docs(&doc),
+            value: format_docs(&doc),
         })
     });
 
@@ -1531,7 +1532,7 @@ pub(crate) fn markup_content(
         ide::HoverDocFormat::Markdown => lsp_types::MarkupKind::Markdown,
         ide::HoverDocFormat::PlainText => lsp_types::MarkupKind::PlainText,
     };
-    let value = crate::markdown::format_docs(markup.as_str());
+    let value = format_docs(&Documentation::new(markup.into()));
     lsp_types::MarkupContent { kind, value }
 }
 
diff --git a/crates/rust-analyzer/src/markdown.rs b/crates/rust-analyzer/src/markdown.rs
deleted file mode 100644
index 140e16ecf1b..00000000000
--- a/crates/rust-analyzer/src/markdown.rs
+++ /dev/null
@@ -1,167 +0,0 @@
-//! Transforms rust like doc content to markdown, replacing rustdoc fences and removing rustdoc code
-//! block comments.
-use ide_db::rust_doc::is_rust_fence;
-
-const RUSTDOC_FENCES: [&str; 2] = ["```", "~~~"];
-
-// FIXME: why is this in this crate?
-pub(crate) fn format_docs(src: &str) -> String {
-    let mut processed_lines = Vec::new();
-    let mut in_code_block = false;
-    let mut is_rust = false;
-
-    for mut line in src.lines() {
-        if in_code_block && is_rust && code_line_ignored_by_rustdoc(line) {
-            continue;
-        }
-
-        if let Some(header) = RUSTDOC_FENCES.into_iter().find_map(|fence| line.strip_prefix(fence))
-        {
-            in_code_block ^= true;
-
-            if in_code_block {
-                is_rust = is_rust_fence(header);
-
-                if is_rust {
-                    line = "```rust";
-                }
-            }
-        }
-
-        if in_code_block {
-            let trimmed = line.trim_start();
-            if is_rust && trimmed.starts_with("##") {
-                line = &trimmed[1..];
-            }
-        }
-
-        processed_lines.push(line);
-    }
-    processed_lines.join("\n")
-}
-
-fn code_line_ignored_by_rustdoc(line: &str) -> bool {
-    let trimmed = line.trim();
-    trimmed == "#" || trimmed.starts_with("# ") || trimmed.starts_with("#\t")
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn test_format_docs_adds_rust() {
-        let comment = "```\nfn some_rust() {}\n```";
-        assert_eq!(format_docs(comment), "```rust\nfn some_rust() {}\n```");
-    }
-
-    #[test]
-    fn test_format_docs_handles_plain_text() {
-        let comment = "```text\nthis is plain text\n```";
-        assert_eq!(format_docs(comment), "```text\nthis is plain text\n```");
-    }
-
-    #[test]
-    fn test_format_docs_handles_non_rust() {
-        let comment = "```sh\nsupposedly shell code\n```";
-        assert_eq!(format_docs(comment), "```sh\nsupposedly shell code\n```");
-    }
-
-    #[test]
-    fn test_format_docs_handles_rust_alias() {
-        let comment = "```ignore\nlet z = 55;\n```";
-        assert_eq!(format_docs(comment), "```rust\nlet z = 55;\n```");
-    }
-
-    #[test]
-    fn test_format_docs_handles_complex_code_block_attrs() {
-        let comment = "```rust,no_run\nlet z = 55;\n```";
-        assert_eq!(format_docs(comment), "```rust\nlet z = 55;\n```");
-    }
-
-    #[test]
-    fn test_format_docs_handles_error_codes() {
-        let comment = "```compile_fail,E0641\nlet b = 0 as *const _;\n```";
-        assert_eq!(format_docs(comment), "```rust\nlet b = 0 as *const _;\n```");
-    }
-
-    #[test]
-    fn test_format_docs_skips_comments_in_rust_block() {
-        let comment =
-            "```rust\n # skip1\n# skip2\n#stay1\nstay2\n#\n #\n   #    \n #\tskip3\n\t#\t\n```";
-        assert_eq!(format_docs(comment), "```rust\n#stay1\nstay2\n```");
-    }
-
-    #[test]
-    fn test_format_docs_does_not_skip_lines_if_plain_text() {
-        let comment =
-            "```text\n # stay1\n# stay2\n#stay3\nstay4\n#\n #\n   #    \n #\tstay5\n\t#\t\n```";
-        assert_eq!(
-            format_docs(comment),
-            "```text\n # stay1\n# stay2\n#stay3\nstay4\n#\n #\n   #    \n #\tstay5\n\t#\t\n```",
-        );
-    }
-
-    #[test]
-    fn test_format_docs_keeps_comments_outside_of_rust_block() {
-        let comment = " # stay1\n# stay2\n#stay3\nstay4\n#\n #\n   #    \n #\tstay5\n\t#\t";
-        assert_eq!(format_docs(comment), comment);
-    }
-
-    #[test]
-    fn test_format_docs_preserves_newlines() {
-        let comment = "this\nis\nmultiline";
-        assert_eq!(format_docs(comment), comment);
-    }
-
-    #[test]
-    fn test_code_blocks_in_comments_marked_as_rust() {
-        let comment = r#"```rust
-fn main(){}
-```
-Some comment.
-```
-let a = 1;
-```"#;
-
-        assert_eq!(
-            format_docs(comment),
-            "```rust\nfn main(){}\n```\nSome comment.\n```rust\nlet a = 1;\n```"
-        );
-    }
-
-    #[test]
-    fn test_code_blocks_in_comments_marked_as_text() {
-        let comment = r#"```text
-filler
-text
-```
-Some comment.
-```
-let a = 1;
-```"#;
-
-        assert_eq!(
-            format_docs(comment),
-            "```text\nfiller\ntext\n```\nSome comment.\n```rust\nlet a = 1;\n```"
-        );
-    }
-
-    #[test]
-    fn test_format_docs_handles_escape_double_hashes() {
-        let comment = r#"```rust
-let s = "foo
-## bar # baz";
-```"#;
-
-        assert_eq!(format_docs(comment), "```rust\nlet s = \"foo\n# bar # baz\";\n```");
-    }
-
-    #[test]
-    fn test_format_docs_handles_double_hashes_non_rust() {
-        let comment = r#"```markdown
-## A second-level heading
-```"#;
-        assert_eq!(format_docs(comment), "```markdown\n## A second-level heading\n```");
-    }
-}