tree-sitter-analyzer 0.6.2__py3-none-any.whl → 0.8.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 (69) 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 +160 -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 +81 -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 +297 -297
  17. tree_sitter_analyzer/core/__init__.py +15 -15
  18. tree_sitter_analyzer/core/analysis_engine.py +555 -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 +346 -333
  40. tree_sitter_analyzer/mcp/tools/__init__.py +30 -30
  41. tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py +654 -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 +300 -300
  45. tree_sitter_analyzer/mcp/tools/table_format_tool.py +362 -362
  46. tree_sitter_analyzer/mcp/tools/universal_analyze_tool.py +543 -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/queries/__init__.py +26 -26
  54. tree_sitter_analyzer/queries/java.py +391 -391
  55. tree_sitter_analyzer/queries/javascript.py +148 -148
  56. tree_sitter_analyzer/queries/python.py +285 -285
  57. tree_sitter_analyzer/queries/typescript.py +229 -229
  58. tree_sitter_analyzer/query_loader.py +257 -257
  59. tree_sitter_analyzer/security/__init__.py +22 -0
  60. tree_sitter_analyzer/security/boundary_manager.py +237 -0
  61. tree_sitter_analyzer/security/regex_checker.py +292 -0
  62. tree_sitter_analyzer/security/validator.py +224 -0
  63. tree_sitter_analyzer/table_formatter.py +652 -473
  64. tree_sitter_analyzer/utils.py +277 -277
  65. {tree_sitter_analyzer-0.6.2.dist-info → tree_sitter_analyzer-0.8.0.dist-info}/METADATA +4 -1
  66. tree_sitter_analyzer-0.8.0.dist-info/RECORD +76 -0
  67. tree_sitter_analyzer-0.6.2.dist-info/RECORD +0 -72
  68. {tree_sitter_analyzer-0.6.2.dist-info → tree_sitter_analyzer-0.8.0.dist-info}/WHEEL +0 -0
  69. {tree_sitter_analyzer-0.6.2.dist-info → tree_sitter_analyzer-0.8.0.dist-info}/entry_points.txt +0 -0
@@ -1,206 +1,206 @@
1
- #!/usr/bin/env python3
2
- """
3
- MCP Adapter for Tree-Sitter Analyzer
4
-
5
- This module provides an adapter interface for integrating with the MCP protocol.
6
- """
7
-
8
- from typing import TYPE_CHECKING, Any
9
-
10
- from ..models import AnalysisResult
11
-
12
- if TYPE_CHECKING:
13
- from ..core.analysis_engine import UnifiedAnalysisEngine
14
-
15
-
16
- def get_analysis_engine() -> "UnifiedAnalysisEngine":
17
- """Get analysis engine instance for testing compatibility."""
18
- from ..core.analysis_engine import UnifiedAnalysisEngine
19
-
20
- return UnifiedAnalysisEngine()
21
-
22
-
23
- def handle_mcp_resource_request(uri: str) -> dict[str, Any]:
24
- """Handle MCP resource request for testing compatibility."""
25
- return {
26
- "contents": [
27
- {"mimeType": "application/json", "text": {"mock": "resource"}, "uri": uri}
28
- ]
29
- }
30
-
31
-
32
- def read_file_safe(file_path: str) -> str:
33
- """Read file safely for MCP resource requests."""
34
- try:
35
- with open(file_path, encoding="utf-8") as f:
36
- return f.read()
37
- except Exception as e:
38
- raise FileNotFoundError(f"Could not read file {file_path}: {e}") from e
39
-
40
-
41
- class MCPAdapter:
42
- """MCP Adapter for testing compatibility."""
43
-
44
- def __init__(self) -> None:
45
- """Initialize MCP Adapter."""
46
- from ..core.analysis_engine import UnifiedAnalysisEngine
47
-
48
- self.engine = UnifiedAnalysisEngine()
49
-
50
- async def analyze_file_async(
51
- self, file_path: str, **kwargs: Any
52
- ) -> "AnalysisResult":
53
- """Analyze file asynchronously."""
54
- from ..core.analysis_engine import AnalysisRequest
55
-
56
- request = AnalysisRequest(
57
- file_path=file_path,
58
- language=kwargs.get("language"),
59
- include_complexity=kwargs.get("include_complexity", False),
60
- include_details=kwargs.get("include_details", True),
61
- format_type=kwargs.get("format_type", "standard"),
62
- )
63
- return await self.engine.analyze(request)
64
-
65
- async def get_file_structure_async(
66
- self, file_path: str, **kwargs: Any
67
- ) -> dict[str, Any]:
68
- """Get file structure asynchronously."""
69
- result = await self.analyze_file_async(file_path, **kwargs)
70
- return {
71
- "file_path": result.file_path,
72
- "language": result.language,
73
- "structure": {
74
- "classes": [
75
- {"name": cls.name, "type": str(type(cls).__name__)}
76
- for cls in result.classes
77
- ],
78
- "methods": [
79
- {"name": method.name, "type": str(type(method).__name__)}
80
- for method in result.methods
81
- ],
82
- "fields": [
83
- {"name": field.name, "type": str(type(field).__name__)}
84
- for field in result.fields
85
- ],
86
- "imports": [
87
- {"name": imp.name, "type": str(type(imp).__name__)}
88
- for imp in result.imports
89
- ],
90
- "annotations": [
91
- {
92
- "name": getattr(ann, "name", str(ann)),
93
- "type": str(type(ann).__name__),
94
- }
95
- for ann in getattr(result, "annotations", [])
96
- ],
97
- },
98
- "metadata": {
99
- "analysis_time": result.analysis_time,
100
- "success": result.success,
101
- "error_message": result.error_message,
102
- "package": result.package,
103
- "class_count": len(result.classes),
104
- "method_count": len(result.methods),
105
- "field_count": len(result.fields),
106
- "import_count": len(result.imports),
107
- "annotation_count": len(result.annotations),
108
- },
109
- }
110
-
111
- async def analyze_batch_async(
112
- self, file_paths: list[str], **kwargs: Any
113
- ) -> list["AnalysisResult"]:
114
- """Analyze multiple files asynchronously."""
115
- results = []
116
- for file_path in file_paths:
117
- try:
118
- result = await self.analyze_file_async(file_path, **kwargs)
119
- results.append(result)
120
- except Exception as e:
121
- # Create error result
122
- from ..models import AnalysisResult
123
-
124
- error_result = AnalysisResult(
125
- file_path=file_path,
126
- language="unknown",
127
- line_count=0,
128
- elements=[],
129
- node_count=0,
130
- query_results={},
131
- source_code="",
132
- package=None,
133
- imports=[],
134
- classes=[],
135
- methods=[],
136
- fields=[],
137
- annotations=[],
138
- analysis_time=0.0,
139
- success=False,
140
- error_message=str(e),
141
- )
142
- results.append(error_result)
143
- return results
144
-
145
- async def handle_mcp_tool_request(
146
- self, tool_name: str, arguments: dict[str, Any]
147
- ) -> dict[str, Any]:
148
- """Handle MCP tool request."""
149
- if tool_name == "analyze_file":
150
- file_path = arguments.get("file_path")
151
- if not file_path:
152
- return {"error": "file_path is required"}
153
-
154
- try:
155
- result = await self.analyze_file_async(file_path)
156
- return {"success": True, "result": result.to_dict()}
157
- except Exception as e:
158
- return {"error": str(e)}
159
-
160
- return {"error": f"Unknown tool: {tool_name}"}
161
-
162
- async def handle_mcp_resource_request(self, uri: str) -> dict[str, Any]:
163
- """Handle MCP resource request."""
164
- if uri.startswith("code://"):
165
- # Extract file path from URI
166
- file_path = uri.replace("code://", "")
167
- try:
168
- content = read_file_safe(file_path)
169
- return {"uri": uri, "content": content, "mimeType": "text/plain"}
170
- except Exception as e:
171
- return {"error": str(e)}
172
-
173
- return {"error": f"Unsupported URI: {uri}"}
174
-
175
- def cleanup(self) -> None:
176
- """Cleanup resources."""
177
- pass
178
-
179
- async def aclose(self) -> None:
180
- """Async cleanup."""
181
- pass
182
-
183
- async def analyze_with_mcp_request(
184
- self, arguments: dict[str, Any]
185
- ) -> AnalysisResult:
186
- """Analyze with MCP request."""
187
- if "file_path" not in arguments:
188
- raise KeyError("file_path is required in MCP request")
189
- result = await self.analyze_file_async(arguments["file_path"])
190
- return result
191
-
192
-
193
- class MCPServerAdapter:
194
- """MCP Server Adapter for testing compatibility."""
195
-
196
- def __init__(self) -> None:
197
- """Initialize MCP Server Adapter."""
198
- self.mcp_adapter = MCPAdapter()
199
-
200
- async def handle_request(
201
- self, method: str, params: dict[str, Any]
202
- ) -> dict[str, Any]:
203
- """Handle MCP request."""
204
- if not params:
205
- return {"error": "params are required"}
206
- return await self.mcp_adapter.handle_mcp_tool_request(method, params)
1
+ #!/usr/bin/env python3
2
+ """
3
+ MCP Adapter for Tree-Sitter Analyzer
4
+
5
+ This module provides an adapter interface for integrating with the MCP protocol.
6
+ """
7
+
8
+ from typing import TYPE_CHECKING, Any
9
+
10
+ from ..models import AnalysisResult
11
+
12
+ if TYPE_CHECKING:
13
+ from ..core.analysis_engine import UnifiedAnalysisEngine
14
+
15
+
16
+ def get_analysis_engine() -> "UnifiedAnalysisEngine":
17
+ """Get analysis engine instance for testing compatibility."""
18
+ from ..core.analysis_engine import UnifiedAnalysisEngine
19
+
20
+ return UnifiedAnalysisEngine()
21
+
22
+
23
+ def handle_mcp_resource_request(uri: str) -> dict[str, Any]:
24
+ """Handle MCP resource request for testing compatibility."""
25
+ return {
26
+ "contents": [
27
+ {"mimeType": "application/json", "text": {"mock": "resource"}, "uri": uri}
28
+ ]
29
+ }
30
+
31
+
32
+ def read_file_safe(file_path: str) -> str:
33
+ """Read file safely for MCP resource requests."""
34
+ try:
35
+ with open(file_path, encoding="utf-8") as f:
36
+ return f.read()
37
+ except Exception as e:
38
+ raise FileNotFoundError(f"Could not read file {file_path}: {e}") from e
39
+
40
+
41
+ class MCPAdapter:
42
+ """MCP Adapter for testing compatibility."""
43
+
44
+ def __init__(self) -> None:
45
+ """Initialize MCP Adapter."""
46
+ from ..core.analysis_engine import UnifiedAnalysisEngine
47
+
48
+ self.engine = UnifiedAnalysisEngine()
49
+
50
+ async def analyze_file_async(
51
+ self, file_path: str, **kwargs: Any
52
+ ) -> "AnalysisResult":
53
+ """Analyze file asynchronously."""
54
+ from ..core.analysis_engine import AnalysisRequest
55
+
56
+ request = AnalysisRequest(
57
+ file_path=file_path,
58
+ language=kwargs.get("language"),
59
+ include_complexity=kwargs.get("include_complexity", False),
60
+ include_details=kwargs.get("include_details", True),
61
+ format_type=kwargs.get("format_type", "standard"),
62
+ )
63
+ return await self.engine.analyze(request)
64
+
65
+ async def get_file_structure_async(
66
+ self, file_path: str, **kwargs: Any
67
+ ) -> dict[str, Any]:
68
+ """Get file structure asynchronously."""
69
+ result = await self.analyze_file_async(file_path, **kwargs)
70
+ return {
71
+ "file_path": result.file_path,
72
+ "language": result.language,
73
+ "structure": {
74
+ "classes": [
75
+ {"name": cls.name, "type": str(type(cls).__name__)}
76
+ for cls in result.classes
77
+ ],
78
+ "methods": [
79
+ {"name": method.name, "type": str(type(method).__name__)}
80
+ for method in result.methods
81
+ ],
82
+ "fields": [
83
+ {"name": field.name, "type": str(type(field).__name__)}
84
+ for field in result.fields
85
+ ],
86
+ "imports": [
87
+ {"name": imp.name, "type": str(type(imp).__name__)}
88
+ for imp in result.imports
89
+ ],
90
+ "annotations": [
91
+ {
92
+ "name": getattr(ann, "name", str(ann)),
93
+ "type": str(type(ann).__name__),
94
+ }
95
+ for ann in getattr(result, "annotations", [])
96
+ ],
97
+ },
98
+ "metadata": {
99
+ "analysis_time": result.analysis_time,
100
+ "success": result.success,
101
+ "error_message": result.error_message,
102
+ "package": result.package,
103
+ "class_count": len(result.classes),
104
+ "method_count": len(result.methods),
105
+ "field_count": len(result.fields),
106
+ "import_count": len(result.imports),
107
+ "annotation_count": len(result.annotations),
108
+ },
109
+ }
110
+
111
+ async def analyze_batch_async(
112
+ self, file_paths: list[str], **kwargs: Any
113
+ ) -> list["AnalysisResult"]:
114
+ """Analyze multiple files asynchronously."""
115
+ results = []
116
+ for file_path in file_paths:
117
+ try:
118
+ result = await self.analyze_file_async(file_path, **kwargs)
119
+ results.append(result)
120
+ except Exception as e:
121
+ # Create error result
122
+ from ..models import AnalysisResult
123
+
124
+ error_result = AnalysisResult(
125
+ file_path=file_path,
126
+ language="unknown",
127
+ line_count=0,
128
+ elements=[],
129
+ node_count=0,
130
+ query_results={},
131
+ source_code="",
132
+ package=None,
133
+ imports=[],
134
+ classes=[],
135
+ methods=[],
136
+ fields=[],
137
+ annotations=[],
138
+ analysis_time=0.0,
139
+ success=False,
140
+ error_message=str(e),
141
+ )
142
+ results.append(error_result)
143
+ return results
144
+
145
+ async def handle_mcp_tool_request(
146
+ self, tool_name: str, arguments: dict[str, Any]
147
+ ) -> dict[str, Any]:
148
+ """Handle MCP tool request."""
149
+ if tool_name == "analyze_file":
150
+ file_path = arguments.get("file_path")
151
+ if not file_path:
152
+ return {"error": "file_path is required"}
153
+
154
+ try:
155
+ result = await self.analyze_file_async(file_path)
156
+ return {"success": True, "result": result.to_dict()}
157
+ except Exception as e:
158
+ return {"error": str(e)}
159
+
160
+ return {"error": f"Unknown tool: {tool_name}"}
161
+
162
+ async def handle_mcp_resource_request(self, uri: str) -> dict[str, Any]:
163
+ """Handle MCP resource request."""
164
+ if uri.startswith("code://"):
165
+ # Extract file path from URI
166
+ file_path = uri.replace("code://", "")
167
+ try:
168
+ content = read_file_safe(file_path)
169
+ return {"uri": uri, "content": content, "mimeType": "text/plain"}
170
+ except Exception as e:
171
+ return {"error": str(e)}
172
+
173
+ return {"error": f"Unsupported URI: {uri}"}
174
+
175
+ def cleanup(self) -> None:
176
+ """Cleanup resources."""
177
+ pass
178
+
179
+ async def aclose(self) -> None:
180
+ """Async cleanup."""
181
+ pass
182
+
183
+ async def analyze_with_mcp_request(
184
+ self, arguments: dict[str, Any]
185
+ ) -> AnalysisResult:
186
+ """Analyze with MCP request."""
187
+ if "file_path" not in arguments:
188
+ raise KeyError("file_path is required in MCP request")
189
+ result = await self.analyze_file_async(arguments["file_path"])
190
+ return result
191
+
192
+
193
+ class MCPServerAdapter:
194
+ """MCP Server Adapter for testing compatibility."""
195
+
196
+ def __init__(self) -> None:
197
+ """Initialize MCP Server Adapter."""
198
+ self.mcp_adapter = MCPAdapter()
199
+
200
+ async def handle_request(
201
+ self, method: str, params: dict[str, Any]
202
+ ) -> dict[str, Any]:
203
+ """Handle MCP request."""
204
+ if not params:
205
+ return {"error": "params are required"}
206
+ return await self.mcp_adapter.handle_mcp_tool_request(method, params)