codegraphcontext 0.1.18__tar.gz → 0.1.20__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 (63) hide show
  1. {codegraphcontext-0.1.18/src/codegraphcontext.egg-info → codegraphcontext-0.1.20}/PKG-INFO +53 -10
  2. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/README.md +45 -4
  3. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/pyproject.toml +9 -6
  4. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/core/__init__.py +20 -5
  5. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/core/database_falkordb.py +6 -0
  6. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/graph_builder.py +97 -38
  7. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/languages/c.py +41 -28
  8. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/languages/cpp.py +114 -36
  9. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/languages/csharp.py +53 -40
  10. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/languages/go.py +48 -30
  11. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/languages/java.py +207 -57
  12. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/languages/javascript.py +61 -43
  13. codegraphcontext-0.1.20/src/codegraphcontext/tools/languages/php.py +486 -0
  14. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/languages/python.py +15 -20
  15. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/languages/ruby.py +70 -30
  16. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/languages/rust.py +115 -60
  17. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/languages/typescript.py +103 -36
  18. codegraphcontext-0.1.20/src/codegraphcontext/utils/tree_sitter_manager.py +271 -0
  19. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20/src/codegraphcontext.egg-info}/PKG-INFO +53 -10
  20. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext.egg-info/SOURCES.txt +3 -0
  21. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext.egg-info/requires.txt +8 -3
  22. codegraphcontext-0.1.20/tests/test_tree_sitter_manager.py +241 -0
  23. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/LICENSE +0 -0
  24. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/MANIFEST.in +0 -0
  25. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/setup.cfg +0 -0
  26. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/__init__.py +0 -0
  27. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/__main__.py +0 -0
  28. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/cli/__init__.py +0 -0
  29. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/cli/cli_helpers.py +0 -0
  30. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/cli/main.py +0 -0
  31. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/cli/setup_macos.py +0 -0
  32. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/cli/setup_wizard.py +0 -0
  33. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/core/database.py +0 -0
  34. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/core/falkor_worker.py +0 -0
  35. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/core/jobs.py +0 -0
  36. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/core/watcher.py +0 -0
  37. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/prompts.py +0 -0
  38. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/server.py +0 -0
  39. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/__init__.py +0 -0
  40. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/advanced_language_query_tool.py +0 -0
  41. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/code_finder.py +0 -0
  42. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/package_resolver.py +0 -0
  43. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/query_tool_languages/c_toolkit.py +0 -0
  44. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/query_tool_languages/cpp_toolkit.py +0 -0
  45. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/query_tool_languages/csharp_toolkit.py +0 -0
  46. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/query_tool_languages/go_toolkit.py +0 -0
  47. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/query_tool_languages/java_toolkit.py +0 -0
  48. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/query_tool_languages/javascript_toolkit.py +0 -0
  49. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/query_tool_languages/python_toolkit.py +0 -0
  50. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/query_tool_languages/ruby_toolkit.py +0 -0
  51. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/query_tool_languages/rust_toolkit.py +0 -0
  52. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/query_tool_languages/typescript_toolkit.py +0 -0
  53. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/tools/system.py +0 -0
  54. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext/utils/debug_log.py +0 -0
  55. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext.egg-info/dependency_links.txt +0 -0
  56. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext.egg-info/entry_points.txt +0 -0
  57. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/src/codegraphcontext.egg-info/top_level.txt +0 -0
  58. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/tests/test_cpp_parser.py +0 -0
  59. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/tests/test_database_validation.py +0 -0
  60. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/tests/test_end_to_end.py +0 -0
  61. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/tests/test_graph_indexing.py +0 -0
  62. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/tests/test_graph_indexing_js.py +0 -0
  63. {codegraphcontext-0.1.18 → codegraphcontext-0.1.20}/tests/test_typescript_parser.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codegraphcontext
3
- Version: 0.1.18
3
+ Version: 0.1.20
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
@@ -33,25 +33,27 @@ Classifier: Operating System :: OS Independent
33
33
  Classifier: Development Status :: 3 - Alpha
34
34
  Classifier: Intended Audience :: Developers
35
35
  Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
36
- Requires-Python: >=3.12
36
+ Requires-Python: >=3.10
37
37
  Description-Content-Type: text/markdown
38
38
  License-File: LICENSE
39
39
  Requires-Dist: neo4j>=5.15.0
40
40
  Requires-Dist: watchdog>=3.0.0
41
- Requires-Dist: requests>=2.31.0
42
41
  Requires-Dist: stdlibs>=2023.11.18
43
42
  Requires-Dist: typer[all]>=0.9.0
44
43
  Requires-Dist: rich>=13.7.0
45
44
  Requires-Dist: inquirerpy>=0.3.4
46
45
  Requires-Dist: python-dotenv>=1.0.0
47
- Requires-Dist: tree-sitter==0.20.4
48
- Requires-Dist: tree-sitter-languages==1.10.2
46
+ Requires-Dist: tree-sitter>=0.21.0
47
+ Requires-Dist: tree-sitter-language-pack>=0.6.0
49
48
  Requires-Dist: pyyaml
50
49
  Requires-Dist: pytest
51
50
  Requires-Dist: nbformat
52
51
  Requires-Dist: nbconvert>=7.16.6
53
52
  Requires-Dist: pathspec>=0.12.1
54
- Requires-Dist: falkordblite>=0.1.0
53
+ Requires-Dist: falkordblite>=0.1.0; python_version >= "3.12"
54
+ Provides-Extra: parsing
55
+ Requires-Dist: tree-sitter>=0.21.0; extra == "parsing"
56
+ Requires-Dist: tree-sitter-language-pack>=0.6.0; extra == "parsing"
55
57
  Provides-Extra: dev
56
58
  Requires-Dist: pytest>=7.4.0; extra == "dev"
57
59
  Requires-Dist: black>=23.11.0; extra == "dev"
@@ -89,7 +91,7 @@ An MCP server that indexes local code into a graph database to provide context t
89
91
  ![Using the MCP server](https://github.com/Shashankss1205/CodeGraphContext/blob/main/images/Usecase.gif)
90
92
 
91
93
  ## Project Details
92
- - **Version:** 0.1.17
94
+ - **Version:** 0.1.20
93
95
  - **Authors:** Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
94
96
  - **License:** MIT License (See [LICENSE](LICENSE) for details)
95
97
  - **Website:** [CodeGraphContext](http://codegraphcontext.vercel.app/)
@@ -103,6 +105,46 @@ An MCP server that indexes local code into a graph database to provide context t
103
105
  - **Relationship Analysis:** Query for callers, callees, class hierarchies, call chains and more.
104
106
  - **Live Updates:** Watches local files for changes and automatically updates the graph.
105
107
  - **Interactive Setup:** A user-friendly command-line wizard for easy setup.
108
+ - **Multi-Language Support:** Full support for 11 programming languages.
109
+ - **Flexible Database Backend:** Choose between Neo4j or FalkorDB Lite.
110
+
111
+ ## Supported Programming Languages
112
+
113
+ CodeGraphContext provides comprehensive parsing and analysis for the following languages:
114
+
115
+ - **Python** (`.py`) - Including Jupyter notebooks (`.ipynb`)
116
+ - **JavaScript** (`.js`)
117
+ - **TypeScript** (`.ts`)
118
+ - **Java** (`.java`)
119
+ - **C** (`.c`, `.h`)
120
+ - **C++** (`.cpp`, `.cc`, `.cxx`, `.hpp`, `.hxx`)
121
+ - **C#** (`.cs`) - Full support for classes, methods, namespaces, and inheritance
122
+ - **Go** (`.go`)
123
+ - **Rust** (`.rs`)
124
+ - **Ruby** (`.rb`)
125
+ - **PHP** (`.php`)
126
+
127
+ Each language parser extracts functions, classes, methods, parameters, inheritance relationships, function calls, and imports to build a comprehensive code graph.
128
+
129
+ ## Database Options
130
+
131
+ CodeGraphContext supports two graph database backends:
132
+
133
+ ### Neo4j (Default)
134
+ - **Production-ready** and widely used graph database
135
+ - Supports local instances (via Docker or native installation) and cloud hosting (Neo4j AuraDB)
136
+ - Full Cypher query support for advanced graph analytics
137
+ - Recommended for most use cases
138
+
139
+ ### FalkorDB Lite
140
+ - **Lightweight** in-memory graph database
141
+ - **No external dependencies** - runs entirely in-process
142
+ - Available for **Python 3.12+** only
143
+ - Perfect for quick testing and development
144
+ - Automatically installed when using Python 3.12 or higher
145
+
146
+ The `cgc setup` wizard helps you configure neo4j database backend while the falkordb database is
147
+ supported inherently.
106
148
 
107
149
  ## Used By
108
150
 
@@ -118,20 +160,21 @@ If you’re using CodeGraphContext in your project, feel free to open a PR and a
118
160
 
119
161
  - `neo4j>=5.15.0`
120
162
  - `watchdog>=3.0.0`
121
- - `requests>=2.31.0`
122
163
  - `stdlibs>=2023.11.18`
123
164
  - `typer[all]>=0.9.0`
124
165
  - `rich>=13.7.0`
125
166
  - `inquirerpy>=0.3.4`
126
167
  - `python-dotenv>=1.0.0`
127
- - `tree-sitter==0.20.4`
128
- - `tree-sitter-languages==1.10.2`
168
+ - `tree-sitter>=0.21.0`
169
+ - `tree-sitter-language-pack>=0.6.0`
129
170
  - `pyyaml`
130
171
  - `pytest`
131
172
  - `nbformat`
132
173
  - `nbconvert>=7.16.6`
133
174
  - `pathspec>=0.12.1`
134
175
 
176
+ **Note:** Python 3.9+ is supported, including Python 3.13 and 3.14.
177
+
135
178
  ## Getting Started
136
179
 
137
180
  1. **Install:** `pip install codegraphcontext`
@@ -29,7 +29,7 @@ An MCP server that indexes local code into a graph database to provide context t
29
29
  ![Using the MCP server](https://github.com/Shashankss1205/CodeGraphContext/blob/main/images/Usecase.gif)
30
30
 
31
31
  ## Project Details
32
- - **Version:** 0.1.17
32
+ - **Version:** 0.1.20
33
33
  - **Authors:** Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
34
34
  - **License:** MIT License (See [LICENSE](LICENSE) for details)
35
35
  - **Website:** [CodeGraphContext](http://codegraphcontext.vercel.app/)
@@ -43,6 +43,46 @@ An MCP server that indexes local code into a graph database to provide context t
43
43
  - **Relationship Analysis:** Query for callers, callees, class hierarchies, call chains and more.
44
44
  - **Live Updates:** Watches local files for changes and automatically updates the graph.
45
45
  - **Interactive Setup:** A user-friendly command-line wizard for easy setup.
46
+ - **Multi-Language Support:** Full support for 11 programming languages.
47
+ - **Flexible Database Backend:** Choose between Neo4j or FalkorDB Lite.
48
+
49
+ ## Supported Programming Languages
50
+
51
+ CodeGraphContext provides comprehensive parsing and analysis for the following languages:
52
+
53
+ - **Python** (`.py`) - Including Jupyter notebooks (`.ipynb`)
54
+ - **JavaScript** (`.js`)
55
+ - **TypeScript** (`.ts`)
56
+ - **Java** (`.java`)
57
+ - **C** (`.c`, `.h`)
58
+ - **C++** (`.cpp`, `.cc`, `.cxx`, `.hpp`, `.hxx`)
59
+ - **C#** (`.cs`) - Full support for classes, methods, namespaces, and inheritance
60
+ - **Go** (`.go`)
61
+ - **Rust** (`.rs`)
62
+ - **Ruby** (`.rb`)
63
+ - **PHP** (`.php`)
64
+
65
+ Each language parser extracts functions, classes, methods, parameters, inheritance relationships, function calls, and imports to build a comprehensive code graph.
66
+
67
+ ## Database Options
68
+
69
+ CodeGraphContext supports two graph database backends:
70
+
71
+ ### Neo4j (Default)
72
+ - **Production-ready** and widely used graph database
73
+ - Supports local instances (via Docker or native installation) and cloud hosting (Neo4j AuraDB)
74
+ - Full Cypher query support for advanced graph analytics
75
+ - Recommended for most use cases
76
+
77
+ ### FalkorDB Lite
78
+ - **Lightweight** in-memory graph database
79
+ - **No external dependencies** - runs entirely in-process
80
+ - Available for **Python 3.12+** only
81
+ - Perfect for quick testing and development
82
+ - Automatically installed when using Python 3.12 or higher
83
+
84
+ The `cgc setup` wizard helps you configure neo4j database backend while the falkordb database is
85
+ supported inherently.
46
86
 
47
87
  ## Used By
48
88
 
@@ -58,20 +98,21 @@ If you’re using CodeGraphContext in your project, feel free to open a PR and a
58
98
 
59
99
  - `neo4j>=5.15.0`
60
100
  - `watchdog>=3.0.0`
61
- - `requests>=2.31.0`
62
101
  - `stdlibs>=2023.11.18`
63
102
  - `typer[all]>=0.9.0`
64
103
  - `rich>=13.7.0`
65
104
  - `inquirerpy>=0.3.4`
66
105
  - `python-dotenv>=1.0.0`
67
- - `tree-sitter==0.20.4`
68
- - `tree-sitter-languages==1.10.2`
106
+ - `tree-sitter>=0.21.0`
107
+ - `tree-sitter-language-pack>=0.6.0`
69
108
  - `pyyaml`
70
109
  - `pytest`
71
110
  - `nbformat`
72
111
  - `nbconvert>=7.16.6`
73
112
  - `pathspec>=0.12.1`
74
113
 
114
+ **Note:** Python 3.9+ is supported, including Python 3.13 and 3.14.
115
+
75
116
  ## Getting Started
76
117
 
77
118
  1. **Install:** `pip install codegraphcontext`
@@ -1,11 +1,11 @@
1
1
  [project]
2
2
  name = "codegraphcontext"
3
- version = "0.1.18"
3
+ version = "0.1.20"
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"
7
7
  license = { file = "LICENSE" }
8
- requires-python = ">=3.12"
8
+ requires-python = ">=3.10"
9
9
  classifiers = [
10
10
  "Programming Language :: Python :: 3",
11
11
  "License :: OSI Approved :: MIT License",
@@ -17,20 +17,19 @@ classifiers = [
17
17
  dependencies = [
18
18
  "neo4j>=5.15.0",
19
19
  "watchdog>=3.0.0",
20
- "requests>=2.31.0",
21
20
  "stdlibs>=2023.11.18",
22
21
  "typer[all]>=0.9.0",
23
22
  "rich>=13.7.0",
24
23
  "inquirerpy>=0.3.4",
25
24
  "python-dotenv>=1.0.0",
26
- "tree-sitter==0.20.4",
27
- "tree-sitter-languages==1.10.2",
25
+ "tree-sitter>=0.21.0",
26
+ "tree-sitter-language-pack>=0.6.0",
28
27
  "pyyaml",
29
28
  "pytest",
30
29
  "nbformat",
31
30
  "nbconvert>=7.16.6",
32
31
  "pathspec>=0.12.1",
33
- "falkordblite>=0.1.0"
32
+ "falkordblite>=0.1.0; python_version >= '3.12'"
34
33
  ]
35
34
 
36
35
  [project.urls]
@@ -42,6 +41,10 @@ cgc = "codegraphcontext.cli.main:app"
42
41
  codegraphcontext = "codegraphcontext.cli.main:app"
43
42
 
44
43
  [project.optional-dependencies]
44
+ parsing = [
45
+ "tree-sitter>=0.21.0",
46
+ "tree-sitter-language-pack>=0.6.0",
47
+ ]
45
48
  dev = [
46
49
  "pytest>=7.4.0",
47
50
  "black>=23.11.0",
@@ -15,6 +15,9 @@ import importlib.util
15
15
 
16
16
  def _is_falkordb_available() -> bool:
17
17
  """Check if FalkorDB Lite is installed (without importing native modules)."""
18
+ import sys
19
+ if sys.version_info < (3, 12):
20
+ return False
18
21
  try:
19
22
  # Check for redislite/falkordb-client spec without loading it
20
23
  return importlib.util.find_spec("redislite") is not None
@@ -79,11 +82,23 @@ def get_database_manager() -> Union['DatabaseManager', 'FalkorDBManager']:
79
82
  info_logger("Using Neo4j Server (auto-detected)")
80
83
  return DatabaseManager()
81
84
 
82
- raise ValueError(
83
- "No database backend available.\n"
84
- "Recommended: Install FalkorDB Lite ('pip install falkordblite')\n"
85
- "Alternative: Run 'cgc setup' to configure Neo4j."
86
- )
85
+ import sys
86
+ error_msg = "No database backend available.\n"
87
+
88
+ if sys.version_info < (3, 12):
89
+ error_msg += (
90
+ "FalkorDB Lite is not supported on Python < 3.12.\n"
91
+ "You are running Python " + str(sys.version_info.major) + "." + str(sys.version_info.minor) + ".\n"
92
+ "Please upgrade to Python 3.12+ to use the embedded database,\n"
93
+ "OR run 'cgc setup' to configure an external Neo4j database."
94
+ )
95
+ else:
96
+ error_msg += (
97
+ "Recommended: Install FalkorDB Lite ('pip install falkordblite')\n"
98
+ "Alternative: Run 'cgc setup' to configure Neo4j."
99
+ )
100
+
101
+ raise ValueError(error_msg)
87
102
 
88
103
  # For backward compatibility, export DatabaseManager
89
104
  from .database import DatabaseManager
@@ -66,6 +66,9 @@ class FalkorDBManager:
66
66
  A FalkorDB graph instance that mimics Neo4j driver interface.
67
67
  """
68
68
  if self._driver is None:
69
+ if sys.version_info < (3, 12):
70
+ raise ValueError("FalkorDB Lite is not supported on Python < 3.12.")
71
+
69
72
  with self._lock:
70
73
  if self._driver is None:
71
74
  # CRITICAL FIX: Prevent ~/.local/bin/falkordb.so from shadowing falkordb package
@@ -212,6 +215,9 @@ class FalkorDBManager:
212
215
  Tests the FalkorDB Lite connection availability.
213
216
  """
214
217
  try:
218
+ if sys.version_info < (3, 12):
219
+ return False, "FalkorDB Lite is not supported on Python < 3.12. Please upgrade or use Neo4j."
220
+
215
221
  import falkordb
216
222
  return True, None
217
223
  except ImportError:
@@ -10,18 +10,21 @@ from ..core.database import DatabaseManager
10
10
  from ..core.jobs import JobManager, JobStatus
11
11
  from ..utils.debug_log import debug_log, info_logger, error_logger, warning_logger
12
12
 
13
- # New imports for tree-sitter
13
+ # New imports for tree-sitter (using tree-sitter-language-pack)
14
14
  from tree_sitter import Language, Parser
15
- from tree_sitter_languages import get_language
15
+ from ..utils.tree_sitter_manager import get_tree_sitter_manager
16
16
 
17
17
  class TreeSitterParser:
18
18
  """A generic parser wrapper for a specific language using tree-sitter."""
19
19
 
20
20
  def __init__(self, language_name: str):
21
21
  self.language_name = language_name
22
- self.language: Language = get_language(language_name)
23
- self.parser = Parser()
24
- self.parser.set_language(self.language)
22
+ self.ts_manager = get_tree_sitter_manager()
23
+
24
+ # Get the language (cached) and create a new parser for this instance
25
+ self.language: Language = self.ts_manager.get_language_safe(language_name)
26
+ # In tree-sitter 0.25+, Parser takes language in constructor
27
+ self.parser = Parser(self.language)
25
28
 
26
29
  self.language_specific_parser = None
27
30
  if self.language_name == 'python':
@@ -54,6 +57,9 @@ class TreeSitterParser:
54
57
  elif self.language_name == 'c_sharp':
55
58
  from .languages.csharp import CSharpTreeSitterParser
56
59
  self.language_specific_parser = CSharpTreeSitterParser(self)
60
+ elif self.language_name == 'php':
61
+ from .languages.php import PhpTreeSitterParser
62
+ self.language_specific_parser = PhpTreeSitterParser(self)
57
63
 
58
64
 
59
65
  def parse(self, file_path: Path, is_dependency: bool = False, **kwargs) -> Dict:
@@ -89,7 +95,10 @@ class GraphBuilder:
89
95
  # '.h': TreeSitterParser('c'), # Need to write an algo for distinguishing C vs C++ headers
90
96
  '.java': TreeSitterParser('java'),
91
97
  '.rb': TreeSitterParser('ruby'),
92
- '.cs': TreeSitterParser('c_sharp')
98
+ '.java': TreeSitterParser('java'),
99
+ '.rb': TreeSitterParser('ruby'),
100
+ '.cs': TreeSitterParser('c_sharp'),
101
+ '.php': TreeSitterParser('php')
93
102
  }
94
103
  self.create_schema()
95
104
 
@@ -147,43 +156,43 @@ class GraphBuilder:
147
156
  if '.py' in files_by_lang:
148
157
  from .languages import python as python_lang_module
149
158
  imports_map.update(python_lang_module.pre_scan_python(files_by_lang['.py'], self.parsers['.py']))
150
- elif '.ipynb' in files_by_lang:
159
+ if '.ipynb' in files_by_lang:
151
160
  from .languages import python as python_lang_module
152
161
  imports_map.update(python_lang_module.pre_scan_python(files_by_lang['.ipynb'], self.parsers['.ipynb']))
153
- elif '.js' in files_by_lang:
162
+ if '.js' in files_by_lang:
154
163
  from .languages import javascript as js_lang_module
155
164
  imports_map.update(js_lang_module.pre_scan_javascript(files_by_lang['.js'], self.parsers['.js']))
156
- elif '.jsx' in files_by_lang:
165
+ if '.jsx' in files_by_lang:
157
166
  from .languages import javascript as js_lang_module
158
167
  imports_map.update(js_lang_module.pre_scan_javascript(files_by_lang['.jsx'], self.parsers['.jsx']))
159
- elif '.mjs' in files_by_lang:
168
+ if '.mjs' in files_by_lang:
160
169
  from .languages import javascript as js_lang_module
161
170
  imports_map.update(js_lang_module.pre_scan_javascript(files_by_lang['.mjs'], self.parsers['.mjs']))
162
- elif '.cjs' in files_by_lang:
171
+ if '.cjs' in files_by_lang:
163
172
  from .languages import javascript as js_lang_module
164
173
  imports_map.update(js_lang_module.pre_scan_javascript(files_by_lang['.cjs'], self.parsers['.cjs']))
165
- elif '.go' in files_by_lang:
174
+ if '.go' in files_by_lang:
166
175
  from .languages import go as go_lang_module
167
176
  imports_map.update(go_lang_module.pre_scan_go(files_by_lang['.go'], self.parsers['.go']))
168
- elif '.ts' in files_by_lang:
177
+ if '.ts' in files_by_lang:
169
178
  from .languages import typescript as ts_lang_module
170
179
  imports_map.update(ts_lang_module.pre_scan_typescript(files_by_lang['.ts'], self.parsers['.ts']))
171
- elif '.tsx' in files_by_lang:
180
+ if '.tsx' in files_by_lang:
172
181
  from .languages import typescript as ts_lang_module
173
182
  imports_map.update(ts_lang_module.pre_scan_typescript(files_by_lang['.tsx'], self.parsers['.tsx']))
174
- elif '.cpp' in files_by_lang:
183
+ if '.cpp' in files_by_lang:
175
184
  from .languages import cpp as cpp_lang_module
176
185
  imports_map.update(cpp_lang_module.pre_scan_cpp(files_by_lang['.cpp'], self.parsers['.cpp']))
177
- elif '.h' in files_by_lang:
186
+ if '.h' in files_by_lang:
178
187
  from .languages import cpp as cpp_lang_module
179
188
  imports_map.update(cpp_lang_module.pre_scan_cpp(files_by_lang['.h'], self.parsers['.h']))
180
- elif '.hpp' in files_by_lang:
189
+ if '.hpp' in files_by_lang:
181
190
  from .languages import cpp as cpp_lang_module
182
191
  imports_map.update(cpp_lang_module.pre_scan_cpp(files_by_lang['.hpp'], self.parsers['.hpp']))
183
- elif '.rs' in files_by_lang:
192
+ if '.rs' in files_by_lang:
184
193
  from .languages import rust as rust_lang_module
185
194
  imports_map.update(rust_lang_module.pre_scan_rust(files_by_lang['.rs'], self.parsers['.rs']))
186
- elif '.c' in files_by_lang:
195
+ if '.c' in files_by_lang:
187
196
  from .languages import c as c_lang_module
188
197
  imports_map.update(c_lang_module.pre_scan_c(files_by_lang['.c'], self.parsers['.c']))
189
198
  elif '.java' in files_by_lang:
@@ -385,7 +394,8 @@ class GraphBuilder:
385
394
  def _create_function_calls(self, session, file_data: Dict, imports_map: dict):
386
395
  """Create CALLS relationships with a unified, prioritized logic flow for all call types."""
387
396
  caller_file_path = str(Path(file_data['file_path']).resolve())
388
- local_function_names = {func['name'] for func in file_data.get('functions', [])}
397
+ local_names = {f['name'] for f in file_data.get('functions', [])} | \
398
+ {c['name'] for c in file_data.get('classes', [])}
389
399
  local_imports = {imp.get('alias') or imp['name'].split('.')[-1]: imp['name']
390
400
  for imp in file_data.get('imports', [])}
391
401
 
@@ -394,40 +404,87 @@ class GraphBuilder:
394
404
  if called_name in __builtins__: continue
395
405
 
396
406
  resolved_path = None
407
+ full_call = call.get('full_name', called_name)
408
+ base_obj = full_call.split('.')[0] if '.' in full_call else None
409
+ lookup_name = base_obj if base_obj else called_name
410
+
411
+ # 1. Check for local context keywords/direct local names
412
+ if base_obj in ('self', 'this', 'super', 'super()', 'cls', '@'):
413
+ resolved_path = caller_file_path
414
+ elif lookup_name in local_names:
415
+ resolved_path = caller_file_path
397
416
 
398
- if call.get('inferred_obj_type'):
417
+ # 2. Check inferred type if available
418
+ elif call.get('inferred_obj_type'):
399
419
  obj_type = call['inferred_obj_type']
400
420
  possible_paths = imports_map.get(obj_type, [])
401
421
  if len(possible_paths) > 0:
402
422
  resolved_path = possible_paths[0]
403
423
 
404
- else:
405
- lookup_name = call['full_name'].split('.')[0] if '.' in call['full_name'] else called_name
424
+ # 3. Check imports map with validation against local imports
425
+ if not resolved_path:
406
426
  possible_paths = imports_map.get(lookup_name, [])
407
-
408
- if lookup_name in local_function_names:
409
- resolved_path = caller_file_path
410
- elif len(possible_paths) == 1:
427
+ if len(possible_paths) == 1:
411
428
  resolved_path = possible_paths[0]
412
- elif len(possible_paths) > 1 and lookup_name in local_imports:
413
- full_import_name = local_imports[lookup_name]
414
- for path in possible_paths:
415
- if full_import_name.replace('.', '/') in path:
416
- resolved_path = path
417
- break
429
+ elif len(possible_paths) > 1:
430
+ if lookup_name in local_imports:
431
+ full_import_name = local_imports[lookup_name]
432
+ for path in possible_paths:
433
+ if full_import_name.replace('.', '/') in path:
434
+ resolved_path = path
435
+ break
436
+
437
+ if not resolved_path:
438
+ warning_logger(f"Could not resolve call {called_name} (lookup: {lookup_name}) in {caller_file_path}")
439
+ # else:
440
+ # info_logger(f"Resolved call {called_name} -> {resolved_path}")
418
441
 
442
+ # Legacy fallback block (was mis-indented)
419
443
  if not resolved_path:
420
- if called_name in imports_map and imports_map[called_name]:
421
- resolved_path = imports_map[called_name][0]
444
+ possible_paths = imports_map.get(lookup_name, [])
445
+ if len(possible_paths) > 0:
446
+ # Final fallback: global candidate
447
+ # Check if it was imported explicitly, otherwise risky
448
+ if lookup_name in local_imports:
449
+ # We already tried specific matching above, but if we are here
450
+ # it means we had ambiguity without matching path?
451
+ pass
452
+ else:
453
+ # Fallback to first available if not imported? Or skip?
454
+ # Original logic: resolved_path = possible_paths[0]
455
+ # But wait, original code logic was:
456
+ pass
457
+ if not resolved_path:
458
+ if called_name in local_names:
459
+ resolved_path = caller_file_path
460
+ elif called_name in imports_map and imports_map[called_name]:
461
+ # Check if any path in imports_map for called_name matches current file's imports
462
+ candidates = imports_map[called_name]
463
+ for path in candidates:
464
+ for imp_name in local_imports.values():
465
+ if imp_name.replace('.', '/') in path:
466
+ resolved_path = path
467
+ break
468
+ if resolved_path: break
469
+ if not resolved_path:
470
+ resolved_path = candidates[0]
422
471
  else:
423
472
  resolved_path = caller_file_path
424
473
 
425
474
  caller_context = call.get('context')
426
475
  if caller_context and len(caller_context) == 3 and caller_context[0] is not None:
427
476
  caller_name, _, caller_line_number = caller_context
477
+ # if called_name == "sumOfSquares":
478
+ # print(f"DEBUG_CYPHER: caller={caller_name}, caller_line={caller_line_number}, called={called_name}, path={resolved_path}")
479
+
428
480
  session.run("""
429
- MATCH (caller:Function {name: $caller_name, file_path: $caller_file_path, line_number: $caller_line_number})
430
- MATCH (called:Function {name: $called_name, file_path: $called_file_path})
481
+ MATCH (caller) WHERE (caller:Function OR caller:Class)
482
+ AND caller.name = $caller_name
483
+ AND caller.file_path = $caller_file_path
484
+ AND caller.line_number = $caller_line_number
485
+ MATCH (called) WHERE (called:Function OR called:Class)
486
+ AND called.name = $called_name
487
+ AND called.file_path = $called_file_path
431
488
  MERGE (caller)-[:CALLS {line_number: $line_number, args: $args, full_call_name: $full_call_name}]->(called)
432
489
  """,
433
490
  caller_name=caller_name,
@@ -441,7 +498,9 @@ class GraphBuilder:
441
498
  else:
442
499
  session.run("""
443
500
  MATCH (caller:File {path: $caller_file_path})
444
- MATCH (called:Function {name: $called_name, file_path: $called_file_path})
501
+ MATCH (called) WHERE (called:Function OR called:Class)
502
+ AND called.name = $called_name
503
+ AND called.file_path = $called_file_path
445
504
  MERGE (caller)-[:CALLS {line_number: $line_number, args: $args, full_call_name: $full_call_name}]->(called)
446
505
  """,
447
506
  caller_file_path=caller_file_path,