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.
Files changed (101) hide show
  1. codegraphcontext/__init__.py +2 -0
  2. codegraphcontext/__main__.py +5 -0
  3. codegraphcontext/_cgc_rust.cp311-win_amd64.pyd +0 -0
  4. codegraphcontext/cli/__init__.py +1 -0
  5. codegraphcontext/cli/cli_helpers.py +774 -0
  6. codegraphcontext/cli/config_manager.py +1051 -0
  7. codegraphcontext/cli/main.py +2386 -0
  8. codegraphcontext/cli/registry_commands.py +404 -0
  9. codegraphcontext/cli/setup_macos.py +93 -0
  10. codegraphcontext/cli/setup_wizard.py +991 -0
  11. codegraphcontext/cli/visualizer.py +50 -0
  12. codegraphcontext/core/__init__.py +165 -0
  13. codegraphcontext/core/bundle_registry.py +181 -0
  14. codegraphcontext/core/cgc_bundle.py +858 -0
  15. codegraphcontext/core/cgcignore.py +118 -0
  16. codegraphcontext/core/database.py +273 -0
  17. codegraphcontext/core/database_falkordb.py +480 -0
  18. codegraphcontext/core/database_falkordb_remote.py +199 -0
  19. codegraphcontext/core/database_kuzu.py +636 -0
  20. codegraphcontext/core/falkor_worker.py +132 -0
  21. codegraphcontext/core/jobs.py +132 -0
  22. codegraphcontext/core/watcher.py +260 -0
  23. codegraphcontext/prompts.py +125 -0
  24. codegraphcontext/server.py +471 -0
  25. codegraphcontext/tool_definitions.py +220 -0
  26. codegraphcontext/tools/__init__.py +0 -0
  27. codegraphcontext/tools/advanced_language_query_tool.py +103 -0
  28. codegraphcontext/tools/code_finder.py +1160 -0
  29. codegraphcontext/tools/graph_builder.py +337 -0
  30. codegraphcontext/tools/handlers/analysis_handlers.py +114 -0
  31. codegraphcontext/tools/handlers/indexing_handlers.py +116 -0
  32. codegraphcontext/tools/handlers/management_handlers.py +339 -0
  33. codegraphcontext/tools/handlers/query_handlers.py +83 -0
  34. codegraphcontext/tools/handlers/watcher_handlers.py +83 -0
  35. codegraphcontext/tools/indexing/__init__.py +1 -0
  36. codegraphcontext/tools/indexing/constants.py +25 -0
  37. codegraphcontext/tools/indexing/discovery.py +64 -0
  38. codegraphcontext/tools/indexing/engine.py +109 -0
  39. codegraphcontext/tools/indexing/persistence/__init__.py +3 -0
  40. codegraphcontext/tools/indexing/persistence/parquet_loader.py +643 -0
  41. codegraphcontext/tools/indexing/persistence/writer.py +1114 -0
  42. codegraphcontext/tools/indexing/pipeline.py +171 -0
  43. codegraphcontext/tools/indexing/pre_scan.py +105 -0
  44. codegraphcontext/tools/indexing/resolution/__init__.py +8 -0
  45. codegraphcontext/tools/indexing/resolution/calls.py +253 -0
  46. codegraphcontext/tools/indexing/resolution/inheritance.py +91 -0
  47. codegraphcontext/tools/indexing/sanitize.py +41 -0
  48. codegraphcontext/tools/indexing/schema.py +79 -0
  49. codegraphcontext/tools/indexing/schema_contract.py +44 -0
  50. codegraphcontext/tools/indexing/scip_pipeline.py +140 -0
  51. codegraphcontext/tools/languages/c.py +563 -0
  52. codegraphcontext/tools/languages/cpp.py +616 -0
  53. codegraphcontext/tools/languages/csharp.py +551 -0
  54. codegraphcontext/tools/languages/dart.py +378 -0
  55. codegraphcontext/tools/languages/elixir.py +460 -0
  56. codegraphcontext/tools/languages/go.py +499 -0
  57. codegraphcontext/tools/languages/haskell.py +426 -0
  58. codegraphcontext/tools/languages/java.py +500 -0
  59. codegraphcontext/tools/languages/javascript.py +589 -0
  60. codegraphcontext/tools/languages/kotlin.py +640 -0
  61. codegraphcontext/tools/languages/perl.py +260 -0
  62. codegraphcontext/tools/languages/php.py +519 -0
  63. codegraphcontext/tools/languages/python.py +576 -0
  64. codegraphcontext/tools/languages/ruby.py +537 -0
  65. codegraphcontext/tools/languages/rust.py +295 -0
  66. codegraphcontext/tools/languages/scala.py +519 -0
  67. codegraphcontext/tools/languages/swift.py +491 -0
  68. codegraphcontext/tools/languages/typescript.py +575 -0
  69. codegraphcontext/tools/languages/typescriptjsx.py +151 -0
  70. codegraphcontext/tools/package_resolver.py +472 -0
  71. codegraphcontext/tools/query_tool_languages/c_toolkit.py +5 -0
  72. codegraphcontext/tools/query_tool_languages/cpp_toolkit.py +87 -0
  73. codegraphcontext/tools/query_tool_languages/csharp_toolkit.py +5 -0
  74. codegraphcontext/tools/query_tool_languages/dart_toolkit.py +5 -0
  75. codegraphcontext/tools/query_tool_languages/go_toolkit.py +5 -0
  76. codegraphcontext/tools/query_tool_languages/haskell_toolkit.py +5 -0
  77. codegraphcontext/tools/query_tool_languages/java_toolkit.py +5 -0
  78. codegraphcontext/tools/query_tool_languages/javascript_toolkit.py +5 -0
  79. codegraphcontext/tools/query_tool_languages/perl_toolkit.py +5 -0
  80. codegraphcontext/tools/query_tool_languages/python_toolkit.py +5 -0
  81. codegraphcontext/tools/query_tool_languages/ruby_toolkit.py +5 -0
  82. codegraphcontext/tools/query_tool_languages/rust_toolkit.py +5 -0
  83. codegraphcontext/tools/query_tool_languages/scala_toolkit.py +5 -0
  84. codegraphcontext/tools/query_tool_languages/swift_toolkit.py +5 -0
  85. codegraphcontext/tools/query_tool_languages/typescript_toolkit.py +5 -0
  86. codegraphcontext/tools/scip_indexer.py +467 -0
  87. codegraphcontext/tools/scip_pb2.py +2455 -0
  88. codegraphcontext/tools/system.py +133 -0
  89. codegraphcontext/tools/tree_sitter_parser.py +103 -0
  90. codegraphcontext/utils/debug_log.py +90 -0
  91. codegraphcontext/utils/path_ignore.py +55 -0
  92. codegraphcontext/utils/repo_path.py +27 -0
  93. codegraphcontext/utils/tree_sitter_manager.py +285 -0
  94. codegraphcontext/utils/visualize_graph.py +0 -0
  95. codegraphcontext/viz/server.py +282 -0
  96. codegraphcontext_rust-0.5.5.dist-info/METADATA +537 -0
  97. codegraphcontext_rust-0.5.5.dist-info/RECORD +101 -0
  98. codegraphcontext_rust-0.5.5.dist-info/WHEEL +4 -0
  99. codegraphcontext_rust-0.5.5.dist-info/entry_points.txt +3 -0
  100. codegraphcontext_rust-0.5.5.dist-info/licenses/LICENSE +21 -0
  101. codegraphcontext_rust-0.5.5.dist-info/sboms/cgc-python.cyclonedx.json +2333 -0
@@ -0,0 +1,426 @@
1
+ """Haskell tree-sitter parser (tree-sitter-haskell grammar)."""
2
+
3
+ from pathlib import Path
4
+ from typing import Any, Dict, List, Optional, Tuple
5
+ import re
6
+
7
+ from codegraphcontext.utils.debug_log import error_logger, warning_logger
8
+ from codegraphcontext.utils.tree_sitter_manager import execute_query
9
+
10
+ # Node names follow https://github.com/tree-sitter/tree-sitter-haskell
11
+ # Top-level: function, class (typeclass), data_type, newtype, type_synomym, import.
12
+ # Application uses node type `apply` (function application).
13
+ HASKELL_QUERIES = {
14
+ "functions": """
15
+ (function) @function_node
16
+ (bind
17
+ name: (variable) @bind_name) @bind_node
18
+ """,
19
+ "classes": """
20
+ (class) @class_node
21
+ (data_type) @data_type_node
22
+ (newtype) @newtype_node
23
+ (type_synomym) @type_synonym_node
24
+ """,
25
+ "imports": """
26
+ (import) @import
27
+ """,
28
+ "calls": """
29
+ (apply
30
+ function: (variable) @callee) @apply_node
31
+ """,
32
+ # Polymorphic parameters use `variable` under type `function`, not a separate `type_variable` kind
33
+ # in tree-sitter-haskell; keep variables to top-level/type signatures only.
34
+ "variables": """
35
+ (signature
36
+ name: (variable) @name) @signature_node
37
+ """,
38
+ }
39
+
40
+
41
+ class HaskellTreeSitterParser:
42
+ """Parse Haskell sources using tree-sitter-haskell."""
43
+
44
+ def __init__(self, generic_parser_wrapper: Any):
45
+ self.generic_parser_wrapper = generic_parser_wrapper
46
+ self.language_name = "haskell"
47
+ self.language = generic_parser_wrapper.language
48
+ self.parser = generic_parser_wrapper.parser
49
+ self.index_source = False
50
+
51
+ def _get_node_text(self, node: Any) -> str:
52
+ if not node:
53
+ return ""
54
+ return node.text.decode("utf-8")
55
+
56
+ def _get_parent_context(
57
+ self,
58
+ node: Any,
59
+ types: Tuple[str, ...] = ("function", "bind", "class", "data_type", "newtype", "instance"),
60
+ ) -> Tuple[Optional[str], Optional[str], Optional[int]]:
61
+ curr = node.parent
62
+ while curr:
63
+ if curr.type in types:
64
+ name_node = curr.child_by_field_name("name")
65
+ if name_node:
66
+ return (
67
+ self._get_node_text(name_node),
68
+ curr.type,
69
+ curr.start_point[0] + 1,
70
+ )
71
+ if curr.type == "function":
72
+ fn_name = curr.child_by_field_name("name")
73
+ if fn_name:
74
+ return (
75
+ self._get_node_text(fn_name),
76
+ curr.type,
77
+ curr.start_point[0] + 1,
78
+ )
79
+ if curr.type == "bind":
80
+ bn = curr.child_by_field_name("name")
81
+ if bn and bn.type == "variable":
82
+ return (
83
+ self._get_node_text(bn),
84
+ curr.type,
85
+ curr.start_point[0] + 1,
86
+ )
87
+ curr = curr.parent
88
+ return None, None, None
89
+
90
+ def _pattern_arg_names(self, patterns_node: Any) -> List[str]:
91
+ if not patterns_node:
92
+ return []
93
+ names: List[str] = []
94
+
95
+ def walk(n: Any) -> None:
96
+ if n.type == "variable":
97
+ names.append(self._get_node_text(n))
98
+ return
99
+ for c in n.children:
100
+ walk(c)
101
+
102
+ walk(patterns_node)
103
+ return names
104
+
105
+ def parse(self, path: Path, is_dependency: bool = False, index_source: bool = False) -> Dict[str, Any]:
106
+ self.index_source = index_source
107
+ try:
108
+ with open(path, "r", encoding="utf-8", errors="ignore") as f:
109
+ source_code = f.read()
110
+ if not source_code.strip():
111
+ warning_logger(f"Empty or whitespace-only file: {path}")
112
+ return self._empty_result(path, is_dependency)
113
+
114
+ tree = self.parser.parse(bytes(source_code, "utf8"))
115
+ root = tree.root_node
116
+
117
+ parsed_variables: List[Dict[str, Any]] = []
118
+ if "variables" in HASKELL_QUERIES:
119
+ var_caps = execute_query(self.language, HASKELL_QUERIES["variables"], root)
120
+ parsed_variables = self._parse_variables(var_caps, source_code, path)
121
+
122
+ parsed_functions: List[Dict[str, Any]] = []
123
+ parsed_classes: List[Dict[str, Any]] = []
124
+ parsed_imports: List[Dict[str, Any]] = []
125
+ parsed_calls: List[Dict[str, Any]] = []
126
+
127
+ for capture_name, query in HASKELL_QUERIES.items():
128
+ if capture_name == "variables":
129
+ continue
130
+ results = execute_query(self.language, query, root)
131
+ if capture_name == "functions":
132
+ parsed_functions.extend(self._parse_functions(results, source_code, path))
133
+ elif capture_name == "classes":
134
+ parsed_classes.extend(self._parse_classes(results, source_code, path))
135
+ elif capture_name == "imports":
136
+ parsed_imports.extend(self._parse_imports(results, source_code))
137
+ elif capture_name == "calls":
138
+ parsed_calls.extend(self._parse_calls(results, source_code, path))
139
+
140
+ return {
141
+ "path": str(path),
142
+ "functions": parsed_functions,
143
+ "classes": parsed_classes,
144
+ "variables": parsed_variables,
145
+ "imports": parsed_imports,
146
+ "function_calls": parsed_calls,
147
+ "is_dependency": is_dependency,
148
+ "lang": self.language_name,
149
+ }
150
+ except Exception as e:
151
+ error_logger(f"Error parsing Haskell file {path}: {e}")
152
+ return self._empty_result(path, is_dependency)
153
+
154
+ def _empty_result(self, path: Path, is_dependency: bool) -> Dict[str, Any]:
155
+ return {
156
+ "path": str(path),
157
+ "functions": [],
158
+ "classes": [],
159
+ "variables": [],
160
+ "imports": [],
161
+ "function_calls": [],
162
+ "is_dependency": is_dependency,
163
+ "lang": self.language_name,
164
+ }
165
+
166
+ def _parse_functions(
167
+ self, captures: List[Tuple[Any, str]], source_code: str, path: Path
168
+ ) -> List[Dict[str, Any]]:
169
+ functions: List[Dict[str, Any]] = []
170
+ seen: set = set()
171
+
172
+ for node, cap in captures:
173
+ if cap == "function_node" and node.type == "function":
174
+ name_node = node.child_by_field_name("name")
175
+ if not name_node:
176
+ continue
177
+ func_name = self._get_node_text(name_node)
178
+ key = ("fn", node.start_byte, node.end_byte)
179
+ if key in seen:
180
+ continue
181
+ seen.add(key)
182
+ patterns = node.child_by_field_name("patterns")
183
+ parameters = self._pattern_arg_names(patterns)
184
+ start_line = node.start_point[0] + 1
185
+ end_line = node.end_point[0] + 1
186
+ ctx_name, ctx_type, ctx_line = self._get_parent_context(node)
187
+ func_data: Dict[str, Any] = {
188
+ "name": func_name,
189
+ "args": parameters,
190
+ "line_number": start_line,
191
+ "end_line": end_line,
192
+ "path": str(path),
193
+ "lang": self.language_name,
194
+ "context": ctx_name,
195
+ "class_context": ctx_name
196
+ if ctx_type and ctx_type in ("class", "instance")
197
+ else None,
198
+ }
199
+ if self.index_source:
200
+ func_data["source"] = self._get_node_text(node)
201
+ functions.append(func_data)
202
+
203
+ elif cap == "bind_node" and node.type == "bind":
204
+ name_node = node.child_by_field_name("name")
205
+ if not name_node or name_node.type != "variable":
206
+ continue
207
+ func_name = self._get_node_text(name_node)
208
+ key = ("bind", node.start_byte, node.end_byte)
209
+ if key in seen:
210
+ continue
211
+ seen.add(key)
212
+ start_line = node.start_point[0] + 1
213
+ end_line = node.end_point[0] + 1
214
+ ctx_name, ctx_type, ctx_line = self._get_parent_context(node)
215
+ func_data = {
216
+ "name": func_name,
217
+ "args": [],
218
+ "line_number": start_line,
219
+ "end_line": end_line,
220
+ "path": str(path),
221
+ "lang": self.language_name,
222
+ "context": ctx_name,
223
+ "class_context": ctx_name
224
+ if ctx_type and ctx_type in ("class", "instance")
225
+ else None,
226
+ }
227
+ if self.index_source:
228
+ func_data["source"] = self._get_node_text(node)
229
+ functions.append(func_data)
230
+
231
+ return functions
232
+
233
+ def _parse_classes(
234
+ self, captures: List[Tuple[Any, str]], source_code: str, path: Path
235
+ ) -> List[Dict[str, Any]]:
236
+ classes: List[Dict[str, Any]] = []
237
+ seen: set = set()
238
+
239
+ for node, cap in captures:
240
+ node_id = (node.start_byte, node.end_byte, node.type)
241
+ if node_id in seen:
242
+ continue
243
+ seen.add(node_id)
244
+
245
+ name_node = node.child_by_field_name("name")
246
+ if not name_node:
247
+ continue
248
+ class_name = self._get_node_text(name_node)
249
+ start_line = node.start_point[0] + 1
250
+ end_line = node.end_point[0] + 1
251
+
252
+ kind = node.type
253
+ if cap == "class_node":
254
+ kind = "typeclass"
255
+
256
+ class_data: Dict[str, Any] = {
257
+ "name": class_name,
258
+ "line_number": start_line,
259
+ "end_line": end_line,
260
+ "bases": [],
261
+ "path": str(path),
262
+ "lang": self.language_name,
263
+ "kind": kind,
264
+ }
265
+ if self.index_source:
266
+ class_data["source"] = self._get_node_text(node)
267
+ classes.append(class_data)
268
+
269
+ return classes
270
+
271
+ def _parse_variables(
272
+ self, captures: List[Tuple[Any, str]], source_code: str, path: Path
273
+ ) -> List[Dict[str, Any]]:
274
+ variables: List[Dict[str, Any]] = []
275
+ seen: set = set()
276
+
277
+ for node, cap in captures:
278
+ if cap == "signature_node":
279
+ name_node = node.child_by_field_name("name")
280
+ if not name_node:
281
+ continue
282
+ var_name = self._get_node_text(name_node)
283
+ key = ("sig", node.start_byte, node.end_byte)
284
+ if key in seen:
285
+ continue
286
+ seen.add(key)
287
+ type_node = node.child_by_field_name("type")
288
+ var_type = self._get_node_text(type_node) if type_node else "Unknown"
289
+ start_line = node.start_point[0] + 1
290
+ ctx_name, ctx_type, ctx_line = self._get_parent_context(node)
291
+ variables.append(
292
+ {
293
+ "name": var_name,
294
+ "type": var_type,
295
+ "line_number": start_line,
296
+ "path": str(path),
297
+ "lang": self.language_name,
298
+ "context": ctx_name,
299
+ "class_context": ctx_name
300
+ if ctx_type and ctx_type in ("class", "instance")
301
+ else None,
302
+ }
303
+ )
304
+ # Type parameters like `a` in `f :: a -> b` appear as `variable` under the type subtree.
305
+ if type_node:
306
+ for tv in self._variables_in_type_ast(type_node):
307
+ tv_key = ("tv", tv.start_byte, tv.end_byte)
308
+ if tv_key in seen:
309
+ continue
310
+ seen.add(tv_key)
311
+ tctx_name, tctx_type, _ = self._get_parent_context(tv)
312
+ variables.append(
313
+ {
314
+ "name": self._get_node_text(tv),
315
+ "type": "type_variable",
316
+ "line_number": tv.start_point[0] + 1,
317
+ "path": str(path),
318
+ "lang": self.language_name,
319
+ "context": tctx_name,
320
+ "class_context": tctx_name
321
+ if tctx_type and tctx_type in ("class", "instance")
322
+ else None,
323
+ }
324
+ )
325
+ return variables
326
+
327
+ def _variables_in_type_ast(self, type_root: Any) -> List[Any]:
328
+ """Collect `variable` nodes that appear in a type (tree-sitter-haskell type parameters)."""
329
+ found: List[Any] = []
330
+
331
+ def walk(n: Any) -> None:
332
+ if n.type == "variable":
333
+ found.append(n)
334
+ return
335
+ for c in n.children:
336
+ walk(c)
337
+
338
+ walk(type_root)
339
+ return found
340
+
341
+ def _parse_imports(self, captures: List[Tuple[Any, str]], source_code: str) -> List[Dict[str, Any]]:
342
+ imports: List[Dict[str, Any]] = []
343
+ for node, cap in captures:
344
+ if cap != "import" or node.type != "import":
345
+ continue
346
+ try:
347
+ mod = node.child_by_field_name("module")
348
+ path_str = self._get_node_text(mod).strip() if mod else ""
349
+ alias_node = node.child_by_field_name("alias")
350
+ alias = self._get_node_text(alias_node).strip() if alias_node else None
351
+ imports.append(
352
+ {
353
+ "name": path_str,
354
+ "full_import_name": path_str,
355
+ "line_number": node.start_point[0] + 1,
356
+ "alias": alias,
357
+ "context": (None, None),
358
+ "lang": self.language_name,
359
+ "is_dependency": False,
360
+ }
361
+ )
362
+ except Exception:
363
+ continue
364
+ return imports
365
+
366
+ def _parse_calls(
367
+ self, captures: List[Tuple[Any, str]], source_code: str, path: Path
368
+ ) -> List[Dict[str, Any]]:
369
+ calls: List[Dict[str, Any]] = []
370
+ seen_calls: set = set()
371
+
372
+ for node, cap in captures:
373
+ if cap != "apply_node" or node.type != "apply":
374
+ continue
375
+ callee = node.child_by_field_name("function")
376
+ if not callee or callee.type != "variable":
377
+ continue
378
+ call_name = self._get_node_text(callee)
379
+ if not call_name:
380
+ continue
381
+ key = (node.start_byte, node.end_byte)
382
+ if key in seen_calls:
383
+ continue
384
+ seen_calls.add(key)
385
+
386
+ start_line = node.start_point[0] + 1
387
+ ctx_name, ctx_type, ctx_line = self._get_parent_context(node)
388
+ calls.append(
389
+ {
390
+ "name": call_name,
391
+ "full_name": call_name,
392
+ "line_number": start_line,
393
+ "args": [],
394
+ "inferred_obj_type": None,
395
+ "context": (ctx_name, ctx_type, ctx_line),
396
+ "class_context": (ctx_name, ctx_line)
397
+ if ctx_type and ctx_type in ("class", "instance")
398
+ else (None, None),
399
+ "lang": self.language_name,
400
+ "is_dependency": False,
401
+ }
402
+ )
403
+ return calls
404
+
405
+
406
+ def pre_scan_haskell(files: list[Path], parser_wrapper) -> dict:
407
+ """Map declared names to file paths using lightweight regex (no full parse)."""
408
+ name_to_files: dict = {}
409
+ patterns = [
410
+ (re.compile(r"^(\w+)\s*::", re.MULTILINE), None),
411
+ (re.compile(r"^data\s+(\w+)", re.MULTILINE), None),
412
+ (re.compile(r"^class\s+(\w+)", re.MULTILINE), None),
413
+ (re.compile(r"^newtype\s+(\w+)", re.MULTILINE), None),
414
+ (re.compile(r"^type\s+(\w+)", re.MULTILINE), None),
415
+ ]
416
+ for path in files:
417
+ try:
418
+ with open(path, "r", encoding="utf-8", errors="ignore") as f:
419
+ content = f.read()
420
+ for rx, _ in patterns:
421
+ for m in rx.finditer(content):
422
+ name = m.group(1)
423
+ name_to_files.setdefault(name, []).append(str(path))
424
+ except Exception:
425
+ pass
426
+ return name_to_files