tree-sitter-analyzer 1.9.17.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.
Files changed (149) hide show
  1. tree_sitter_analyzer/__init__.py +132 -0
  2. tree_sitter_analyzer/__main__.py +11 -0
  3. tree_sitter_analyzer/api.py +853 -0
  4. tree_sitter_analyzer/cli/__init__.py +39 -0
  5. tree_sitter_analyzer/cli/__main__.py +12 -0
  6. tree_sitter_analyzer/cli/argument_validator.py +89 -0
  7. tree_sitter_analyzer/cli/commands/__init__.py +26 -0
  8. tree_sitter_analyzer/cli/commands/advanced_command.py +226 -0
  9. tree_sitter_analyzer/cli/commands/base_command.py +181 -0
  10. tree_sitter_analyzer/cli/commands/default_command.py +18 -0
  11. tree_sitter_analyzer/cli/commands/find_and_grep_cli.py +188 -0
  12. tree_sitter_analyzer/cli/commands/list_files_cli.py +133 -0
  13. tree_sitter_analyzer/cli/commands/partial_read_command.py +139 -0
  14. tree_sitter_analyzer/cli/commands/query_command.py +109 -0
  15. tree_sitter_analyzer/cli/commands/search_content_cli.py +161 -0
  16. tree_sitter_analyzer/cli/commands/structure_command.py +156 -0
  17. tree_sitter_analyzer/cli/commands/summary_command.py +116 -0
  18. tree_sitter_analyzer/cli/commands/table_command.py +414 -0
  19. tree_sitter_analyzer/cli/info_commands.py +124 -0
  20. tree_sitter_analyzer/cli_main.py +472 -0
  21. tree_sitter_analyzer/constants.py +85 -0
  22. tree_sitter_analyzer/core/__init__.py +15 -0
  23. tree_sitter_analyzer/core/analysis_engine.py +580 -0
  24. tree_sitter_analyzer/core/cache_service.py +333 -0
  25. tree_sitter_analyzer/core/engine.py +585 -0
  26. tree_sitter_analyzer/core/parser.py +293 -0
  27. tree_sitter_analyzer/core/query.py +605 -0
  28. tree_sitter_analyzer/core/query_filter.py +200 -0
  29. tree_sitter_analyzer/core/query_service.py +340 -0
  30. tree_sitter_analyzer/encoding_utils.py +530 -0
  31. tree_sitter_analyzer/exceptions.py +747 -0
  32. tree_sitter_analyzer/file_handler.py +246 -0
  33. tree_sitter_analyzer/formatters/__init__.py +1 -0
  34. tree_sitter_analyzer/formatters/base_formatter.py +201 -0
  35. tree_sitter_analyzer/formatters/csharp_formatter.py +367 -0
  36. tree_sitter_analyzer/formatters/formatter_config.py +197 -0
  37. tree_sitter_analyzer/formatters/formatter_factory.py +84 -0
  38. tree_sitter_analyzer/formatters/formatter_registry.py +377 -0
  39. tree_sitter_analyzer/formatters/formatter_selector.py +96 -0
  40. tree_sitter_analyzer/formatters/go_formatter.py +368 -0
  41. tree_sitter_analyzer/formatters/html_formatter.py +498 -0
  42. tree_sitter_analyzer/formatters/java_formatter.py +423 -0
  43. tree_sitter_analyzer/formatters/javascript_formatter.py +611 -0
  44. tree_sitter_analyzer/formatters/kotlin_formatter.py +268 -0
  45. tree_sitter_analyzer/formatters/language_formatter_factory.py +123 -0
  46. tree_sitter_analyzer/formatters/legacy_formatter_adapters.py +228 -0
  47. tree_sitter_analyzer/formatters/markdown_formatter.py +725 -0
  48. tree_sitter_analyzer/formatters/php_formatter.py +301 -0
  49. tree_sitter_analyzer/formatters/python_formatter.py +830 -0
  50. tree_sitter_analyzer/formatters/ruby_formatter.py +278 -0
  51. tree_sitter_analyzer/formatters/rust_formatter.py +233 -0
  52. tree_sitter_analyzer/formatters/sql_formatter_wrapper.py +689 -0
  53. tree_sitter_analyzer/formatters/sql_formatters.py +536 -0
  54. tree_sitter_analyzer/formatters/typescript_formatter.py +543 -0
  55. tree_sitter_analyzer/formatters/yaml_formatter.py +462 -0
  56. tree_sitter_analyzer/interfaces/__init__.py +9 -0
  57. tree_sitter_analyzer/interfaces/cli.py +535 -0
  58. tree_sitter_analyzer/interfaces/cli_adapter.py +359 -0
  59. tree_sitter_analyzer/interfaces/mcp_adapter.py +224 -0
  60. tree_sitter_analyzer/interfaces/mcp_server.py +428 -0
  61. tree_sitter_analyzer/language_detector.py +553 -0
  62. tree_sitter_analyzer/language_loader.py +271 -0
  63. tree_sitter_analyzer/languages/__init__.py +10 -0
  64. tree_sitter_analyzer/languages/csharp_plugin.py +1076 -0
  65. tree_sitter_analyzer/languages/css_plugin.py +449 -0
  66. tree_sitter_analyzer/languages/go_plugin.py +836 -0
  67. tree_sitter_analyzer/languages/html_plugin.py +496 -0
  68. tree_sitter_analyzer/languages/java_plugin.py +1299 -0
  69. tree_sitter_analyzer/languages/javascript_plugin.py +1622 -0
  70. tree_sitter_analyzer/languages/kotlin_plugin.py +656 -0
  71. tree_sitter_analyzer/languages/markdown_plugin.py +1928 -0
  72. tree_sitter_analyzer/languages/php_plugin.py +862 -0
  73. tree_sitter_analyzer/languages/python_plugin.py +1636 -0
  74. tree_sitter_analyzer/languages/ruby_plugin.py +757 -0
  75. tree_sitter_analyzer/languages/rust_plugin.py +673 -0
  76. tree_sitter_analyzer/languages/sql_plugin.py +2444 -0
  77. tree_sitter_analyzer/languages/typescript_plugin.py +1892 -0
  78. tree_sitter_analyzer/languages/yaml_plugin.py +695 -0
  79. tree_sitter_analyzer/legacy_table_formatter.py +860 -0
  80. tree_sitter_analyzer/mcp/__init__.py +34 -0
  81. tree_sitter_analyzer/mcp/resources/__init__.py +43 -0
  82. tree_sitter_analyzer/mcp/resources/code_file_resource.py +208 -0
  83. tree_sitter_analyzer/mcp/resources/project_stats_resource.py +586 -0
  84. tree_sitter_analyzer/mcp/server.py +869 -0
  85. tree_sitter_analyzer/mcp/tools/__init__.py +28 -0
  86. tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py +779 -0
  87. tree_sitter_analyzer/mcp/tools/analyze_scale_tool_cli_compatible.py +291 -0
  88. tree_sitter_analyzer/mcp/tools/base_tool.py +139 -0
  89. tree_sitter_analyzer/mcp/tools/fd_rg_utils.py +816 -0
  90. tree_sitter_analyzer/mcp/tools/find_and_grep_tool.py +686 -0
  91. tree_sitter_analyzer/mcp/tools/list_files_tool.py +413 -0
  92. tree_sitter_analyzer/mcp/tools/output_format_validator.py +148 -0
  93. tree_sitter_analyzer/mcp/tools/query_tool.py +443 -0
  94. tree_sitter_analyzer/mcp/tools/read_partial_tool.py +464 -0
  95. tree_sitter_analyzer/mcp/tools/search_content_tool.py +836 -0
  96. tree_sitter_analyzer/mcp/tools/table_format_tool.py +572 -0
  97. tree_sitter_analyzer/mcp/tools/universal_analyze_tool.py +653 -0
  98. tree_sitter_analyzer/mcp/utils/__init__.py +113 -0
  99. tree_sitter_analyzer/mcp/utils/error_handler.py +569 -0
  100. tree_sitter_analyzer/mcp/utils/file_output_factory.py +217 -0
  101. tree_sitter_analyzer/mcp/utils/file_output_manager.py +322 -0
  102. tree_sitter_analyzer/mcp/utils/gitignore_detector.py +358 -0
  103. tree_sitter_analyzer/mcp/utils/path_resolver.py +414 -0
  104. tree_sitter_analyzer/mcp/utils/search_cache.py +343 -0
  105. tree_sitter_analyzer/models.py +840 -0
  106. tree_sitter_analyzer/mypy_current_errors.txt +2 -0
  107. tree_sitter_analyzer/output_manager.py +255 -0
  108. tree_sitter_analyzer/platform_compat/__init__.py +3 -0
  109. tree_sitter_analyzer/platform_compat/adapter.py +324 -0
  110. tree_sitter_analyzer/platform_compat/compare.py +224 -0
  111. tree_sitter_analyzer/platform_compat/detector.py +67 -0
  112. tree_sitter_analyzer/platform_compat/fixtures.py +228 -0
  113. tree_sitter_analyzer/platform_compat/profiles.py +217 -0
  114. tree_sitter_analyzer/platform_compat/record.py +55 -0
  115. tree_sitter_analyzer/platform_compat/recorder.py +155 -0
  116. tree_sitter_analyzer/platform_compat/report.py +92 -0
  117. tree_sitter_analyzer/plugins/__init__.py +280 -0
  118. tree_sitter_analyzer/plugins/base.py +647 -0
  119. tree_sitter_analyzer/plugins/manager.py +384 -0
  120. tree_sitter_analyzer/project_detector.py +328 -0
  121. tree_sitter_analyzer/queries/__init__.py +27 -0
  122. tree_sitter_analyzer/queries/csharp.py +216 -0
  123. tree_sitter_analyzer/queries/css.py +615 -0
  124. tree_sitter_analyzer/queries/go.py +275 -0
  125. tree_sitter_analyzer/queries/html.py +543 -0
  126. tree_sitter_analyzer/queries/java.py +402 -0
  127. tree_sitter_analyzer/queries/javascript.py +724 -0
  128. tree_sitter_analyzer/queries/kotlin.py +192 -0
  129. tree_sitter_analyzer/queries/markdown.py +258 -0
  130. tree_sitter_analyzer/queries/php.py +95 -0
  131. tree_sitter_analyzer/queries/python.py +859 -0
  132. tree_sitter_analyzer/queries/ruby.py +92 -0
  133. tree_sitter_analyzer/queries/rust.py +223 -0
  134. tree_sitter_analyzer/queries/sql.py +555 -0
  135. tree_sitter_analyzer/queries/typescript.py +871 -0
  136. tree_sitter_analyzer/queries/yaml.py +236 -0
  137. tree_sitter_analyzer/query_loader.py +272 -0
  138. tree_sitter_analyzer/security/__init__.py +22 -0
  139. tree_sitter_analyzer/security/boundary_manager.py +277 -0
  140. tree_sitter_analyzer/security/regex_checker.py +297 -0
  141. tree_sitter_analyzer/security/validator.py +599 -0
  142. tree_sitter_analyzer/table_formatter.py +782 -0
  143. tree_sitter_analyzer/utils/__init__.py +53 -0
  144. tree_sitter_analyzer/utils/logging.py +433 -0
  145. tree_sitter_analyzer/utils/tree_sitter_compat.py +289 -0
  146. tree_sitter_analyzer-1.9.17.1.dist-info/METADATA +485 -0
  147. tree_sitter_analyzer-1.9.17.1.dist-info/RECORD +149 -0
  148. tree_sitter_analyzer-1.9.17.1.dist-info/WHEEL +4 -0
  149. tree_sitter_analyzer-1.9.17.1.dist-info/entry_points.txt +25 -0
@@ -0,0 +1,840 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Data Models for Multi-Language Code Analysis
4
+
5
+ Data classes for representing code structures extracted through
6
+ Tree-sitter analysis across multiple programming languages.
7
+ """
8
+
9
+ from abc import ABC
10
+ from collections.abc import Callable
11
+ from dataclasses import dataclass, field
12
+ from enum import Enum
13
+ from typing import TYPE_CHECKING, Any
14
+
15
+ from .constants import (
16
+ ELEMENT_TYPE_ANNOTATION,
17
+ ELEMENT_TYPE_CLASS,
18
+ ELEMENT_TYPE_FUNCTION,
19
+ ELEMENT_TYPE_IMPORT,
20
+ ELEMENT_TYPE_PACKAGE,
21
+ ELEMENT_TYPE_VARIABLE,
22
+ is_element_of_type,
23
+ )
24
+
25
+ if TYPE_CHECKING:
26
+ pass
27
+
28
+
29
+ # Use dataclass with slots for Python 3.10+
30
+ def dataclass_with_slots(*args: Any, **kwargs: Any) -> Callable[..., Any]:
31
+ return dataclass(*args, slots=True, **kwargs) # type: ignore[no-any-return]
32
+
33
+
34
+ # ========================================
35
+ # Base Generic Models (Language Agnostic)
36
+ # ========================================
37
+
38
+
39
+ @dataclass(frozen=False)
40
+ class CodeElement(ABC):
41
+ """Base class for all code elements"""
42
+
43
+ name: str
44
+ start_line: int
45
+ end_line: int
46
+ raw_text: str = ""
47
+ language: str = "unknown"
48
+ docstring: str | None = None # JavaDoc/docstring for this element
49
+ element_type: str = "unknown"
50
+
51
+ def to_summary_item(self) -> dict[str, Any]:
52
+ return {
53
+ "name": self.name,
54
+ "type": self.element_type,
55
+ "lines": {"start": self.start_line, "end": self.end_line},
56
+ }
57
+
58
+
59
+ @dataclass(frozen=False)
60
+ class Function(CodeElement):
61
+ """Generic function/method representation"""
62
+
63
+ parameters: list[str] = field(default_factory=list)
64
+ return_type: str | None = None
65
+ modifiers: list[str] = field(default_factory=list)
66
+ is_async: bool = False
67
+ is_static: bool = False
68
+ is_private: bool = False
69
+ is_public: bool = True
70
+ is_constructor: bool = False
71
+ visibility: str = "public"
72
+ element_type: str = "function"
73
+ # Java-specific fields for detailed analysis
74
+ annotations: list[dict[str, Any]] = field(default_factory=list)
75
+ throws: list[str] = field(default_factory=list)
76
+ complexity_score: int = 1
77
+ is_abstract: bool = False
78
+ is_final: bool = False
79
+ # JavaScript-specific fields
80
+ is_generator: bool = False
81
+ is_arrow: bool = False
82
+ is_method: bool = False
83
+ framework_type: str | None = None
84
+ # Python-specific fields
85
+ is_property: bool = False
86
+ is_classmethod: bool = False
87
+ is_staticmethod: bool = False
88
+
89
+
90
+ @dataclass(frozen=False)
91
+ class Class(CodeElement):
92
+ """Generic class representation"""
93
+
94
+ class_type: str = "class"
95
+ full_qualified_name: str | None = None
96
+ package_name: str | None = None
97
+ superclass: str | None = None
98
+ interfaces: list[str] = field(default_factory=list)
99
+ modifiers: list[str] = field(default_factory=list)
100
+ visibility: str = "public"
101
+ element_type: str = "class"
102
+ methods: list[Function] = field(default_factory=list)
103
+ # Java-specific fields for detailed analysis
104
+ annotations: list[dict[str, Any]] = field(default_factory=list)
105
+ is_nested: bool = False
106
+ parent_class: str | None = None
107
+ extends_class: str | None = None # Alias for superclass
108
+ implements_interfaces: list[str] = field(
109
+ default_factory=list
110
+ ) # Alias for interfaces
111
+ # JavaScript-specific fields
112
+ is_react_component: bool = False
113
+ framework_type: str | None = None
114
+ is_exported: bool = False
115
+ # Python-specific fields
116
+ is_dataclass: bool = False
117
+ is_abstract: bool = False
118
+ is_exception: bool = False
119
+
120
+
121
+ @dataclass(frozen=False)
122
+ class Variable(CodeElement):
123
+ """Generic variable representation"""
124
+
125
+ variable_type: str | None = None
126
+ modifiers: list[str] = field(default_factory=list)
127
+ is_constant: bool = False
128
+ is_static: bool = False
129
+ visibility: str = "private"
130
+ element_type: str = "variable"
131
+ initializer: str | None = None
132
+ # Java-specific fields for detailed analysis
133
+ annotations: list[dict[str, Any]] = field(default_factory=list)
134
+ is_final: bool = False
135
+ field_type: str | None = None # Alias for variable_type
136
+
137
+
138
+ @dataclass(frozen=False)
139
+ class Import(CodeElement):
140
+ """Generic import statement representation"""
141
+
142
+ module_name: str = ""
143
+ module_path: str = "" # Add module_path for compatibility with plugins
144
+ imported_names: list[str] = field(default_factory=list)
145
+ is_wildcard: bool = False
146
+ is_static: bool = False
147
+ element_type: str = "import"
148
+ alias: str | None = None
149
+ # Java-specific fields for detailed analysis
150
+ imported_name: str = "" # Alias for name
151
+ import_statement: str = "" # Full import statement
152
+ line_number: int = 0 # Line number for compatibility
153
+
154
+
155
+ @dataclass(frozen=False)
156
+ class Package(CodeElement):
157
+ """Generic package declaration representation"""
158
+
159
+ element_type: str = "package"
160
+
161
+
162
+ # ========================================
163
+ # HTML/CSS-Specific Models
164
+ # ========================================
165
+
166
+
167
+ @dataclass(frozen=False)
168
+ class MarkupElement(CodeElement):
169
+ """
170
+ HTML要素を表現するデータモデル。
171
+ CodeElementを継承し、マークアップ固有の属性を追加する。
172
+ """
173
+
174
+ tag_name: str = ""
175
+ attributes: dict[str, str] = field(default_factory=dict)
176
+ parent: "MarkupElement | None" = None
177
+ children: list["MarkupElement"] = field(default_factory=list)
178
+ element_class: str = "" # 分類システムのカテゴリ (例: 'structure', 'media', 'form')
179
+ element_type: str = "html_element"
180
+
181
+ def to_summary_item(self) -> dict[str, Any]:
182
+ """Return dictionary for summary item"""
183
+ return {
184
+ "name": self.name,
185
+ "tag_name": self.tag_name,
186
+ "type": "html_element",
187
+ "element_class": self.element_class,
188
+ "lines": {"start": self.start_line, "end": self.end_line},
189
+ }
190
+
191
+
192
+ @dataclass(frozen=False)
193
+ class StyleElement(CodeElement):
194
+ """
195
+ CSSルールを表現するデータモデル。
196
+ CodeElementを継承する。
197
+ """
198
+
199
+ selector: str = ""
200
+ properties: dict[str, str] = field(default_factory=dict)
201
+ element_class: str = (
202
+ "" # 分類システムのカテゴリ (例: 'layout', 'typography', 'color')
203
+ )
204
+ element_type: str = "css_rule"
205
+
206
+ def to_summary_item(self) -> dict[str, Any]:
207
+ """Return dictionary for summary item"""
208
+ return {
209
+ "name": self.name,
210
+ "selector": self.selector,
211
+ "type": "css_rule",
212
+ "element_class": self.element_class,
213
+ "lines": {"start": self.start_line, "end": self.end_line},
214
+ }
215
+
216
+
217
+ # ========================================
218
+ # Java-Specific Models
219
+ # ========================================
220
+
221
+
222
+ @dataclass(frozen=False)
223
+ class JavaAnnotation:
224
+ """Java annotation representation"""
225
+
226
+ name: str
227
+ parameters: list[str] = field(default_factory=list)
228
+ start_line: int = 0
229
+ end_line: int = 0
230
+ raw_text: str = ""
231
+
232
+ def to_summary_item(self) -> dict[str, Any]:
233
+ """Return dictionary for summary item"""
234
+ return {
235
+ "name": self.name,
236
+ "type": "annotation",
237
+ "lines": {"start": self.start_line, "end": self.end_line},
238
+ }
239
+
240
+
241
+ @dataclass(frozen=False)
242
+ class JavaMethod:
243
+ """Java method representation with comprehensive details"""
244
+
245
+ name: str
246
+ return_type: str | None = None
247
+ parameters: list[str] = field(default_factory=list)
248
+ modifiers: list[str] = field(default_factory=list)
249
+ visibility: str = "package"
250
+ annotations: list[JavaAnnotation] = field(default_factory=list)
251
+ throws: list[str] = field(default_factory=list)
252
+ start_line: int = 0
253
+ end_line: int = 0
254
+ is_constructor: bool = False
255
+ is_abstract: bool = False
256
+ is_static: bool = False
257
+ is_final: bool = False
258
+ complexity_score: int = 1
259
+ file_path: str = ""
260
+
261
+ def to_summary_item(self) -> dict[str, Any]:
262
+ """Return dictionary for summary item"""
263
+ return {
264
+ "name": self.name,
265
+ "type": "method",
266
+ "lines": {"start": self.start_line, "end": self.end_line},
267
+ }
268
+
269
+
270
+ @dataclass(frozen=False)
271
+ class JavaClass:
272
+ """Java class representation with comprehensive details"""
273
+
274
+ name: str
275
+ full_qualified_name: str = ""
276
+ package_name: str = ""
277
+ class_type: str = "class"
278
+ modifiers: list[str] = field(default_factory=list)
279
+ visibility: str = "package"
280
+ extends_class: str | None = None
281
+ implements_interfaces: list[str] = field(default_factory=list)
282
+ start_line: int = 0
283
+ end_line: int = 0
284
+ annotations: list[JavaAnnotation] = field(default_factory=list)
285
+ is_nested: bool = False
286
+ parent_class: str | None = None
287
+ file_path: str = ""
288
+
289
+ def to_summary_item(self) -> dict[str, Any]:
290
+ """Return dictionary for summary item"""
291
+ return {
292
+ "name": self.name,
293
+ "type": "class",
294
+ "lines": {"start": self.start_line, "end": self.end_line},
295
+ }
296
+
297
+
298
+ @dataclass(frozen=False)
299
+ class JavaField:
300
+ """Java field representation"""
301
+
302
+ name: str
303
+ field_type: str = ""
304
+ modifiers: list[str] = field(default_factory=list)
305
+ visibility: str = "package"
306
+ annotations: list[JavaAnnotation] = field(default_factory=list)
307
+ start_line: int = 0
308
+ end_line: int = 0
309
+ is_static: bool = False
310
+ is_final: bool = False
311
+ file_path: str = ""
312
+
313
+ def to_summary_item(self) -> dict[str, Any]:
314
+ """Return dictionary for summary item"""
315
+ return {
316
+ "name": self.name,
317
+ "type": "field",
318
+ "lines": {"start": self.start_line, "end": self.end_line},
319
+ }
320
+
321
+
322
+ @dataclass(frozen=False)
323
+ class JavaImport:
324
+ """Java import statement representation"""
325
+
326
+ name: str
327
+ module_name: str = "" # Add module_name for compatibility
328
+ imported_name: str = "" # Add imported_name for compatibility
329
+ import_statement: str = "" # Add import_statement for compatibility
330
+ line_number: int = 0 # Add line_number for compatibility
331
+ is_static: bool = False
332
+ is_wildcard: bool = False
333
+ start_line: int = 0
334
+ end_line: int = 0
335
+
336
+ def to_summary_item(self) -> dict[str, Any]:
337
+ """要約アイテムとして辞書を返す"""
338
+ return {
339
+ "name": self.name,
340
+ "type": "import",
341
+ "lines": {"start": self.start_line, "end": self.end_line},
342
+ }
343
+
344
+
345
+ @dataclass(frozen=False)
346
+ class JavaPackage:
347
+ """Java package declaration representation"""
348
+
349
+ name: str
350
+ start_line: int = 0
351
+ end_line: int = 0
352
+
353
+ def to_summary_item(self) -> dict[str, Any]:
354
+ """Return dictionary for summary item"""
355
+ return {
356
+ "name": self.name,
357
+ "type": "package",
358
+ "lines": {"start": self.start_line, "end": self.end_line},
359
+ }
360
+
361
+
362
+ @dataclass(frozen=False)
363
+ class AnalysisResult:
364
+ """Comprehensive analysis result container"""
365
+
366
+ file_path: str
367
+ language: str = "unknown" # Add language field for new architecture compatibility
368
+ line_count: int = 0 # Add line_count for compatibility
369
+ elements: list[CodeElement] = field(
370
+ default_factory=list
371
+ ) # Generic elements for new architecture
372
+ node_count: int = 0 # Node count for new architecture
373
+ query_results: dict[str, Any] = field(
374
+ default_factory=dict
375
+ ) # Query results for new architecture
376
+ source_code: str = "" # Source code for new architecture
377
+ package: JavaPackage | None = None
378
+ # Legacy fields removed - use elements list instead
379
+ # imports: list[JavaImport] = field(default_factory=list)
380
+ # classes: list[JavaClass] = field(default_factory=list)
381
+ # methods: list[JavaMethod] = field(default_factory=list)
382
+ # fields: list[JavaField] = field(default_factory=list)
383
+ # annotations: list[JavaAnnotation] = field(default_factory=list)
384
+ analysis_time: float = 0.0
385
+ success: bool = True
386
+ error_message: str | None = None
387
+
388
+ def to_dict(self) -> dict[str, Any]:
389
+ """Convert analysis result to dictionary for serialization using unified elements"""
390
+ # Use unified elements list for consistent data structure
391
+ elements = self.elements or []
392
+
393
+ # Extract elements by type from unified list using constants
394
+ classes = [e for e in elements if is_element_of_type(e, ELEMENT_TYPE_CLASS)]
395
+ methods = [e for e in elements if is_element_of_type(e, ELEMENT_TYPE_FUNCTION)]
396
+ fields = [e for e in elements if is_element_of_type(e, ELEMENT_TYPE_VARIABLE)]
397
+ imports = [e for e in elements if is_element_of_type(e, ELEMENT_TYPE_IMPORT)]
398
+ packages = [e for e in elements if is_element_of_type(e, ELEMENT_TYPE_PACKAGE)]
399
+
400
+ return {
401
+ "file_path": self.file_path,
402
+ "line_count": self.line_count,
403
+ "package": {"name": packages[0].name} if packages else None,
404
+ "imports": [
405
+ {
406
+ "name": imp.name,
407
+ "is_static": getattr(imp, "is_static", False),
408
+ "is_wildcard": getattr(imp, "is_wildcard", False),
409
+ }
410
+ for imp in imports
411
+ ],
412
+ "classes": [
413
+ {
414
+ "name": cls.name,
415
+ "type": getattr(cls, "class_type", "class"),
416
+ "package": getattr(cls, "package_name", None),
417
+ }
418
+ for cls in classes
419
+ ],
420
+ "methods": [
421
+ {
422
+ "name": method.name,
423
+ "return_type": getattr(method, "return_type", None),
424
+ "parameters": getattr(method, "parameters", []),
425
+ }
426
+ for method in methods
427
+ ],
428
+ "fields": [
429
+ {"name": field.name, "type": getattr(field, "field_type", None)}
430
+ for field in fields
431
+ ],
432
+ "annotations": [
433
+ {"name": getattr(ann, "name", str(ann))}
434
+ for ann in getattr(self, "annotations", [])
435
+ ],
436
+ "analysis_time": self.analysis_time,
437
+ "success": self.success,
438
+ "error_message": self.error_message,
439
+ }
440
+
441
+ def to_summary_dict(self, types: list[str] | None = None) -> dict[str, Any]:
442
+ """
443
+ Return analysis summary as a dictionary using unified elements.
444
+ Only include specified element types (e.g., 'classes', 'methods', 'fields').
445
+ """
446
+ if types is None:
447
+ types = ["classes", "methods"] # default
448
+
449
+ summary: dict[str, Any] = {"file_path": self.file_path, "summary_elements": []}
450
+ elements = self.elements or []
451
+
452
+ # Map type names to element_type constants
453
+ type_mapping = {
454
+ "imports": ELEMENT_TYPE_IMPORT,
455
+ "classes": ELEMENT_TYPE_CLASS,
456
+ "methods": ELEMENT_TYPE_FUNCTION,
457
+ "fields": ELEMENT_TYPE_VARIABLE,
458
+ "annotations": ELEMENT_TYPE_ANNOTATION,
459
+ }
460
+
461
+ for type_name, element_type in type_mapping.items():
462
+ if "all" in types or type_name in types:
463
+ type_elements = [
464
+ e for e in elements if is_element_of_type(e, element_type)
465
+ ]
466
+ for element in type_elements:
467
+ # Call each element model's to_summary_item()
468
+ summary["summary_elements"].append(element.to_summary_item())
469
+
470
+ return summary
471
+
472
+ def get_summary(self) -> dict[str, Any]:
473
+ """Get analysis summary statistics using unified elements"""
474
+ elements = self.elements or []
475
+
476
+ # Count elements by type from unified list using constants
477
+ classes = [e for e in elements if is_element_of_type(e, ELEMENT_TYPE_CLASS)]
478
+ methods = [e for e in elements if is_element_of_type(e, ELEMENT_TYPE_FUNCTION)]
479
+ fields = [e for e in elements if is_element_of_type(e, ELEMENT_TYPE_VARIABLE)]
480
+ imports = [e for e in elements if is_element_of_type(e, ELEMENT_TYPE_IMPORT)]
481
+ annotations = [
482
+ e for e in elements if is_element_of_type(e, ELEMENT_TYPE_ANNOTATION)
483
+ ]
484
+
485
+ return {
486
+ "file_path": self.file_path,
487
+ "line_count": self.line_count,
488
+ "class_count": len(classes),
489
+ "method_count": len(methods),
490
+ "field_count": len(fields),
491
+ "import_count": len(imports),
492
+ "annotation_count": len(annotations),
493
+ "success": self.success,
494
+ "analysis_time": self.analysis_time,
495
+ }
496
+
497
+ def to_mcp_format(self) -> dict[str, Any]:
498
+ """
499
+ Produce output in MCP-compatible format
500
+
501
+ Returns:
502
+ MCP-style result dictionary
503
+ """
504
+ # packageの安全な処理
505
+ package_info = None
506
+ if self.package:
507
+ if hasattr(self.package, "name"):
508
+ package_info = {"name": self.package.name}
509
+ elif isinstance(self.package, dict):
510
+ package_info = self.package
511
+ else:
512
+ package_info = {"name": str(self.package)}
513
+
514
+ # 安全なアイテム処理ヘルパー関数
515
+ def safe_get_attr(obj: Any, attr: str, default: Any = "") -> Any:
516
+ if hasattr(obj, attr):
517
+ return getattr(obj, attr)
518
+ elif isinstance(obj, dict):
519
+ return obj.get(attr, default)
520
+ else:
521
+ return default
522
+
523
+ return {
524
+ "file_path": self.file_path,
525
+ "structure": {
526
+ "package": package_info,
527
+ "imports": [
528
+ {
529
+ "name": safe_get_attr(imp, "name"),
530
+ "is_static": safe_get_attr(imp, "is_static", False),
531
+ "is_wildcard": safe_get_attr(imp, "is_wildcard", False),
532
+ "line_range": {
533
+ "start": safe_get_attr(imp, "start_line", 0),
534
+ "end": safe_get_attr(imp, "end_line", 0),
535
+ },
536
+ }
537
+ for imp in [
538
+ e
539
+ for e in (self.elements or [])
540
+ if is_element_of_type(e, ELEMENT_TYPE_IMPORT)
541
+ ]
542
+ ],
543
+ "classes": [
544
+ {
545
+ "name": safe_get_attr(cls, "name"),
546
+ "type": safe_get_attr(cls, "class_type"),
547
+ "package": safe_get_attr(cls, "package_name"),
548
+ "line_range": {
549
+ "start": safe_get_attr(cls, "start_line", 0),
550
+ "end": safe_get_attr(cls, "end_line", 0),
551
+ },
552
+ }
553
+ for cls in [
554
+ e
555
+ for e in (self.elements or [])
556
+ if is_element_of_type(e, ELEMENT_TYPE_CLASS)
557
+ ]
558
+ ],
559
+ "methods": [
560
+ {
561
+ "name": safe_get_attr(method, "name"),
562
+ "return_type": safe_get_attr(method, "return_type"),
563
+ "parameters": safe_get_attr(method, "parameters", []),
564
+ "line_range": {
565
+ "start": safe_get_attr(method, "start_line", 0),
566
+ "end": safe_get_attr(method, "end_line", 0),
567
+ },
568
+ }
569
+ for method in [
570
+ e
571
+ for e in (self.elements or [])
572
+ if is_element_of_type(e, ELEMENT_TYPE_FUNCTION)
573
+ ]
574
+ ],
575
+ "fields": [
576
+ {
577
+ "name": safe_get_attr(field, "name"),
578
+ "type": safe_get_attr(field, "field_type"),
579
+ "line_range": {
580
+ "start": safe_get_attr(field, "start_line", 0),
581
+ "end": safe_get_attr(field, "end_line", 0),
582
+ },
583
+ }
584
+ for field in [
585
+ e
586
+ for e in (self.elements or [])
587
+ if is_element_of_type(e, ELEMENT_TYPE_VARIABLE)
588
+ ]
589
+ ],
590
+ "annotations": [
591
+ {
592
+ "name": safe_get_attr(ann, "name"),
593
+ "line_range": {
594
+ "start": safe_get_attr(ann, "start_line", 0),
595
+ "end": safe_get_attr(ann, "end_line", 0),
596
+ },
597
+ }
598
+ for ann in [
599
+ e
600
+ for e in (self.elements or [])
601
+ if is_element_of_type(e, ELEMENT_TYPE_ANNOTATION)
602
+ ]
603
+ ],
604
+ },
605
+ "metadata": {
606
+ "line_count": self.line_count,
607
+ "class_count": len(
608
+ [
609
+ e
610
+ for e in (self.elements or [])
611
+ if is_element_of_type(e, ELEMENT_TYPE_CLASS)
612
+ ]
613
+ ),
614
+ "method_count": len(
615
+ [
616
+ e
617
+ for e in (self.elements or [])
618
+ if is_element_of_type(e, ELEMENT_TYPE_FUNCTION)
619
+ ]
620
+ ),
621
+ "field_count": len(
622
+ [
623
+ e
624
+ for e in (self.elements or [])
625
+ if is_element_of_type(e, ELEMENT_TYPE_VARIABLE)
626
+ ]
627
+ ),
628
+ "import_count": len(
629
+ [
630
+ e
631
+ for e in (self.elements or [])
632
+ if is_element_of_type(e, ELEMENT_TYPE_IMPORT)
633
+ ]
634
+ ),
635
+ "annotation_count": len(
636
+ [
637
+ e
638
+ for e in (self.elements or [])
639
+ if is_element_of_type(e, ELEMENT_TYPE_ANNOTATION)
640
+ ]
641
+ ),
642
+ "analysis_time": self.analysis_time,
643
+ "success": self.success,
644
+ "error_message": self.error_message,
645
+ },
646
+ }
647
+
648
+ def get_statistics(self) -> dict[str, Any]:
649
+ """Get detailed statistics (alias for get_summary)"""
650
+ return self.get_summary()
651
+
652
+ def to_json(self) -> dict[str, Any]:
653
+ """Convert to JSON-serializable format (alias for to_dict)"""
654
+ return self.to_dict()
655
+
656
+
657
+ # ========================================
658
+ # SQL-Specific Models
659
+ # ========================================
660
+
661
+
662
+ class SQLElementType(Enum):
663
+ """SQL element types for database objects"""
664
+
665
+ TABLE = "table"
666
+ VIEW = "view"
667
+ PROCEDURE = "procedure"
668
+ FUNCTION = "function"
669
+ TRIGGER = "trigger"
670
+ INDEX = "index"
671
+
672
+
673
+ @dataclass(frozen=False)
674
+ class SQLColumn:
675
+ """SQL column definition"""
676
+
677
+ name: str
678
+ data_type: str
679
+ nullable: bool = True
680
+ default_value: str | None = None
681
+ is_primary_key: bool = False
682
+ is_foreign_key: bool = False
683
+ foreign_key_reference: str | None = None
684
+
685
+
686
+ @dataclass(frozen=False)
687
+ class SQLParameter:
688
+ """SQL procedure/function parameter"""
689
+
690
+ name: str
691
+ data_type: str
692
+ direction: str = "IN" # IN, OUT, INOUT
693
+
694
+
695
+ @dataclass(frozen=False)
696
+ class SQLConstraint:
697
+ """SQL constraint definition"""
698
+
699
+ name: str | None
700
+ constraint_type: str # PRIMARY_KEY, FOREIGN_KEY, UNIQUE, CHECK
701
+ columns: list[str] = field(default_factory=list)
702
+ reference_table: str | None = None
703
+ reference_columns: list[str] | None = None
704
+
705
+
706
+ @dataclass(frozen=False)
707
+ class SQLElement(CodeElement):
708
+ """Base SQL element with database-specific metadata"""
709
+
710
+ sql_element_type: SQLElementType = SQLElementType.TABLE
711
+ columns: list[SQLColumn] = field(default_factory=list)
712
+ parameters: list[SQLParameter] = field(default_factory=list)
713
+ dependencies: list[str] = field(default_factory=list)
714
+ constraints: list[SQLConstraint] = field(default_factory=list)
715
+ element_type: str = "sql_element"
716
+
717
+ # SQL-specific metadata
718
+ schema_name: str | None = None
719
+ table_name: str | None = None # For indexes, triggers
720
+ return_type: str | None = None # For functions
721
+ trigger_timing: str | None = None # BEFORE, AFTER
722
+ trigger_event: str | None = None # INSERT, UPDATE, DELETE
723
+ index_type: str | None = None # UNIQUE, CLUSTERED, etc.
724
+
725
+ def to_summary_item(self) -> dict[str, Any]:
726
+ """Return dictionary for summary item with SQL-specific information"""
727
+ return {
728
+ "name": self.name,
729
+ "type": self.sql_element_type.value,
730
+ "lines": {"start": self.start_line, "end": self.end_line},
731
+ "columns_count": len(self.columns),
732
+ "parameters_count": len(self.parameters),
733
+ "dependencies": self.dependencies,
734
+ }
735
+
736
+
737
+ @dataclass(frozen=False)
738
+ class SQLTable(SQLElement):
739
+ """SQL table representation"""
740
+
741
+ sql_element_type: SQLElementType = SQLElementType.TABLE
742
+ element_type: str = "table"
743
+
744
+ def get_primary_key_columns(self) -> list[str]:
745
+ """Get primary key column names"""
746
+ return [col.name for col in self.columns if col.is_primary_key]
747
+
748
+ def get_foreign_key_columns(self) -> list[str]:
749
+ """Get foreign key column names"""
750
+ return [col.name for col in self.columns if col.is_foreign_key]
751
+
752
+
753
+ @dataclass(frozen=False)
754
+ class SQLView(SQLElement):
755
+ """SQL view representation"""
756
+
757
+ sql_element_type: SQLElementType = SQLElementType.VIEW
758
+ element_type: str = "view"
759
+ source_tables: list[str] = field(default_factory=list)
760
+ view_definition: str = ""
761
+
762
+
763
+ @dataclass(frozen=False)
764
+ class SQLProcedure(SQLElement):
765
+ """SQL stored procedure representation"""
766
+
767
+ sql_element_type: SQLElementType = SQLElementType.PROCEDURE
768
+ element_type: str = "procedure"
769
+
770
+
771
+ @dataclass(frozen=False)
772
+ class SQLFunction(SQLElement):
773
+ """SQL function representation"""
774
+
775
+ sql_element_type: SQLElementType = SQLElementType.FUNCTION
776
+ element_type: str = "function"
777
+ is_deterministic: bool = False
778
+ reads_sql_data: bool = False
779
+
780
+
781
+ @dataclass(frozen=False)
782
+ class SQLTrigger(SQLElement):
783
+ """SQL trigger representation"""
784
+
785
+ sql_element_type: SQLElementType = SQLElementType.TRIGGER
786
+ element_type: str = "trigger"
787
+ table_name: str | None = None
788
+ trigger_timing: str | None = None
789
+ trigger_event: str | None = None
790
+
791
+
792
+ @dataclass(frozen=False)
793
+ class SQLIndex(SQLElement):
794
+ """SQL index representation"""
795
+
796
+ sql_element_type: SQLElementType = SQLElementType.INDEX
797
+ element_type: str = "index"
798
+ indexed_columns: list[str] = field(default_factory=list)
799
+ is_unique: bool = False
800
+
801
+
802
+ @dataclass(frozen=False)
803
+ class YAMLElement(CodeElement):
804
+ """
805
+ YAML要素を表現するデータモデル。
806
+
807
+ Attributes:
808
+ element_type: 要素タイプ (mapping, sequence, scalar, anchor, alias, comment, document)
809
+ key: マッピングのキー
810
+ value: スカラー値(複合構造の場合はNone)
811
+ value_type: 値の型 (string, number, boolean, null, mapping, sequence)
812
+ anchor_name: アンカー名 (&name)
813
+ alias_target: エイリアスの参照先名(展開しない)
814
+ nesting_level: AST上の論理的な深さ
815
+ document_index: マルチドキュメントYAMLでのドキュメントインデックス
816
+ child_count: 複合構造の子要素数
817
+ """
818
+
819
+ language: str = "yaml"
820
+ element_type: str = "yaml"
821
+ key: str | None = None
822
+ value: str | None = None
823
+ value_type: str | None = None
824
+ anchor_name: str | None = None
825
+ alias_target: str | None = None
826
+ nesting_level: int = 0
827
+ document_index: int = 0
828
+ child_count: int | None = None
829
+
830
+ def to_summary_item(self) -> dict[str, Any]:
831
+ """Return dictionary for summary item with YAML-specific information."""
832
+ return {
833
+ "name": self.name,
834
+ "type": self.element_type,
835
+ "lines": {"start": self.start_line, "end": self.end_line},
836
+ "key": self.key,
837
+ "value_type": self.value_type,
838
+ "nesting_level": self.nesting_level,
839
+ "document_index": self.document_index,
840
+ }