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.

@@ -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.6
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
  [![Python Version](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://python.org)
139
139
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
140
- [![Tests](https://img.shields.io/badge/tests-1420%20passed-brightgreen.svg)](#quality-assurance)
141
- [![Coverage](https://img.shields.io/badge/coverage-74.36%25-green.svg)](#quality-assurance)
140
+ [![Tests](https://img.shields.io/badge/tests-1358%20passed-brightgreen.svg)](#quality-assurance)
141
+ [![Coverage](https://img.shields.io/badge/coverage-74.54%25-green.svg)](#quality-assurance)
142
142
  [![Quality](https://img.shields.io/badge/quality-enterprise%20grade-blue.svg)](#quality-assurance)
143
143
  [![PyPI](https://img.shields.io/pypi/v/tree-sitter-analyzer.svg)](https://pypi.org/project/tree-sitter-analyzer/)
144
+ [![Version](https://img.shields.io/badge/version-0.9.8-blue.svg)](https://github.com/aimasteracc/tree-sitter-analyzer/releases)
144
145
  [![GitHub Stars](https://img.shields.io/github/stars/aimasteracc/tree-sitter-analyzer.svg?style=social)](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": 100, "end_line": 105}
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": {"start_line": 100, "end_line": 105},
357
- "content": "Actual code content...",
358
- "content_length": 245
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 (NEW!)**
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 (NEW!)
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,420 Tests** - 100% pass rate ✅
549
- - **74.36% Code Coverage** - Industry-leading level
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=JBnnkxDQchD9fes65p315c62-Pat2QTvNGRKaeumtDo,3067
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=j9v3w2j3axhxzFEbZLovDNT2h6kF4PWbJVL_PmKl3ho,5542
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=cVBhq4_KxwcqdmA5s9iZLH4YDy7T_TKLNNdqqaGKnFU,27369
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=FBsxsWhoSYA0ql_IaMGSLR6vmg3M4b1rDsYZsZuVGWQ,7996
60
- tree_sitter_analyzer/mcp/tools/read_partial_tool.py,sha256=MkAeXc-n-8fxRGtE3RQ_yZOPQ1lzdUppVFKrRzBPogU,11790
61
- tree_sitter_analyzer/mcp/tools/table_format_tool.py,sha256=flFEcDOozJSJOtsQVHsk5eTYsutBi_T_2ft9XUpceSM,15896
62
- tree_sitter_analyzer/mcp/tools/universal_analyze_tool.py,sha256=RSbztW_b07DL5e1an4BE--snX744v4KmlRGab5bGj6U,21677
63
- tree_sitter_analyzer/mcp/utils/__init__.py,sha256=hibcoJc9PEetXqPIpvwHw1cpr1rabAm0QQaDZpxvA_g,2956
64
- tree_sitter_analyzer/mcp/utils/error_handler.py,sha256=msrQHX67K3vhJsEc3OPRz5mmWU_yoHz55Lnxy0IZuy4,18404
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.6.dist-info/METADATA,sha256=_bMzqpiKdK1seg16PqwJhmF2vxPGsPL3HkB48XSNhVg,22608
78
- tree_sitter_analyzer-0.9.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
79
- tree_sitter_analyzer-0.9.6.dist-info/entry_points.txt,sha256=U4tfLGXgCWubKm2PyEb3zxhQ2pm7zVotMyfyS0CodD8,486
80
- tree_sitter_analyzer-0.9.6.dist-info/RECORD,,
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,,