Skip to content

Commit cb37a48

Browse files
authored
🦀 Rust support (#50)
1 parent bb88d52 commit cb37a48

File tree

11 files changed

+185
-6
lines changed

11 files changed

+185
-6
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
^^^^^^^^^

‎docs/source/components/features.rst‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,30 @@ Features
134134
.. fault:: Sphinx-codelinks halucinates traceability objects in YAML
135135
:id: FAULT_YAML_2
136136

137+
.. feature:: Rust Language Support
138+
:id: FE_RUST
139+
140+
Support for defining traceability objects in Rust source code.
141+
142+
The Rust language parser leverages tree-sitter to accurately identify and extract
143+
comments from Rust source files, including single-line (``//``, ``///``) and multi-line
144+
(``/* */``) comment styles. This ensures that traceability markers are correctly
145+
associated with the appropriate code structures such as functions, structs, enums,
146+
and traits.
147+
148+
Key capabilities:
149+
150+
* Detection of inline and block comments
151+
* Association of comments with function and method definitions
152+
* Support for standard Rust comment conventions
153+
* Accurate scope detection for nested structures
154+
155+
.. fault:: Traceability objects are not detected in Rust language
156+
:id: FAULT_RUST_1
157+
158+
.. fault:: Sphinx-codelinks halucinates traceability objects in Rust
159+
:id: FAULT_RUST_2
160+
137161
.. feature:: Customized comment styles
138162
:id: FE_CMT
139163

‎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: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@
2020
CommentType.cpp: {"function_definition", "class_definition"},
2121
CommentType.cs: {"method_declaration", "class_declaration", "property_declaration"},
2222
CommentType.yaml: {"block_mapping_pair", "block_sequence_item", "document"},
23+
# @Rust Scope Node Types, IMPL_RUST_2, impl, [FE_RUST];
24+
CommentType.rust: {
25+
"function_item",
26+
"struct_item",
27+
"enum_item",
28+
"impl_item",
29+
"trait_item",
30+
"mod_item",
31+
},
2332
}
2433

2534
# initialize logger
@@ -47,6 +56,10 @@
4756
CPP_QUERY = """(comment) @comment"""
4857
C_SHARP_QUERY = """(comment) @comment"""
4958
YAML_QUERY = """(comment) @comment"""
59+
RUST_QUERY = """
60+
(line_comment) @comment
61+
(block_comment) @comment
62+
"""
5063

5164

5265
def is_text_file(filepath: Path, sample_size: int = 2048) -> bool:
@@ -64,7 +77,7 @@ def is_text_file(filepath: Path, sample_size: int = 2048) -> bool:
6477
return False
6578

6679

67-
# @Tree-sitter parser initialization for multiple languages, IMPL_LANG_1, impl, [FE_C_SUPPORT, FE_CPP, FE_PY, FE_YAML]
80+
# @Tree-sitter parser initialization for multiple languages, IMPL_LANG_1, impl, [FE_C_SUPPORT, FE_CPP, FE_PY, FE_YAML, FE_RUST]
6881
def init_tree_sitter(comment_type: CommentType) -> tuple[Parser, Query]:
6982
if comment_type == CommentType.cpp:
7083
import tree_sitter_cpp # noqa: PLC0415
@@ -86,6 +99,11 @@ def init_tree_sitter(comment_type: CommentType) -> tuple[Parser, Query]:
8699

87100
parsed_language = Language(tree_sitter_yaml.language())
88101
query = Query(parsed_language, YAML_QUERY)
102+
elif comment_type == CommentType.rust:
103+
import tree_sitter_rust # noqa: PLC0415
104+
105+
parsed_language = Language(tree_sitter_rust.language())
106+
query = Query(parsed_language, RUST_QUERY)
89107
else:
90108
raise ValueError(f"Unsupported comment style: {comment_type}")
91109
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
@@ -104,6 +104,20 @@ def test_analyse(src_dir, src_paths, tmp_path, snapshot_marks):
104104
"warnings_path_exists": True,
105105
},
106106
),
107+
(
108+
TEST_DIR / "data" / "rust",
109+
[
110+
TEST_DIR / "data" / "rust" / "demo.rs",
111+
],
112+
ONELINE_COMMENT_STYLE_DEFAULT,
113+
{
114+
"num_src_files": 1,
115+
"num_uncached_files": 1,
116+
"num_cached_files": 0,
117+
"num_comments": 6,
118+
"num_oneline_warnings": 0,
119+
},
120+
),
107121
],
108122
)
109123
def test_analyse_oneline_needs(

‎tests/test_analyse_utils.py‎

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import tree_sitter_c_sharp
1010
import tree_sitter_cpp
1111
import tree_sitter_python
12+
import tree_sitter_rust
1213
import tree_sitter_yaml
1314

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

5051

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

286295

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

‎tests/test_source_discover.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
"comment_type": "java",
4646
},
4747
[
48-
"Schema validation error in field 'comment_type': 'java' is not one of ['cpp', 'cs', 'python', 'yaml']"
48+
"Schema validation error in field 'comment_type': 'java' is not one of ['cpp', 'cs', 'python', 'rust', 'yaml']"
4949
],
5050
),
5151
(

0 commit comments

Comments
 (0)