tree-sitter-analyzer 0.1.3__py3-none-any.whl → 0.3.0__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 (79) hide show
  1. tree_sitter_analyzer/__init__.py +133 -121
  2. tree_sitter_analyzer/__main__.py +11 -12
  3. tree_sitter_analyzer/api.py +531 -539
  4. tree_sitter_analyzer/cli/__init__.py +39 -39
  5. tree_sitter_analyzer/cli/__main__.py +12 -13
  6. tree_sitter_analyzer/cli/commands/__init__.py +26 -27
  7. tree_sitter_analyzer/cli/commands/advanced_command.py +88 -88
  8. tree_sitter_analyzer/cli/commands/base_command.py +160 -155
  9. tree_sitter_analyzer/cli/commands/default_command.py +18 -19
  10. tree_sitter_analyzer/cli/commands/partial_read_command.py +141 -133
  11. tree_sitter_analyzer/cli/commands/query_command.py +81 -82
  12. tree_sitter_analyzer/cli/commands/structure_command.py +138 -121
  13. tree_sitter_analyzer/cli/commands/summary_command.py +101 -93
  14. tree_sitter_analyzer/cli/commands/table_command.py +232 -233
  15. tree_sitter_analyzer/cli/info_commands.py +120 -121
  16. tree_sitter_analyzer/cli_main.py +277 -276
  17. tree_sitter_analyzer/core/__init__.py +15 -20
  18. tree_sitter_analyzer/core/analysis_engine.py +591 -574
  19. tree_sitter_analyzer/core/cache_service.py +320 -330
  20. tree_sitter_analyzer/core/engine.py +557 -560
  21. tree_sitter_analyzer/core/parser.py +293 -288
  22. tree_sitter_analyzer/core/query.py +494 -502
  23. tree_sitter_analyzer/encoding_utils.py +458 -460
  24. tree_sitter_analyzer/exceptions.py +337 -340
  25. tree_sitter_analyzer/file_handler.py +217 -222
  26. tree_sitter_analyzer/formatters/__init__.py +1 -1
  27. tree_sitter_analyzer/formatters/base_formatter.py +167 -168
  28. tree_sitter_analyzer/formatters/formatter_factory.py +78 -74
  29. tree_sitter_analyzer/formatters/java_formatter.py +287 -270
  30. tree_sitter_analyzer/formatters/python_formatter.py +255 -235
  31. tree_sitter_analyzer/interfaces/__init__.py +9 -10
  32. tree_sitter_analyzer/interfaces/cli.py +528 -557
  33. tree_sitter_analyzer/interfaces/cli_adapter.py +322 -319
  34. tree_sitter_analyzer/interfaces/mcp_adapter.py +180 -170
  35. tree_sitter_analyzer/interfaces/mcp_server.py +405 -416
  36. tree_sitter_analyzer/java_analyzer.py +218 -219
  37. tree_sitter_analyzer/language_detector.py +398 -400
  38. tree_sitter_analyzer/language_loader.py +224 -228
  39. tree_sitter_analyzer/languages/__init__.py +10 -11
  40. tree_sitter_analyzer/languages/java_plugin.py +1129 -1113
  41. tree_sitter_analyzer/languages/python_plugin.py +737 -712
  42. tree_sitter_analyzer/mcp/__init__.py +31 -32
  43. tree_sitter_analyzer/mcp/resources/__init__.py +44 -47
  44. tree_sitter_analyzer/mcp/resources/code_file_resource.py +212 -213
  45. tree_sitter_analyzer/mcp/resources/project_stats_resource.py +560 -550
  46. tree_sitter_analyzer/mcp/server.py +333 -345
  47. tree_sitter_analyzer/mcp/tools/__init__.py +30 -31
  48. tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py +621 -557
  49. tree_sitter_analyzer/mcp/tools/analyze_scale_tool_cli_compatible.py +242 -245
  50. tree_sitter_analyzer/mcp/tools/base_tool.py +54 -55
  51. tree_sitter_analyzer/mcp/tools/read_partial_tool.py +300 -302
  52. tree_sitter_analyzer/mcp/tools/table_format_tool.py +362 -359
  53. tree_sitter_analyzer/mcp/tools/universal_analyze_tool.py +543 -476
  54. tree_sitter_analyzer/mcp/utils/__init__.py +105 -106
  55. tree_sitter_analyzer/mcp/utils/error_handler.py +549 -549
  56. tree_sitter_analyzer/models.py +470 -481
  57. tree_sitter_analyzer/output_manager.py +261 -264
  58. tree_sitter_analyzer/plugins/__init__.py +333 -334
  59. tree_sitter_analyzer/plugins/base.py +477 -446
  60. tree_sitter_analyzer/plugins/java_plugin.py +608 -625
  61. tree_sitter_analyzer/plugins/javascript_plugin.py +446 -439
  62. tree_sitter_analyzer/plugins/manager.py +362 -355
  63. tree_sitter_analyzer/plugins/plugin_loader.py +85 -83
  64. tree_sitter_analyzer/plugins/python_plugin.py +606 -598
  65. tree_sitter_analyzer/plugins/registry.py +374 -366
  66. tree_sitter_analyzer/queries/__init__.py +26 -27
  67. tree_sitter_analyzer/queries/java.py +391 -394
  68. tree_sitter_analyzer/queries/javascript.py +148 -149
  69. tree_sitter_analyzer/queries/python.py +285 -286
  70. tree_sitter_analyzer/queries/typescript.py +229 -230
  71. tree_sitter_analyzer/query_loader.py +254 -260
  72. tree_sitter_analyzer/table_formatter.py +468 -448
  73. tree_sitter_analyzer/utils.py +277 -277
  74. tree_sitter_analyzer-0.3.0.dist-info/METADATA +346 -0
  75. tree_sitter_analyzer-0.3.0.dist-info/RECORD +77 -0
  76. tree_sitter_analyzer-0.1.3.dist-info/METADATA +0 -444
  77. tree_sitter_analyzer-0.1.3.dist-info/RECORD +0 -77
  78. {tree_sitter_analyzer-0.1.3.dist-info → tree_sitter_analyzer-0.3.0.dist-info}/WHEEL +0 -0
  79. {tree_sitter_analyzer-0.1.3.dist-info → tree_sitter_analyzer-0.3.0.dist-info}/entry_points.txt +0 -0
@@ -1,340 +1,337 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """
4
- Tree-sitter Analyzer Custom Exceptions
5
-
6
- Unified exception handling system for consistent error management
7
- across the entire framework.
8
- """
9
-
10
- from typing import Any, Dict, Optional, Union
11
- from pathlib import Path
12
-
13
-
14
- class TreeSitterAnalyzerError(Exception):
15
- """Base exception for all tree-sitter analyzer errors."""
16
-
17
- def __init__(
18
- self,
19
- message: str,
20
- error_code: Optional[str] = None,
21
- context: Optional[Dict[str, Any]] = None
22
- ) -> None:
23
- super().__init__(message)
24
- self.message = message
25
- self.error_code = error_code or self.__class__.__name__
26
- self.context = context or {}
27
-
28
- def to_dict(self) -> Dict[str, Any]:
29
- """Convert exception to dictionary format."""
30
- return {
31
- "error_type": self.__class__.__name__,
32
- "error_code": self.error_code,
33
- "message": self.message,
34
- "context": self.context
35
- }
36
-
37
-
38
- class AnalysisError(TreeSitterAnalyzerError):
39
- """Raised when file analysis fails."""
40
-
41
- def __init__(
42
- self,
43
- message: str,
44
- file_path: Optional[Union[str, Path]] = None,
45
- language: Optional[str] = None,
46
- **kwargs
47
- ) -> None:
48
- context = kwargs.get('context', {})
49
- if file_path:
50
- context['file_path'] = str(file_path)
51
- if language:
52
- context['language'] = language
53
- super().__init__(message, context=context, **kwargs)
54
-
55
-
56
- class ParseError(TreeSitterAnalyzerError):
57
- """Raised when parsing fails."""
58
-
59
- def __init__(
60
- self,
61
- message: str,
62
- language: Optional[str] = None,
63
- source_info: Optional[Dict[str, Any]] = None,
64
- **kwargs
65
- ) -> None:
66
- context = kwargs.get('context', {})
67
- if language:
68
- context['language'] = language
69
- if source_info:
70
- context.update(source_info)
71
- super().__init__(message, context=context, **kwargs)
72
-
73
-
74
- class LanguageNotSupportedError(TreeSitterAnalyzerError):
75
- """Raised when a language is not supported."""
76
-
77
- def __init__(
78
- self,
79
- language: str,
80
- supported_languages: Optional[list] = None,
81
- **kwargs
82
- ) -> None:
83
- message = f"Language '{language}' is not supported"
84
- context = kwargs.get('context', {})
85
- context['language'] = language
86
- if supported_languages:
87
- context['supported_languages'] = supported_languages
88
- message += f". Supported languages: {', '.join(supported_languages)}"
89
- super().__init__(message, context=context, **kwargs)
90
-
91
-
92
- class PluginError(TreeSitterAnalyzerError):
93
- """Raised when plugin operations fail."""
94
-
95
- def __init__(
96
- self,
97
- message: str,
98
- plugin_name: Optional[str] = None,
99
- operation: Optional[str] = None,
100
- **kwargs
101
- ) -> None:
102
- context = kwargs.get('context', {})
103
- if plugin_name:
104
- context['plugin_name'] = plugin_name
105
- if operation:
106
- context['operation'] = operation
107
- super().__init__(message, context=context, **kwargs)
108
-
109
-
110
- class QueryError(TreeSitterAnalyzerError):
111
- """Raised when query execution fails."""
112
-
113
- def __init__(
114
- self,
115
- message: str,
116
- query_name: Optional[str] = None,
117
- query_string: Optional[str] = None,
118
- language: Optional[str] = None,
119
- **kwargs
120
- ) -> None:
121
- context = kwargs.get('context', {})
122
- if query_name:
123
- context['query_name'] = query_name
124
- if query_string:
125
- context['query_string'] = query_string
126
- if language:
127
- context['language'] = language
128
- super().__init__(message, context=context, **kwargs)
129
-
130
-
131
- class FileHandlingError(TreeSitterAnalyzerError):
132
- """Raised when file operations fail."""
133
-
134
- def __init__(
135
- self,
136
- message: str,
137
- file_path: Optional[Union[str, Path]] = None,
138
- operation: Optional[str] = None,
139
- **kwargs
140
- ) -> None:
141
- context = kwargs.get('context', {})
142
- if file_path:
143
- context['file_path'] = str(file_path)
144
- if operation:
145
- context['operation'] = operation
146
- super().__init__(message, context=context, **kwargs)
147
-
148
-
149
- class ConfigurationError(TreeSitterAnalyzerError):
150
- """Raised when configuration is invalid."""
151
-
152
- def __init__(
153
- self,
154
- message: str,
155
- config_key: Optional[str] = None,
156
- config_value: Optional[Any] = None,
157
- **kwargs
158
- ) -> None:
159
- context = kwargs.get('context', {})
160
- if config_key:
161
- context['config_key'] = config_key
162
- if config_value is not None:
163
- context['config_value'] = config_value
164
- super().__init__(message, context=context, **kwargs)
165
-
166
-
167
- class ValidationError(TreeSitterAnalyzerError):
168
- """Raised when validation fails."""
169
-
170
- def __init__(
171
- self,
172
- message: str,
173
- validation_type: Optional[str] = None,
174
- invalid_value: Optional[Any] = None,
175
- **kwargs
176
- ) -> None:
177
- context = kwargs.get('context', {})
178
- if validation_type:
179
- context['validation_type'] = validation_type
180
- if invalid_value is not None:
181
- context['invalid_value'] = invalid_value
182
- super().__init__(message, context=context, **kwargs)
183
-
184
-
185
- class MCPError(TreeSitterAnalyzerError):
186
- """Raised when MCP operations fail."""
187
-
188
- def __init__(
189
- self,
190
- message: str,
191
- tool_name: Optional[str] = None,
192
- resource_uri: Optional[str] = None,
193
- **kwargs
194
- ) -> None:
195
- context = kwargs.get('context', {})
196
- if tool_name:
197
- context['tool_name'] = tool_name
198
- if resource_uri:
199
- context['resource_uri'] = resource_uri
200
- super().__init__(message, context=context, **kwargs)
201
-
202
-
203
- # Exception handling utilities
204
- def handle_exception(
205
- exception: Exception,
206
- context: Optional[Dict[str, Any]] = None,
207
- reraise_as: Optional[type] = None
208
- ) -> None:
209
- """
210
- Handle exceptions with optional context and re-raising.
211
-
212
- Args:
213
- exception: The original exception
214
- context: Additional context information
215
- reraise_as: Exception class to re-raise as
216
- """
217
- from .utils import log_error
218
-
219
- # Log the original exception
220
- error_context = context or {}
221
- if hasattr(exception, 'context'):
222
- error_context.update(exception.context)
223
-
224
- log_error(f"Exception handled: {exception}", extra=error_context)
225
-
226
- # Re-raise as different exception type if requested
227
- if reraise_as and not isinstance(exception, reraise_as):
228
- if issubclass(reraise_as, TreeSitterAnalyzerError):
229
- raise reraise_as(str(exception), context=error_context)
230
- else:
231
- raise reraise_as(str(exception))
232
-
233
- # Re-raise original exception
234
- raise exception
235
-
236
-
237
- def safe_execute(
238
- func,
239
- *args,
240
- default_return=None,
241
- exception_types: tuple = (Exception,),
242
- log_errors: bool = True,
243
- **kwargs
244
- ):
245
- """
246
- Safely execute a function with exception handling.
247
-
248
- Args:
249
- func: Function to execute
250
- *args: Function arguments
251
- default_return: Value to return on exception
252
- exception_types: Exception types to catch
253
- log_errors: Whether to log errors
254
- **kwargs: Function keyword arguments
255
-
256
- Returns:
257
- Function result or default_return on exception
258
- """
259
- try:
260
- return func(*args, **kwargs)
261
- except exception_types as e:
262
- if log_errors:
263
- from .utils import log_error
264
- log_error(f"Safe execution failed for {func.__name__}: {e}")
265
- return default_return
266
-
267
-
268
- def create_error_response(
269
- exception: Exception,
270
- include_traceback: bool = False
271
- ) -> Dict[str, Any]:
272
- """
273
- Create standardized error response dictionary.
274
-
275
- Args:
276
- exception: The exception to convert
277
- include_traceback: Whether to include traceback
278
-
279
- Returns:
280
- Error response dictionary
281
- """
282
- import traceback
283
-
284
- response = {
285
- "success": False,
286
- "error": {
287
- "type": exception.__class__.__name__,
288
- "message": str(exception)
289
- }
290
- }
291
-
292
- # Add context if available
293
- if hasattr(exception, 'context'):
294
- response["error"]["context"] = exception.context
295
-
296
- # Add error code if available
297
- if hasattr(exception, 'error_code'):
298
- response["error"]["code"] = exception.error_code
299
-
300
- # Add traceback if requested
301
- if include_traceback:
302
- response["error"]["traceback"] = traceback.format_exc()
303
-
304
- return response
305
-
306
-
307
- # Decorator for exception handling
308
- def handle_exceptions(
309
- default_return=None,
310
- exception_types: tuple = (Exception,),
311
- reraise_as: Optional[type] = None,
312
- log_errors: bool = True
313
- ):
314
- """
315
- Decorator for automatic exception handling.
316
-
317
- Args:
318
- default_return: Value to return on exception
319
- exception_types: Exception types to catch
320
- reraise_as: Exception class to re-raise as
321
- log_errors: Whether to log errors
322
- """
323
- def decorator(func):
324
- def wrapper(*args, **kwargs):
325
- try:
326
- return func(*args, **kwargs)
327
- except exception_types as e:
328
- if log_errors:
329
- from .utils import log_error
330
- log_error(f"Exception in {func.__name__}: {e}")
331
-
332
- if reraise_as:
333
- if issubclass(reraise_as, TreeSitterAnalyzerError):
334
- raise reraise_as(str(e))
335
- else:
336
- raise reraise_as(str(e))
337
-
338
- return default_return
339
- return wrapper
340
- return decorator
1
+ #!/usr/bin/env python3
2
+ """
3
+ Tree-sitter Analyzer Custom Exceptions
4
+
5
+ Unified exception handling system for consistent error management
6
+ across the entire framework.
7
+ """
8
+
9
+ from pathlib import Path
10
+ from typing import Any
11
+
12
+
13
+ class TreeSitterAnalyzerError(Exception):
14
+ """Base exception for all tree-sitter analyzer errors."""
15
+
16
+ def __init__(
17
+ self,
18
+ message: str,
19
+ error_code: str | None = None,
20
+ context: dict[str, Any] | None = None,
21
+ ) -> None:
22
+ super().__init__(message)
23
+ self.message = message
24
+ self.error_code = error_code or self.__class__.__name__
25
+ self.context = context or {}
26
+
27
+ def to_dict(self) -> dict[str, Any]:
28
+ """Convert exception to dictionary format."""
29
+ return {
30
+ "error_type": self.__class__.__name__,
31
+ "error_code": self.error_code,
32
+ "message": self.message,
33
+ "context": self.context,
34
+ }
35
+
36
+
37
+ class AnalysisError(TreeSitterAnalyzerError):
38
+ """Raised when file analysis fails."""
39
+
40
+ def __init__(
41
+ self,
42
+ message: str,
43
+ file_path: str | Path | None = None,
44
+ language: str | None = None,
45
+ **kwargs,
46
+ ) -> None:
47
+ context = kwargs.get("context", {})
48
+ if file_path:
49
+ context["file_path"] = str(file_path)
50
+ if language:
51
+ context["language"] = language
52
+ super().__init__(message, context=context, **kwargs)
53
+
54
+
55
+ class ParseError(TreeSitterAnalyzerError):
56
+ """Raised when parsing fails."""
57
+
58
+ def __init__(
59
+ self,
60
+ message: str,
61
+ language: str | None = None,
62
+ source_info: dict[str, Any] | None = None,
63
+ **kwargs,
64
+ ) -> None:
65
+ context = kwargs.get("context", {})
66
+ if language:
67
+ context["language"] = language
68
+ if source_info:
69
+ context.update(source_info)
70
+ super().__init__(message, context=context, **kwargs)
71
+
72
+
73
+ class LanguageNotSupportedError(TreeSitterAnalyzerError):
74
+ """Raised when a language is not supported."""
75
+
76
+ def __init__(
77
+ self, language: str, supported_languages: list | None = None, **kwargs
78
+ ) -> None:
79
+ message = f"Language '{language}' is not supported"
80
+ context = kwargs.get("context", {})
81
+ context["language"] = language
82
+ if supported_languages:
83
+ context["supported_languages"] = supported_languages
84
+ message += f". Supported languages: {', '.join(supported_languages)}"
85
+ super().__init__(message, context=context, **kwargs)
86
+
87
+
88
+ class PluginError(TreeSitterAnalyzerError):
89
+ """Raised when plugin operations fail."""
90
+
91
+ def __init__(
92
+ self,
93
+ message: str,
94
+ plugin_name: str | None = None,
95
+ operation: str | None = None,
96
+ **kwargs,
97
+ ) -> None:
98
+ context = kwargs.get("context", {})
99
+ if plugin_name:
100
+ context["plugin_name"] = plugin_name
101
+ if operation:
102
+ context["operation"] = operation
103
+ super().__init__(message, context=context, **kwargs)
104
+
105
+
106
+ class QueryError(TreeSitterAnalyzerError):
107
+ """Raised when query execution fails."""
108
+
109
+ def __init__(
110
+ self,
111
+ message: str,
112
+ query_name: str | None = None,
113
+ query_string: str | None = None,
114
+ language: str | None = None,
115
+ **kwargs,
116
+ ) -> None:
117
+ context = kwargs.get("context", {})
118
+ if query_name:
119
+ context["query_name"] = query_name
120
+ if query_string:
121
+ context["query_string"] = query_string
122
+ if language:
123
+ context["language"] = language
124
+ super().__init__(message, context=context, **kwargs)
125
+
126
+
127
+ class FileHandlingError(TreeSitterAnalyzerError):
128
+ """Raised when file operations fail."""
129
+
130
+ def __init__(
131
+ self,
132
+ message: str,
133
+ file_path: str | Path | None = None,
134
+ operation: str | None = None,
135
+ **kwargs,
136
+ ) -> None:
137
+ context = kwargs.get("context", {})
138
+ if file_path:
139
+ context["file_path"] = str(file_path)
140
+ if operation:
141
+ context["operation"] = operation
142
+ super().__init__(message, context=context, **kwargs)
143
+
144
+
145
+ class ConfigurationError(TreeSitterAnalyzerError):
146
+ """Raised when configuration is invalid."""
147
+
148
+ def __init__(
149
+ self,
150
+ message: str,
151
+ config_key: str | None = None,
152
+ config_value: Any | None = None,
153
+ **kwargs,
154
+ ) -> None:
155
+ context = kwargs.get("context", {})
156
+ if config_key:
157
+ context["config_key"] = config_key
158
+ if config_value is not None:
159
+ context["config_value"] = config_value
160
+ super().__init__(message, context=context, **kwargs)
161
+
162
+
163
+ class ValidationError(TreeSitterAnalyzerError):
164
+ """Raised when validation fails."""
165
+
166
+ def __init__(
167
+ self,
168
+ message: str,
169
+ validation_type: str | None = None,
170
+ invalid_value: Any | None = None,
171
+ **kwargs,
172
+ ) -> None:
173
+ context = kwargs.get("context", {})
174
+ if validation_type:
175
+ context["validation_type"] = validation_type
176
+ if invalid_value is not None:
177
+ context["invalid_value"] = invalid_value
178
+ super().__init__(message, context=context, **kwargs)
179
+
180
+
181
+ class MCPError(TreeSitterAnalyzerError):
182
+ """Raised when MCP operations fail."""
183
+
184
+ def __init__(
185
+ self,
186
+ message: str,
187
+ tool_name: str | None = None,
188
+ resource_uri: str | None = None,
189
+ **kwargs,
190
+ ) -> None:
191
+ context = kwargs.get("context", {})
192
+ if tool_name:
193
+ context["tool_name"] = tool_name
194
+ if resource_uri:
195
+ context["resource_uri"] = resource_uri
196
+ super().__init__(message, context=context, **kwargs)
197
+
198
+
199
+ # Exception handling utilities
200
+ def handle_exception(
201
+ exception: Exception,
202
+ context: dict[str, Any] | None = None,
203
+ reraise_as: type | None = None,
204
+ ) -> None:
205
+ """
206
+ Handle exceptions with optional context and re-raising.
207
+
208
+ Args:
209
+ exception: The original exception
210
+ context: Additional context information
211
+ reraise_as: Exception class to re-raise as
212
+ """
213
+ from .utils import log_error
214
+
215
+ # Log the original exception
216
+ error_context = context or {}
217
+ if hasattr(exception, "context"):
218
+ error_context.update(exception.context)
219
+
220
+ log_error(f"Exception handled: {exception}", extra=error_context)
221
+
222
+ # Re-raise as different exception type if requested
223
+ if reraise_as and not isinstance(exception, reraise_as):
224
+ if issubclass(reraise_as, TreeSitterAnalyzerError):
225
+ raise reraise_as(str(exception), context=error_context)
226
+ else:
227
+ raise reraise_as(str(exception))
228
+
229
+ # Re-raise original exception
230
+ raise exception
231
+
232
+
233
+ def safe_execute(
234
+ func,
235
+ *args,
236
+ default_return=None,
237
+ exception_types: tuple = (Exception,),
238
+ log_errors: bool = True,
239
+ **kwargs,
240
+ ):
241
+ """
242
+ Safely execute a function with exception handling.
243
+
244
+ Args:
245
+ func: Function to execute
246
+ *args: Function arguments
247
+ default_return: Value to return on exception
248
+ exception_types: Exception types to catch
249
+ log_errors: Whether to log errors
250
+ **kwargs: Function keyword arguments
251
+
252
+ Returns:
253
+ Function result or default_return on exception
254
+ """
255
+ try:
256
+ return func(*args, **kwargs)
257
+ except exception_types as e:
258
+ if log_errors:
259
+ from .utils import log_error
260
+
261
+ log_error(f"Safe execution failed for {func.__name__}: {e}")
262
+ return default_return
263
+
264
+
265
+ def create_error_response(
266
+ exception: Exception, include_traceback: bool = False
267
+ ) -> dict[str, Any]:
268
+ """
269
+ Create standardized error response dictionary.
270
+
271
+ Args:
272
+ exception: The exception to convert
273
+ include_traceback: Whether to include traceback
274
+
275
+ Returns:
276
+ Error response dictionary
277
+ """
278
+ import traceback
279
+
280
+ response = {
281
+ "success": False,
282
+ "error": {"type": exception.__class__.__name__, "message": str(exception)},
283
+ }
284
+
285
+ # Add context if available
286
+ if hasattr(exception, "context"):
287
+ response["error"]["context"] = exception.context
288
+
289
+ # Add error code if available
290
+ if hasattr(exception, "error_code"):
291
+ response["error"]["code"] = exception.error_code
292
+
293
+ # Add traceback if requested
294
+ if include_traceback:
295
+ response["error"]["traceback"] = traceback.format_exc()
296
+
297
+ return response
298
+
299
+
300
+ # Decorator for exception handling
301
+ def handle_exceptions(
302
+ default_return=None,
303
+ exception_types: tuple = (Exception,),
304
+ reraise_as: type | None = None,
305
+ log_errors: bool = True,
306
+ ):
307
+ """
308
+ Decorator for automatic exception handling.
309
+
310
+ Args:
311
+ default_return: Value to return on exception
312
+ exception_types: Exception types to catch
313
+ reraise_as: Exception class to re-raise as
314
+ log_errors: Whether to log errors
315
+ """
316
+
317
+ def decorator(func):
318
+ def wrapper(*args, **kwargs):
319
+ try:
320
+ return func(*args, **kwargs)
321
+ except exception_types as e:
322
+ if log_errors:
323
+ from .utils import log_error
324
+
325
+ log_error(f"Exception in {func.__name__}: {e}")
326
+
327
+ if reraise_as:
328
+ if issubclass(reraise_as, TreeSitterAnalyzerError):
329
+ raise reraise_as(str(e)) from e
330
+ else:
331
+ raise reraise_as(str(e)) from e
332
+
333
+ return default_return
334
+
335
+ return wrapper
336
+
337
+ return decorator