tree-sitter-analyzer 0.9.3__py3-none-any.whl → 0.9.5__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.

Files changed (33) hide show
  1. tree_sitter_analyzer/cli/commands/default_command.py +18 -18
  2. tree_sitter_analyzer/cli/commands/partial_read_command.py +139 -141
  3. tree_sitter_analyzer/cli/commands/query_command.py +92 -88
  4. tree_sitter_analyzer/cli/commands/table_command.py +235 -235
  5. tree_sitter_analyzer/cli/info_commands.py +121 -121
  6. tree_sitter_analyzer/cli_main.py +307 -307
  7. tree_sitter_analyzer/core/analysis_engine.py +584 -584
  8. tree_sitter_analyzer/core/cache_service.py +5 -4
  9. tree_sitter_analyzer/core/query.py +502 -502
  10. tree_sitter_analyzer/encoding_utils.py +9 -2
  11. tree_sitter_analyzer/exceptions.py +400 -406
  12. tree_sitter_analyzer/formatters/java_formatter.py +291 -291
  13. tree_sitter_analyzer/formatters/python_formatter.py +259 -259
  14. tree_sitter_analyzer/interfaces/mcp_server.py +426 -425
  15. tree_sitter_analyzer/language_detector.py +398 -398
  16. tree_sitter_analyzer/language_loader.py +224 -224
  17. tree_sitter_analyzer/languages/java_plugin.py +1202 -1202
  18. tree_sitter_analyzer/mcp/resources/project_stats_resource.py +559 -555
  19. tree_sitter_analyzer/mcp/server.py +30 -9
  20. tree_sitter_analyzer/mcp/tools/read_partial_tool.py +21 -4
  21. tree_sitter_analyzer/mcp/tools/table_format_tool.py +22 -4
  22. tree_sitter_analyzer/mcp/utils/error_handler.py +569 -567
  23. tree_sitter_analyzer/models.py +470 -470
  24. tree_sitter_analyzer/security/__init__.py +22 -22
  25. tree_sitter_analyzer/security/boundary_manager.py +251 -243
  26. tree_sitter_analyzer/security/regex_checker.py +297 -292
  27. tree_sitter_analyzer/table_formatter.py +708 -652
  28. tree_sitter_analyzer/utils.py +61 -19
  29. tree_sitter_analyzer-0.9.5.dist-info/METADATA +567 -0
  30. {tree_sitter_analyzer-0.9.3.dist-info → tree_sitter_analyzer-0.9.5.dist-info}/RECORD +32 -32
  31. tree_sitter_analyzer-0.9.3.dist-info/METADATA +0 -409
  32. {tree_sitter_analyzer-0.9.3.dist-info → tree_sitter_analyzer-0.9.5.dist-info}/WHEEL +0 -0
  33. {tree_sitter_analyzer-0.9.3.dist-info → tree_sitter_analyzer-0.9.5.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(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(file_path).exists():
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(file_path)
171
+ language = detect_language_from_file(resolved_path)
159
172
 
160
173
  # Create analysis request
161
174
  request = AnalysisRequest(
162
- file_path=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
- if not self.security_validator.validate_file_path(file_path):
336
- raise ValueError(f"Invalid or unsafe file path: {file_path}")
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, it's safe to ignore
472
- pass
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
- # Security validation
108
- is_valid, error_msg = self.security_validator.validate_file_path(file_path)
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(file_path).exists():
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
- file_path, start_line, end_line, start_column, end_column
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(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(file_path).exists():
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(file_path)
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=file_path,
326
+ file_path=resolved_path,
309
327
  language=language,
310
328
  include_complexity=True,
311
329
  include_details=True,