Skip to content

Commit 28de3de

Browse files
committed
Add description parsers for Markdown/RST
See more info in PR or merge commit.
1 parent 010b3ea commit 28de3de

File tree

15 files changed

+5387
-8
lines changed

15 files changed

+5387
-8
lines changed

Cargo.lock

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ members = [
99
# local
1010
emmylua_code_analysis = { path = "crates/emmylua_code_analysis", version = "0.10.0" }
1111
emmylua_parser = { path = "crates/emmylua_parser", version = "0.12.0" }
12+
emmylua_parser_desc = { path = "crates/emmylua_parser_desc", version = "0.12.0" }
1213
emmylua_diagnostic_macro = { path = "crates/emmylua_diagnostic_macro", version = "0.5.0" }
1314

1415
# external
@@ -51,3 +52,4 @@ ansi_term = "0.12.1"
5152
num-traits = { version = "0.2", features = ["std"] }
5253
mimalloc = "0.1.47"
5354
googletest = "0.14.2"
55+
unicode-general-category = "1.0.0"

README.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,14 @@
7979

8080
Our project is meticulously organized into specialized crates, each serving a critical role in the Lua analysis ecosystem:
8181

82-
| Crate | Badge | Description |
83-
| ----- | ----- | ----------- |
84-
| [🔍 **emmylua_parser**](./crates/emmylua_parser) | [![emmylua_parser](https://img.shields.io/crates/v/emmylua_parser.svg?style=flat-square)](https://crates.io/crates/emmylua_parser) | The foundational Rust-based Lua parser engineered for maximum efficiency and accuracy. Powers all downstream analysis tools. |
82+
| Crate | Badge | Description |
83+
|----------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| ----------- |
84+
| [🔍 **emmylua_parser**](./crates/emmylua_parser) | [![emmylua_parser](https://img.shields.io/crates/v/emmylua_parser.svg?style=flat-square)](https://crates.io/crates/emmylua_parser) | The foundational Rust-based Lua parser engineered for maximum efficiency and accuracy. Powers all downstream analysis tools. |
85+
| [📑 **emmylua_parser_desc**](./crates/emmylua_parser_desc) | [![emmylua_parser_desc](https://img.shields.io/crates/v/emmylua_parser_desc.svg?style=flat-square)](https://crates.io/crates/emmylua_parser_desc) | Extension for EmmyLua-Parser that handles Markdown/RST highlighting in comments. |
8586
| [🧠 **emmylua_code_analysis**](./crates/emmylua_code_analysis) | [![emmylua_code_analysis](https://img.shields.io/crates/v/emmylua_code_analysis.svg?style=flat-square)](https://crates.io/crates/emmylua_code_analysis) | Advanced semantic analysis engine providing deep code understanding, type inference, and cross-reference resolution. |
86-
| [🖥️ **emmylua_ls**](./crates/emmylua_ls) | [![emmylua_ls](https://img.shields.io/crates/v/emmylua_ls.svg?style=flat-square)](https://crates.io/crates/emmylua_ls) | The complete Language Server Protocol implementation offering rich IDE features across all major editors. |
87-
| [📚 **emmylua_doc_cli**](./crates/emmylua_doc_cli/) | [![emmylua_doc_cli](https://img.shields.io/crates/v/emmylua_doc_cli.svg?style=flat-square)](https://crates.io/crates/emmylua_doc_cli) | Professional documentation generator creating beautiful, searchable API docs from your Lua code and annotations. |
88-
| [**emmylua_check**](./crates/emmylua_check) | [![emmylua_check](https://img.shields.io/crates/v/emmylua_check.svg?style=flat-square)](https://crates.io/crates/emmylua_check) | Comprehensive static analysis tool for code quality assurance, catching bugs before they reach production. |
87+
| [🖥️ **emmylua_ls**](./crates/emmylua_ls) | [![emmylua_ls](https://img.shields.io/crates/v/emmylua_ls.svg?style=flat-square)](https://crates.io/crates/emmylua_ls) | The complete Language Server Protocol implementation offering rich IDE features across all major editors. |
88+
| [📚 **emmylua_doc_cli**](./crates/emmylua_doc_cli/) | [![emmylua_doc_cli](https://img.shields.io/crates/v/emmylua_doc_cli.svg?style=flat-square)](https://crates.io/crates/emmylua_doc_cli) | Professional documentation generator creating beautiful, searchable API docs from your Lua code and annotations. |
89+
| [**emmylua_check**](./crates/emmylua_check) | [![emmylua_check](https://img.shields.io/crates/v/emmylua_check.svg?style=flat-square)](https://crates.io/crates/emmylua_check) | Comprehensive static analysis tool for code quality assurance, catching bugs before they reach production. |
8990

9091

9192
---

crates/emmylua_ls/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ categories = ["development-tools"]
1414
# local
1515
emmylua_code_analysis.workspace = true
1616
emmylua_parser.workspace = true
17+
emmylua_parser_desc.workspace = true
1718

1819
# external
1920
lsp-server.workspace = true

crates/emmylua_parser/src/lexer/lua_lexer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,7 @@ impl<'a> LuaLexer<'a> {
693693

694694
if self.reader.current_char().is_alphabetic() {
695695
let ch = self.reader.current_char();
696-
self.error(|| format!("unexpected character '{ch}' after number literal"));
696+
self.error(|| t!("unexpected character '%{ch}' after number literal", ch = ch));
697697
}
698698

699699
match state {

crates/emmylua_parser/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ mod syntax;
77
mod text;
88

99
pub use kind::*;
10+
pub use lexer::{LexerConfig, LuaLexer, LuaLexerState, LuaTokenData};
1011
pub use parser::{LuaParser, ParserConfig, SpecialFunction};
1112
pub use parser_error::{LuaParseError, LuaParseErrorKind};
1213
pub use syntax::*;
1314
pub use text::LineIndex;
15+
pub use text::{Reader, SourceRange};
1416

1517
#[macro_use]
1618
extern crate rust_i18n;

crates/emmylua_parser/src/text/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ mod text_range;
55

66
pub use line_index::LineIndex;
77
pub use reader::Reader;
8-
pub(crate) use text_range::SourceRange;
8+
pub use text_range::SourceRange;

crates/emmylua_parser_desc/Cargo.toml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[package]
2+
name = "emmylua_parser_desc"
3+
version = "0.12.0"
4+
edition = "2024"
5+
authors = ["CppCXY", "taminomara"]
6+
description = "A parser for markup within Lua comments"
7+
license = "MIT"
8+
repository = "https://github.com/CppCXY/emmylua-analyzer-rust"
9+
readme = "README.md"
10+
keywords = ["emmylua", "luals", "parser", "lua"]
11+
categories = ["development-tools", "parsing"]
12+
13+
[dependencies]
14+
# local
15+
emmylua_parser.workspace = true
16+
17+
# external
18+
rowan.workspace = true
19+
unicode-general-category.workspace = true

crates/emmylua_parser_desc/README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
## EmmyLua-Parser-Desc
2+
3+
EmmyLua-Parser-Desc is an extension for EmmyLua-Parser that uses its internal machinery to provide lexic information about markup of documentation comments. It supports parsing Markdown, MyST and RST.
4+
5+
6+
### Features
7+
8+
- Ability to parse description blocks provided by EmmyLua-Parser and report ranges of interest: highlighted keywords, code blocks, cross-references and so on
9+
- Supports Markdown, MyST and RST
10+
- Ability to parse possible broken or unterminated MyST and RST cross-references in order to facilitate Autocompletion and Go To Definition functionality
11+
12+
### Usage
13+
14+
```rust
15+
let code = r#"
16+
--- Description in **markdown format**, with example code:
17+
---
18+
--- ```lua
19+
--- print(a)
20+
--- ```
21+
local a = 1
22+
"#;
23+
let tree = LuaParser::parse(code, ParserConfig::default());
24+
25+
let chunk = tree.get_chunk_node();
26+
for desc in chunk.descendants::<LuaDocDescription>() {
27+
let doc_items = emmylua_parser_desc::parse(
28+
DescParserType::Md,
29+
code,
30+
desc,
31+
None
32+
);
33+
println!("{:?}", doc_items);
34+
}
35+
```

crates/emmylua_parser_desc/src/lib.rs

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
use emmylua_parser::{LuaDocDescription, LuaTokenKind};
2+
use rowan::TextRange;
3+
4+
mod md;
5+
mod ref_target;
6+
mod rst;
7+
mod util;
8+
9+
pub use ref_target::*;
10+
use util::sort_result;
11+
12+
#[cfg(test)]
13+
mod testlib;
14+
15+
#[derive(Debug, Clone, Eq, PartialEq)]
16+
pub enum DescItemKind {
17+
/// Generic block of documentation.
18+
Scope,
19+
20+
/// Cross-reference to a Lua object.
21+
Ref,
22+
23+
/// Emphasis.
24+
Em,
25+
26+
/// Strong emphasis.
27+
Strong,
28+
29+
/// Code markup.
30+
Code,
31+
32+
/// Hyperlink.
33+
Link,
34+
35+
/// Inline markup, like stars around emphasized text.
36+
Markup,
37+
38+
/// Directive name, code-block syntax name, role name,
39+
/// or some other form of argument.
40+
Arg,
41+
42+
/// Line of code in a code block.
43+
CodeBlock,
44+
45+
/// Line of code in a code block highlighted by Lua lexer.
46+
CodeBlockHl(LuaTokenKind),
47+
}
48+
49+
#[derive(Debug, Clone)]
50+
pub struct DescItem {
51+
pub range: TextRange,
52+
pub kind: DescItemKind,
53+
}
54+
55+
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
56+
pub enum DescParserType {
57+
None,
58+
Md,
59+
MySt {
60+
primary_domain: Option<String>,
61+
},
62+
Rst {
63+
primary_domain: Option<String>,
64+
default_role: Option<String>,
65+
},
66+
}
67+
68+
impl Default for DescParserType {
69+
fn default() -> Self {
70+
DescParserType::None
71+
}
72+
}
73+
74+
/// Parses markup in comments.
75+
pub trait LuaDescParser {
76+
/// Process a description node and yield found documentation ranges.
77+
fn parse(&mut self, text: &str, desc: LuaDocDescription) -> Vec<DescItem>;
78+
}
79+
80+
pub fn parse(
81+
kind: DescParserType,
82+
text: &str,
83+
desc: LuaDocDescription,
84+
cursor_position: Option<usize>,
85+
) -> Vec<DescItem> {
86+
let mut items = match kind {
87+
DescParserType::None => Vec::new(),
88+
DescParserType::Md => md::MdParser::new(cursor_position).parse(text, desc),
89+
DescParserType::MySt { primary_domain } => {
90+
md::MdParser::new_myst(primary_domain, cursor_position).parse(text, desc)
91+
}
92+
DescParserType::Rst {
93+
primary_domain,
94+
default_role,
95+
} => rst::RstParser::new(primary_domain, default_role, cursor_position).parse(text, desc),
96+
};
97+
98+
sort_result(&mut items);
99+
100+
items
101+
}

0 commit comments

Comments
 (0)