codegraphcontext-rust 0.5.5__cp311-cp311-win_amd64.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.
- codegraphcontext/__init__.py +2 -0
- codegraphcontext/__main__.py +5 -0
- codegraphcontext/_cgc_rust.cp311-win_amd64.pyd +0 -0
- codegraphcontext/cli/__init__.py +1 -0
- codegraphcontext/cli/cli_helpers.py +774 -0
- codegraphcontext/cli/config_manager.py +1051 -0
- codegraphcontext/cli/main.py +2386 -0
- codegraphcontext/cli/registry_commands.py +404 -0
- codegraphcontext/cli/setup_macos.py +93 -0
- codegraphcontext/cli/setup_wizard.py +991 -0
- codegraphcontext/cli/visualizer.py +50 -0
- codegraphcontext/core/__init__.py +165 -0
- codegraphcontext/core/bundle_registry.py +181 -0
- codegraphcontext/core/cgc_bundle.py +858 -0
- codegraphcontext/core/cgcignore.py +118 -0
- codegraphcontext/core/database.py +273 -0
- codegraphcontext/core/database_falkordb.py +480 -0
- codegraphcontext/core/database_falkordb_remote.py +199 -0
- codegraphcontext/core/database_kuzu.py +636 -0
- codegraphcontext/core/falkor_worker.py +132 -0
- codegraphcontext/core/jobs.py +132 -0
- codegraphcontext/core/watcher.py +260 -0
- codegraphcontext/prompts.py +125 -0
- codegraphcontext/server.py +471 -0
- codegraphcontext/tool_definitions.py +220 -0
- codegraphcontext/tools/__init__.py +0 -0
- codegraphcontext/tools/advanced_language_query_tool.py +103 -0
- codegraphcontext/tools/code_finder.py +1160 -0
- codegraphcontext/tools/graph_builder.py +337 -0
- codegraphcontext/tools/handlers/analysis_handlers.py +114 -0
- codegraphcontext/tools/handlers/indexing_handlers.py +116 -0
- codegraphcontext/tools/handlers/management_handlers.py +339 -0
- codegraphcontext/tools/handlers/query_handlers.py +83 -0
- codegraphcontext/tools/handlers/watcher_handlers.py +83 -0
- codegraphcontext/tools/indexing/__init__.py +1 -0
- codegraphcontext/tools/indexing/constants.py +25 -0
- codegraphcontext/tools/indexing/discovery.py +64 -0
- codegraphcontext/tools/indexing/engine.py +109 -0
- codegraphcontext/tools/indexing/persistence/__init__.py +3 -0
- codegraphcontext/tools/indexing/persistence/parquet_loader.py +643 -0
- codegraphcontext/tools/indexing/persistence/writer.py +1114 -0
- codegraphcontext/tools/indexing/pipeline.py +171 -0
- codegraphcontext/tools/indexing/pre_scan.py +105 -0
- codegraphcontext/tools/indexing/resolution/__init__.py +8 -0
- codegraphcontext/tools/indexing/resolution/calls.py +253 -0
- codegraphcontext/tools/indexing/resolution/inheritance.py +91 -0
- codegraphcontext/tools/indexing/sanitize.py +41 -0
- codegraphcontext/tools/indexing/schema.py +79 -0
- codegraphcontext/tools/indexing/schema_contract.py +44 -0
- codegraphcontext/tools/indexing/scip_pipeline.py +140 -0
- codegraphcontext/tools/languages/c.py +563 -0
- codegraphcontext/tools/languages/cpp.py +616 -0
- codegraphcontext/tools/languages/csharp.py +551 -0
- codegraphcontext/tools/languages/dart.py +378 -0
- codegraphcontext/tools/languages/elixir.py +460 -0
- codegraphcontext/tools/languages/go.py +499 -0
- codegraphcontext/tools/languages/haskell.py +426 -0
- codegraphcontext/tools/languages/java.py +500 -0
- codegraphcontext/tools/languages/javascript.py +589 -0
- codegraphcontext/tools/languages/kotlin.py +640 -0
- codegraphcontext/tools/languages/perl.py +260 -0
- codegraphcontext/tools/languages/php.py +519 -0
- codegraphcontext/tools/languages/python.py +576 -0
- codegraphcontext/tools/languages/ruby.py +537 -0
- codegraphcontext/tools/languages/rust.py +295 -0
- codegraphcontext/tools/languages/scala.py +519 -0
- codegraphcontext/tools/languages/swift.py +491 -0
- codegraphcontext/tools/languages/typescript.py +575 -0
- codegraphcontext/tools/languages/typescriptjsx.py +151 -0
- codegraphcontext/tools/package_resolver.py +472 -0
- codegraphcontext/tools/query_tool_languages/c_toolkit.py +5 -0
- codegraphcontext/tools/query_tool_languages/cpp_toolkit.py +87 -0
- codegraphcontext/tools/query_tool_languages/csharp_toolkit.py +5 -0
- codegraphcontext/tools/query_tool_languages/dart_toolkit.py +5 -0
- codegraphcontext/tools/query_tool_languages/go_toolkit.py +5 -0
- codegraphcontext/tools/query_tool_languages/haskell_toolkit.py +5 -0
- codegraphcontext/tools/query_tool_languages/java_toolkit.py +5 -0
- codegraphcontext/tools/query_tool_languages/javascript_toolkit.py +5 -0
- codegraphcontext/tools/query_tool_languages/perl_toolkit.py +5 -0
- codegraphcontext/tools/query_tool_languages/python_toolkit.py +5 -0
- codegraphcontext/tools/query_tool_languages/ruby_toolkit.py +5 -0
- codegraphcontext/tools/query_tool_languages/rust_toolkit.py +5 -0
- codegraphcontext/tools/query_tool_languages/scala_toolkit.py +5 -0
- codegraphcontext/tools/query_tool_languages/swift_toolkit.py +5 -0
- codegraphcontext/tools/query_tool_languages/typescript_toolkit.py +5 -0
- codegraphcontext/tools/scip_indexer.py +467 -0
- codegraphcontext/tools/scip_pb2.py +2455 -0
- codegraphcontext/tools/system.py +133 -0
- codegraphcontext/tools/tree_sitter_parser.py +103 -0
- codegraphcontext/utils/debug_log.py +90 -0
- codegraphcontext/utils/path_ignore.py +55 -0
- codegraphcontext/utils/repo_path.py +27 -0
- codegraphcontext/utils/tree_sitter_manager.py +285 -0
- codegraphcontext/utils/visualize_graph.py +0 -0
- codegraphcontext/viz/server.py +282 -0
- codegraphcontext_rust-0.5.5.dist-info/METADATA +537 -0
- codegraphcontext_rust-0.5.5.dist-info/RECORD +101 -0
- codegraphcontext_rust-0.5.5.dist-info/WHEEL +4 -0
- codegraphcontext_rust-0.5.5.dist-info/entry_points.txt +3 -0
- codegraphcontext_rust-0.5.5.dist-info/licenses/LICENSE +21 -0
- codegraphcontext_rust-0.5.5.dist-info/sboms/cgc-python.cyclonedx.json +2333 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Any, Dict, Optional, Tuple
|
|
3
|
+
import re
|
|
4
|
+
from codegraphcontext.utils.debug_log import debug_log, info_logger, error_logger, warning_logger, debug_logger
|
|
5
|
+
from codegraphcontext.utils.tree_sitter_manager import execute_query
|
|
6
|
+
|
|
7
|
+
RUST_QUERIES = {
|
|
8
|
+
"functions": """
|
|
9
|
+
(function_item
|
|
10
|
+
name: (identifier) @name
|
|
11
|
+
parameters: (parameters) @params
|
|
12
|
+
) @function_node
|
|
13
|
+
""",
|
|
14
|
+
"classes": """
|
|
15
|
+
[
|
|
16
|
+
(struct_item name: (type_identifier) @name)
|
|
17
|
+
(enum_item name: (type_identifier) @name)
|
|
18
|
+
(trait_item name: (type_identifier) @name)
|
|
19
|
+
] @class
|
|
20
|
+
""",
|
|
21
|
+
"imports": """
|
|
22
|
+
(use_declaration) @import
|
|
23
|
+
""",
|
|
24
|
+
"calls": """
|
|
25
|
+
(call_expression
|
|
26
|
+
function: [
|
|
27
|
+
(identifier) @name
|
|
28
|
+
(field_expression field: (field_identifier) @name)
|
|
29
|
+
(scoped_identifier name: (identifier) @name)
|
|
30
|
+
]
|
|
31
|
+
)
|
|
32
|
+
""",
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
class RustTreeSitterParser:
|
|
36
|
+
"""A Rust-specific parser using tree-sitter."""
|
|
37
|
+
|
|
38
|
+
def __init__(self, generic_parser_wrapper: Any):
|
|
39
|
+
self.generic_parser_wrapper = generic_parser_wrapper
|
|
40
|
+
self.language_name = "rust"
|
|
41
|
+
self.language = generic_parser_wrapper.language
|
|
42
|
+
self.parser = generic_parser_wrapper.parser
|
|
43
|
+
|
|
44
|
+
def _get_node_text(self, node: Any) -> str:
|
|
45
|
+
return node.text.decode("utf-8")
|
|
46
|
+
|
|
47
|
+
def parse(self, path: Path, is_dependency: bool = False, index_source: bool = False) -> Dict[str, Any]:
|
|
48
|
+
"""Parses a Rust file and returns its structure."""
|
|
49
|
+
self.index_source = index_source
|
|
50
|
+
with open(path, "r", encoding="utf-8", errors="ignore") as f:
|
|
51
|
+
source_code = f.read()
|
|
52
|
+
|
|
53
|
+
tree = self.parser.parse(bytes(source_code, "utf8"))
|
|
54
|
+
root_node = tree.root_node
|
|
55
|
+
|
|
56
|
+
functions = self._find_functions(root_node)
|
|
57
|
+
classes = self._find_structs(root_node)
|
|
58
|
+
imports = self._find_imports(root_node)
|
|
59
|
+
function_calls = self._find_calls(root_node)
|
|
60
|
+
traits = self._find_traits(root_node) # <-- Added trait detection
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
"path": str(path),
|
|
64
|
+
"functions": functions,
|
|
65
|
+
"classes": classes,
|
|
66
|
+
"traits": traits, # <-- Result for traits
|
|
67
|
+
"variables": [],
|
|
68
|
+
"imports": imports,
|
|
69
|
+
"function_calls": function_calls,
|
|
70
|
+
"is_dependency": is_dependency,
|
|
71
|
+
"lang": self.language_name,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
def _get_parent_context(self, node: Any, types: Tuple[str, ...] = ("function_item", "struct_item", "enum_item", "trait_item", "impl_item")) -> Tuple[Optional[str], Optional[str], Optional[int]]:
|
|
75
|
+
curr = node.parent
|
|
76
|
+
while curr:
|
|
77
|
+
if curr.type in types:
|
|
78
|
+
name_node = curr.child_by_field_name("name")
|
|
79
|
+
if not name_node and curr.type == "impl_item":
|
|
80
|
+
# For impl blocks, use the type name
|
|
81
|
+
# impl Trait for Type { ... } -> we want Type
|
|
82
|
+
# impl Type { ... } -> we want Type
|
|
83
|
+
# Let's find the last type_identifier before the block
|
|
84
|
+
for child in reversed(curr.children):
|
|
85
|
+
if child.type == "type_identifier":
|
|
86
|
+
name_node = child
|
|
87
|
+
break
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
self._get_node_text(name_node) if name_node else None,
|
|
91
|
+
curr.type,
|
|
92
|
+
curr.start_point[0] + 1,
|
|
93
|
+
)
|
|
94
|
+
curr = curr.parent
|
|
95
|
+
return None, None, None
|
|
96
|
+
|
|
97
|
+
def _parse_function_args(self, params_node: Any) -> list[Dict[str, Any]]:
|
|
98
|
+
"""Helper to parse function arguments from a (parameters) node."""
|
|
99
|
+
args = []
|
|
100
|
+
for param in params_node.named_children:
|
|
101
|
+
arg_info: Dict[str, Any] = {"name": "", "type": None}
|
|
102
|
+
if param.type == "parameter":
|
|
103
|
+
pattern_node = param.child_by_field_name("pattern")
|
|
104
|
+
type_node = param.child_by_field_name("type")
|
|
105
|
+
if pattern_node:
|
|
106
|
+
arg_info["name"] = self._get_node_text(pattern_node)
|
|
107
|
+
if type_node:
|
|
108
|
+
arg_info["type"] = self._get_node_text(type_node)
|
|
109
|
+
args.append(arg_info)
|
|
110
|
+
elif param.type == "self_parameter":
|
|
111
|
+
arg_info["name"] = self._get_node_text(param)
|
|
112
|
+
arg_info["type"] = "self"
|
|
113
|
+
args.append(arg_info)
|
|
114
|
+
return args
|
|
115
|
+
|
|
116
|
+
def _find_functions(self, root_node: Any) -> list[Dict[str, Any]]:
|
|
117
|
+
functions = []
|
|
118
|
+
# Query that just finds the function items
|
|
119
|
+
query_str = "(function_item) @f"
|
|
120
|
+
|
|
121
|
+
for func_node, _ in execute_query(self.language, query_str, root_node):
|
|
122
|
+
# Use child_by_field_name for reliable identification
|
|
123
|
+
name_node = func_node.child_by_field_name("name")
|
|
124
|
+
params_node = func_node.child_by_field_name("parameters")
|
|
125
|
+
|
|
126
|
+
if name_node:
|
|
127
|
+
name = self._get_node_text(name_node)
|
|
128
|
+
# Convert args to a list of strings for Neo4j property compatibility
|
|
129
|
+
raw_args = self._parse_function_args(params_node) if params_node else []
|
|
130
|
+
params = []
|
|
131
|
+
for arg in raw_args:
|
|
132
|
+
arg_str = arg["name"]
|
|
133
|
+
if arg["type"]:
|
|
134
|
+
arg_str += f": {arg['type']}"
|
|
135
|
+
params.append(arg_str)
|
|
136
|
+
|
|
137
|
+
func_data = {
|
|
138
|
+
"name": name,
|
|
139
|
+
"line_number": name_node.start_point[0] + 1,
|
|
140
|
+
"end_line": func_node.end_point[0] + 1,
|
|
141
|
+
"params": params, # Renamed to params to match other languages
|
|
142
|
+
"args": params, # Keep args for compatibility
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if self.index_source:
|
|
146
|
+
func_data["source"] = self._get_node_text(func_node)
|
|
147
|
+
|
|
148
|
+
functions.append(func_data)
|
|
149
|
+
return functions
|
|
150
|
+
|
|
151
|
+
def _find_structs(self, root_node: Any) -> list[Dict[str, Any]]:
|
|
152
|
+
structs = []
|
|
153
|
+
query_str = """
|
|
154
|
+
[
|
|
155
|
+
(struct_item) @s
|
|
156
|
+
(enum_item) @e
|
|
157
|
+
(trait_item) @t
|
|
158
|
+
]
|
|
159
|
+
"""
|
|
160
|
+
for item_node, _ in execute_query(self.language, query_str, root_node):
|
|
161
|
+
# Find name using field name or fallback
|
|
162
|
+
name_node = item_node.child_by_field_name("name")
|
|
163
|
+
if not name_node:
|
|
164
|
+
# Fallback: find first type_identifier
|
|
165
|
+
for child in item_node.children:
|
|
166
|
+
if child.type == "type_identifier":
|
|
167
|
+
name_node = child
|
|
168
|
+
break
|
|
169
|
+
|
|
170
|
+
if name_node:
|
|
171
|
+
name = self._get_node_text(name_node)
|
|
172
|
+
struct_data = {
|
|
173
|
+
"name": name,
|
|
174
|
+
"line_number": name_node.start_point[0] + 1,
|
|
175
|
+
"end_line": item_node.end_point[0] + 1,
|
|
176
|
+
"bases": [],
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if self.index_source:
|
|
180
|
+
struct_data["source"] = self._get_node_text(item_node)
|
|
181
|
+
|
|
182
|
+
structs.append(struct_data)
|
|
183
|
+
return structs
|
|
184
|
+
|
|
185
|
+
def _find_traits(self, root_node: Any) -> list[Dict[str, Any]]:
|
|
186
|
+
traits = []
|
|
187
|
+
query_str = "(trait_item) @trait"
|
|
188
|
+
for trait_node, _ in execute_query(self.language, query_str, root_node):
|
|
189
|
+
name_node = trait_node.child_by_field_name("name")
|
|
190
|
+
if not name_node:
|
|
191
|
+
for child in trait_node.children:
|
|
192
|
+
if child.type == "type_identifier":
|
|
193
|
+
name_node = child
|
|
194
|
+
break
|
|
195
|
+
if name_node:
|
|
196
|
+
name = self._get_node_text(name_node)
|
|
197
|
+
trait_data = {
|
|
198
|
+
"name": name,
|
|
199
|
+
"line_number": name_node.start_point[0] + 1,
|
|
200
|
+
"end_line": trait_node.end_point[0] + 1,
|
|
201
|
+
}
|
|
202
|
+
if self.index_source:
|
|
203
|
+
trait_data["source"] = self._get_node_text(trait_node)
|
|
204
|
+
traits.append(trait_data)
|
|
205
|
+
return traits
|
|
206
|
+
|
|
207
|
+
def _find_imports(self, root_node: Any) -> list[Dict[str, Any]]:
|
|
208
|
+
imports = []
|
|
209
|
+
query_str = RUST_QUERIES["imports"]
|
|
210
|
+
for node, _ in execute_query(self.language, query_str, root_node):
|
|
211
|
+
full_import_name = self._get_node_text(node)
|
|
212
|
+
alias = None
|
|
213
|
+
|
|
214
|
+
alias_match = re.search(r"as\s+(\w+)\s*;?$", full_import_name)
|
|
215
|
+
if alias_match:
|
|
216
|
+
alias = alias_match.group(1)
|
|
217
|
+
name = alias
|
|
218
|
+
else:
|
|
219
|
+
cleaned_path = re.sub(r";$", "", full_import_name).strip()
|
|
220
|
+
last_part = cleaned_path.split("::")[-1]
|
|
221
|
+
if last_part.strip() == "*":
|
|
222
|
+
name = "*"
|
|
223
|
+
else:
|
|
224
|
+
name_match = re.findall(r"(\w+)", last_part)
|
|
225
|
+
name = name_match[-1] if name_match else last_part
|
|
226
|
+
|
|
227
|
+
imports.append(
|
|
228
|
+
{
|
|
229
|
+
"name": name,
|
|
230
|
+
"full_import_name": full_import_name,
|
|
231
|
+
"line_number": node.start_point[0] + 1,
|
|
232
|
+
"alias": alias,
|
|
233
|
+
}
|
|
234
|
+
)
|
|
235
|
+
return imports
|
|
236
|
+
|
|
237
|
+
def _find_calls(self, root_node: Any) -> list[Dict[str, Any]]:
|
|
238
|
+
"""Finds all function and method calls."""
|
|
239
|
+
calls = []
|
|
240
|
+
query_str = RUST_QUERIES["calls"]
|
|
241
|
+
for node, capture_name in execute_query(self.language, query_str, root_node):
|
|
242
|
+
if capture_name == "name":
|
|
243
|
+
# Find the call_expression
|
|
244
|
+
call_node = node.parent
|
|
245
|
+
while call_node and call_node.type != 'call_expression' and call_node.type != 'source_file':
|
|
246
|
+
call_node = call_node.parent
|
|
247
|
+
|
|
248
|
+
call_name = self._get_node_text(node)
|
|
249
|
+
|
|
250
|
+
# Extract arguments
|
|
251
|
+
args = []
|
|
252
|
+
if call_node and call_node.type == 'call_expression':
|
|
253
|
+
args_node = call_node.child_by_field_name('arguments')
|
|
254
|
+
if args_node:
|
|
255
|
+
for child in args_node.children:
|
|
256
|
+
if child.type not in ('(', ')', ','):
|
|
257
|
+
args.append(self._get_node_text(child))
|
|
258
|
+
|
|
259
|
+
calls.append(
|
|
260
|
+
{
|
|
261
|
+
"name": call_name,
|
|
262
|
+
"full_name": self._get_node_text(call_node) if call_node else call_name,
|
|
263
|
+
"line_number": node.start_point[0] + 1,
|
|
264
|
+
"args": args,
|
|
265
|
+
"context": self._get_parent_context(node),
|
|
266
|
+
"lang": self.language_name,
|
|
267
|
+
"is_dependency": False,
|
|
268
|
+
}
|
|
269
|
+
)
|
|
270
|
+
return calls
|
|
271
|
+
|
|
272
|
+
def pre_scan_rust(files: list[Path], parser_wrapper) -> dict:
|
|
273
|
+
"""Scans Rust files to create a map of function/struct/enum/trait names to their file paths."""
|
|
274
|
+
imports_map = {}
|
|
275
|
+
query_str = """
|
|
276
|
+
(function_item name: (identifier) @name)
|
|
277
|
+
(struct_item name: (type_identifier) @name)
|
|
278
|
+
(enum_item name: (type_identifier) @name)
|
|
279
|
+
(trait_item name: (type_identifier) @name)
|
|
280
|
+
"""
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
for path in files:
|
|
284
|
+
try:
|
|
285
|
+
with open(path, "r", encoding="utf-8", errors="ignore") as f:
|
|
286
|
+
tree = parser_wrapper.parser.parse(bytes(f.read(), "utf8"))
|
|
287
|
+
|
|
288
|
+
for capture, _ in execute_query(parser_wrapper.language, query_str, tree.root_node):
|
|
289
|
+
name = capture.text.decode('utf-8')
|
|
290
|
+
if name not in imports_map:
|
|
291
|
+
imports_map[name] = []
|
|
292
|
+
imports_map[name].append(str(path.resolve()))
|
|
293
|
+
except Exception as e:
|
|
294
|
+
warning_logger(f"Tree-sitter pre-scan failed for {path}: {e}")
|
|
295
|
+
return imports_map
|