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,481 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Data Models for Multi-Language Code Analysis
5
+
6
+ Data classes for representing code structures extracted through
7
+ Tree-sitter analysis across multiple programming languages.
8
+ """
9
+
10
+ import sys
11
+ from abc import ABC, abstractmethod
12
+ from dataclasses import dataclass, field
13
+ from typing import (
14
+ TYPE_CHECKING,
15
+ Any,
16
+ Callable,
17
+ Dict,
18
+ List,
19
+ Optional,
20
+ Sequence,
21
+ TypeVar,
22
+ Union,
23
+ )
24
+
25
+ if TYPE_CHECKING:
26
+ from typing_extensions import Self
27
+
28
+ # Python 3.10+ supports slots in dataclass, fallback for older versions
29
+ if sys.version_info >= (3, 10):
30
+
31
+ def dataclass_with_slots(*args: Any, **kwargs: Any) -> Callable[..., Any]:
32
+ return dataclass(*args, slots=True, **kwargs) # type: ignore[no-any-return]
33
+
34
+ else:
35
+ # For Python < 3.10, use standard dataclass without slots for mypy compatibility
36
+ def dataclass_with_slots(*args: Any, **kwargs: Any) -> Callable[..., Any]:
37
+ return dataclass(*args, **kwargs) # type: ignore[no-any-return]
38
+
39
+
40
+ # ========================================
41
+ # Base Generic Models (Language Agnostic)
42
+ # ========================================
43
+
44
+
45
+ @dataclass(frozen=False)
46
+ class CodeElement(ABC):
47
+ """Base class for all code elements"""
48
+
49
+ name: str
50
+ start_line: int
51
+ end_line: int
52
+ raw_text: str = ""
53
+ language: str = "unknown"
54
+ docstring: Optional[str] = None # JavaDoc/docstring for this element
55
+
56
+
57
+ @dataclass(frozen=False)
58
+ class Function(CodeElement):
59
+ """Generic function/method representation"""
60
+
61
+ parameters: List[str] = field(default_factory=list)
62
+ return_type: Optional[str] = None
63
+ modifiers: List[str] = field(default_factory=list)
64
+ is_async: bool = False
65
+ is_static: bool = False
66
+ is_private: bool = False
67
+ is_public: bool = True
68
+ is_constructor: bool = False
69
+ visibility: str = "public"
70
+ element_type: str = "function"
71
+ # Java-specific fields for detailed analysis
72
+ annotations: List[Dict[str, Any]] = field(default_factory=list)
73
+ throws: List[str] = field(default_factory=list)
74
+ complexity_score: int = 1
75
+ is_abstract: bool = False
76
+ is_final: bool = False
77
+
78
+
79
+ @dataclass(frozen=False)
80
+ class Class(CodeElement):
81
+ """Generic class representation"""
82
+
83
+ class_type: str = "class"
84
+ full_qualified_name: Optional[str] = None
85
+ package_name: Optional[str] = None
86
+ superclass: Optional[str] = None
87
+ interfaces: List[str] = field(default_factory=list)
88
+ modifiers: List[str] = field(default_factory=list)
89
+ visibility: str = "public"
90
+ element_type: str = "class"
91
+ methods: List[Function] = field(default_factory=list)
92
+ # Java-specific fields for detailed analysis
93
+ annotations: List[Dict[str, Any]] = field(default_factory=list)
94
+ is_nested: bool = False
95
+ parent_class: Optional[str] = None
96
+ extends_class: Optional[str] = None # Alias for superclass
97
+ implements_interfaces: List[str] = field(default_factory=list) # Alias for interfaces
98
+
99
+
100
+ @dataclass(frozen=False)
101
+ class Variable(CodeElement):
102
+ """Generic variable representation"""
103
+
104
+ variable_type: Optional[str] = None
105
+ modifiers: List[str] = field(default_factory=list)
106
+ is_constant: bool = False
107
+ is_static: bool = False
108
+ visibility: str = "private"
109
+ element_type: str = "variable"
110
+ initializer: Optional[str] = None
111
+ # Java-specific fields for detailed analysis
112
+ annotations: List[Dict[str, Any]] = field(default_factory=list)
113
+ is_final: bool = False
114
+ field_type: Optional[str] = None # Alias for variable_type
115
+
116
+
117
+ @dataclass(frozen=False)
118
+ class Import(CodeElement):
119
+ """Generic import statement representation"""
120
+
121
+ module_name: str = ""
122
+ module_path: str = "" # Add module_path for compatibility with plugins
123
+ imported_names: List[str] = field(default_factory=list)
124
+ is_wildcard: bool = False
125
+ is_static: bool = False
126
+ element_type: str = "import"
127
+ alias: Optional[str] = None
128
+ # Java-specific fields for detailed analysis
129
+ imported_name: str = "" # Alias for name
130
+ import_statement: str = "" # Full import statement
131
+ line_number: int = 0 # Line number for compatibility
132
+
133
+
134
+ @dataclass(frozen=False)
135
+ class Package(CodeElement):
136
+ """Generic package declaration representation"""
137
+
138
+ element_type: str = "package"
139
+
140
+
141
+ # ========================================
142
+ # Java-Specific Models
143
+ # ========================================
144
+
145
+
146
+ @dataclass(frozen=False)
147
+ class JavaAnnotation:
148
+ """Java annotation representation"""
149
+
150
+ name: str
151
+ parameters: List[str] = field(default_factory=list)
152
+ start_line: int = 0
153
+ end_line: int = 0
154
+ raw_text: str = ""
155
+
156
+ def to_summary_item(self) -> Dict[str, Any]:
157
+ """要約アイテムとして辞書を返す"""
158
+ return {
159
+ "name": self.name,
160
+ "type": "annotation",
161
+ "lines": {"start": self.start_line, "end": self.end_line},
162
+ }
163
+
164
+
165
+ @dataclass(frozen=False)
166
+ class JavaMethod:
167
+ """Java method representation with comprehensive details"""
168
+
169
+ name: str
170
+ return_type: Optional[str] = None
171
+ parameters: List[str] = field(default_factory=list)
172
+ modifiers: List[str] = field(default_factory=list)
173
+ visibility: str = "package"
174
+ annotations: List[JavaAnnotation] = field(default_factory=list)
175
+ throws: List[str] = field(default_factory=list)
176
+ start_line: int = 0
177
+ end_line: int = 0
178
+ is_constructor: bool = False
179
+ is_abstract: bool = False
180
+ is_static: bool = False
181
+ is_final: bool = False
182
+ complexity_score: int = 1
183
+ file_path: str = ""
184
+
185
+ def to_summary_item(self) -> Dict[str, Any]:
186
+ """要約アイテムとして辞書を返す"""
187
+ return {
188
+ "name": self.name,
189
+ "type": "method",
190
+ "lines": {"start": self.start_line, "end": self.end_line},
191
+ }
192
+
193
+
194
+ @dataclass(frozen=False)
195
+ class JavaClass:
196
+ """Java class representation with comprehensive details"""
197
+
198
+ name: str
199
+ full_qualified_name: str = ""
200
+ package_name: str = ""
201
+ class_type: str = "class"
202
+ modifiers: List[str] = field(default_factory=list)
203
+ visibility: str = "package"
204
+ extends_class: Optional[str] = None
205
+ implements_interfaces: List[str] = field(default_factory=list)
206
+ start_line: int = 0
207
+ end_line: int = 0
208
+ annotations: List[JavaAnnotation] = field(default_factory=list)
209
+ is_nested: bool = False
210
+ parent_class: Optional[str] = None
211
+ file_path: str = ""
212
+
213
+ def to_summary_item(self) -> Dict[str, Any]:
214
+ """要約アイテムとして辞書を返す"""
215
+ return {
216
+ "name": self.name,
217
+ "type": "class",
218
+ "lines": {"start": self.start_line, "end": self.end_line},
219
+ }
220
+
221
+
222
+ @dataclass(frozen=False)
223
+ class JavaField:
224
+ """Java field representation"""
225
+
226
+ name: str
227
+ field_type: str = ""
228
+ modifiers: List[str] = field(default_factory=list)
229
+ visibility: str = "package"
230
+ annotations: List[JavaAnnotation] = field(default_factory=list)
231
+ start_line: int = 0
232
+ end_line: int = 0
233
+ is_static: bool = False
234
+ is_final: bool = False
235
+ file_path: str = ""
236
+
237
+ def to_summary_item(self) -> Dict[str, Any]:
238
+ """要約アイテムとして辞書を返す"""
239
+ return {
240
+ "name": self.name,
241
+ "type": "field",
242
+ "lines": {"start": self.start_line, "end": self.end_line},
243
+ }
244
+
245
+
246
+ @dataclass(frozen=False)
247
+ class JavaImport:
248
+ """Java import statement representation"""
249
+
250
+ name: str
251
+ module_name: str = "" # Add module_name for compatibility
252
+ imported_name: str = "" # Add imported_name for compatibility
253
+ import_statement: str = "" # Add import_statement for compatibility
254
+ line_number: int = 0 # Add line_number for compatibility
255
+ is_static: bool = False
256
+ is_wildcard: bool = False
257
+ start_line: int = 0
258
+ end_line: int = 0
259
+
260
+ def to_summary_item(self) -> Dict[str, Any]:
261
+ """要約アイテムとして辞書を返す"""
262
+ return {
263
+ "name": self.name,
264
+ "type": "import",
265
+ "lines": {"start": self.start_line, "end": self.end_line},
266
+ }
267
+
268
+
269
+ @dataclass(frozen=False)
270
+ class JavaPackage:
271
+ """Java package declaration representation"""
272
+
273
+ name: str
274
+ start_line: int = 0
275
+ end_line: int = 0
276
+
277
+
278
+ @dataclass(frozen=False)
279
+ class AnalysisResult:
280
+ """Comprehensive analysis result container"""
281
+
282
+ file_path: str
283
+ language: str = "unknown" # Add language field for new architecture compatibility
284
+ line_count: int = 0 # Add line_count for compatibility
285
+ elements: List[CodeElement] = field(default_factory=list) # Generic elements for new architecture
286
+ node_count: int = 0 # Node count for new architecture
287
+ query_results: Dict[str, Any] = field(default_factory=dict) # Query results for new architecture
288
+ source_code: str = "" # Source code for new architecture
289
+ package: Optional[JavaPackage] = None
290
+ imports: List[JavaImport] = field(default_factory=list)
291
+ classes: List[JavaClass] = field(default_factory=list)
292
+ methods: List[JavaMethod] = field(default_factory=list)
293
+ fields: List[JavaField] = field(default_factory=list)
294
+ annotations: List[JavaAnnotation] = field(default_factory=list)
295
+ analysis_time: float = 0.0
296
+ success: bool = True
297
+ error_message: Optional[str] = None
298
+
299
+ def to_dict(self) -> Dict[str, Any]:
300
+ """Convert analysis result to dictionary for serialization"""
301
+ return {
302
+ "file_path": self.file_path,
303
+ "line_count": self.line_count,
304
+ "package": {"name": self.package.name} if self.package else None,
305
+ "imports": [
306
+ {
307
+ "name": imp.name,
308
+ "is_static": imp.is_static,
309
+ "is_wildcard": imp.is_wildcard,
310
+ }
311
+ for imp in self.imports
312
+ ],
313
+ "classes": [
314
+ {"name": cls.name, "type": cls.class_type, "package": cls.package_name}
315
+ for cls in self.classes
316
+ ],
317
+ "methods": [
318
+ {
319
+ "name": method.name,
320
+ "return_type": method.return_type,
321
+ "parameters": method.parameters,
322
+ }
323
+ for method in self.methods
324
+ ],
325
+ "fields": [
326
+ {"name": field.name, "type": field.field_type} for field in self.fields
327
+ ],
328
+ "annotations": [{"name": ann.name} for ann in self.annotations],
329
+ "analysis_time": self.analysis_time,
330
+ "success": self.success,
331
+ "error_message": self.error_message,
332
+ }
333
+
334
+ def to_summary_dict(self, types: Optional[List[str]] = None) -> Dict[str, Any]:
335
+ """
336
+ 分析結果の要約を辞書として返します。
337
+ 指定された型('classes', 'methods', 'fields'など)の要素のみを含みます。
338
+ """
339
+ if types is None:
340
+ types = ["classes", "methods"] # デフォルト値
341
+
342
+ summary: Dict[str, Any] = {"file_path": self.file_path, "summary_elements": []}
343
+
344
+ all_elements: Dict[str, List[Any]] = {
345
+ "imports": self.imports,
346
+ "classes": self.classes,
347
+ "methods": self.methods,
348
+ "fields": self.fields,
349
+ "annotations": self.annotations,
350
+ }
351
+
352
+ for type_name, elements in all_elements.items():
353
+ if "all" in types or type_name in types:
354
+ for element in elements:
355
+ # 各要素モデルの to_summary_item() を呼び出し
356
+ summary["summary_elements"].append(element.to_summary_item())
357
+
358
+ return summary
359
+
360
+ def get_summary(self) -> Dict[str, Any]:
361
+ """Get analysis summary statistics"""
362
+ return {
363
+ "file_path": self.file_path,
364
+ "line_count": self.line_count,
365
+ "class_count": len(self.classes),
366
+ "method_count": len(self.methods),
367
+ "field_count": len(self.fields),
368
+ "import_count": len(self.imports),
369
+ "annotation_count": len(self.annotations),
370
+ "success": self.success,
371
+ "analysis_time": self.analysis_time,
372
+ }
373
+
374
+ def to_mcp_format(self) -> Dict[str, Any]:
375
+ """
376
+ MCP形式での出力を生成
377
+
378
+ Returns:
379
+ MCP形式の分析結果辞書
380
+ """
381
+ # packageの安全な処理
382
+ package_info = None
383
+ if self.package:
384
+ if hasattr(self.package, 'name'):
385
+ package_info = {"name": self.package.name}
386
+ elif isinstance(self.package, dict):
387
+ package_info = self.package
388
+ else:
389
+ package_info = {"name": str(self.package)}
390
+
391
+ # 安全なアイテム処理ヘルパー関数
392
+ def safe_get_attr(obj, attr, default=""):
393
+ if hasattr(obj, attr):
394
+ return getattr(obj, attr)
395
+ elif isinstance(obj, dict):
396
+ return obj.get(attr, default)
397
+ else:
398
+ return default
399
+
400
+ return {
401
+ "file_path": self.file_path,
402
+ "structure": {
403
+ "package": package_info,
404
+ "imports": [
405
+ {
406
+ "name": safe_get_attr(imp, "name"),
407
+ "is_static": safe_get_attr(imp, "is_static", False),
408
+ "is_wildcard": safe_get_attr(imp, "is_wildcard", False),
409
+ "line_range": {
410
+ "start": safe_get_attr(imp, "start_line", 0),
411
+ "end": safe_get_attr(imp, "end_line", 0)
412
+ }
413
+ }
414
+ for imp in self.imports
415
+ ],
416
+ "classes": [
417
+ {
418
+ "name": safe_get_attr(cls, "name"),
419
+ "type": safe_get_attr(cls, "class_type"),
420
+ "package": safe_get_attr(cls, "package_name"),
421
+ "line_range": {
422
+ "start": safe_get_attr(cls, "start_line", 0),
423
+ "end": safe_get_attr(cls, "end_line", 0)
424
+ }
425
+ }
426
+ for cls in self.classes
427
+ ],
428
+ "methods": [
429
+ {
430
+ "name": safe_get_attr(method, "name"),
431
+ "return_type": safe_get_attr(method, "return_type"),
432
+ "parameters": safe_get_attr(method, "parameters", []),
433
+ "line_range": {
434
+ "start": safe_get_attr(method, "start_line", 0),
435
+ "end": safe_get_attr(method, "end_line", 0)
436
+ }
437
+ }
438
+ for method in self.methods
439
+ ],
440
+ "fields": [
441
+ {
442
+ "name": safe_get_attr(field, "name"),
443
+ "type": safe_get_attr(field, "field_type"),
444
+ "line_range": {
445
+ "start": safe_get_attr(field, "start_line", 0),
446
+ "end": safe_get_attr(field, "end_line", 0)
447
+ }
448
+ }
449
+ for field in self.fields
450
+ ],
451
+ "annotations": [
452
+ {
453
+ "name": safe_get_attr(ann, "name"),
454
+ "line_range": {
455
+ "start": safe_get_attr(ann, "start_line", 0),
456
+ "end": safe_get_attr(ann, "end_line", 0)
457
+ }
458
+ }
459
+ for ann in self.annotations
460
+ ]
461
+ },
462
+ "metadata": {
463
+ "line_count": self.line_count,
464
+ "class_count": len(self.classes),
465
+ "method_count": len(self.methods),
466
+ "field_count": len(self.fields),
467
+ "import_count": len(self.imports),
468
+ "annotation_count": len(self.annotations),
469
+ "analysis_time": self.analysis_time,
470
+ "success": self.success,
471
+ "error_message": self.error_message
472
+ }
473
+ }
474
+
475
+ def get_statistics(self) -> Dict[str, Any]:
476
+ """Get detailed statistics (alias for get_summary)"""
477
+ return self.get_summary()
478
+
479
+ def to_json(self) -> Dict[str, Any]:
480
+ """Convert to JSON-serializable format (alias for to_dict)"""
481
+ return self.to_dict()