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