tree-sitter-analyzer 0.9.3__py3-none-any.whl → 0.9.4__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/cli/commands/default_command.py +18 -18
- tree_sitter_analyzer/cli/commands/partial_read_command.py +139 -141
- tree_sitter_analyzer/cli/commands/query_command.py +92 -88
- tree_sitter_analyzer/cli/commands/table_command.py +235 -235
- tree_sitter_analyzer/cli/info_commands.py +121 -121
- tree_sitter_analyzer/cli_main.py +307 -307
- tree_sitter_analyzer/core/analysis_engine.py +584 -584
- tree_sitter_analyzer/core/cache_service.py +5 -4
- tree_sitter_analyzer/core/query.py +502 -502
- tree_sitter_analyzer/encoding_utils.py +6 -2
- tree_sitter_analyzer/exceptions.py +400 -406
- tree_sitter_analyzer/formatters/java_formatter.py +291 -291
- tree_sitter_analyzer/formatters/python_formatter.py +259 -259
- tree_sitter_analyzer/interfaces/mcp_server.py +426 -425
- tree_sitter_analyzer/language_detector.py +398 -398
- tree_sitter_analyzer/language_loader.py +224 -224
- tree_sitter_analyzer/languages/java_plugin.py +1202 -1202
- tree_sitter_analyzer/mcp/resources/project_stats_resource.py +559 -555
- tree_sitter_analyzer/mcp/server.py +30 -9
- tree_sitter_analyzer/mcp/tools/read_partial_tool.py +21 -4
- tree_sitter_analyzer/mcp/tools/table_format_tool.py +22 -4
- tree_sitter_analyzer/mcp/utils/error_handler.py +569 -567
- tree_sitter_analyzer/models.py +470 -470
- tree_sitter_analyzer/security/__init__.py +22 -22
- tree_sitter_analyzer/security/boundary_manager.py +243 -243
- tree_sitter_analyzer/security/regex_checker.py +297 -292
- tree_sitter_analyzer/table_formatter.py +703 -652
- tree_sitter_analyzer/utils.py +50 -19
- {tree_sitter_analyzer-0.9.3.dist-info → tree_sitter_analyzer-0.9.4.dist-info}/METADATA +1 -1
- {tree_sitter_analyzer-0.9.3.dist-info → tree_sitter_analyzer-0.9.4.dist-info}/RECORD +32 -32
- {tree_sitter_analyzer-0.9.3.dist-info → tree_sitter_analyzer-0.9.4.dist-info}/WHEEL +0 -0
- {tree_sitter_analyzer-0.9.3.dist-info → tree_sitter_analyzer-0.9.4.dist-info}/entry_points.txt +0 -0
|
@@ -138,8 +138,21 @@ class TreeSitterAnalyzerMCPServer:
|
|
|
138
138
|
include_complexity = arguments.get("include_complexity", True)
|
|
139
139
|
include_details = arguments.get("include_details", False)
|
|
140
140
|
|
|
141
|
+
# Resolve relative path against project root for consistent behavior
|
|
142
|
+
import os
|
|
143
|
+
|
|
144
|
+
base_root = getattr(
|
|
145
|
+
getattr(self.security_validator, "boundary_manager", None),
|
|
146
|
+
"project_root",
|
|
147
|
+
None,
|
|
148
|
+
)
|
|
149
|
+
if not os.path.isabs(file_path) and base_root:
|
|
150
|
+
resolved_path = os.path.realpath(os.path.join(base_root, file_path))
|
|
151
|
+
else:
|
|
152
|
+
resolved_path = file_path
|
|
153
|
+
|
|
141
154
|
# Security validation
|
|
142
|
-
is_valid, error_msg = self.security_validator.validate_file_path(
|
|
155
|
+
is_valid, error_msg = self.security_validator.validate_file_path(resolved_path)
|
|
143
156
|
if not is_valid:
|
|
144
157
|
raise ValueError(f"Invalid file path: {error_msg}")
|
|
145
158
|
|
|
@@ -150,16 +163,16 @@ class TreeSitterAnalyzerMCPServer:
|
|
|
150
163
|
from ..language_detector import detect_language_from_file
|
|
151
164
|
|
|
152
165
|
# Validate file exists
|
|
153
|
-
if not Path(
|
|
166
|
+
if not Path(resolved_path).exists():
|
|
154
167
|
raise FileNotFoundError(f"File not found: {file_path}")
|
|
155
168
|
|
|
156
169
|
# Detect language if not specified
|
|
157
170
|
if not language:
|
|
158
|
-
language = detect_language_from_file(
|
|
171
|
+
language = detect_language_from_file(resolved_path)
|
|
159
172
|
|
|
160
173
|
# Create analysis request
|
|
161
174
|
request = AnalysisRequest(
|
|
162
|
-
file_path=
|
|
175
|
+
file_path=resolved_path,
|
|
163
176
|
language=language,
|
|
164
177
|
include_complexity=include_complexity,
|
|
165
178
|
include_details=include_details,
|
|
@@ -332,8 +345,13 @@ class TreeSitterAnalyzerMCPServer:
|
|
|
332
345
|
# Validate file path security
|
|
333
346
|
if "file_path" in arguments:
|
|
334
347
|
file_path = arguments["file_path"]
|
|
335
|
-
|
|
336
|
-
|
|
348
|
+
is_valid, error_msg = self.security_validator.validate_file_path(
|
|
349
|
+
file_path
|
|
350
|
+
)
|
|
351
|
+
if not is_valid:
|
|
352
|
+
raise ValueError(
|
|
353
|
+
f"Invalid or unsafe file path: {error_msg or file_path}"
|
|
354
|
+
)
|
|
337
355
|
|
|
338
356
|
# Handle tool calls with simplified parameter handling
|
|
339
357
|
if name == "check_code_scale":
|
|
@@ -467,9 +485,12 @@ class TreeSitterAnalyzerMCPServer:
|
|
|
467
485
|
logger.info("Client requested prompts list (returning empty)")
|
|
468
486
|
return []
|
|
469
487
|
|
|
470
|
-
except Exception:
|
|
471
|
-
# If Prompt type is unavailable,
|
|
472
|
-
|
|
488
|
+
except Exception as e:
|
|
489
|
+
# If Prompt type is unavailable, log at debug level and continue safely
|
|
490
|
+
try:
|
|
491
|
+
logger.debug(f"Prompts API unavailable or incompatible: {e}")
|
|
492
|
+
except (ValueError, OSError):
|
|
493
|
+
pass
|
|
473
494
|
|
|
474
495
|
self.server = server
|
|
475
496
|
try:
|
|
@@ -7,6 +7,7 @@ allowing selective content extraction with line and column range support.
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
import json
|
|
10
|
+
import os
|
|
10
11
|
from pathlib import Path
|
|
11
12
|
from typing import Any
|
|
12
13
|
|
|
@@ -29,6 +30,7 @@ class ReadPartialTool:
|
|
|
29
30
|
def __init__(self, project_root: str = None) -> None:
|
|
30
31
|
"""Initialize the read partial tool."""
|
|
31
32
|
self.security_validator = SecurityValidator(project_root)
|
|
33
|
+
self.project_root = project_root
|
|
32
34
|
logger.info("ReadPartialTool initialized with security validation")
|
|
33
35
|
|
|
34
36
|
def get_tool_schema(self) -> dict[str, Any]:
|
|
@@ -104,8 +106,23 @@ class ReadPartialTool:
|
|
|
104
106
|
end_column = arguments.get("end_column")
|
|
105
107
|
# output_format = arguments.get("format", "text") # Not used currently
|
|
106
108
|
|
|
107
|
-
#
|
|
108
|
-
|
|
109
|
+
# Resolve relative path against project root for consistent behavior
|
|
110
|
+
base_root = (
|
|
111
|
+
getattr(
|
|
112
|
+
getattr(self.security_validator, "boundary_manager", None),
|
|
113
|
+
"project_root",
|
|
114
|
+
None,
|
|
115
|
+
)
|
|
116
|
+
or self.project_root
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
if not os.path.isabs(file_path) and base_root:
|
|
120
|
+
resolved_path = os.path.realpath(os.path.join(base_root, file_path))
|
|
121
|
+
else:
|
|
122
|
+
resolved_path = file_path
|
|
123
|
+
|
|
124
|
+
# Security validation (validate resolved absolute path when possible)
|
|
125
|
+
is_valid, error_msg = self.security_validator.validate_file_path(resolved_path)
|
|
109
126
|
if not is_valid:
|
|
110
127
|
logger.warning(
|
|
111
128
|
f"Security validation failed for file path: {file_path} - {error_msg}"
|
|
@@ -113,7 +130,7 @@ class ReadPartialTool:
|
|
|
113
130
|
raise ValueError(f"Invalid file path: {error_msg}")
|
|
114
131
|
|
|
115
132
|
# Validate file exists
|
|
116
|
-
if not Path(
|
|
133
|
+
if not Path(resolved_path).exists():
|
|
117
134
|
raise ValueError("Invalid file path: file does not exist")
|
|
118
135
|
|
|
119
136
|
# Validate line numbers
|
|
@@ -141,7 +158,7 @@ class ReadPartialTool:
|
|
|
141
158
|
|
|
142
159
|
with get_performance_monitor().measure_operation("read_code_partial"):
|
|
143
160
|
content = self._read_file_partial(
|
|
144
|
-
|
|
161
|
+
resolved_path, start_line, end_line, start_column, end_column
|
|
145
162
|
)
|
|
146
163
|
|
|
147
164
|
if content is None:
|
|
@@ -6,6 +6,7 @@ This tool provides table-formatted output for code analysis results through the
|
|
|
6
6
|
equivalent to the CLI --table=full option functionality.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
+
import os
|
|
9
10
|
from pathlib import Path
|
|
10
11
|
from typing import Any
|
|
11
12
|
|
|
@@ -271,8 +272,25 @@ class TableFormatTool:
|
|
|
271
272
|
format_type = args.get("format_type", "full")
|
|
272
273
|
language = args.get("language")
|
|
273
274
|
|
|
275
|
+
# Resolve relative path against project root for consistent behavior
|
|
276
|
+
base_root = (
|
|
277
|
+
getattr(
|
|
278
|
+
getattr(self.security_validator, "boundary_manager", None),
|
|
279
|
+
"project_root",
|
|
280
|
+
None,
|
|
281
|
+
)
|
|
282
|
+
or self.project_root
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
if not os.path.isabs(file_path) and base_root:
|
|
286
|
+
resolved_path = os.path.realpath(os.path.join(base_root, file_path))
|
|
287
|
+
else:
|
|
288
|
+
resolved_path = file_path
|
|
289
|
+
|
|
274
290
|
# Security validation
|
|
275
|
-
is_valid, error_msg = self.security_validator.validate_file_path(
|
|
291
|
+
is_valid, error_msg = self.security_validator.validate_file_path(
|
|
292
|
+
resolved_path
|
|
293
|
+
)
|
|
276
294
|
if not is_valid:
|
|
277
295
|
self.logger.warning(
|
|
278
296
|
f"Security validation failed for file path: {file_path} - {error_msg}"
|
|
@@ -292,20 +310,20 @@ class TableFormatTool:
|
|
|
292
310
|
)
|
|
293
311
|
|
|
294
312
|
# Validate file exists
|
|
295
|
-
if not Path(
|
|
313
|
+
if not Path(resolved_path).exists():
|
|
296
314
|
# Tests expect FileNotFoundError here
|
|
297
315
|
raise FileNotFoundError(f"File not found: {file_path}")
|
|
298
316
|
|
|
299
317
|
# Detect language if not provided
|
|
300
318
|
if not language:
|
|
301
|
-
language = detect_language_from_file(
|
|
319
|
+
language = detect_language_from_file(resolved_path)
|
|
302
320
|
|
|
303
321
|
# Use performance monitoring
|
|
304
322
|
monitor = get_performance_monitor()
|
|
305
323
|
with monitor.measure_operation("code_structure_analysis"):
|
|
306
324
|
# Analyze structure using the unified analysis engine
|
|
307
325
|
request = AnalysisRequest(
|
|
308
|
-
file_path=
|
|
326
|
+
file_path=resolved_path,
|
|
309
327
|
language=language,
|
|
310
328
|
include_complexity=True,
|
|
311
329
|
include_details=True,
|