rbtr-lang-rust 2026.9.0.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rbtr_lang_rust/__init__.py +1 -0
- rbtr_lang_rust/plugin.py +147 -0
- rbtr_lang_rust/py.typed +0 -0
- rbtr_lang_rust/rust.scm +52 -0
- rbtr_lang_rust/tests/__init__.py +0 -0
- rbtr_lang_rust/tests/__snapshots__/test_samples/test_edges_match_snapshot.json +3 -0
- rbtr_lang_rust/tests/__snapshots__/test_samples/test_extraction_matches_snapshot.json +496 -0
- rbtr_lang_rust/tests/cases_docstrings.py +135 -0
- rbtr_lang_rust/tests/cases_extraction.py +294 -0
- rbtr_lang_rust/tests/samples/rust/rust.rs +87 -0
- rbtr_lang_rust/tests/samples/rust/src/config.rs +2 -0
- rbtr_lang_rust/tests/test_docstrings.py +43 -0
- rbtr_lang_rust/tests/test_extraction.py +78 -0
- rbtr_lang_rust/tests/test_samples.py +74 -0
- rbtr_lang_rust-2026.9.0.dev0.dist-info/METADATA +67 -0
- rbtr_lang_rust-2026.9.0.dev0.dist-info/RECORD +19 -0
- rbtr_lang_rust-2026.9.0.dev0.dist-info/WHEEL +4 -0
- rbtr_lang_rust-2026.9.0.dev0.dist-info/entry_points.txt +3 -0
- rbtr_lang_rust-2026.9.0.dev0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Rust language plugin package."""
|
rbtr_lang_rust/plugin.py
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"""Rust language plugin.
|
|
2
|
+
|
|
3
|
+
Provides full support: functions, structs, enums, unions, type
|
|
4
|
+
aliases, traits, modules, impl blocks, `macro_rules!` definitions,
|
|
5
|
+
and `use` declaration extraction. Traits, modules, and impl blocks
|
|
6
|
+
form naming scopes; trait and impl members are methods.
|
|
7
|
+
|
|
8
|
+
Extracted chunks::
|
|
9
|
+
|
|
10
|
+
fn hello() {} → function "hello", scope ""
|
|
11
|
+
struct User { name: String } → class "User", scope ""
|
|
12
|
+
enum Color { Red, Green } → class "Color", scope ""
|
|
13
|
+
impl Svc {
|
|
14
|
+
fn start(&self) {} → method "start", scope "Svc"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
use std::collections::HashMap
|
|
18
|
+
→ import, metadata {module: "std/collections", names: "HashMap"}
|
|
19
|
+
use crate::models::{Chunk, Edge}
|
|
20
|
+
→ import, metadata {module: "crate/models", names: "Chunk,Edge"}
|
|
21
|
+
use super::utils
|
|
22
|
+
→ import, metadata {names: "utils", dots: "2"}
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
from typing import TYPE_CHECKING
|
|
28
|
+
|
|
29
|
+
from rbtr.domain.models import ImportMeta
|
|
30
|
+
from rbtr.languages.registration import (
|
|
31
|
+
ImportResolver,
|
|
32
|
+
LanguageRegistration,
|
|
33
|
+
QueryExtraction,
|
|
34
|
+
collect_scoped_path,
|
|
35
|
+
load_query,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
if TYPE_CHECKING:
|
|
39
|
+
from tree_sitter import Node
|
|
40
|
+
|
|
41
|
+
# ── Query ────────────────────────────────────────────────────────────
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# ── Import extractor ─────────────────────────────────────────────────
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _path_to_meta(parts: list[str], meta: ImportMeta) -> None:
|
|
48
|
+
"""Convert collected Rust path segments into module/dots metadata.
|
|
49
|
+
|
|
50
|
+
Leading `super` segments are counted as relative dots using
|
|
51
|
+
the unified convention (each `super` = one extra level up,
|
|
52
|
+
plus 1 for the file itself). `crate` is kept as a literal
|
|
53
|
+
path segment — it's root-relative, not parent-relative.
|
|
54
|
+
"""
|
|
55
|
+
dots = 0
|
|
56
|
+
while parts and parts[0] == "super":
|
|
57
|
+
dots += 1
|
|
58
|
+
parts = parts[1:]
|
|
59
|
+
if dots:
|
|
60
|
+
meta.dots = str(dots + 1) # +1: super = parent dir = 2 levels from file
|
|
61
|
+
|
|
62
|
+
if parts:
|
|
63
|
+
meta.module = "/".join(parts)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def extract_import_meta(
|
|
67
|
+
_resolver: ImportResolver, node: Node, captures: dict[str, list[Node]]
|
|
68
|
+
) -> ImportMeta:
|
|
69
|
+
"""Extract import data from a Rust `use_declaration` node.
|
|
70
|
+
|
|
71
|
+
Walks the node's `argument` field for module path and names.
|
|
72
|
+
The query only captures `@import` — module extraction needs
|
|
73
|
+
`collect_scoped_path` to flatten `scoped_identifier` trees
|
|
74
|
+
and `_path_to_meta` to convert `super` segments to dots.
|
|
75
|
+
|
|
76
|
+
Examples:
|
|
77
|
+
|
|
78
|
+
`use std::collections::HashMap;`:
|
|
79
|
+
module="std/collections", names="HashMap"
|
|
80
|
+
|
|
81
|
+
`use crate::models::{Chunk, Edge};`:
|
|
82
|
+
module="crate/models", names="Chunk,Edge"
|
|
83
|
+
|
|
84
|
+
`use super::utils;`:
|
|
85
|
+
names="utils", dots="2"
|
|
86
|
+
|
|
87
|
+
`use std::io::{self, Read};`:
|
|
88
|
+
module="std/io", names="self,Read"
|
|
89
|
+
|
|
90
|
+
`use serde;`:
|
|
91
|
+
module="serde"
|
|
92
|
+
"""
|
|
93
|
+
meta = ImportMeta()
|
|
94
|
+
arg = node.child_by_field_name("argument")
|
|
95
|
+
if arg is None:
|
|
96
|
+
return meta
|
|
97
|
+
|
|
98
|
+
match arg.type:
|
|
99
|
+
case "scoped_identifier":
|
|
100
|
+
parts = collect_scoped_path(arg)
|
|
101
|
+
if len(parts) > 1:
|
|
102
|
+
_path_to_meta(parts[:-1], meta)
|
|
103
|
+
meta.names = parts[-1]
|
|
104
|
+
elif parts:
|
|
105
|
+
_path_to_meta(parts, meta)
|
|
106
|
+
|
|
107
|
+
case "scoped_use_list":
|
|
108
|
+
path_parts: list[str] = []
|
|
109
|
+
names: list[str] = []
|
|
110
|
+
for sc in arg.children:
|
|
111
|
+
if sc.type == "scoped_identifier":
|
|
112
|
+
path_parts = collect_scoped_path(sc)
|
|
113
|
+
elif sc.type == "use_list":
|
|
114
|
+
for item in sc.children:
|
|
115
|
+
if item.type == "identifier" and item.text:
|
|
116
|
+
names.append(item.text.decode())
|
|
117
|
+
elif item.type == "self":
|
|
118
|
+
names.append("self")
|
|
119
|
+
_path_to_meta(path_parts, meta)
|
|
120
|
+
if names:
|
|
121
|
+
meta.names = ",".join(names)
|
|
122
|
+
|
|
123
|
+
case "identifier":
|
|
124
|
+
if arg.text:
|
|
125
|
+
meta.module = arg.text.decode()
|
|
126
|
+
|
|
127
|
+
return meta
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
# ── Plugin ───────────────────────────────────────────────────────────
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
rust = LanguageRegistration(
|
|
134
|
+
id="rust",
|
|
135
|
+
extensions=frozenset({".rs"}),
|
|
136
|
+
grammar_module="tree_sitter_rust",
|
|
137
|
+
extraction=QueryExtraction(
|
|
138
|
+
query=load_query(__package__, "rust"),
|
|
139
|
+
scope_types=frozenset({"impl_item", "struct_item", "trait_item", "mod_item", "enum_item"}),
|
|
140
|
+
class_scope_types=frozenset({"impl_item", "struct_item", "trait_item"}),
|
|
141
|
+
),
|
|
142
|
+
index_files=frozenset({"mod.rs"}),
|
|
143
|
+
path_substitutions=(("crate/", "src/"),),
|
|
144
|
+
extraction_serial=6,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
rust.import_extractor(extract_import_meta)
|
rbtr_lang_rust/py.typed
ADDED
|
File without changes
|
rbtr_lang_rust/rust.scm
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
; Comments (Rust: `//`/`///`/`//!` line and `/* */` block).
|
|
2
|
+
[(line_comment) (block_comment)] @comment
|
|
3
|
+
|
|
4
|
+
; An attribute documents the item below it and is its sibling in the
|
|
5
|
+
; tree, so it folds into that item exactly as a comment block does. One
|
|
6
|
+
; standing alone — a module's `#![allow(...)]` — becomes its own chunk.
|
|
7
|
+
(source_file [(attribute_item) (inner_attribute_item)] @comment)
|
|
8
|
+
|
|
9
|
+
(function_item
|
|
10
|
+
name: (identifier) @_fn_name) @function
|
|
11
|
+
|
|
12
|
+
(function_signature_item
|
|
13
|
+
name: (identifier) @_fn_name) @function
|
|
14
|
+
|
|
15
|
+
(struct_item
|
|
16
|
+
name: (type_identifier) @_cls_name) @class
|
|
17
|
+
|
|
18
|
+
(enum_item
|
|
19
|
+
name: (type_identifier) @_cls_name) @class
|
|
20
|
+
|
|
21
|
+
(enum_item
|
|
22
|
+
body: (enum_variant_list
|
|
23
|
+
(enum_variant
|
|
24
|
+
name: (identifier) @_var_name) @variable))
|
|
25
|
+
|
|
26
|
+
(union_item
|
|
27
|
+
name: (type_identifier) @_cls_name) @class
|
|
28
|
+
|
|
29
|
+
(type_item
|
|
30
|
+
name: (type_identifier) @_cls_name) @class
|
|
31
|
+
|
|
32
|
+
(trait_item
|
|
33
|
+
name: (type_identifier) @_cls_name) @class
|
|
34
|
+
|
|
35
|
+
(mod_item
|
|
36
|
+
name: (identifier) @_cls_name) @class
|
|
37
|
+
|
|
38
|
+
(macro_definition
|
|
39
|
+
name: (identifier) @_fn_name) @function
|
|
40
|
+
|
|
41
|
+
(impl_item
|
|
42
|
+
type: (type_identifier) @_cls_name) @class
|
|
43
|
+
|
|
44
|
+
(use_declaration) @import
|
|
45
|
+
|
|
46
|
+
(source_file
|
|
47
|
+
(const_item
|
|
48
|
+
name: (identifier) @_var_name) @variable)
|
|
49
|
+
|
|
50
|
+
(source_file
|
|
51
|
+
(static_item
|
|
52
|
+
name: (identifier) @_var_name) @variable)
|
|
File without changes
|