tree-sitter-analyzer 0.7.0__py3-none-any.whl → 0.8.1__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 (70) 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 +178 -160
  9. tree_sitter_analyzer/cli/commands/default_command.py +18 -18
  10. tree_sitter_analyzer/cli/commands/partial_read_command.py +141 -141
  11. tree_sitter_analyzer/cli/commands/query_command.py +88 -81
  12. tree_sitter_analyzer/cli/commands/structure_command.py +138 -138
  13. tree_sitter_analyzer/cli/commands/summary_command.py +101 -101
  14. tree_sitter_analyzer/cli/commands/table_command.py +235 -235
  15. tree_sitter_analyzer/cli/info_commands.py +121 -121
  16. tree_sitter_analyzer/cli_main.py +303 -297
  17. tree_sitter_analyzer/core/__init__.py +15 -15
  18. tree_sitter_analyzer/core/analysis_engine.py +580 -555
  19. tree_sitter_analyzer/core/cache_service.py +320 -320
  20. tree_sitter_analyzer/core/engine.py +566 -566
  21. tree_sitter_analyzer/core/parser.py +293 -293
  22. tree_sitter_analyzer/encoding_utils.py +459 -459
  23. tree_sitter_analyzer/exceptions.py +406 -337
  24. tree_sitter_analyzer/file_handler.py +210 -210
  25. tree_sitter_analyzer/formatters/__init__.py +1 -1
  26. tree_sitter_analyzer/formatters/base_formatter.py +167 -167
  27. tree_sitter_analyzer/formatters/formatter_factory.py +78 -78
  28. tree_sitter_analyzer/interfaces/__init__.py +9 -9
  29. tree_sitter_analyzer/interfaces/cli.py +528 -528
  30. tree_sitter_analyzer/interfaces/cli_adapter.py +343 -343
  31. tree_sitter_analyzer/interfaces/mcp_adapter.py +206 -206
  32. tree_sitter_analyzer/interfaces/mcp_server.py +425 -405
  33. tree_sitter_analyzer/languages/__init__.py +10 -10
  34. tree_sitter_analyzer/languages/javascript_plugin.py +446 -446
  35. tree_sitter_analyzer/languages/python_plugin.py +755 -755
  36. tree_sitter_analyzer/mcp/__init__.py +31 -31
  37. tree_sitter_analyzer/mcp/resources/__init__.py +44 -44
  38. tree_sitter_analyzer/mcp/resources/code_file_resource.py +209 -209
  39. tree_sitter_analyzer/mcp/server.py +408 -333
  40. tree_sitter_analyzer/mcp/tools/__init__.py +30 -30
  41. tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py +673 -654
  42. tree_sitter_analyzer/mcp/tools/analyze_scale_tool_cli_compatible.py +247 -247
  43. tree_sitter_analyzer/mcp/tools/base_tool.py +54 -54
  44. tree_sitter_analyzer/mcp/tools/read_partial_tool.py +308 -300
  45. tree_sitter_analyzer/mcp/tools/table_format_tool.py +379 -362
  46. tree_sitter_analyzer/mcp/tools/universal_analyze_tool.py +559 -543
  47. tree_sitter_analyzer/mcp/utils/__init__.py +107 -107
  48. tree_sitter_analyzer/mcp/utils/error_handler.py +549 -549
  49. tree_sitter_analyzer/output_manager.py +253 -253
  50. tree_sitter_analyzer/plugins/__init__.py +280 -280
  51. tree_sitter_analyzer/plugins/base.py +529 -529
  52. tree_sitter_analyzer/plugins/manager.py +379 -379
  53. tree_sitter_analyzer/project_detector.py +317 -0
  54. tree_sitter_analyzer/queries/__init__.py +26 -26
  55. tree_sitter_analyzer/queries/java.py +391 -391
  56. tree_sitter_analyzer/queries/javascript.py +148 -148
  57. tree_sitter_analyzer/queries/python.py +285 -285
  58. tree_sitter_analyzer/queries/typescript.py +229 -229
  59. tree_sitter_analyzer/query_loader.py +257 -257
  60. tree_sitter_analyzer/security/__init__.py +22 -0
  61. tree_sitter_analyzer/security/boundary_manager.py +237 -0
  62. tree_sitter_analyzer/security/regex_checker.py +292 -0
  63. tree_sitter_analyzer/security/validator.py +241 -0
  64. tree_sitter_analyzer/table_formatter.py +652 -589
  65. tree_sitter_analyzer/utils.py +277 -277
  66. {tree_sitter_analyzer-0.7.0.dist-info → tree_sitter_analyzer-0.8.1.dist-info}/METADATA +27 -1
  67. tree_sitter_analyzer-0.8.1.dist-info/RECORD +77 -0
  68. tree_sitter_analyzer-0.7.0.dist-info/RECORD +0 -72
  69. {tree_sitter_analyzer-0.7.0.dist-info → tree_sitter_analyzer-0.8.1.dist-info}/WHEEL +0 -0
  70. {tree_sitter_analyzer-0.7.0.dist-info → tree_sitter_analyzer-0.8.1.dist-info}/entry_points.txt +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()