tree-sitter-analyzer 0.9.6__py3-none-any.whl → 0.9.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of tree-sitter-analyzer might be problematic. Click here for more details.
- tree_sitter_analyzer/__init__.py +1 -1
- tree_sitter_analyzer/core/query_service.py +162 -162
- tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py +22 -10
- tree_sitter_analyzer/mcp/tools/query_tool.py +18 -6
- tree_sitter_analyzer/mcp/tools/read_partial_tool.py +4 -15
- tree_sitter_analyzer/mcp/tools/table_format_tool.py +11 -24
- tree_sitter_analyzer/mcp/tools/universal_analyze_tool.py +32 -22
- tree_sitter_analyzer/mcp/utils/__init__.py +7 -0
- tree_sitter_analyzer/mcp/utils/error_handler.py +569 -569
- tree_sitter_analyzer/mcp/utils/path_resolver.py +194 -0
- {tree_sitter_analyzer-0.9.6.dist-info → tree_sitter_analyzer-0.9.8.dist-info}/METADATA +22 -11
- {tree_sitter_analyzer-0.9.6.dist-info → tree_sitter_analyzer-0.9.8.dist-info}/RECORD +14 -13
- {tree_sitter_analyzer-0.9.6.dist-info → tree_sitter_analyzer-0.9.8.dist-info}/WHEEL +0 -0
- {tree_sitter_analyzer-0.9.6.dist-info → tree_sitter_analyzer-0.9.8.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Path Resolver Utility for MCP Tools
|
|
4
|
+
|
|
5
|
+
This module provides unified path resolution functionality for all MCP tools,
|
|
6
|
+
ensuring consistent handling of relative and absolute paths across different
|
|
7
|
+
operating systems.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
import os
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class PathResolver:
|
|
17
|
+
"""
|
|
18
|
+
Utility class for resolving file paths in MCP tools.
|
|
19
|
+
|
|
20
|
+
Handles relative path resolution against project root and provides
|
|
21
|
+
cross-platform compatibility for Windows, macOS, and Linux.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(self, project_root: str | None = None):
|
|
25
|
+
"""
|
|
26
|
+
Initialize the path resolver.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
project_root: Optional project root directory for resolving relative paths
|
|
30
|
+
"""
|
|
31
|
+
self.project_root = project_root
|
|
32
|
+
if project_root:
|
|
33
|
+
# Normalize project root path
|
|
34
|
+
self.project_root = os.path.normpath(project_root)
|
|
35
|
+
logger.debug(
|
|
36
|
+
f"PathResolver initialized with project root: {self.project_root}"
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
def resolve(self, file_path: str) -> str:
|
|
40
|
+
"""
|
|
41
|
+
Resolve a file path to an absolute path.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
file_path: Input file path (can be relative or absolute)
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
Resolved absolute file path
|
|
48
|
+
|
|
49
|
+
Raises:
|
|
50
|
+
ValueError: If file_path is empty or None
|
|
51
|
+
"""
|
|
52
|
+
if not file_path:
|
|
53
|
+
raise ValueError("file_path cannot be empty or None")
|
|
54
|
+
|
|
55
|
+
# If already absolute, return as is
|
|
56
|
+
if os.path.isabs(file_path):
|
|
57
|
+
resolved_path = os.path.normpath(file_path)
|
|
58
|
+
logger.debug(f"Path already absolute: {file_path} -> {resolved_path}")
|
|
59
|
+
return resolved_path
|
|
60
|
+
|
|
61
|
+
# If we have a project root, resolve relative to it
|
|
62
|
+
if self.project_root:
|
|
63
|
+
resolved_path = os.path.join(self.project_root, file_path)
|
|
64
|
+
# Normalize path separators for cross-platform compatibility
|
|
65
|
+
resolved_path = os.path.normpath(resolved_path)
|
|
66
|
+
logger.debug(
|
|
67
|
+
f"Resolved relative path '{file_path}' to '{resolved_path}' using project root"
|
|
68
|
+
)
|
|
69
|
+
return resolved_path
|
|
70
|
+
|
|
71
|
+
# Fallback: try to resolve relative to current working directory
|
|
72
|
+
resolved_path = os.path.abspath(file_path)
|
|
73
|
+
resolved_path = os.path.normpath(resolved_path)
|
|
74
|
+
logger.debug(
|
|
75
|
+
f"Resolved relative path '{file_path}' to '{resolved_path}' using current working directory"
|
|
76
|
+
)
|
|
77
|
+
return resolved_path
|
|
78
|
+
|
|
79
|
+
def is_relative(self, file_path: str) -> bool:
|
|
80
|
+
"""
|
|
81
|
+
Check if a file path is relative.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
file_path: File path to check
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
True if the path is relative, False if absolute
|
|
88
|
+
"""
|
|
89
|
+
return not os.path.isabs(file_path)
|
|
90
|
+
|
|
91
|
+
def get_relative_path(self, absolute_path: str) -> str:
|
|
92
|
+
"""
|
|
93
|
+
Get the relative path from project root to the given absolute path.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
absolute_path: Absolute file path
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
Relative path from project root, or the original path if no project root
|
|
100
|
+
|
|
101
|
+
Raises:
|
|
102
|
+
ValueError: If absolute_path is not actually absolute
|
|
103
|
+
"""
|
|
104
|
+
if not os.path.isabs(absolute_path):
|
|
105
|
+
raise ValueError(f"Path is not absolute: {absolute_path}")
|
|
106
|
+
|
|
107
|
+
if not self.project_root:
|
|
108
|
+
return absolute_path
|
|
109
|
+
|
|
110
|
+
try:
|
|
111
|
+
# Get relative path from project root
|
|
112
|
+
relative_path = os.path.relpath(absolute_path, self.project_root)
|
|
113
|
+
logger.debug(
|
|
114
|
+
f"Converted absolute path '{absolute_path}' to relative path '{relative_path}'"
|
|
115
|
+
)
|
|
116
|
+
return relative_path
|
|
117
|
+
except ValueError:
|
|
118
|
+
# Paths are on different drives (Windows) or other error
|
|
119
|
+
logger.warning(
|
|
120
|
+
f"Could not convert absolute path '{absolute_path}' to relative path"
|
|
121
|
+
)
|
|
122
|
+
return absolute_path
|
|
123
|
+
|
|
124
|
+
def validate_path(self, file_path: str) -> tuple[bool, str | None]:
|
|
125
|
+
"""
|
|
126
|
+
Validate if a file path is valid and safe.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
file_path: File path to validate
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
Tuple of (is_valid, error_message)
|
|
133
|
+
"""
|
|
134
|
+
try:
|
|
135
|
+
resolved_path = self.resolve(file_path)
|
|
136
|
+
|
|
137
|
+
# Check if file exists
|
|
138
|
+
if not os.path.exists(resolved_path):
|
|
139
|
+
return False, f"File does not exist: {resolved_path}"
|
|
140
|
+
|
|
141
|
+
# Check if it's a file (not directory)
|
|
142
|
+
if not os.path.isfile(resolved_path):
|
|
143
|
+
return False, f"Path is not a file: {resolved_path}"
|
|
144
|
+
|
|
145
|
+
# Check if it's within project root (if we have one)
|
|
146
|
+
if self.project_root:
|
|
147
|
+
try:
|
|
148
|
+
os.path.commonpath([resolved_path, self.project_root])
|
|
149
|
+
except ValueError:
|
|
150
|
+
return False, f"File path is outside project root: {resolved_path}"
|
|
151
|
+
|
|
152
|
+
return True, None
|
|
153
|
+
|
|
154
|
+
except Exception as e:
|
|
155
|
+
return False, f"Path validation error: {str(e)}"
|
|
156
|
+
|
|
157
|
+
def get_project_root(self) -> str | None:
|
|
158
|
+
"""
|
|
159
|
+
Get the current project root.
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
Project root path or None if not set
|
|
163
|
+
"""
|
|
164
|
+
return self.project_root
|
|
165
|
+
|
|
166
|
+
def set_project_root(self, project_root: str) -> None:
|
|
167
|
+
"""
|
|
168
|
+
Set or update the project root.
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
project_root: New project root directory
|
|
172
|
+
"""
|
|
173
|
+
if project_root:
|
|
174
|
+
self.project_root = os.path.normpath(project_root)
|
|
175
|
+
logger.info(f"Project root updated to: {self.project_root}")
|
|
176
|
+
else:
|
|
177
|
+
self.project_root = None
|
|
178
|
+
logger.info("Project root cleared")
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
# Convenience function for backward compatibility
|
|
182
|
+
def resolve_path(file_path: str, project_root: str | None = None) -> str:
|
|
183
|
+
"""
|
|
184
|
+
Convenience function to resolve a file path.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
file_path: File path to resolve
|
|
188
|
+
project_root: Optional project root directory
|
|
189
|
+
|
|
190
|
+
Returns:
|
|
191
|
+
Resolved absolute file path
|
|
192
|
+
"""
|
|
193
|
+
resolver = PathResolver(project_root)
|
|
194
|
+
return resolver.resolve(file_path)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tree-sitter-analyzer
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.8
|
|
4
4
|
Summary: Extensible multi-language code analyzer framework using Tree-sitter with dynamic plugin architecture
|
|
5
5
|
Project-URL: Homepage, https://github.com/aimasteracc/tree-sitter-analyzer
|
|
6
6
|
Project-URL: Documentation, https://github.com/aimasteracc/tree-sitter-analyzer#readme
|
|
@@ -137,10 +137,11 @@ Description-Content-Type: text/markdown
|
|
|
137
137
|
|
|
138
138
|
[](https://python.org)
|
|
139
139
|
[](LICENSE)
|
|
140
|
-
[](#quality-assurance)
|
|
141
|
+
[](#quality-assurance)
|
|
142
142
|
[](#quality-assurance)
|
|
143
143
|
[](https://pypi.org/project/tree-sitter-analyzer/)
|
|
144
|
+
[](https://github.com/aimasteracc/tree-sitter-analyzer/releases)
|
|
144
145
|
[](https://github.com/aimasteracc/tree-sitter-analyzer)
|
|
145
146
|
|
|
146
147
|
## 🚀 Break Through LLM Token Limits, Let AI Understand Code Files of Any Size
|
|
@@ -346,20 +347,30 @@ Parameters: {"file_path": "examples/BigService.java"}
|
|
|
346
347
|
**Prompt:**
|
|
347
348
|
```
|
|
348
349
|
Use MCP tool extract_code_section to extract specified code section
|
|
349
|
-
Parameters: {"file_path": "examples/BigService.java", "start_line":
|
|
350
|
+
Parameters: {"file_path": "examples/BigService.java", "start_line": 93, "end_line": 105}
|
|
350
351
|
```
|
|
351
352
|
|
|
352
353
|
**Return Format:**
|
|
353
354
|
```json
|
|
354
355
|
{
|
|
355
356
|
"file_path": "examples/BigService.java",
|
|
356
|
-
"range": {
|
|
357
|
-
|
|
358
|
-
|
|
357
|
+
"range": {
|
|
358
|
+
"start_line": 93,
|
|
359
|
+
"end_line": 105,
|
|
360
|
+
"start_column": null,
|
|
361
|
+
"end_column": null
|
|
362
|
+
},
|
|
363
|
+
"content": " private void checkMemoryUsage() {\n Runtime runtime = Runtime.getRuntime();\n long totalMemory = runtime.totalMemory();\n long freeMemory = runtime.freeMemory();\n long usedMemory = totalMemory - freeMemory;\n\n System.out.println(\"Total Memory: \" + totalMemory);\n System.out.println(\"Free Memory: \" + freeMemory);\n System.out.println(\"Used Memory: \" + usedMemory);\n\n if (usedMemory > totalMemory * 0.8) {\n System.out.println(\"WARNING: High memory usage detected!\");\n }\n",
|
|
364
|
+
"content_length": 542
|
|
359
365
|
}
|
|
360
366
|
```
|
|
361
367
|
|
|
362
|
-
#### 🔍 **Step 4: Smart Query Filtering (
|
|
368
|
+
#### 🔍 **Step 4: Smart Query Filtering (v0.9.6+)**
|
|
369
|
+
|
|
370
|
+
**Enhanced Error Handling (v0.9.7):**
|
|
371
|
+
- Improved `@handle_mcp_errors` decorator with tool name identification
|
|
372
|
+
- Better error context for debugging and troubleshooting
|
|
373
|
+
- Enhanced security validation for file paths
|
|
363
374
|
|
|
364
375
|
**Find specific methods:**
|
|
365
376
|
```
|
|
@@ -418,7 +429,7 @@ uv run python -m tree_sitter_analyzer examples/BigService.java --partial-read --
|
|
|
418
429
|
# Silent mode (display results only)
|
|
419
430
|
uv run python -m tree_sitter_analyzer examples/BigService.java --table=full --quiet
|
|
420
431
|
|
|
421
|
-
# 🔍 Query filtering examples (
|
|
432
|
+
# 🔍 Query filtering examples (v0.9.6+)
|
|
422
433
|
# Find specific methods
|
|
423
434
|
uv run python -m tree_sitter_analyzer examples/BigService.java --query-key methods --filter "name=main"
|
|
424
435
|
|
|
@@ -545,8 +556,8 @@ Tree-sitter Analyzer automatically detects and protects project boundaries:
|
|
|
545
556
|
## 🏆 Quality Assurance
|
|
546
557
|
|
|
547
558
|
### 📊 **Quality Metrics**
|
|
548
|
-
- **1,
|
|
549
|
-
- **74.
|
|
559
|
+
- **1,358 Tests** - 100% pass rate ✅
|
|
560
|
+
- **74.54% Code Coverage** - Industry-leading level
|
|
550
561
|
- **Zero Test Failures** - Complete CI/CD ready
|
|
551
562
|
- **Cross-platform Compatible** - Windows, macOS, Linux
|
|
552
563
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
tree_sitter_analyzer/__init__.py,sha256=
|
|
1
|
+
tree_sitter_analyzer/__init__.py,sha256=lWzOrA7xrd-u8fEv4rQova4X-E4LRPH_pDJiajwNZCw,3067
|
|
2
2
|
tree_sitter_analyzer/__main__.py,sha256=Zl79tpe4UaMu-7yeztc06tgP0CVMRnvGgas4ZQP5SCs,228
|
|
3
3
|
tree_sitter_analyzer/api.py,sha256=naRtGuZ27AIVfn6Rid0zQcHDI71UpO9Nh4NQM9JyD3c,16954
|
|
4
4
|
tree_sitter_analyzer/cli_main.py,sha256=4uIwje6n2qQvTsX4RBgqFgznxJs8RcCnS1GQjrR5IGQ,10354
|
|
@@ -32,7 +32,7 @@ tree_sitter_analyzer/core/engine.py,sha256=VFXGowDj6EfjFSh2MQDkQIc-4ISXaOg38n4lU
|
|
|
32
32
|
tree_sitter_analyzer/core/parser.py,sha256=qT3yIlTRdod4tf_2o1hU_B-GYGukyM2BtaFxzSoxois,9293
|
|
33
33
|
tree_sitter_analyzer/core/query.py,sha256=UhQxUmQitFobe2YM7Ifhi3X2WdHVb02KzeBunueYJ4I,16397
|
|
34
34
|
tree_sitter_analyzer/core/query_filter.py,sha256=PvGztAZFooFNZe6iHNmbg6RUNtMvq6f6hBZFzllig6Y,6591
|
|
35
|
-
tree_sitter_analyzer/core/query_service.py,sha256=
|
|
35
|
+
tree_sitter_analyzer/core/query_service.py,sha256=lHlvtu7LoG-IEAOqQ-RwF-a5puEI9wqaGez4cnJZiO4,5704
|
|
36
36
|
tree_sitter_analyzer/formatters/__init__.py,sha256=yVb4HF_4EEPRwTf3y3-vM2NllrhykG3zlvQhN-6dB4c,31
|
|
37
37
|
tree_sitter_analyzer/formatters/base_formatter.py,sha256=Uv6uVgUKwbBn6of26bnvr4u6CmX2ka1a405VL17CGFU,5763
|
|
38
38
|
tree_sitter_analyzer/formatters/formatter_factory.py,sha256=mCnAbEHycoSttSuF4dU78hzcxyg-h57bo0_bj00zw58,2069
|
|
@@ -53,15 +53,16 @@ tree_sitter_analyzer/mcp/resources/__init__.py,sha256=SWnK8liTQkuQXlVgyRP9mf5Hzp
|
|
|
53
53
|
tree_sitter_analyzer/mcp/resources/code_file_resource.py,sha256=ZX5ZYSJfylBedpL80kTDlco2YZqgRMb5f3OW0VvOVRM,6166
|
|
54
54
|
tree_sitter_analyzer/mcp/resources/project_stats_resource.py,sha256=V5-daZ99SU4rOt7qLk9GmhkzdXJpEINBobNlT14ojYY,19441
|
|
55
55
|
tree_sitter_analyzer/mcp/tools/__init__.py,sha256=u7JrSLwE95y50mfjSus6HRdtdhkNbVrW8jP4AooawEU,762
|
|
56
|
-
tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py,sha256=
|
|
56
|
+
tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py,sha256=ZiwIzVbzSMoUXpuC94-N9_xLrlSCWEFlHv2nB_ibOgU,27856
|
|
57
57
|
tree_sitter_analyzer/mcp/tools/analyze_scale_tool_cli_compatible.py,sha256=mssed7bEfGeGxW4mOf7dg8BDS1oqHLolIBNX9DaZ3DM,8997
|
|
58
58
|
tree_sitter_analyzer/mcp/tools/base_tool.py,sha256=FVSMgKIliQ5EBVQEfjYwWeqzWt9OqOFDr3dyACIDxig,1210
|
|
59
|
-
tree_sitter_analyzer/mcp/tools/query_tool.py,sha256=
|
|
60
|
-
tree_sitter_analyzer/mcp/tools/read_partial_tool.py,sha256=
|
|
61
|
-
tree_sitter_analyzer/mcp/tools/table_format_tool.py,sha256=
|
|
62
|
-
tree_sitter_analyzer/mcp/tools/universal_analyze_tool.py,sha256=
|
|
63
|
-
tree_sitter_analyzer/mcp/utils/__init__.py,sha256=
|
|
64
|
-
tree_sitter_analyzer/mcp/utils/error_handler.py,sha256=
|
|
59
|
+
tree_sitter_analyzer/mcp/tools/query_tool.py,sha256=UzJSfVXr6DsF1E8EdysMHxlYOREZOKrym1Zv9OtK_8Y,8545
|
|
60
|
+
tree_sitter_analyzer/mcp/tools/read_partial_tool.py,sha256=Hc4PnF7wBBRhxVlzuqaz1rBA5rWSNvC6qEiWSLqdogI,11504
|
|
61
|
+
tree_sitter_analyzer/mcp/tools/table_format_tool.py,sha256=YeZs5tL8hjWOCR-v6VekNDMyCQOcNI06wHGbGdnacIQ,15451
|
|
62
|
+
tree_sitter_analyzer/mcp/tools/universal_analyze_tool.py,sha256=cdc1K-NZomQK7PD1viVR1kBaNWwDeo1FrU0nn5sb1YA,22141
|
|
63
|
+
tree_sitter_analyzer/mcp/utils/__init__.py,sha256=6f4xTAfA7kCdk3e8r_ee-j7h84OLBEFSNvA3o-TOMqM,3148
|
|
64
|
+
tree_sitter_analyzer/mcp/utils/error_handler.py,sha256=_XeGjfF331EEeHUnJ5cGvJB7WP0lHkD8RXtBayQElr4,18973
|
|
65
|
+
tree_sitter_analyzer/mcp/utils/path_resolver.py,sha256=L9qTXEDwJw3I9nFIQCOdaec0Nuq-6ZvM_UXaOBV-w-c,6196
|
|
65
66
|
tree_sitter_analyzer/plugins/__init__.py,sha256=ITE9bTz7NO4axnn8g5Z-1_ydhSLT0RnY6Y1J9OhUP3E,10326
|
|
66
67
|
tree_sitter_analyzer/plugins/base.py,sha256=FMRAOtjtDutNV8RnB6cmFgdvcjxKRAbrrzqldBBT1yk,17167
|
|
67
68
|
tree_sitter_analyzer/plugins/manager.py,sha256=PyEY3jeuCBpDVqguWhaAu7nzUZM17_pI6wml2e0Hamo,12535
|
|
@@ -74,7 +75,7 @@ tree_sitter_analyzer/security/__init__.py,sha256=ZTqTt24hsljCpTXAZpJC57L7MU5lJLT
|
|
|
74
75
|
tree_sitter_analyzer/security/boundary_manager.py,sha256=CUQWU5j1zdjEbN9UmArcYkq9HbemhttQzk0pVk-vxZs,8153
|
|
75
76
|
tree_sitter_analyzer/security/regex_checker.py,sha256=jWK6H8PTPgzbwRPfK_RZ8bBTS6rtEbgjY5vr3YWjQ_U,9616
|
|
76
77
|
tree_sitter_analyzer/security/validator.py,sha256=UPAPcrnmI2mNzbYOm0MabnJMGllK6HlOQ9KX-2bRfgU,8986
|
|
77
|
-
tree_sitter_analyzer-0.9.
|
|
78
|
-
tree_sitter_analyzer-0.9.
|
|
79
|
-
tree_sitter_analyzer-0.9.
|
|
80
|
-
tree_sitter_analyzer-0.9.
|
|
78
|
+
tree_sitter_analyzer-0.9.8.dist-info/METADATA,sha256=zFg_OCSiYitBph2K6aHC7HRooxgkDN1kbj9WF76FrEU,23557
|
|
79
|
+
tree_sitter_analyzer-0.9.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
80
|
+
tree_sitter_analyzer-0.9.8.dist-info/entry_points.txt,sha256=U4tfLGXgCWubKm2PyEb3zxhQ2pm7zVotMyfyS0CodD8,486
|
|
81
|
+
tree_sitter_analyzer-0.9.8.dist-info/RECORD,,
|
|
File without changes
|
{tree_sitter_analyzer-0.9.6.dist-info → tree_sitter_analyzer-0.9.8.dist-info}/entry_points.txt
RENAMED
|
File without changes
|