tree-sitter-analyzer 0.1.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 +121 -0
  2. tree_sitter_analyzer/__main__.py +12 -0
  3. tree_sitter_analyzer/api.py +539 -0
  4. tree_sitter_analyzer/cli/__init__.py +39 -0
  5. tree_sitter_analyzer/cli/__main__.py +13 -0
  6. tree_sitter_analyzer/cli/commands/__init__.py +27 -0
  7. tree_sitter_analyzer/cli/commands/advanced_command.py +88 -0
  8. tree_sitter_analyzer/cli/commands/base_command.py +155 -0
  9. tree_sitter_analyzer/cli/commands/default_command.py +19 -0
  10. tree_sitter_analyzer/cli/commands/partial_read_command.py +133 -0
  11. tree_sitter_analyzer/cli/commands/query_command.py +82 -0
  12. tree_sitter_analyzer/cli/commands/structure_command.py +121 -0
  13. tree_sitter_analyzer/cli/commands/summary_command.py +93 -0
  14. tree_sitter_analyzer/cli/commands/table_command.py +233 -0
  15. tree_sitter_analyzer/cli/info_commands.py +121 -0
  16. tree_sitter_analyzer/cli_main.py +276 -0
  17. tree_sitter_analyzer/core/__init__.py +20 -0
  18. tree_sitter_analyzer/core/analysis_engine.py +574 -0
  19. tree_sitter_analyzer/core/cache_service.py +330 -0
  20. tree_sitter_analyzer/core/engine.py +560 -0
  21. tree_sitter_analyzer/core/parser.py +288 -0
  22. tree_sitter_analyzer/core/query.py +502 -0
  23. tree_sitter_analyzer/encoding_utils.py +460 -0
  24. tree_sitter_analyzer/exceptions.py +340 -0
  25. tree_sitter_analyzer/file_handler.py +222 -0
  26. tree_sitter_analyzer/formatters/__init__.py +1 -0
  27. tree_sitter_analyzer/formatters/base_formatter.py +168 -0
  28. tree_sitter_analyzer/formatters/formatter_factory.py +74 -0
  29. tree_sitter_analyzer/formatters/java_formatter.py +270 -0
  30. tree_sitter_analyzer/formatters/python_formatter.py +235 -0
  31. tree_sitter_analyzer/interfaces/__init__.py +10 -0
  32. tree_sitter_analyzer/interfaces/cli.py +557 -0
  33. tree_sitter_analyzer/interfaces/cli_adapter.py +319 -0
  34. tree_sitter_analyzer/interfaces/mcp_adapter.py +170 -0
  35. tree_sitter_analyzer/interfaces/mcp_server.py +416 -0
  36. tree_sitter_analyzer/java_analyzer.py +219 -0
  37. tree_sitter_analyzer/language_detector.py +400 -0
  38. tree_sitter_analyzer/language_loader.py +228 -0
  39. tree_sitter_analyzer/languages/__init__.py +11 -0
  40. tree_sitter_analyzer/languages/java_plugin.py +1113 -0
  41. tree_sitter_analyzer/languages/python_plugin.py +712 -0
  42. tree_sitter_analyzer/mcp/__init__.py +32 -0
  43. tree_sitter_analyzer/mcp/resources/__init__.py +47 -0
  44. tree_sitter_analyzer/mcp/resources/code_file_resource.py +213 -0
  45. tree_sitter_analyzer/mcp/resources/project_stats_resource.py +550 -0
  46. tree_sitter_analyzer/mcp/server.py +319 -0
  47. tree_sitter_analyzer/mcp/tools/__init__.py +36 -0
  48. tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py +558 -0
  49. tree_sitter_analyzer/mcp/tools/analyze_scale_tool_cli_compatible.py +245 -0
  50. tree_sitter_analyzer/mcp/tools/base_tool.py +55 -0
  51. tree_sitter_analyzer/mcp/tools/get_positions_tool.py +448 -0
  52. tree_sitter_analyzer/mcp/tools/read_partial_tool.py +302 -0
  53. tree_sitter_analyzer/mcp/tools/table_format_tool.py +359 -0
  54. tree_sitter_analyzer/mcp/tools/universal_analyze_tool.py +476 -0
  55. tree_sitter_analyzer/mcp/utils/__init__.py +106 -0
  56. tree_sitter_analyzer/mcp/utils/error_handler.py +549 -0
  57. tree_sitter_analyzer/models.py +481 -0
  58. tree_sitter_analyzer/output_manager.py +264 -0
  59. tree_sitter_analyzer/plugins/__init__.py +334 -0
  60. tree_sitter_analyzer/plugins/base.py +446 -0
  61. tree_sitter_analyzer/plugins/java_plugin.py +625 -0
  62. tree_sitter_analyzer/plugins/javascript_plugin.py +439 -0
  63. tree_sitter_analyzer/plugins/manager.py +355 -0
  64. tree_sitter_analyzer/plugins/plugin_loader.py +83 -0
  65. tree_sitter_analyzer/plugins/python_plugin.py +598 -0
  66. tree_sitter_analyzer/plugins/registry.py +366 -0
  67. tree_sitter_analyzer/queries/__init__.py +27 -0
  68. tree_sitter_analyzer/queries/java.py +394 -0
  69. tree_sitter_analyzer/queries/javascript.py +149 -0
  70. tree_sitter_analyzer/queries/python.py +286 -0
  71. tree_sitter_analyzer/queries/typescript.py +230 -0
  72. tree_sitter_analyzer/query_loader.py +260 -0
  73. tree_sitter_analyzer/table_formatter.py +448 -0
  74. tree_sitter_analyzer/utils.py +201 -0
  75. tree_sitter_analyzer-0.1.0.dist-info/METADATA +581 -0
  76. tree_sitter_analyzer-0.1.0.dist-info/RECORD +78 -0
  77. tree_sitter_analyzer-0.1.0.dist-info/WHEEL +4 -0
  78. tree_sitter_analyzer-0.1.0.dist-info/entry_points.txt +8 -0
@@ -0,0 +1,319 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ MCP Server implementation for Tree-sitter Analyzer (Fixed Version)
5
+
6
+ This module provides the main MCP server that exposes tree-sitter analyzer
7
+ functionality through the Model Context Protocol.
8
+ """
9
+
10
+ import asyncio
11
+ import json
12
+ import logging
13
+ import sys
14
+ from pathlib import Path
15
+ from typing import Any, Dict, List, Optional, Sequence, Union
16
+
17
+ try:
18
+ from mcp.server import Server
19
+ from mcp.server.models import InitializationOptions
20
+ from mcp.server.stdio import stdio_server
21
+ from mcp.types import (
22
+ EmbeddedResource,
23
+ ImageContent,
24
+ Resource,
25
+ TextContent,
26
+ Tool,
27
+ )
28
+
29
+ MCP_AVAILABLE = True
30
+ except ImportError:
31
+ MCP_AVAILABLE = False
32
+
33
+ # Fallback types for development without MCP
34
+ class FallbackServer:
35
+ pass
36
+
37
+ class FallbackInitializationOptions:
38
+ pass
39
+
40
+
41
+ from tree_sitter_analyzer.core.analysis_engine import get_analysis_engine
42
+ from ..core.analysis_engine import get_analysis_engine, AnalysisRequest
43
+ from ..language_detector import detect_language_from_file
44
+ from ..utils import setup_logger
45
+ from . import MCP_INFO
46
+ from .resources import CodeFileResource, ProjectStatsResource
47
+ from .tools.base_tool import MCPTool
48
+ from .tools.get_positions_tool import GetPositionsTool
49
+ from .tools.read_partial_tool import ReadPartialTool
50
+ from .tools.table_format_tool import TableFormatTool
51
+ from .tools.universal_analyze_tool import UniversalAnalyzeTool
52
+ from .utils.error_handler import handle_mcp_errors
53
+ from .utils import get_performance_monitor
54
+
55
+ # Set up logging
56
+ logger = setup_logger(__name__)
57
+
58
+
59
+ class TreeSitterAnalyzerMCPServer:
60
+ """
61
+ MCP Server for Tree-sitter Analyzer
62
+
63
+ Provides code analysis capabilities through the Model Context Protocol,
64
+ integrating with existing analyzer components.
65
+ """
66
+
67
+ def __init__(self) -> None:
68
+ """Initialize the MCP server with analyzer components."""
69
+ self.server: Optional[Server] = None
70
+ self.analysis_engine = get_analysis_engine()
71
+ # Use unified analysis engine instead of deprecated AdvancedAnalyzer
72
+
73
+ # Initialize MCP tools
74
+ self.read_partial_tool: MCPTool = ReadPartialTool()
75
+ self.universal_analyze_tool: MCPTool = UniversalAnalyzeTool()
76
+ self.get_positions_tool: MCPTool = GetPositionsTool()
77
+ self.table_format_tool: MCPTool = TableFormatTool()
78
+
79
+ # Initialize MCP resources
80
+ self.code_file_resource = CodeFileResource()
81
+ self.project_stats_resource = ProjectStatsResource()
82
+
83
+ # Server metadata
84
+ self.name = MCP_INFO["name"]
85
+ self.version = MCP_INFO["version"]
86
+
87
+ logger.info(f"Initializing {self.name} v{self.version}")
88
+
89
+ @handle_mcp_errors("analyze_code_scale")
90
+ async def _analyze_code_scale(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
91
+ """
92
+ Analyze code scale and complexity metrics by delegating to the universal_analyze_tool.
93
+ """
94
+ # Delegate the execution to the already initialized tool
95
+ return await self.universal_analyze_tool.execute(arguments)
96
+
97
+ def create_server(self) -> Server:
98
+ """
99
+ Create and configure the MCP server.
100
+
101
+ Returns:
102
+ Configured MCP Server instance
103
+ """
104
+ if not MCP_AVAILABLE:
105
+ raise RuntimeError("MCP library not available. Please install mcp package.")
106
+
107
+ server: Server = Server(self.name)
108
+
109
+ # Register tools
110
+ @server.list_tools()
111
+ async def handle_list_tools() -> List[Tool]:
112
+ """List available tools."""
113
+ tools = [
114
+ Tool(
115
+ name="analyze_code_scale",
116
+ description="Analyze code scale, complexity, and structure metrics",
117
+ inputSchema={
118
+ "type": "object",
119
+ "properties": {
120
+ "file_path": {
121
+ "type": "string",
122
+ "description": "Path to the code file to analyze",
123
+ },
124
+ "language": {
125
+ "type": "string",
126
+ "description": "Programming language (optional, auto-detected if not specified)",
127
+ },
128
+ "include_complexity": {
129
+ "type": "boolean",
130
+ "description": "Include complexity metrics in the analysis",
131
+ "default": True,
132
+ },
133
+ "include_details": {
134
+ "type": "boolean",
135
+ "description": "Include detailed element information",
136
+ "default": False,
137
+ },
138
+ },
139
+ "required": ["file_path"],
140
+ "additionalProperties": False,
141
+ },
142
+ )
143
+ ]
144
+
145
+ # Add tools from tool classes - FIXED VERSION
146
+ for tool_instance in [
147
+ self.read_partial_tool,
148
+ self.get_positions_tool,
149
+ self.table_format_tool,
150
+ self.universal_analyze_tool,
151
+ ]:
152
+ tool_def = tool_instance.get_tool_definition()
153
+ if isinstance(tool_def, dict):
154
+ # Convert dict to Tool object
155
+ tools.append(Tool(**tool_def))
156
+ else:
157
+ # Already a Tool object
158
+ tools.append(tool_def)
159
+
160
+ return tools
161
+
162
+ @server.call_tool()
163
+ async def handle_call_tool(
164
+ name: str, arguments: Dict[str, Any]
165
+ ) -> List[TextContent]:
166
+ """Handle tool calls."""
167
+ try:
168
+ if name == "analyze_code_scale":
169
+ result = await self._analyze_code_scale(arguments)
170
+ return [
171
+ TextContent(
172
+ type="text",
173
+ text=json.dumps(result, indent=2, ensure_ascii=False),
174
+ )
175
+ ]
176
+ elif name == "read_code_partial":
177
+ result = await self.read_partial_tool.execute(arguments)
178
+ return [
179
+ TextContent(
180
+ type="text",
181
+ text=json.dumps(result, indent=2, ensure_ascii=False),
182
+ )
183
+ ]
184
+ elif name == "get_code_positions":
185
+ result = await self.get_positions_tool.execute(arguments)
186
+ return [
187
+ TextContent(
188
+ type="text",
189
+ text=json.dumps(result, indent=2, ensure_ascii=False),
190
+ )
191
+ ]
192
+ elif name == "format_table":
193
+ result = await self.table_format_tool.execute(arguments)
194
+ return [
195
+ TextContent(
196
+ type="text",
197
+ text=json.dumps(result, indent=2, ensure_ascii=False),
198
+ )
199
+ ]
200
+ elif name == "analyze_code_universal":
201
+ result = await self.universal_analyze_tool.execute(arguments)
202
+ return [
203
+ TextContent(
204
+ type="text",
205
+ text=json.dumps(result, indent=2, ensure_ascii=False),
206
+ )
207
+ ]
208
+ else:
209
+ raise ValueError(f"Unknown tool: {name}")
210
+
211
+ except Exception as e:
212
+ logger.error(f"Tool call error for {name}: {e}")
213
+ return [
214
+ TextContent(
215
+ type="text",
216
+ text=json.dumps(
217
+ {"error": str(e), "tool": name, "arguments": arguments},
218
+ indent=2,
219
+ ),
220
+ )
221
+ ]
222
+
223
+ # Register resources
224
+ @server.list_resources()
225
+ async def handle_list_resources() -> List[Resource]:
226
+ """List available resources."""
227
+ return [
228
+ Resource(
229
+ uri=self.code_file_resource.get_resource_info()["uri_template"],
230
+ name=self.code_file_resource.get_resource_info()["name"],
231
+ description=self.code_file_resource.get_resource_info()[
232
+ "description"
233
+ ],
234
+ mimeType=self.code_file_resource.get_resource_info()["mime_type"],
235
+ ),
236
+ Resource(
237
+ uri=self.project_stats_resource.get_resource_info()["uri_template"],
238
+ name=self.project_stats_resource.get_resource_info()["name"],
239
+ description=self.project_stats_resource.get_resource_info()[
240
+ "description"
241
+ ],
242
+ mimeType=self.project_stats_resource.get_resource_info()[
243
+ "mime_type"
244
+ ],
245
+ ),
246
+ ]
247
+
248
+ @server.read_resource()
249
+ async def handle_read_resource(uri: str) -> str:
250
+ """Read resource content."""
251
+ try:
252
+ # Check which resource matches the URI
253
+ if self.code_file_resource.matches_uri(uri):
254
+ return await self.code_file_resource.read_resource(uri)
255
+ elif self.project_stats_resource.matches_uri(uri):
256
+ return await self.project_stats_resource.read_resource(uri)
257
+ else:
258
+ raise ValueError(f"Resource not found: {uri}")
259
+
260
+ except Exception as e:
261
+ logger.error(f"Resource read error for {uri}: {e}")
262
+ raise
263
+
264
+ self.server = server
265
+ logger.info("MCP server created successfully")
266
+ return server
267
+
268
+ def set_project_path(self, project_path: str) -> None:
269
+ """
270
+ Set the project path for statistics resource
271
+
272
+ Args:
273
+ project_path: Path to the project directory
274
+ """
275
+ self.project_stats_resource.set_project_path(project_path)
276
+ logger.info(f"Set project path to: {project_path}")
277
+
278
+ async def run(self) -> None:
279
+ """
280
+ Run the MCP server.
281
+
282
+ This method starts the server and handles stdio communication.
283
+ """
284
+ if not MCP_AVAILABLE:
285
+ raise RuntimeError("MCP library not available. Please install mcp package.")
286
+
287
+ server = self.create_server()
288
+
289
+ # Initialize server options
290
+ options = InitializationOptions(
291
+ server_name=self.name,
292
+ server_version=self.version,
293
+ capabilities=MCP_INFO["capabilities"],
294
+ )
295
+
296
+ logger.info(f"Starting MCP server: {self.name} v{self.version}")
297
+
298
+ try:
299
+ async with stdio_server() as (read_stream, write_stream):
300
+ await server.run(read_stream, write_stream, options)
301
+ except Exception as e:
302
+ logger.error(f"Server error: {e}")
303
+ raise
304
+
305
+
306
+ async def main() -> None:
307
+ """Main entry point for the MCP server."""
308
+ try:
309
+ server = TreeSitterAnalyzerMCPServer()
310
+ await server.run()
311
+ except KeyboardInterrupt:
312
+ logger.info("Server stopped by user")
313
+ except Exception as e:
314
+ logger.error(f"Server failed: {e}")
315
+ sys.exit(1)
316
+
317
+
318
+ if __name__ == "__main__":
319
+ asyncio.run(main())
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ MCP Tools package for Tree-sitter Analyzer
5
+
6
+ This package contains all MCP tools that provide specific functionality
7
+ through the Model Context Protocol.
8
+ """
9
+
10
+ from typing import Any, Dict, List
11
+
12
+ __version__ = "1.0.0"
13
+
14
+ # Tool registry for easy access
15
+ AVAILABLE_TOOLS: Dict[str, Dict[str, Any]] = {
16
+ "analyze_code_scale": {
17
+ "description": "Analyze code scale, complexity, and structure metrics",
18
+ "module": "analyze_scale_tool",
19
+ "class": "AnalyzeScaleTool",
20
+ },
21
+ # Future tools will be added here
22
+ # "read_code_partial": {
23
+ # "description": "Read partial content from code files",
24
+ # "module": "read_partial_tool",
25
+ # "class": "ReadPartialTool",
26
+ # },
27
+ # "get_code_positions": {
28
+ # "description": "Get position information for code elements",
29
+ # "module": "get_positions_tool",
30
+ # "class": "GetPositionsTool",
31
+ # },
32
+ }
33
+
34
+ __all__ = [
35
+ "AVAILABLE_TOOLS",
36
+ ]