Skip to content

Commit 105fcbb

Browse files
committed
[#49] Rust support
1 parent 83bcb95 commit 105fcbb

File tree

8 files changed

+158
-3
lines changed

8 files changed

+158
-3
lines changed

docs/source/components/analyse.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Limitations
4747

4848
**Current Limitations:**
4949

50-
- **Language Support**: C/C++ (``//``, ``/* */``), C# (``//``, ``/* */``, ``///``), Python (``#``) and YAML (``#``) comment styles are supported
50+
- **Language Support**: C/C++ (``//``, ``/* */``), C# (``//``, ``/* */``, ``///``), Python (``#``), YAML (``#``) and Rust (``//``, ``/* */``, ``///``) comment styles are supported
5151
- **Single Comment Style**: Each analysis run processes only one comment style at a time
5252

5353
Extraction Examples

docs/source/components/configuration.rst

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ Specifies the comment syntax style used in the source code files. This determine
267267

268268
**Type:** ``str``
269269
**Default:** ``"cpp"``
270-
**Supported values:** ``"cpp"``, ``"python"``, ``"cs"``, ``"yaml"``
270+
**Supported values:** ``"cpp"``, ``"python"``, ``"cs"``, ``"yaml"``, ``"rust"``
271271

272272
.. code-block:: toml
273273
@@ -304,8 +304,15 @@ Specifies the comment syntax style used in the source code files. This determine
304304
- ``"yaml"``
305305
- ``#`` (single-line)
306306
- ``.yaml``, ``.yml``
307+
* - Rust
308+
- ``"rust"``
309+
- ``//`` (single-line),
310+
``/* */`` (multi-line),
311+
``///`` (doc comments),
312+
``//!`` (inner doc comments)
313+
- ``.rs``
307314

308-
.. note:: Future versions may support additional programming languages. Currently, only C/C++ and Python comment styles are supported.
315+
.. note:: Future versions may support additional programming languages.
309316

310317
gitignore
311318
^^^^^^^^^

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ dependencies = [
2929
"tree-sitter~=0.25.1",
3030
"tree-sitter-c-sharp>=0.23.1",
3131
"tree-sitter-yaml>=0.7.1",
32+
"tree-sitter-rust>=0.23.0",
3233
]
3334

3435
[build-system]

src/sphinx_codelinks/analyse/utils.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@
1818
CommentType.cpp: {"function_definition", "class_definition"},
1919
CommentType.cs: {"method_declaration", "class_declaration", "property_declaration"},
2020
CommentType.yaml: {"block_mapping_pair", "block_sequence_item", "document"},
21+
# @Rust Scope Node Types, IMPL_RUST_2, impl, [FE_RUST];
22+
CommentType.rust: {
23+
"function_item",
24+
"struct_item",
25+
"enum_item",
26+
"impl_item",
27+
"trait_item",
28+
"mod_item",
29+
},
2130
}
2231

2332
# initialize logger
@@ -45,6 +54,10 @@
4554
CPP_QUERY = """(comment) @comment"""
4655
C_SHARP_QUERY = """(comment) @comment"""
4756
YAML_QUERY = """(comment) @comment"""
57+
RUST_QUERY = """
58+
(line_comment) @comment
59+
(block_comment) @comment
60+
"""
4861

4962

5063
def is_text_file(filepath: Path, sample_size: int = 2048) -> bool:
@@ -83,6 +96,11 @@ def init_tree_sitter(comment_type: CommentType) -> tuple[Parser, Query]:
8396

8497
parsed_language = Language(tree_sitter_yaml.language())
8598
query = Query(parsed_language, YAML_QUERY)
99+
elif comment_type == CommentType.rust:
100+
import tree_sitter_rust # noqa: PLC0415
101+
102+
parsed_language = Language(tree_sitter_rust.language())
103+
query = Query(parsed_language, RUST_QUERY)
86104
else:
87105
raise ValueError(f"Unsupported comment style: {comment_type}")
88106
parser = Parser(parsed_language)

src/sphinx_codelinks/source_discover/config.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"python": ["py"],
1111
"cs": ["cs"],
1212
"yaml": ["yml", "yaml"],
13+
"rust": ["rs"],
1314
}
1415

1516

@@ -18,6 +19,8 @@ class CommentType(str, Enum):
1819
cpp = "cpp"
1920
cs = "cs"
2021
yaml = "yaml"
22+
# @Support Rust style comments, IMPL_RUST_1, impl, [FE_RUST];
23+
rust = "rust"
2124

2225

2326
class SourceDiscoverSectionConfigType(TypedDict, total=False):

tests/data/rust/demo.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// demo.rs
2+
3+
/// This is a doc comment for the main function
4+
/// @Main function implementation, main_demo, impl, [REQ_001]
5+
fn main() {
6+
println!("Hello from Rust!");
7+
process_data();
8+
}
9+
10+
// @Data processing function, process_func, impl, [REQ_002]
11+
fn process_data() {
12+
let data = vec![1, 2, 3];
13+
for item in data {
14+
println!("Processing: {}", item);
15+
}
16+
}
17+
18+
/* Block comment with marker
19+
@User data structure, struct_def, impl, [REQ_003]
20+
*/
21+
struct User {
22+
name: String,
23+
age: u32,
24+
}
25+
26+
impl User {
27+
// @User constructor method, new_user, impl, [REQ_004]
28+
fn new(name: String, age: u32) -> Self {
29+
User { name, age }
30+
}
31+
}

tests/test_analyse.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,20 @@ def test_analyse(src_dir, src_paths, tmp_path, snapshot_marks):
103103
"warnings_path_exists": True,
104104
},
105105
),
106+
(
107+
TEST_DIR / "data" / "rust",
108+
[
109+
TEST_DIR / "data" / "rust" / "demo.rs",
110+
],
111+
ONELINE_COMMENT_STYLE_DEFAULT,
112+
{
113+
"num_src_files": 1,
114+
"num_uncached_files": 1,
115+
"num_cached_files": 0,
116+
"num_comments": 6,
117+
"num_oneline_warnings": 0,
118+
},
119+
),
106120
],
107121
)
108122
def test_analyse_oneline_needs(

tests/test_analyse_utils.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import tree_sitter_c_sharp
99
import tree_sitter_cpp
1010
import tree_sitter_python
11+
import tree_sitter_rust
1112
import tree_sitter_yaml
1213

1314
from sphinx_codelinks.analyse import utils
@@ -47,6 +48,14 @@ def init_yaml_tree_sitter() -> tuple[Parser, Query]:
4748
return parser, query
4849

4950

51+
@pytest.fixture(scope="session")
52+
def init_rust_tree_sitter() -> tuple[Parser, Query]:
53+
parsed_language = Language(tree_sitter_rust.language())
54+
query = Query(parsed_language, utils.RUST_QUERY)
55+
parser = Parser(parsed_language)
56+
return parser, query
57+
58+
5059
@pytest.mark.parametrize(
5160
("code", "result"),
5261
[
@@ -283,6 +292,78 @@ def test_find_associated_scope_yaml(code, result, init_yaml_tree_sitter):
283292
assert result in yaml_structure
284293

285294

295+
@pytest.mark.parametrize(
296+
("code", "result"),
297+
[
298+
(
299+
b"""
300+
// @req-id: need_001
301+
fn dummy_func1() {
302+
}
303+
""",
304+
"fn dummy_func1()",
305+
),
306+
(
307+
b"""
308+
fn dummy_func2() {
309+
}
310+
// @req-id: need_001
311+
fn dummy_func1() {
312+
}
313+
""",
314+
"fn dummy_func1()",
315+
),
316+
(
317+
b"""
318+
fn dummy_func1() {
319+
let a = 1;
320+
/* @req-id: need_001 */
321+
}
322+
""",
323+
"fn dummy_func1()",
324+
),
325+
(
326+
b"""
327+
fn dummy_func1() {
328+
// @req-id: need_001
329+
let a = 1;
330+
}
331+
fn dummy_func2() {
332+
}
333+
""",
334+
"fn dummy_func1()",
335+
),
336+
(
337+
b"""
338+
/// @req-id: need_001
339+
fn dummy_func1() {
340+
}
341+
""",
342+
"fn dummy_func1()",
343+
),
344+
(
345+
b"""
346+
struct MyStruct {
347+
// @req-id: need_001
348+
field: i32,
349+
}
350+
""",
351+
"struct MyStruct",
352+
),
353+
],
354+
)
355+
def test_find_associated_scope_rust(code, result, init_rust_tree_sitter):
356+
parser, query = init_rust_tree_sitter
357+
comments = utils.extract_comments(code, parser, query)
358+
node: TreeSitterNode | None = utils.find_associated_scope(
359+
comments[0], CommentType.rust
360+
)
361+
assert node
362+
assert node.text
363+
rust_def = node.text.decode("utf-8")
364+
assert result in rust_def
365+
366+
286367
@pytest.mark.parametrize(
287368
("code", "result"),
288369
[

0 commit comments

Comments
 (0)