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
@@ -1,293 +1,293 @@
1
- #!/usr/bin/env python3
2
- """
3
- Parser module for tree_sitter_analyzer.core.
4
-
5
- This module provides the Parser class which handles Tree-sitter parsing
6
- operations in the new architecture.
7
- """
8
-
9
- import logging
10
- from pathlib import Path
11
- from typing import Any, NamedTuple
12
-
13
- from tree_sitter import Tree
14
-
15
- from ..encoding_utils import EncodingManager
16
- from ..language_loader import get_loader
17
-
18
- # Configure logging
19
- logger = logging.getLogger(__name__)
20
-
21
-
22
- class ParseResult(NamedTuple):
23
- """
24
- Result of parsing operation containing tree and metadata.
25
-
26
- Attributes:
27
- tree: The parsed Tree-sitter tree (None if parsing failed)
28
- source_code: The source code that was parsed
29
- language: The programming language used for parsing
30
- file_path: Path to the file (if parsing from file)
31
- success: Whether parsing was successful
32
- error_message: Error message if parsing failed
33
- """
34
-
35
- tree: Tree | None
36
- source_code: str
37
- language: str
38
- file_path: str | None
39
- success: bool
40
- error_message: str | None
41
-
42
-
43
- class Parser:
44
- """
45
- Tree-sitter parser wrapper for the new architecture.
46
-
47
- This class provides a unified interface for parsing code files and strings
48
- using Tree-sitter parsers with proper error handling and encoding support.
49
- """
50
-
51
- def __init__(self) -> None:
52
- """Initialize the Parser with language loader."""
53
- self._loader = get_loader()
54
- self._encoding_manager = EncodingManager()
55
- logger.info("Parser initialized successfully")
56
-
57
- def parse_file(self, file_path: str | Path, language: str) -> ParseResult:
58
- """
59
- Parse a source code file.
60
-
61
- Args:
62
- file_path: Path to the file to parse
63
- language: Programming language for parsing
64
-
65
- Returns:
66
- ParseResult containing the parsed tree and metadata
67
- """
68
- file_path_str = str(file_path)
69
-
70
- try:
71
- # Check if file exists
72
- path_obj = Path(file_path_str)
73
- if not path_obj.exists():
74
- return ParseResult(
75
- tree=None,
76
- source_code="",
77
- language=language,
78
- file_path=file_path_str,
79
- success=False,
80
- error_message=f"File not found: {file_path_str}",
81
- )
82
-
83
- # Read file content with encoding detection
84
- try:
85
- source_code, detected_encoding = self._encoding_manager.read_file_safe(
86
- path_obj
87
- )
88
- logger.debug(
89
- f"Read file {file_path_str} with encoding {detected_encoding}"
90
- )
91
- except PermissionError as e:
92
- return ParseResult(
93
- tree=None,
94
- source_code="",
95
- language=language,
96
- file_path=file_path_str,
97
- success=False,
98
- error_message=f"Permission denied: {str(e)}",
99
- )
100
- except Exception as e:
101
- return ParseResult(
102
- tree=None,
103
- source_code="",
104
- language=language,
105
- file_path=file_path_str,
106
- success=False,
107
- error_message=f"Error reading file: {str(e)}",
108
- )
109
-
110
- # Parse the code
111
- return self.parse_code(source_code, language, filename=file_path_str)
112
-
113
- except Exception as e:
114
- logger.error(f"Unexpected error parsing file {file_path_str}: {e}")
115
- return ParseResult(
116
- tree=None,
117
- source_code="",
118
- language=language,
119
- file_path=file_path_str,
120
- success=False,
121
- error_message=f"Unexpected error: {str(e)}",
122
- )
123
-
124
- def parse_code(
125
- self, source_code: str, language: str, filename: str | None = None
126
- ) -> ParseResult:
127
- """
128
- Parse source code string.
129
-
130
- Args:
131
- source_code: The source code to parse
132
- language: Programming language for parsing
133
- filename: Optional filename for metadata
134
-
135
- Returns:
136
- ParseResult containing the parsed tree and metadata
137
- """
138
- try:
139
- # Check if language is supported
140
- if not self.is_language_supported(language):
141
- return ParseResult(
142
- tree=None,
143
- source_code=source_code,
144
- language=language,
145
- file_path=filename,
146
- success=False,
147
- error_message=f"Unsupported language: {language}",
148
- )
149
-
150
- # Create parser for the language
151
- parser = self._loader.create_parser_safely(language)
152
- if parser is None:
153
- return ParseResult(
154
- tree=None,
155
- source_code=source_code,
156
- language=language,
157
- file_path=filename,
158
- success=False,
159
- error_message=f"Failed to create parser for language: {language}",
160
- )
161
-
162
- # Parse the code
163
- source_bytes = self._encoding_manager.safe_encode(source_code)
164
- tree = parser.parse(source_bytes)
165
-
166
- if tree is None:
167
- return ParseResult( # type: ignore[unreachable]
168
- tree=None,
169
- source_code=source_code,
170
- language=language,
171
- file_path=filename,
172
- success=False,
173
- error_message="Parsing failed - tree is None",
174
- )
175
-
176
- logger.debug(f"Successfully parsed {language} code")
177
- return ParseResult(
178
- tree=tree,
179
- source_code=source_code,
180
- language=language,
181
- file_path=filename,
182
- success=True,
183
- error_message=None,
184
- )
185
-
186
- except Exception as e:
187
- logger.error(f"Error parsing {language} code: {e}")
188
- return ParseResult(
189
- tree=None,
190
- source_code=source_code,
191
- language=language,
192
- file_path=filename,
193
- success=False,
194
- error_message=f"Parsing error: {str(e)}",
195
- )
196
-
197
- def is_language_supported(self, language: str) -> bool:
198
- """
199
- Check if a programming language is supported.
200
-
201
- Args:
202
- language: Programming language to check
203
-
204
- Returns:
205
- True if language is supported, False otherwise
206
- """
207
- try:
208
- return self._loader.is_language_available(language)
209
- except Exception as e:
210
- logger.error(f"Error checking language support for {language}: {e}")
211
- return False
212
-
213
- def get_supported_languages(self) -> list[str]:
214
- """
215
- Get list of supported programming languages.
216
-
217
- Returns:
218
- List of supported language names
219
- """
220
- try:
221
- return self._loader.get_supported_languages()
222
- except Exception as e:
223
- logger.error(f"Error getting supported languages: {e}")
224
- return []
225
-
226
- def validate_ast(self, tree: Tree | None) -> bool:
227
- """
228
- Validate an AST tree.
229
-
230
- Args:
231
- tree: Tree-sitter tree to validate
232
-
233
- Returns:
234
- True if tree is valid, False otherwise
235
- """
236
- if tree is None:
237
- return False
238
-
239
- try:
240
- # Basic validation - check if tree has a root node
241
- root_node = tree.root_node
242
- return root_node is not None
243
- except Exception as e:
244
- logger.error(f"Error validating AST: {e}")
245
- return False
246
-
247
- def get_parse_errors(self, tree: Tree) -> list[dict[str, Any]]:
248
- """
249
- Extract parse errors from a tree.
250
-
251
- Args:
252
- tree: Tree-sitter tree to check for errors
253
-
254
- Returns:
255
- List of error information dictionaries
256
- """
257
- errors = []
258
-
259
- try:
260
-
261
- def find_error_nodes(node: Any) -> None:
262
- """Recursively find error nodes in the tree."""
263
- if hasattr(node, "type") and node.type == "ERROR":
264
- errors.append(
265
- {
266
- "type": "ERROR",
267
- "start_point": node.start_point,
268
- "end_point": node.end_point,
269
- "text": (
270
- node.text.decode("utf-8", errors="replace")
271
- if node.text
272
- else ""
273
- ),
274
- }
275
- )
276
-
277
- if hasattr(node, "children"):
278
- for child in node.children:
279
- find_error_nodes(child)
280
-
281
- if tree and tree.root_node:
282
- find_error_nodes(tree.root_node)
283
-
284
- except Exception as e:
285
- logger.error(f"Error extracting parse errors: {e}")
286
-
287
- return errors
288
-
289
-
290
- # Module-level loader for backward compatibility
291
- loader = get_loader()
292
-
293
- loader = get_loader()
1
+ #!/usr/bin/env python3
2
+ """
3
+ Parser module for tree_sitter_analyzer.core.
4
+
5
+ This module provides the Parser class which handles Tree-sitter parsing
6
+ operations in the new architecture.
7
+ """
8
+
9
+ import logging
10
+ from pathlib import Path
11
+ from typing import Any, NamedTuple
12
+
13
+ from tree_sitter import Tree
14
+
15
+ from ..encoding_utils import EncodingManager
16
+ from ..language_loader import get_loader
17
+
18
+ # Configure logging
19
+ logger = logging.getLogger(__name__)
20
+
21
+
22
+ class ParseResult(NamedTuple):
23
+ """
24
+ Result of parsing operation containing tree and metadata.
25
+
26
+ Attributes:
27
+ tree: The parsed Tree-sitter tree (None if parsing failed)
28
+ source_code: The source code that was parsed
29
+ language: The programming language used for parsing
30
+ file_path: Path to the file (if parsing from file)
31
+ success: Whether parsing was successful
32
+ error_message: Error message if parsing failed
33
+ """
34
+
35
+ tree: Tree | None
36
+ source_code: str
37
+ language: str
38
+ file_path: str | None
39
+ success: bool
40
+ error_message: str | None
41
+
42
+
43
+ class Parser:
44
+ """
45
+ Tree-sitter parser wrapper for the new architecture.
46
+
47
+ This class provides a unified interface for parsing code files and strings
48
+ using Tree-sitter parsers with proper error handling and encoding support.
49
+ """
50
+
51
+ def __init__(self) -> None:
52
+ """Initialize the Parser with language loader."""
53
+ self._loader = get_loader()
54
+ self._encoding_manager = EncodingManager()
55
+ logger.info("Parser initialized successfully")
56
+
57
+ def parse_file(self, file_path: str | Path, language: str) -> ParseResult:
58
+ """
59
+ Parse a source code file.
60
+
61
+ Args:
62
+ file_path: Path to the file to parse
63
+ language: Programming language for parsing
64
+
65
+ Returns:
66
+ ParseResult containing the parsed tree and metadata
67
+ """
68
+ file_path_str = str(file_path)
69
+
70
+ try:
71
+ # Check if file exists
72
+ path_obj = Path(file_path_str)
73
+ if not path_obj.exists():
74
+ return ParseResult(
75
+ tree=None,
76
+ source_code="",
77
+ language=language,
78
+ file_path=file_path_str,
79
+ success=False,
80
+ error_message=f"File not found: {file_path_str}",
81
+ )
82
+
83
+ # Read file content with encoding detection
84
+ try:
85
+ source_code, detected_encoding = self._encoding_manager.read_file_safe(
86
+ path_obj
87
+ )
88
+ logger.debug(
89
+ f"Read file {file_path_str} with encoding {detected_encoding}"
90
+ )
91
+ except PermissionError as e:
92
+ return ParseResult(
93
+ tree=None,
94
+ source_code="",
95
+ language=language,
96
+ file_path=file_path_str,
97
+ success=False,
98
+ error_message=f"Permission denied: {str(e)}",
99
+ )
100
+ except Exception as e:
101
+ return ParseResult(
102
+ tree=None,
103
+ source_code="",
104
+ language=language,
105
+ file_path=file_path_str,
106
+ success=False,
107
+ error_message=f"Error reading file: {str(e)}",
108
+ )
109
+
110
+ # Parse the code
111
+ return self.parse_code(source_code, language, filename=file_path_str)
112
+
113
+ except Exception as e:
114
+ logger.error(f"Unexpected error parsing file {file_path_str}: {e}")
115
+ return ParseResult(
116
+ tree=None,
117
+ source_code="",
118
+ language=language,
119
+ file_path=file_path_str,
120
+ success=False,
121
+ error_message=f"Unexpected error: {str(e)}",
122
+ )
123
+
124
+ def parse_code(
125
+ self, source_code: str, language: str, filename: str | None = None
126
+ ) -> ParseResult:
127
+ """
128
+ Parse source code string.
129
+
130
+ Args:
131
+ source_code: The source code to parse
132
+ language: Programming language for parsing
133
+ filename: Optional filename for metadata
134
+
135
+ Returns:
136
+ ParseResult containing the parsed tree and metadata
137
+ """
138
+ try:
139
+ # Check if language is supported
140
+ if not self.is_language_supported(language):
141
+ return ParseResult(
142
+ tree=None,
143
+ source_code=source_code,
144
+ language=language,
145
+ file_path=filename,
146
+ success=False,
147
+ error_message=f"Unsupported language: {language}",
148
+ )
149
+
150
+ # Create parser for the language
151
+ parser = self._loader.create_parser_safely(language)
152
+ if parser is None:
153
+ return ParseResult(
154
+ tree=None,
155
+ source_code=source_code,
156
+ language=language,
157
+ file_path=filename,
158
+ success=False,
159
+ error_message=f"Failed to create parser for language: {language}",
160
+ )
161
+
162
+ # Parse the code
163
+ source_bytes = self._encoding_manager.safe_encode(source_code)
164
+ tree = parser.parse(source_bytes)
165
+
166
+ if tree is None:
167
+ return ParseResult( # type: ignore[unreachable]
168
+ tree=None,
169
+ source_code=source_code,
170
+ language=language,
171
+ file_path=filename,
172
+ success=False,
173
+ error_message="Parsing failed - tree is None",
174
+ )
175
+
176
+ logger.debug(f"Successfully parsed {language} code")
177
+ return ParseResult(
178
+ tree=tree,
179
+ source_code=source_code,
180
+ language=language,
181
+ file_path=filename,
182
+ success=True,
183
+ error_message=None,
184
+ )
185
+
186
+ except Exception as e:
187
+ logger.error(f"Error parsing {language} code: {e}")
188
+ return ParseResult(
189
+ tree=None,
190
+ source_code=source_code,
191
+ language=language,
192
+ file_path=filename,
193
+ success=False,
194
+ error_message=f"Parsing error: {str(e)}",
195
+ )
196
+
197
+ def is_language_supported(self, language: str) -> bool:
198
+ """
199
+ Check if a programming language is supported.
200
+
201
+ Args:
202
+ language: Programming language to check
203
+
204
+ Returns:
205
+ True if language is supported, False otherwise
206
+ """
207
+ try:
208
+ return self._loader.is_language_available(language)
209
+ except Exception as e:
210
+ logger.error(f"Error checking language support for {language}: {e}")
211
+ return False
212
+
213
+ def get_supported_languages(self) -> list[str]:
214
+ """
215
+ Get list of supported programming languages.
216
+
217
+ Returns:
218
+ List of supported language names
219
+ """
220
+ try:
221
+ return self._loader.get_supported_languages()
222
+ except Exception as e:
223
+ logger.error(f"Error getting supported languages: {e}")
224
+ return []
225
+
226
+ def validate_ast(self, tree: Tree | None) -> bool:
227
+ """
228
+ Validate an AST tree.
229
+
230
+ Args:
231
+ tree: Tree-sitter tree to validate
232
+
233
+ Returns:
234
+ True if tree is valid, False otherwise
235
+ """
236
+ if tree is None:
237
+ return False
238
+
239
+ try:
240
+ # Basic validation - check if tree has a root node
241
+ root_node = tree.root_node
242
+ return root_node is not None
243
+ except Exception as e:
244
+ logger.error(f"Error validating AST: {e}")
245
+ return False
246
+
247
+ def get_parse_errors(self, tree: Tree) -> list[dict[str, Any]]:
248
+ """
249
+ Extract parse errors from a tree.
250
+
251
+ Args:
252
+ tree: Tree-sitter tree to check for errors
253
+
254
+ Returns:
255
+ List of error information dictionaries
256
+ """
257
+ errors = []
258
+
259
+ try:
260
+
261
+ def find_error_nodes(node: Any) -> None:
262
+ """Recursively find error nodes in the tree."""
263
+ if hasattr(node, "type") and node.type == "ERROR":
264
+ errors.append(
265
+ {
266
+ "type": "ERROR",
267
+ "start_point": node.start_point,
268
+ "end_point": node.end_point,
269
+ "text": (
270
+ node.text.decode("utf-8", errors="replace")
271
+ if node.text
272
+ else ""
273
+ ),
274
+ }
275
+ )
276
+
277
+ if hasattr(node, "children"):
278
+ for child in node.children:
279
+ find_error_nodes(child)
280
+
281
+ if tree and tree.root_node:
282
+ find_error_nodes(tree.root_node)
283
+
284
+ except Exception as e:
285
+ logger.error(f"Error extracting parse errors: {e}")
286
+
287
+ return errors
288
+
289
+
290
+ # Module-level loader for backward compatibility
291
+ loader = get_loader()
292
+
293
+ loader = get_loader()