tree-sitter-analyzer 0.8.3__py3-none-any.whl → 0.9.2__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 (62) hide show
  1. tree_sitter_analyzer/__init__.py +132 -132
  2. tree_sitter_analyzer/__main__.py +11 -11
  3. tree_sitter_analyzer/api.py +533 -533
  4. tree_sitter_analyzer/cli/__init__.py +39 -39
  5. tree_sitter_analyzer/cli/__main__.py +12 -12
  6. tree_sitter_analyzer/cli/commands/__init__.py +26 -26
  7. tree_sitter_analyzer/cli/commands/advanced_command.py +88 -88
  8. tree_sitter_analyzer/cli/commands/base_command.py +182 -180
  9. tree_sitter_analyzer/cli/commands/structure_command.py +138 -138
  10. tree_sitter_analyzer/cli/commands/summary_command.py +101 -101
  11. tree_sitter_analyzer/core/__init__.py +15 -15
  12. tree_sitter_analyzer/core/analysis_engine.py +74 -78
  13. tree_sitter_analyzer/core/cache_service.py +320 -320
  14. tree_sitter_analyzer/core/engine.py +566 -566
  15. tree_sitter_analyzer/core/parser.py +293 -293
  16. tree_sitter_analyzer/encoding_utils.py +459 -459
  17. tree_sitter_analyzer/file_handler.py +210 -210
  18. tree_sitter_analyzer/formatters/__init__.py +1 -1
  19. tree_sitter_analyzer/formatters/base_formatter.py +167 -167
  20. tree_sitter_analyzer/formatters/formatter_factory.py +78 -78
  21. tree_sitter_analyzer/formatters/java_formatter.py +18 -18
  22. tree_sitter_analyzer/formatters/python_formatter.py +19 -19
  23. tree_sitter_analyzer/interfaces/__init__.py +9 -9
  24. tree_sitter_analyzer/interfaces/cli.py +528 -528
  25. tree_sitter_analyzer/interfaces/cli_adapter.py +344 -343
  26. tree_sitter_analyzer/interfaces/mcp_adapter.py +206 -206
  27. tree_sitter_analyzer/language_detector.py +53 -53
  28. tree_sitter_analyzer/languages/__init__.py +10 -10
  29. tree_sitter_analyzer/languages/java_plugin.py +1 -1
  30. tree_sitter_analyzer/languages/javascript_plugin.py +446 -446
  31. tree_sitter_analyzer/languages/python_plugin.py +755 -755
  32. tree_sitter_analyzer/mcp/__init__.py +34 -31
  33. tree_sitter_analyzer/mcp/resources/__init__.py +44 -44
  34. tree_sitter_analyzer/mcp/resources/code_file_resource.py +209 -209
  35. tree_sitter_analyzer/mcp/server.py +623 -436
  36. tree_sitter_analyzer/mcp/tools/__init__.py +30 -30
  37. tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py +10 -6
  38. tree_sitter_analyzer/mcp/tools/analyze_scale_tool_cli_compatible.py +247 -242
  39. tree_sitter_analyzer/mcp/tools/base_tool.py +54 -54
  40. tree_sitter_analyzer/mcp/tools/read_partial_tool.py +310 -308
  41. tree_sitter_analyzer/mcp/tools/table_format_tool.py +386 -379
  42. tree_sitter_analyzer/mcp/tools/universal_analyze_tool.py +563 -559
  43. tree_sitter_analyzer/mcp/utils/__init__.py +107 -107
  44. tree_sitter_analyzer/models.py +10 -10
  45. tree_sitter_analyzer/output_manager.py +253 -253
  46. tree_sitter_analyzer/plugins/__init__.py +280 -280
  47. tree_sitter_analyzer/plugins/base.py +529 -529
  48. tree_sitter_analyzer/plugins/manager.py +379 -379
  49. tree_sitter_analyzer/queries/__init__.py +26 -26
  50. tree_sitter_analyzer/queries/java.py +391 -391
  51. tree_sitter_analyzer/queries/javascript.py +148 -148
  52. tree_sitter_analyzer/queries/python.py +285 -285
  53. tree_sitter_analyzer/queries/typescript.py +229 -229
  54. tree_sitter_analyzer/query_loader.py +257 -257
  55. tree_sitter_analyzer/security/boundary_manager.py +237 -279
  56. tree_sitter_analyzer/security/validator.py +60 -58
  57. tree_sitter_analyzer/utils.py +294 -277
  58. {tree_sitter_analyzer-0.8.3.dist-info → tree_sitter_analyzer-0.9.2.dist-info}/METADATA +28 -19
  59. tree_sitter_analyzer-0.9.2.dist-info/RECORD +77 -0
  60. {tree_sitter_analyzer-0.8.3.dist-info → tree_sitter_analyzer-0.9.2.dist-info}/entry_points.txt +1 -0
  61. tree_sitter_analyzer-0.8.3.dist-info/RECORD +0 -77
  62. {tree_sitter_analyzer-0.8.3.dist-info → tree_sitter_analyzer-0.9.2.dist-info}/WHEEL +0 -0
@@ -8,8 +8,6 @@ ValidationHelper but enhanced for tree-sitter analyzer's requirements.
8
8
 
9
9
  import os
10
10
  import re
11
- from pathlib import Path
12
- from typing import Optional, Tuple
13
11
 
14
12
  from ..exceptions import SecurityError
15
13
  from ..utils import log_debug, log_warning
@@ -20,10 +18,10 @@ from .regex_checker import RegexSafetyChecker
20
18
  class SecurityValidator:
21
19
  """
22
20
  Unified security validation framework.
23
-
21
+
24
22
  This class provides comprehensive security validation for file paths,
25
23
  regex patterns, and other user inputs to prevent security vulnerabilities.
26
-
24
+
27
25
  Features:
28
26
  - Multi-layer path traversal protection
29
27
  - Project boundary enforcement
@@ -31,10 +29,10 @@ class SecurityValidator:
31
29
  - Input sanitization
32
30
  """
33
31
 
34
- def __init__(self, project_root: Optional[str] = None) -> None:
32
+ def __init__(self, project_root: str | None = None) -> None:
35
33
  """
36
34
  Initialize security validator.
37
-
35
+
38
36
  Args:
39
37
  project_root: Optional project root directory for boundary checks
40
38
  """
@@ -42,25 +40,25 @@ class SecurityValidator:
42
40
  ProjectBoundaryManager(project_root) if project_root else None
43
41
  )
44
42
  self.regex_checker = RegexSafetyChecker()
45
-
43
+
46
44
  log_debug(f"SecurityValidator initialized with project_root: {project_root}")
47
45
 
48
46
  def validate_file_path(
49
- self, file_path: str, base_path: Optional[str] = None
50
- ) -> Tuple[bool, str]:
47
+ self, file_path: str, base_path: str | None = None
48
+ ) -> tuple[bool, str]:
51
49
  """
52
50
  Validate file path with comprehensive security checks.
53
-
51
+
54
52
  Implements multi-layer defense against path traversal attacks
55
53
  and ensures file access stays within project boundaries.
56
-
54
+
57
55
  Args:
58
56
  file_path: File path to validate
59
57
  base_path: Optional base path for relative path validation
60
-
58
+
61
59
  Returns:
62
60
  Tuple of (is_valid, error_message)
63
-
61
+
64
62
  Example:
65
63
  >>> validator = SecurityValidator("/project/root")
66
64
  >>> is_valid, error = validator.validate_file_path("src/main.py")
@@ -70,71 +68,75 @@ class SecurityValidator:
70
68
  # Layer 1: Basic input validation
71
69
  if not file_path or not isinstance(file_path, str):
72
70
  return False, "File path must be a non-empty string"
73
-
71
+
74
72
  # Layer 2: Null byte injection check
75
73
  if "\x00" in file_path:
76
74
  log_warning(f"Null byte detected in file path: {file_path}")
77
75
  return False, "File path contains null bytes"
78
-
76
+
79
77
  # Layer 3: Windows drive letter check (only on non-Windows systems)
80
- if len(file_path) > 1 and file_path[1] == ":" and os.name != 'nt':
78
+ if len(file_path) > 1 and file_path[1] == ":" and os.name != "nt":
81
79
  return False, "Windows drive letters are not allowed on this system"
82
80
 
83
- # Layer 4: Absolute path check (handle Windows leading slash/backslash explicitly)
84
- is_abs = os.path.isabs(file_path) or (
85
- os.name == 'nt' and (file_path.startswith('/') or file_path.startswith('\\'))
86
- )
87
- if is_abs:
88
- # If we have a project root, check if the absolute path is within it
81
+ # Layer 4: Absolute path check (cross-platform)
82
+ if os.path.isabs(file_path) or file_path.startswith(("/", "\\")):
83
+ # If project boundaries are configured, enforce them strictly
89
84
  if self.boundary_manager and self.boundary_manager.project_root:
90
85
  if not self.boundary_manager.is_within_project(file_path):
91
86
  return False, "Absolute path must be within project directory"
87
+ # Within project
88
+ return True, ""
92
89
  else:
93
- # In test environments (temp directories), allow absolute paths
90
+ # In test/dev contexts without project boundaries, allow absolute
91
+ # paths under system temp folder only (safe sandbox)
94
92
  import tempfile
95
- temp_dir = tempfile.gettempdir()
96
- if file_path.startswith(temp_dir):
93
+
94
+ temp_dir = os.path.realpath(tempfile.gettempdir())
95
+ real_path = os.path.realpath(file_path)
96
+ if real_path.startswith(temp_dir + os.sep) or real_path == temp_dir:
97
97
  return True, ""
98
- # No project root defined, reject all other absolute paths
99
98
  return False, "Absolute file paths are not allowed"
100
-
99
+
101
100
  # Layer 5: Path normalization and traversal check
102
101
  norm_path = os.path.normpath(file_path)
103
102
  if "..\\" in norm_path or "../" in norm_path or norm_path.startswith(".."):
104
103
  log_warning(f"Path traversal attempt detected: {file_path}")
105
104
  return False, "Directory traversal not allowed"
106
-
105
+
107
106
  # Layer 6: Project boundary validation
108
107
  if self.boundary_manager and base_path:
109
108
  if not self.boundary_manager.is_within_project(
110
109
  os.path.join(base_path, norm_path)
111
110
  ):
112
- return False, "Access denied. File path must be within project directory"
113
-
111
+ return (
112
+ False,
113
+ "Access denied. File path must be within project directory",
114
+ )
115
+
114
116
  # Layer 7: Symbolic link check (if file exists)
115
117
  if base_path:
116
118
  full_path = os.path.join(base_path, norm_path)
117
119
  if os.path.exists(full_path) and os.path.islink(full_path):
118
120
  log_warning(f"Symbolic link detected: {full_path}")
119
121
  return False, "Symbolic links are not allowed"
120
-
122
+
121
123
  log_debug(f"File path validation passed: {file_path}")
122
124
  return True, ""
123
-
125
+
124
126
  except Exception as e:
125
127
  log_warning(f"File path validation error: {e}")
126
128
  return False, f"Validation error: {str(e)}"
127
129
 
128
130
  def validate_directory_path(
129
131
  self, dir_path: str, must_exist: bool = True
130
- ) -> Tuple[bool, str]:
132
+ ) -> tuple[bool, str]:
131
133
  """
132
134
  Validate directory path for security and existence.
133
-
135
+
134
136
  Args:
135
137
  dir_path: Directory path to validate
136
138
  must_exist: Whether directory must exist
137
-
139
+
138
140
  Returns:
139
141
  Tuple of (is_valid, error_message)
140
142
  """
@@ -143,29 +145,29 @@ class SecurityValidator:
143
145
  is_valid, error = self.validate_file_path(dir_path)
144
146
  if not is_valid:
145
147
  return False, error
146
-
148
+
147
149
  # Check if path exists and is directory
148
150
  if must_exist:
149
151
  if not os.path.exists(dir_path):
150
152
  return False, f"Directory does not exist: {dir_path}"
151
-
153
+
152
154
  if not os.path.isdir(dir_path):
153
155
  return False, f"Path is not a directory: {dir_path}"
154
-
156
+
155
157
  log_debug(f"Directory path validation passed: {dir_path}")
156
158
  return True, ""
157
-
159
+
158
160
  except Exception as e:
159
161
  log_warning(f"Directory path validation error: {e}")
160
162
  return False, f"Validation error: {str(e)}"
161
163
 
162
- def validate_regex_pattern(self, pattern: str) -> Tuple[bool, str]:
164
+ def validate_regex_pattern(self, pattern: str) -> tuple[bool, str]:
163
165
  """
164
166
  Validate regex pattern for ReDoS attack prevention.
165
-
167
+
166
168
  Args:
167
169
  pattern: Regex pattern to validate
168
-
170
+
169
171
  Returns:
170
172
  Tuple of (is_valid, error_message)
171
173
  """
@@ -174,31 +176,31 @@ class SecurityValidator:
174
176
  def sanitize_input(self, user_input: str, max_length: int = 1000) -> str:
175
177
  """
176
178
  Sanitize user input by removing dangerous characters.
177
-
179
+
178
180
  Args:
179
181
  user_input: Input string to sanitize
180
182
  max_length: Maximum allowed length
181
-
183
+
182
184
  Returns:
183
185
  Sanitized input string
184
-
186
+
185
187
  Raises:
186
188
  SecurityError: If input is too long or contains dangerous content
187
189
  """
188
190
  if not isinstance(user_input, str):
189
191
  raise SecurityError("Input must be a string")
190
-
192
+
191
193
  if len(user_input) > max_length:
192
194
  raise SecurityError(f"Input too long: {len(user_input)} > {max_length}")
193
-
195
+
194
196
  # Remove null bytes and control characters
195
- sanitized = re.sub(r'[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]', '', user_input)
197
+ sanitized = re.sub(r"[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]", "", user_input)
196
198
 
197
199
  # Remove HTML/XML tags for XSS prevention
198
- sanitized = re.sub(r'<[^>]*>', '', sanitized)
200
+ sanitized = re.sub(r"<[^>]*>", "", sanitized)
199
201
 
200
202
  # Remove potentially dangerous characters
201
- sanitized = re.sub(r'[<>"\']', '', sanitized)
203
+ sanitized = re.sub(r'[<>"\']', "", sanitized)
202
204
 
203
205
  # Log if sanitization occurred
204
206
  if sanitized != user_input:
@@ -206,13 +208,13 @@ class SecurityValidator:
206
208
 
207
209
  return sanitized
208
210
 
209
- def validate_glob_pattern(self, pattern: str) -> Tuple[bool, str]:
211
+ def validate_glob_pattern(self, pattern: str) -> tuple[bool, str]:
210
212
  """
211
213
  Validate glob pattern for safe file matching.
212
-
214
+
213
215
  Args:
214
216
  pattern: Glob pattern to validate
215
-
217
+
216
218
  Returns:
217
219
  Tuple of (is_valid, error_message)
218
220
  """
@@ -220,25 +222,25 @@ class SecurityValidator:
220
222
  # Basic input validation
221
223
  if not pattern or not isinstance(pattern, str):
222
224
  return False, "Pattern must be a non-empty string"
223
-
225
+
224
226
  # Check for dangerous patterns
225
227
  dangerous_patterns = [
226
228
  "..", # Path traversal
227
229
  "//", # Double slashes
228
230
  "\\\\", # Double backslashes
229
231
  ]
230
-
232
+
231
233
  for dangerous in dangerous_patterns:
232
234
  if dangerous in pattern:
233
235
  return False, f"Dangerous pattern detected: {dangerous}"
234
-
236
+
235
237
  # Validate length
236
238
  if len(pattern) > 500:
237
239
  return False, "Pattern too long"
238
-
240
+
239
241
  log_debug(f"Glob pattern validation passed: {pattern}")
240
242
  return True, ""
241
-
243
+
242
244
  except Exception as e:
243
245
  log_warning(f"Glob pattern validation error: {e}")
244
246
  return False, f"Validation error: {str(e)}"