codegraphcontext 0.1.37__tar.gz → 0.1.39__tar.gz

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 (85) hide show
  1. {codegraphcontext-0.1.37/src/codegraphcontext.egg-info → codegraphcontext-0.1.39}/PKG-INFO +4 -23
  2. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/README.md +3 -22
  3. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/pyproject.toml +11 -1
  4. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/cli/cli_helpers.py +34 -41
  5. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/cli/config_manager.py +3 -0
  6. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/graph_builder.py +15 -5
  7. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/languages/c.py +37 -17
  8. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/languages/cpp.py +39 -22
  9. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/languages/csharp.py +11 -4
  10. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/languages/go.py +15 -13
  11. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/languages/haskell.py +16 -7
  12. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/languages/java.py +16 -7
  13. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/languages/javascript.py +11 -11
  14. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/languages/kotlin.py +16 -7
  15. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/languages/php.py +11 -5
  16. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/languages/python.py +19 -13
  17. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/languages/ruby.py +28 -22
  18. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/languages/rust.py +22 -11
  19. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/languages/scala.py +16 -7
  20. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/languages/swift.py +12 -5
  21. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/languages/typescript.py +17 -8
  22. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/languages/typescriptjsx.py +18 -5
  23. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39/src/codegraphcontext.egg-info}/PKG-INFO +4 -23
  24. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext.egg-info/SOURCES.txt +1 -11
  25. codegraphcontext-0.1.37/tests/test_cpp_parser.py +0 -171
  26. codegraphcontext-0.1.37/tests/test_database_validation.py +0 -221
  27. codegraphcontext-0.1.37/tests/test_end_to_end.py +0 -195
  28. codegraphcontext-0.1.37/tests/test_graph_indexing.py +0 -487
  29. codegraphcontext-0.1.37/tests/test_graph_indexing_js.py +0 -115
  30. codegraphcontext-0.1.37/tests/test_kotlin_parser.py +0 -97
  31. codegraphcontext-0.1.37/tests/test_swift_parser.py +0 -157
  32. codegraphcontext-0.1.37/tests/test_tree_sitter_manager.py +0 -241
  33. codegraphcontext-0.1.37/tests/test_typescript_parser.py +0 -60
  34. codegraphcontext-0.1.37/tests/test_visualization.py +0 -548
  35. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/LICENSE +0 -0
  36. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/MANIFEST.in +0 -0
  37. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/setup.cfg +0 -0
  38. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/__init__.py +0 -0
  39. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/__main__.py +0 -0
  40. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/cli/__init__.py +0 -0
  41. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/cli/main.py +0 -0
  42. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/cli/registry_commands.py +0 -0
  43. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/cli/setup_macos.py +0 -0
  44. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/cli/setup_wizard.py +0 -0
  45. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/cli/visualizer.py +0 -0
  46. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/core/__init__.py +0 -0
  47. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/core/cgc_bundle.py +0 -0
  48. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/core/database.py +0 -0
  49. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/core/database_falkordb.py +0 -0
  50. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/core/falkor_worker.py +0 -0
  51. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/core/jobs.py +0 -0
  52. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/core/watcher.py +0 -0
  53. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/prompts.py +0 -0
  54. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/server.py +0 -0
  55. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tool_definitions.py +0 -0
  56. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/__init__.py +0 -0
  57. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/advanced_language_query_tool.py +0 -0
  58. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/code_finder.py +0 -0
  59. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/handlers/analysis_handlers.py +0 -0
  60. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/handlers/indexing_handlers.py +0 -0
  61. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/handlers/management_handlers.py +0 -0
  62. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/handlers/query_handlers.py +0 -0
  63. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/handlers/watcher_handlers.py +0 -0
  64. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/package_resolver.py +0 -0
  65. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/query_tool_languages/c_toolkit.py +0 -0
  66. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/query_tool_languages/cpp_toolkit.py +0 -0
  67. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/query_tool_languages/csharp_toolkit.py +0 -0
  68. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/query_tool_languages/go_toolkit.py +0 -0
  69. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/query_tool_languages/haskell_toolkit.py +0 -0
  70. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/query_tool_languages/java_toolkit.py +0 -0
  71. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/query_tool_languages/javascript_toolkit.py +0 -0
  72. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/query_tool_languages/python_toolkit.py +0 -0
  73. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/query_tool_languages/ruby_toolkit.py +0 -0
  74. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/query_tool_languages/rust_toolkit.py +0 -0
  75. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/query_tool_languages/scala_toolkit.py +0 -0
  76. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/query_tool_languages/swift_toolkit.py +0 -0
  77. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/query_tool_languages/typescript_toolkit.py +0 -0
  78. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/tools/system.py +0 -0
  79. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/utils/debug_log.py +0 -0
  80. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/utils/tree_sitter_manager.py +0 -0
  81. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext/utils/visualize_graph.py +0 -0
  82. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext.egg-info/dependency_links.txt +0 -0
  83. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext.egg-info/entry_points.txt +0 -0
  84. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext.egg-info/requires.txt +0 -0
  85. {codegraphcontext-0.1.37 → codegraphcontext-0.1.39}/src/codegraphcontext.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codegraphcontext
3
- Version: 0.1.37
3
+ Version: 0.1.39
4
4
  Summary: An MCP server that indexes local code into a graph database to provide context to AI assistants.
5
5
  Author-email: Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
6
6
  License: MIT License
@@ -76,8 +76,8 @@ Dynamic: license-file
76
76
  <img src="https://img.shields.io/github/license/CodeGraphContext/CodeGraphContext?style=flat-square" alt="License">
77
77
  </a>
78
78
  <img src="https://img.shields.io/badge/MCP-Compatible-green?style=flat-square" alt="MCP Compatible">
79
- <a href="https://discord.gg/dR4QY32uYQ">
80
- <img src="https://img.shields.io/discord/dR4QY32uYQ?style=flat-square&logo=discord" alt="Discord">
79
+ <a href="https://discord.gg/VCwUdCnn">
80
+ <img src="https://img.shields.io/discord/1421769154507309150?label=Discord&logo=discord&logoColor=white&style=flat-square">
81
81
  </a>
82
82
  <br><br>
83
83
  <a href="https://github.com/CodeGraphContext/CodeGraphContext/stargazers">
@@ -139,7 +139,7 @@ A powerful **MCP server** and **CLI toolkit** that indexes local code into a gra
139
139
  ---
140
140
 
141
141
  ## Project Details
142
- - **Version:** 0.1.37
142
+ - **Version:** 0.1.39
143
143
  - **Authors:** Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
144
144
  - **License:** MIT License (See [LICENSE](LICENSE) for details)
145
145
  - **Website:** [CodeGraphContext](http://codegraphcontext.vercel.app/)
@@ -419,25 +419,6 @@ Add the following server configuration to your client's settings file (e.g., VS
419
419
  "NEO4J_USERNAME": "YOUR_NEO4J_USERNAME",
420
420
  "NEO4J_PASSWORD": "YOUR_NEO4J_PASSWORD"
421
421
  },
422
- "tools": {
423
- "alwaysAllow": [
424
- "add_code_to_graph",
425
- "add_package_to_graph",
426
- "check_job_status",
427
- "list_jobs",
428
- "find_code",
429
- "analyze_code_relationships",
430
- "watch_directory",
431
- "find_dead_code",
432
- "execute_cypher_query",
433
- "calculate_cyclomatic_complexity",
434
- "find_most_complex_functions",
435
- "list_indexed_repositories",
436
- "delete_repository",
437
- "visualize_graph_query",
438
- "list_watched_paths",
439
- "unwatch_directory"
440
- ],
441
422
  "disabled": false
442
423
  },
443
424
  "disabled": false,
@@ -14,8 +14,8 @@
14
14
  <img src="https://img.shields.io/github/license/CodeGraphContext/CodeGraphContext?style=flat-square" alt="License">
15
15
  </a>
16
16
  <img src="https://img.shields.io/badge/MCP-Compatible-green?style=flat-square" alt="MCP Compatible">
17
- <a href="https://discord.gg/dR4QY32uYQ">
18
- <img src="https://img.shields.io/discord/dR4QY32uYQ?style=flat-square&logo=discord" alt="Discord">
17
+ <a href="https://discord.gg/VCwUdCnn">
18
+ <img src="https://img.shields.io/discord/1421769154507309150?label=Discord&logo=discord&logoColor=white&style=flat-square">
19
19
  </a>
20
20
  <br><br>
21
21
  <a href="https://github.com/CodeGraphContext/CodeGraphContext/stargazers">
@@ -77,7 +77,7 @@ A powerful **MCP server** and **CLI toolkit** that indexes local code into a gra
77
77
  ---
78
78
 
79
79
  ## Project Details
80
- - **Version:** 0.1.37
80
+ - **Version:** 0.1.39
81
81
  - **Authors:** Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
82
82
  - **License:** MIT License (See [LICENSE](LICENSE) for details)
83
83
  - **Website:** [CodeGraphContext](http://codegraphcontext.vercel.app/)
@@ -357,25 +357,6 @@ Add the following server configuration to your client's settings file (e.g., VS
357
357
  "NEO4J_USERNAME": "YOUR_NEO4J_USERNAME",
358
358
  "NEO4J_PASSWORD": "YOUR_NEO4J_PASSWORD"
359
359
  },
360
- "tools": {
361
- "alwaysAllow": [
362
- "add_code_to_graph",
363
- "add_package_to_graph",
364
- "check_job_status",
365
- "list_jobs",
366
- "find_code",
367
- "analyze_code_relationships",
368
- "watch_directory",
369
- "find_dead_code",
370
- "execute_cypher_query",
371
- "calculate_cyclomatic_complexity",
372
- "find_most_complex_functions",
373
- "list_indexed_repositories",
374
- "delete_repository",
375
- "visualize_graph_query",
376
- "list_watched_paths",
377
- "unwatch_directory"
378
- ],
379
360
  "disabled": false
380
361
  },
381
362
  "disabled": false,
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "codegraphcontext"
3
- version = "0.1.37"
3
+ version = "0.1.39"
4
4
  description = "An MCP server that indexes local code into a graph database to provide context to AI assistants."
5
5
  authors = [{ name = "Shashank Shekhar Singh", email = "shashankshekharsingh1205@gmail.com" }]
6
6
  readme = "README.md"
@@ -57,3 +57,13 @@ package-dir = { "" = "src" }
57
57
  [tool.setuptools.packages.find]
58
58
  where = ["src"]
59
59
  include = ["codegraphcontext*"]
60
+
61
+ [tool.pytest.ini_options]
62
+ testpaths = ["tests"]
63
+ python_files = ["test_*.py"]
64
+ norecursedirs = ["tests/fixtures", "tests/e2e/sample_projects", "venv", ".git", "__pycache__"]
65
+ markers = [
66
+ "integration: mark a test as an integration test.",
67
+ "e2e: mark a test as an end-to-end test.",
68
+ "slow: mark test as slow."
69
+ ]
@@ -542,29 +542,32 @@ def stats_helper(path: str = None):
542
542
  return
543
543
 
544
544
  # Get stats
545
- stats_query = """
546
- MATCH (r:Repository {path: $path})-[:CONTAINS]->(f:File)
547
- WITH r, count(f) as file_count, f
548
- OPTIONAL MATCH (f)-[:CONTAINS]->(func:Function)
549
- OPTIONAL MATCH (f)-[:CONTAINS]->(cls:Class)
550
- OPTIONAL MATCH (f)-[:IMPORTS]->(m:Module)
551
- RETURN
552
- file_count,
553
- count(DISTINCT func) as function_count,
554
- count(DISTINCT cls) as class_count,
555
- count(DISTINCT m) as module_count
556
- """
557
- result = session.run(stats_query, path=str(path_obj))
558
- record = result.single()
545
+ # Get stats using separate queries to handle depth and avoid Cartesian products
546
+ # 1. Files
547
+ file_query = "MATCH (r:Repository {path: $path})-[:CONTAINS*]->(f:File) RETURN count(f) as c"
548
+ file_count = session.run(file_query, path=str(path_obj)).single()["c"]
549
+
550
+ # 2. Functions (including methods in classes)
551
+ func_query = "MATCH (r:Repository {path: $path})-[:CONTAINS*]->(func:Function) RETURN count(func) as c"
552
+ func_count = session.run(func_query, path=str(path_obj)).single()["c"]
553
+
554
+ # 3. Classes
555
+ class_query = "MATCH (r:Repository {path: $path})-[:CONTAINS*]->(c:Class) RETURN count(c) as c"
556
+ class_count = session.run(class_query, path=str(path_obj)).single()["c"]
559
557
 
558
+ # 4. Modules (imported) - Note: Module nodes are outside the repo structure usually, connected via IMPORTS
559
+ # We need to traverse from files to modules
560
+ module_query = "MATCH (r:Repository {path: $path})-[:CONTAINS*]->(f:File)-[:IMPORTS]->(m:Module) RETURN count(DISTINCT m) as c"
561
+ module_count = session.run(module_query, path=str(path_obj)).single()["c"]
562
+
560
563
  table = Table(show_header=True, header_style="bold magenta")
561
564
  table.add_column("Metric", style="cyan")
562
565
  table.add_column("Count", style="green", justify="right")
563
566
 
564
- table.add_row("Files", str(record["file_count"] if record else 0))
565
- table.add_row("Functions", str(record["function_count"] if record else 0))
566
- table.add_row("Classes", str(record["class_count"] if record else 0))
567
- table.add_row("Imported Modules", str(record["module_count"] if record else 0))
567
+ table.add_row("Files", str(file_count))
568
+ table.add_row("Functions", str(func_count))
569
+ table.add_row("Classes", str(class_count))
570
+ table.add_row("Imported Modules", str(module_count))
568
571
 
569
572
  console.print(table)
570
573
  else:
@@ -572,34 +575,24 @@ def stats_helper(path: str = None):
572
575
  console.print("[cyan]📊 Overall Database Statistics[/cyan]\n")
573
576
 
574
577
  with db_manager.get_driver().session() as session:
575
- # Get overall counts using separate queries to avoid empty results
576
- # when some node types don't exist
577
- stats_query = """
578
- MATCH (r:Repository)
579
- OPTIONAL MATCH (f:File)
580
- OPTIONAL MATCH (func:Function)
581
- OPTIONAL MATCH (cls:Class)
582
- OPTIONAL MATCH (m:Module)
583
- RETURN
584
- count(DISTINCT r) as repo_count,
585
- count(DISTINCT f) as file_count,
586
- count(DISTINCT func) as function_count,
587
- count(DISTINCT cls) as class_count,
588
- count(DISTINCT m) as module_count
589
- """
590
- result = session.run(stats_query)
591
- record = result.single()
578
+ # Get overall counts using separate O(1) queries
579
+ repo_count = session.run("MATCH (r:Repository) RETURN count(r) as c").single()["c"]
592
580
 
593
- if record and record["repo_count"] > 0:
581
+ if repo_count > 0:
582
+ file_count = session.run("MATCH (f:File) RETURN count(f) as c").single()["c"]
583
+ func_count = session.run("MATCH (f:Function) RETURN count(f) as c").single()["c"]
584
+ class_count = session.run("MATCH (c:Class) RETURN count(c) as c").single()["c"]
585
+ module_count = session.run("MATCH (m:Module) RETURN count(m) as c").single()["c"]
586
+
594
587
  table = Table(show_header=True, header_style="bold magenta")
595
588
  table.add_column("Metric", style="cyan")
596
589
  table.add_column("Count", style="green", justify="right")
597
590
 
598
- table.add_row("Repositories", str(record["repo_count"]))
599
- table.add_row("Files", str(record["file_count"]))
600
- table.add_row("Functions", str(record["function_count"]))
601
- table.add_row("Classes", str(record["class_count"]))
602
- table.add_row("Modules", str(record["module_count"]))
591
+ table.add_row("Repositories", str(repo_count))
592
+ table.add_row("Files", str(file_count))
593
+ table.add_row("Functions", str(func_count))
594
+ table.add_row("Classes", str(class_count))
595
+ table.add_row("Modules", str(module_count))
603
596
 
604
597
  console.print(table)
605
598
  else:
@@ -38,6 +38,7 @@ DEFAULT_CONFIG = {
38
38
  "PARALLEL_WORKERS": "4",
39
39
  "CACHE_ENABLED": "true",
40
40
  "IGNORE_DIRS": "node_modules,venv,.venv,env,.env,dist,build,target,out,.git,.idea,.vscode,__pycache__",
41
+ "INDEX_SOURCE": "false",
41
42
  }
42
43
 
43
44
  # Configuration key descriptions
@@ -60,6 +61,7 @@ CONFIG_DESCRIPTIONS = {
60
61
  "PARALLEL_WORKERS": "Number of parallel indexing workers",
61
62
  "CACHE_ENABLED": "Enable caching for faster re-indexing",
62
63
  "IGNORE_DIRS": "Comma-separated list of directory names to ignore during indexing",
64
+ "INDEX_SOURCE": "Store full source code in graph database (recommended false)",
63
65
  }
64
66
 
65
67
  # Valid values for each config key
@@ -73,6 +75,7 @@ CONFIG_VALIDATORS = {
73
75
  "IGNORE_HIDDEN_FILES": ["true", "false"],
74
76
  "ENABLE_AUTO_WATCH": ["true", "false"],
75
77
  "CACHE_ENABLED": ["true", "false"],
78
+ "INDEX_SOURCE": ["true", "false"],
76
79
  }
77
80
 
78
81
 
@@ -15,6 +15,7 @@ from tree_sitter import Language, Parser
15
15
  from ..utils.tree_sitter_manager import get_tree_sitter_manager
16
16
  from ..cli.config_manager import get_config_value
17
17
 
18
+
18
19
  class TreeSitterParser:
19
20
  """A generic parser wrapper for a specific language using tree-sitter."""
20
21
 
@@ -151,7 +152,7 @@ class GraphBuilder:
151
152
  session.run("""
152
153
  CREATE FULLTEXT INDEX code_search_index IF NOT EXISTS
153
154
  FOR (n:Function|Class|Variable)
154
- ON EACH [n.name, n.source, n.docstring]
155
+ ON EACH [n.name, coalesce(n.source, ''), coalesce(n.docstring, '')]
155
156
  """ )
156
157
 
157
158
  info_logger("Database schema verified/created successfully")
@@ -333,6 +334,7 @@ class GraphBuilder:
333
334
  SET n += $props
334
335
  MERGE (f)-[:CONTAINS]->(n)
335
336
  """
337
+
336
338
  session.run(query, file_path=file_path_str, name=item['name'], line_number=item['line_number'], props=item)
337
339
 
338
340
  if label == 'Function':
@@ -802,15 +804,23 @@ class GraphBuilder:
802
804
 
803
805
  debug_log(f"[parse_file] Starting parsing for: {file_path} with {parser.language_name} parser")
804
806
  try:
807
+ index_source = (get_config_value("INDEX_SOURCE") or "false").lower() == "true"
805
808
  if parser.language_name == 'python':
806
809
  is_notebook = file_path.suffix == '.ipynb'
807
- file_data = parser.parse(file_path, is_dependency, is_notebook=is_notebook)
810
+ file_data = parser.parse(
811
+ file_path,
812
+ is_dependency,
813
+ is_notebook=is_notebook,
814
+ index_source=index_source
815
+ )
808
816
  else:
809
- file_data = parser.parse(file_path, is_dependency)
817
+ file_data = parser.parse(
818
+ file_path,
819
+ is_dependency,
820
+ index_source=index_source
821
+ )
810
822
  file_data['repo_path'] = str(repo_path)
811
- debug_log(f"[parse_file] Successfully parsed: {file_path}")
812
823
  return file_data
813
-
814
824
  except Exception as e:
815
825
  error_logger(f"Error parsing {file_path} with {parser.language_name} parser: {e}")
816
826
  debug_log(f"[parse_file] Error parsing {file_path}: {e}")
@@ -96,8 +96,9 @@ class CTreeSitterParser:
96
96
  def _get_node_text(self, node: Any) -> str:
97
97
  return node.text.decode("utf-8")
98
98
 
99
- def parse(self, file_path: Path, is_dependency: bool = False) -> Dict[str, Any]:
99
+ def parse(self, file_path: Path, is_dependency: bool = False, index_source: bool = False) -> Dict[str, Any]:
100
100
  """Parses a C file and returns its structure."""
101
+ self.index_source = index_source
101
102
  with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
102
103
  source_code = f.read()
103
104
 
@@ -238,13 +239,11 @@ class CTreeSitterParser:
238
239
  args = self._parse_function_args(params_node) if params_node else []
239
240
  context, context_type, _ = self._get_parent_context(func_node)
240
241
 
241
- functions.append({
242
+ func_data = {
242
243
  "name": name,
243
244
  "line_number": node.start_point[0] + 1,
244
245
  "end_line": func_node.end_point[0] + 1,
245
246
  "args": [arg["name"] for arg in args if arg["name"]], # Simplified args for compatibility
246
- "source": self._get_node_text(func_node),
247
-
248
247
  "docstring": self._get_docstring(func_node),
249
248
  "cyclomatic_complexity": self._calculate_complexity(func_node),
250
249
  "context": context,
@@ -254,7 +253,12 @@ class CTreeSitterParser:
254
253
  "lang": self.language_name,
255
254
  "is_dependency": False,
256
255
  "detailed_args": args, # Keep detailed args for future use
257
- })
256
+ }
257
+
258
+ if self.index_source:
259
+ func_data["source"] = self._get_node_text(func_node)
260
+
261
+ functions.append(func_data)
258
262
  return functions
259
263
 
260
264
  def _find_structs_unions_enums(self, root_node: Any) -> list[Dict[str, Any]]:
@@ -271,19 +275,23 @@ class CTreeSitterParser:
271
275
  name = self._get_node_text(node)
272
276
  context, context_type, _ = self._get_parent_context(struct_node)
273
277
 
274
- classes.append({
278
+ struct_data = {
275
279
  "name": name,
276
280
  "line_number": node.start_point[0] + 1,
277
281
  "end_line": struct_node.end_point[0] + 1,
278
282
  "bases": [], # C doesn't have inheritance
279
- "source": self._get_node_text(struct_node),
280
283
  "docstring": self._get_docstring(struct_node),
281
284
  "context": context,
282
285
  "decorators": [],
283
286
  "lang": self.language_name,
284
287
  "is_dependency": False,
285
288
  "type": "struct",
286
- })
289
+ }
290
+
291
+ if self.index_source:
292
+ struct_data["source"] = self._get_node_text(struct_node)
293
+
294
+ classes.append(struct_data)
287
295
 
288
296
  # Find unions
289
297
  query_str = C_QUERIES["unions"]
@@ -295,19 +303,23 @@ class CTreeSitterParser:
295
303
  name = self._get_node_text(node)
296
304
  context, context_type, _ = self._get_parent_context(union_node)
297
305
 
298
- classes.append({
306
+ union_data = {
299
307
  "name": name,
300
308
  "line_number": node.start_point[0] + 1,
301
309
  "end_line": union_node.end_point[0] + 1,
302
310
  "bases": [],
303
- "source": self._get_node_text(union_node),
304
311
  "docstring": self._get_docstring(union_node),
305
312
  "context": context,
306
313
  "decorators": [],
307
314
  "lang": self.language_name,
308
315
  "is_dependency": False,
309
316
  "type": "union",
310
- })
317
+ }
318
+
319
+ if self.index_source:
320
+ union_data["source"] = self._get_node_text(union_node)
321
+
322
+ classes.append(union_data)
311
323
 
312
324
  # Find enums
313
325
  query_str = C_QUERIES["enums"]
@@ -319,19 +331,23 @@ class CTreeSitterParser:
319
331
  name = self._get_node_text(node)
320
332
  context, context_type, _ = self._get_parent_context(enum_node)
321
333
 
322
- classes.append({
334
+ enum_data = {
323
335
  "name": name,
324
336
  "line_number": node.start_point[0] + 1,
325
337
  "end_line": enum_node.end_point[0] + 1,
326
338
  "bases": [],
327
- "source": self._get_node_text(enum_node),
328
339
  "docstring": self._get_docstring(enum_node),
329
340
  "context": context,
330
341
  "decorators": [],
331
342
  "lang": self.language_name,
332
343
  "is_dependency": False,
333
344
  "type": "enum",
334
- })
345
+ }
346
+
347
+ if self.index_source:
348
+ enum_data["source"] = self._get_node_text(enum_node)
349
+
350
+ classes.append(enum_data)
335
351
 
336
352
  return classes
337
353
 
@@ -474,17 +490,21 @@ class CTreeSitterParser:
474
490
 
475
491
  context, context_type, _ = self._get_parent_context(macro_node)
476
492
 
477
- macros.append({
493
+ macro_data = {
478
494
  "name": name,
479
495
  "line_number": node.start_point[0] + 1,
480
496
  "end_line": macro_node.end_point[0] + 1,
481
- "source": self._get_node_text(macro_node),
482
497
  "value": value,
483
498
  "params": params,
484
499
  "context": context,
485
500
  "lang": self.language_name,
486
501
  "is_dependency": False,
487
- })
502
+ }
503
+
504
+ if self.index_source:
505
+ macro_data["source"] = self._get_node_text(macro_node)
506
+
507
+ macros.append(macro_data)
488
508
  return macros
489
509
 
490
510
 
@@ -116,8 +116,9 @@ class CppTreeSitterParser:
116
116
  def _get_node_text(self, node) -> str:
117
117
  return node.text.decode('utf-8')
118
118
 
119
- def parse(self, file_path: Path, is_dependency: bool = False, **kwargs) -> Dict:
119
+ def parse(self, file_path: Path, is_dependency: bool = False, index_source: bool = False, **kwargs) -> Dict:
120
120
  """Parses a C++ file and returns its structure."""
121
+ self.index_source = index_source
121
122
  with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
122
123
  source_code = f.read()
123
124
 
@@ -177,13 +178,17 @@ class CppTreeSitterParser:
177
178
 
178
179
  params = self._extract_function_params(func_node)
179
180
 
180
- functions.append({
181
+ func_data = {
181
182
  "name": name,
182
183
  "line_number": node.start_point[0] + 1,
183
184
  "end_line": func_node.end_point[0] + 1,
184
- "source": self._get_node_text(func_node),
185
185
  "args": params,
186
- })
186
+ }
187
+
188
+ if self.index_source:
189
+ func_data["source"] = self._get_node_text(func_node)
190
+
191
+ functions.append(func_data)
187
192
  return functions
188
193
 
189
194
  def _extract_function_params(self, func_node) -> list[str]:
@@ -233,13 +238,15 @@ class CppTreeSitterParser:
233
238
  if capture_name == 'name':
234
239
  class_node = node.parent
235
240
  name = self._get_node_text(node)
236
- classes.append({
241
+ class_data = {
237
242
  "name": name,
238
243
  "line_number": node.start_point[0] + 1,
239
244
  "end_line": class_node.end_point[0] + 1,
240
- "source": self._get_node_text(class_node),
241
245
  "bases": [], # Placeholder
242
- })
246
+ }
247
+ if self.index_source:
248
+ class_data["source"] = self._get_node_text(class_node)
249
+ classes.append(class_data)
243
250
  return classes
244
251
 
245
252
  def _find_imports(self, root_node):
@@ -263,14 +270,15 @@ class CppTreeSitterParser:
263
270
  query_str = CPP_QUERIES['enums']
264
271
  for node, capture_name in execute_query(self.language, query_str, root_node):
265
272
  if capture_name == 'name':
266
- name = self._get_node_text(node)
267
273
  enum_node = node.parent
268
- enums.append({
274
+ enum_data = {
269
275
  "name": name,
270
276
  "line_number": node.start_point[0] + 1,
271
277
  "end_line": enum_node.end_point[0] + 1,
272
- "source": self._get_node_text(enum_node),
273
- })
278
+ }
279
+ if self.index_source:
280
+ enum_data["source"] = self._get_node_text(enum_node)
281
+ enums.append(enum_data)
274
282
  return enums
275
283
 
276
284
  def _find_structs(self, root_node):
@@ -280,12 +288,14 @@ class CppTreeSitterParser:
280
288
  if capture_name == 'name':
281
289
  name = self._get_node_text(node)
282
290
  struct_node = node.parent
283
- structs.append({
291
+ struct_data = {
284
292
  "name": name,
285
293
  "line_number": node.start_point[0] + 1,
286
294
  "end_line": struct_node.end_point[0] + 1,
287
- "source": self._get_node_text(struct_node),
288
- })
295
+ }
296
+ if self.index_source:
297
+ struct_data["source"] = self._get_node_text(struct_node)
298
+ structs.append(struct_data)
289
299
  return structs
290
300
 
291
301
  def _find_unions(self, root_node):
@@ -295,12 +305,14 @@ class CppTreeSitterParser:
295
305
  if capture_name == 'name':
296
306
  name = self._get_node_text(node)
297
307
  union_node = node.parent
298
- unions.append({
308
+ union_data = {
299
309
  "name": name,
300
310
  "line_number": node.start_point[0] + 1,
301
311
  "end_line": union_node.end_point[0] + 1,
302
- "source": self._get_node_text(union_node),
303
- })
312
+ }
313
+ if self.index_source:
314
+ union_data["source"] = self._get_node_text(union_node)
315
+ unions.append(union_data)
304
316
  return unions
305
317
 
306
318
  def _find_macros(self, root_node):
@@ -312,12 +324,14 @@ class CppTreeSitterParser:
312
324
  if capture_name == 'name':
313
325
  macro_node = node.parent
314
326
  name = self._get_node_text(node)
315
- macros.append({
327
+ macro_data = {
316
328
  "name": name,
317
329
  "line_number": node.start_point[0] + 1,
318
330
  "end_line": macro_node.end_point[0] + 1,
319
- "source": self._get_node_text(macro_node),
320
- })
331
+ }
332
+ if self.index_source:
333
+ macro_data["source"] = self._get_node_text(macro_node)
334
+ macros.append(macro_data)
321
335
  return macros
322
336
 
323
337
  def _find_lambda_assignments(self, root_node):
@@ -349,8 +363,7 @@ class CppTreeSitterParser:
349
363
  "line_number": node.start_point[0] + 1,
350
364
  "end_line": assignment_node.end_point[0] + 1,
351
365
  "args": [p for p in [self._get_node_text(p) for p in params_node.children if p.type == 'identifier'] if p] if params_node else [],
352
- "source": self._get_node_text(assignment_node),
353
-
366
+
354
367
  "docstring": None,
355
368
  "cyclomatic_complexity": 1,
356
369
  "context": context,
@@ -360,6 +373,10 @@ class CppTreeSitterParser:
360
373
  "lang": self.language_name,
361
374
  "is_dependency": False,
362
375
  }
376
+
377
+ if self.index_source:
378
+ func_data["source"] = self._get_node_text(assignment_node)
379
+
363
380
  functions.append(func_data)
364
381
  return functions
365
382
 
@@ -84,8 +84,9 @@ class CSharpTreeSitterParser:
84
84
  self.language = generic_parser_wrapper.language
85
85
  self.parser = generic_parser_wrapper.parser
86
86
 
87
- def parse(self, file_path: Path, is_dependency: bool = False) -> Dict[str, Any]:
87
+ def parse(self, file_path: Path, is_dependency: bool = False, index_source: bool = False) -> Dict[str, Any]:
88
88
  try:
89
+ self.index_source = index_source
89
90
  with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
90
91
  source_code = f.read()
91
92
 
@@ -221,7 +222,6 @@ class CSharpTreeSitterParser:
221
222
  "attributes": attributes,
222
223
  "line_number": start_line,
223
224
  "end_line": end_line,
224
- "source": source_text,
225
225
  "file_path": str(file_path),
226
226
  "lang": self.language_name,
227
227
  }
@@ -229,6 +229,9 @@ class CSharpTreeSitterParser:
229
229
  # Add class context if found
230
230
  if class_context:
231
231
  func_data["class_context"] = class_context
232
+
233
+ if self.index_source:
234
+ func_data["source"] = source_text
232
235
 
233
236
  functions.append(func_data)
234
237
 
@@ -288,7 +291,6 @@ class CSharpTreeSitterParser:
288
291
  "name": type_name,
289
292
  "line_number": start_line,
290
293
  "end_line": end_line,
291
- "source": source_text,
292
294
  "file_path": str(file_path),
293
295
  "lang": self.language_name,
294
296
  }
@@ -296,6 +298,9 @@ class CSharpTreeSitterParser:
296
298
  # Add bases if found
297
299
  if bases:
298
300
  type_data["bases"] = bases
301
+
302
+ if self.index_source:
303
+ type_data["source"] = source_text
299
304
 
300
305
  types.append(type_data)
301
306
 
@@ -467,13 +472,15 @@ class CSharpTreeSitterParser:
467
472
  "type": prop_type,
468
473
  "line_number": start_line,
469
474
  "end_line": end_line,
470
- "source": source_text,
471
475
  "file_path": str(file_path),
472
476
  "lang": self.language_name,
473
477
  }
474
478
 
475
479
  if class_context:
476
480
  prop_data["class_context"] = class_context
481
+
482
+ if self.index_source:
483
+ prop_data["source"] = source_text
477
484
 
478
485
  properties.append(prop_data)
479
486