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,268 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Kotlin-specific table formatter.
4
+ """
5
+
6
+ from typing import Any
7
+
8
+ from .base_formatter import BaseTableFormatter
9
+
10
+
11
+ class KotlinTableFormatter(BaseTableFormatter):
12
+ """Table formatter specialized for Kotlin"""
13
+
14
+ def _format_full_table(self, data: dict[str, Any]) -> str:
15
+ """Full table format for Kotlin"""
16
+ lines = []
17
+
18
+ # Header - Kotlin
19
+ package_name = (data.get("package") or {}).get("name", "default")
20
+ file_name = data.get("file_path", "Unknown").split("/")[-1].split("\\")[-1]
21
+ if package_name != "default":
22
+ lines.append(f"# {package_name}.{file_name}")
23
+ else:
24
+ lines.append(f"# {file_name}")
25
+ lines.append("")
26
+
27
+ # Imports
28
+ imports = data.get("imports", [])
29
+ if imports:
30
+ lines.append("## Imports")
31
+ lines.append("```kotlin")
32
+ for imp in imports:
33
+ lines.append(str(imp.get("statement", "")))
34
+ lines.append("```")
35
+ lines.append("")
36
+
37
+ # Classes/Objects/Interfaces
38
+ classes = data.get("classes", [])
39
+ if classes:
40
+ lines.append("## Classes & Objects")
41
+ lines.append("| Name | Type | Visibility | Lines | Props | Methods |")
42
+ lines.append("|------|------|------------|-------|-------|---------|")
43
+
44
+ for cls in classes:
45
+ name = str(cls.get("name", "Unknown"))
46
+ cls_type = str(cls.get("type", "class"))
47
+ visibility = str(cls.get("visibility", "public"))
48
+ line_range = cls.get("line_range", {})
49
+ lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
50
+
51
+ # Count props/methods within
52
+ class_props = len(
53
+ [
54
+ p
55
+ for p in data.get("fields", [])
56
+ if line_range.get("start", 0)
57
+ <= p.get("line_range", {}).get("start", 0)
58
+ <= line_range.get("end", 0)
59
+ ]
60
+ )
61
+ class_methods = len(
62
+ [
63
+ m
64
+ for m in data.get("methods", [])
65
+ if line_range.get("start", 0)
66
+ <= m.get("line_range", {}).get("start", 0)
67
+ <= line_range.get("end", 0)
68
+ ]
69
+ )
70
+
71
+ lines.append(
72
+ f"| {name} | {cls_type} | {visibility} | {lines_str} | {class_props} | {class_methods} |"
73
+ )
74
+ lines.append("")
75
+
76
+ # Top-level Functions
77
+ # We want to list all functions, but maybe group them or just list them.
78
+ # BaseTableFormatter lists all methods in data.get("methods") usually.
79
+ fns = data.get("methods", [])
80
+ if fns:
81
+ lines.append("## Functions")
82
+ lines.append("| Function | Signature | Vis | Lines | Suspend | Doc |")
83
+ lines.append("|----------|-----------|-----|-------|---------|-----|")
84
+
85
+ for fn in fns:
86
+ lines.append(self._format_fn_row(fn))
87
+ lines.append("")
88
+
89
+ # Top-level Properties
90
+ props = data.get("fields", []) # Mapped to fields
91
+ if props:
92
+ lines.append("## Properties")
93
+ lines.append("| Name | Type | Vis | Kind | Line | Doc |")
94
+ lines.append("|------|------|-----|------|------|-----|")
95
+
96
+ for prop in props:
97
+ lines.append(self._format_prop_row(prop))
98
+ lines.append("")
99
+
100
+ return "\n".join(lines)
101
+
102
+ def _format_compact_table(self, data: dict[str, Any]) -> str:
103
+ """Compact table format for Kotlin"""
104
+ lines = []
105
+
106
+ # Header
107
+ package_name = (data.get("package") or {}).get("name", "default")
108
+ file_name = data.get("file_path", "Unknown").split("/")[-1].split("\\")[-1]
109
+ if package_name != "default":
110
+ lines.append(f"# {package_name}.{file_name}")
111
+ else:
112
+ lines.append(f"# {file_name}")
113
+ lines.append("")
114
+
115
+ # Info
116
+ stats = data.get("statistics") or {}
117
+ lines.append("## Info")
118
+ lines.append("| Property | Value |")
119
+ lines.append("|----------|-------|")
120
+ lines.append(f"| Package | {package_name} |")
121
+ lines.append(f"| Classes | {len(data.get('classes', []))} |")
122
+ lines.append(f"| Functions | {stats.get('method_count', 0)} |")
123
+ lines.append(f"| Properties | {stats.get('field_count', 0)} |")
124
+ lines.append("")
125
+
126
+ # Functions (compact)
127
+ fns = data.get("methods", [])
128
+ if fns:
129
+ lines.append("## Functions")
130
+ lines.append("| Fn | Sig | V | S | L | Doc |")
131
+ lines.append("|----|-----|---|---|---|-----|")
132
+
133
+ for fn in fns:
134
+ name = str(fn.get("name", ""))
135
+ signature = self._create_compact_signature(fn)
136
+ visibility = self._convert_visibility(str(fn.get("visibility", "")))
137
+ is_suspend = "Y" if fn.get("is_suspend", False) else "-"
138
+ line_range = fn.get("line_range", {})
139
+ lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
140
+ doc = self._clean_csv_text(
141
+ self._extract_doc_summary(str(fn.get("docstring", "") or ""))
142
+ )
143
+
144
+ lines.append(
145
+ f"| {name} | {signature} | {visibility} | {is_suspend} | {lines_str} | {doc} |"
146
+ )
147
+ lines.append("")
148
+
149
+ return "\n".join(lines)
150
+
151
+ def _format_fn_row(self, fn: dict[str, Any]) -> str:
152
+ """Format a function table row for Kotlin"""
153
+ name = str(fn.get("name", ""))
154
+ signature = self._create_full_signature(fn)
155
+ visibility = self._convert_visibility(str(fn.get("visibility", "")))
156
+ is_suspend = "Yes" if fn.get("is_suspend", False) else "-"
157
+ line_range = fn.get("line_range", {})
158
+ lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
159
+ doc = self._clean_csv_text(
160
+ self._extract_doc_summary(str(fn.get("docstring", "") or ""))
161
+ )
162
+
163
+ return f"| {name} | {signature} | {visibility} | {lines_str} | {is_suspend} | {doc} |"
164
+
165
+ def _format_prop_row(self, prop: dict[str, Any]) -> str:
166
+ """Format a property table row for Kotlin"""
167
+ name = str(prop.get("name", ""))
168
+ prop_type = str(prop.get("type", ""))
169
+ visibility = self._convert_visibility(str(prop.get("visibility", "")))
170
+ # Check val/var if extracted
171
+ kind = (
172
+ "val"
173
+ if prop.get("is_val", False)
174
+ else ("var" if prop.get("is_var", False) else "-")
175
+ )
176
+ line = prop.get("line_range", {}).get("start", 0)
177
+ doc = self._clean_csv_text(
178
+ self._extract_doc_summary(str(prop.get("docstring", "") or ""))
179
+ )
180
+
181
+ return f"| {name} | {prop_type} | {visibility} | {kind} | {line} | {doc} |"
182
+
183
+ def _create_full_signature(self, fn: dict[str, Any]) -> str:
184
+ """Create full function signature for Kotlin"""
185
+ # Kotlin: fun name(p1: T1, p2: T2): R
186
+ params = fn.get("parameters", [])
187
+ params_str_list = []
188
+ for p in params:
189
+ if isinstance(p, dict):
190
+ # "name: type" is expected
191
+ params_str_list.append(f"{p.get('name')}: {p.get('type')}")
192
+ else:
193
+ params_str_list.append(str(p))
194
+
195
+ params_str = ", ".join(params_str_list)
196
+ return_type = fn.get("return_type", "")
197
+ ret_str = f": {return_type}" if return_type and return_type != "Unit" else ""
198
+
199
+ return f"fun({params_str}){ret_str}"
200
+
201
+ def _create_compact_signature(self, fn: dict[str, Any]) -> str:
202
+ """Create compact function signature for Kotlin"""
203
+ params = fn.get("parameters", [])
204
+ params_summary = f"({len(params)})"
205
+ return_type = fn.get("return_type", "")
206
+ ret_str = f":{return_type}" if return_type and return_type != "Unit" else ""
207
+
208
+ return f"{params_summary}{ret_str}"
209
+
210
+ def _convert_visibility(self, visibility: str) -> str:
211
+ """Convert visibility to short symbol"""
212
+ if visibility == "public":
213
+ return "pub"
214
+ elif visibility == "private":
215
+ return "priv"
216
+ elif visibility == "protected":
217
+ return "prot"
218
+ elif visibility == "internal":
219
+ return "int"
220
+ return visibility
221
+
222
+ def format_table(
223
+ self, analysis_result: dict[str, Any], table_type: str = "full"
224
+ ) -> str:
225
+ """Format table output for Kotlin"""
226
+ # Set the format type based on table_type parameter
227
+ original_format_type = self.format_type
228
+ self.format_type = table_type
229
+
230
+ try:
231
+ # Handle json format separately
232
+ if table_type == "json":
233
+ return self._format_json(analysis_result)
234
+ # Use the existing format_structure method
235
+ return self.format_structure(analysis_result)
236
+ finally:
237
+ # Restore original format type
238
+ self.format_type = original_format_type
239
+
240
+ def format_summary(self, analysis_result: dict[str, Any]) -> str:
241
+ """Format summary output for Kotlin"""
242
+ return self._format_compact_table(analysis_result)
243
+
244
+ def format_structure(self, analysis_result: dict[str, Any]) -> str:
245
+ """Format structure analysis output for Kotlin"""
246
+ if self.format_type == "compact":
247
+ return self._format_compact_table(analysis_result)
248
+ return self._format_full_table(analysis_result)
249
+
250
+ def format_advanced(
251
+ self, analysis_result: dict[str, Any], output_format: str = "json"
252
+ ) -> str:
253
+ """Format advanced analysis output for Kotlin"""
254
+ if output_format == "json":
255
+ return self._format_json(analysis_result)
256
+ elif output_format == "csv":
257
+ return self._format_csv(analysis_result)
258
+ else:
259
+ return self._format_full_table(analysis_result)
260
+
261
+ def _format_json(self, data: dict[str, Any]) -> str:
262
+ """Format data as JSON"""
263
+ import json
264
+
265
+ try:
266
+ return json.dumps(data, indent=2, ensure_ascii=False)
267
+ except (TypeError, ValueError) as e:
268
+ return f"# JSON serialization error: {e}\n"
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Factory for creating language-specific formatters for different output types.
4
+ """
5
+
6
+ from .base_formatter import BaseFormatter
7
+ from .csharp_formatter import CSharpTableFormatter
8
+ from .go_formatter import GoTableFormatter
9
+ from .html_formatter import HtmlFormatter
10
+ from .java_formatter import JavaTableFormatter
11
+ from .javascript_formatter import JavaScriptTableFormatter
12
+ from .kotlin_formatter import KotlinTableFormatter
13
+ from .markdown_formatter import MarkdownFormatter
14
+ from .php_formatter import PHPTableFormatter
15
+ from .python_formatter import PythonTableFormatter
16
+ from .ruby_formatter import RubyTableFormatter
17
+ from .rust_formatter import RustTableFormatter
18
+ from .sql_formatter_wrapper import SQLFormatterWrapper
19
+ from .typescript_formatter import TypeScriptTableFormatter
20
+ from .yaml_formatter import YAMLFormatter
21
+
22
+
23
+ class LanguageFormatterFactory:
24
+ """Factory for creating language-specific formatters"""
25
+
26
+ _formatters: dict[str, type[BaseFormatter]] = {
27
+ "markdown": MarkdownFormatter,
28
+ "md": MarkdownFormatter, # Alias
29
+ "html": HtmlFormatter,
30
+ "css": HtmlFormatter, # CSS files also use HTML formatter
31
+ "sql": SQLFormatterWrapper, # SQL-specific formatter
32
+ "python": PythonTableFormatter, # Python files use Python formatter
33
+ "py": PythonTableFormatter, # Python alias
34
+ "java": JavaTableFormatter, # Java files use Java formatter
35
+ "kotlin": KotlinTableFormatter, # Kotlin files use Kotlin formatter
36
+ "kt": KotlinTableFormatter, # Kotlin alias
37
+ "kts": KotlinTableFormatter, # Kotlin script alias
38
+ "javascript": JavaScriptTableFormatter, # JavaScript files use JavaScript formatter
39
+ "js": JavaScriptTableFormatter, # JavaScript alias
40
+ "typescript": TypeScriptTableFormatter, # TypeScript files use TypeScript formatter
41
+ "ts": TypeScriptTableFormatter, # TypeScript alias
42
+ "csharp": CSharpTableFormatter, # C# files use C# formatter
43
+ "cs": CSharpTableFormatter, # C# alias
44
+ "php": PHPTableFormatter, # PHP files use PHP formatter
45
+ "ruby": RubyTableFormatter, # Ruby files use Ruby formatter
46
+ "rb": RubyTableFormatter, # Ruby alias
47
+ "rust": RustTableFormatter, # Rust files use Rust formatter
48
+ "rs": RustTableFormatter, # Rust alias
49
+ "go": GoTableFormatter, # Go files use Go formatter
50
+ "yaml": YAMLFormatter, # YAML files use YAML formatter
51
+ "yml": YAMLFormatter, # YAML alias
52
+ }
53
+
54
+ @classmethod
55
+ def create_formatter(cls, language: str) -> BaseFormatter:
56
+ """
57
+ Create formatter for specified language
58
+
59
+ Args:
60
+ language: Programming language name
61
+
62
+ Returns:
63
+ Language-specific formatter
64
+ """
65
+ formatter_class = cls._formatters.get(language.lower())
66
+
67
+ if formatter_class is None:
68
+ raise ValueError(f"Unsupported language: {language}")
69
+
70
+ return formatter_class()
71
+
72
+ @classmethod
73
+ def register_formatter(
74
+ cls, language: str, formatter_class: type[BaseFormatter]
75
+ ) -> None:
76
+ """
77
+ Register new language formatter
78
+
79
+ Args:
80
+ language: Programming language name
81
+ formatter_class: Formatter class
82
+ """
83
+ cls._formatters[language.lower()] = formatter_class
84
+
85
+ @classmethod
86
+ def get_supported_languages(cls) -> list[str]:
87
+ """
88
+ Get list of supported languages
89
+
90
+ Returns:
91
+ List of supported languages
92
+ """
93
+ return list(cls._formatters.keys())
94
+
95
+ @classmethod
96
+ def supports_language(cls, language: str) -> bool:
97
+ """
98
+ Check if language is supported
99
+
100
+ Args:
101
+ language: Programming language name
102
+
103
+ Returns:
104
+ True if language is supported
105
+ """
106
+ return language.lower() in cls._formatters
107
+
108
+
109
+ def create_language_formatter(language: str) -> BaseFormatter | None:
110
+ """
111
+ Create language formatter (function for compatibility)
112
+
113
+ Args:
114
+ language: Programming language name
115
+
116
+ Returns:
117
+ Language formatter or None if not supported
118
+ """
119
+ try:
120
+ return LanguageFormatterFactory.create_formatter(language)
121
+ except ValueError:
122
+ # Return None for unsupported languages instead of raising exception
123
+ return None
@@ -0,0 +1,228 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Legacy Formatter Adapters
4
+
5
+ Adapters to integrate the legacy v1.6.1.4 TableFormatter with the v1.9.4 FormatterRegistry system.
6
+ This ensures backward compatibility while maintaining the new architecture.
7
+ """
8
+
9
+ import logging
10
+ from typing import TYPE_CHECKING, Any
11
+
12
+ if TYPE_CHECKING:
13
+ pass
14
+
15
+ from ..constants import (
16
+ ELEMENT_TYPE_CLASS,
17
+ ELEMENT_TYPE_FUNCTION,
18
+ ELEMENT_TYPE_IMPORT,
19
+ ELEMENT_TYPE_PACKAGE,
20
+ ELEMENT_TYPE_VARIABLE,
21
+ get_element_type,
22
+ is_element_of_type,
23
+ )
24
+ from ..legacy_table_formatter import LegacyTableFormatter
25
+ from ..models import CodeElement
26
+ from .formatter_registry import IFormatter
27
+
28
+ logger = logging.getLogger(__name__)
29
+
30
+
31
+ class LegacyFormatterAdapter(IFormatter):
32
+ """
33
+ Base adapter class for legacy table formatters.
34
+
35
+ Converts CodeElement lists to the legacy data structure format
36
+ and delegates formatting to LegacyTableFormatter.
37
+ """
38
+
39
+ @staticmethod
40
+ def get_format_name() -> str:
41
+ """Return the format name this formatter supports"""
42
+ # This will be overridden in subclasses
43
+ return "legacy"
44
+
45
+ def __init__(
46
+ self, format_type: str, language: str = "java", include_javadoc: bool = False
47
+ ):
48
+ """
49
+ Initialize the legacy formatter adapter.
50
+
51
+ Args:
52
+ format_type: Format type (full, compact, csv)
53
+ language: Programming language for syntax highlighting
54
+ include_javadoc: Whether to include JavaDoc/documentation
55
+ """
56
+ self.format_type = format_type
57
+ self.language = language
58
+ self.include_javadoc = include_javadoc
59
+ self.formatter = LegacyTableFormatter(
60
+ format_type=format_type, language=language, include_javadoc=include_javadoc
61
+ )
62
+
63
+ def format(self, elements: list[CodeElement]) -> str:
64
+ """
65
+ Format CodeElement list using legacy formatter.
66
+
67
+ Args:
68
+ elements: List of CodeElement objects to format
69
+
70
+ Returns:
71
+ Formatted string in legacy v1.6.1.4 format
72
+ """
73
+ # Convert CodeElement list to legacy data structure
74
+ legacy_data = self._convert_to_legacy_format(elements)
75
+
76
+ # Use legacy formatter
77
+ result = self.formatter.format_structure(legacy_data)
78
+
79
+ # Ensure Unix-style line endings for consistency
80
+ result = result.replace("\r\n", "\n").replace("\r", "\n")
81
+
82
+ return result
83
+
84
+ def _convert_to_legacy_format(self, elements: list[CodeElement]) -> dict[str, Any]:
85
+ """
86
+ Convert CodeElement list to legacy data structure format.
87
+
88
+ Args:
89
+ elements: List of CodeElement objects
90
+
91
+ Returns:
92
+ Dictionary in legacy format expected by LegacyTableFormatter
93
+ """
94
+ # Extract file_path from first element if available
95
+ file_path = "Unknown"
96
+ if elements and hasattr(elements[0], "file_path"):
97
+ file_path = elements[0].file_path or "Unknown"
98
+
99
+ # Initialize legacy data structure
100
+ legacy_data: dict[str, Any] = {
101
+ "file_path": file_path,
102
+ "package": {"name": "unknown"},
103
+ "imports": [],
104
+ "classes": [],
105
+ "methods": [],
106
+ "fields": [],
107
+ "statistics": {"method_count": 0, "field_count": 0, "class_count": 0},
108
+ }
109
+
110
+ # Process elements by type
111
+ package_name = "unknown"
112
+ for element in elements:
113
+ # Use is_element_of_type helper for accurate type checking
114
+ # Also handle legacy "method" and "field" type names
115
+ element_type = get_element_type(element)
116
+
117
+ if is_element_of_type(element, ELEMENT_TYPE_PACKAGE):
118
+ package_name = element.name
119
+ legacy_data["package"]["name"] = package_name
120
+ elif is_element_of_type(element, ELEMENT_TYPE_CLASS):
121
+ legacy_data["classes"].append(self._convert_class_element(element))
122
+ elif (
123
+ is_element_of_type(element, ELEMENT_TYPE_FUNCTION)
124
+ or element_type == "method"
125
+ ):
126
+ legacy_data["methods"].append(self._convert_method_element(element))
127
+ elif (
128
+ is_element_of_type(element, ELEMENT_TYPE_VARIABLE)
129
+ or element_type == "field"
130
+ ):
131
+ legacy_data["fields"].append(self._convert_field_element(element))
132
+ elif is_element_of_type(element, ELEMENT_TYPE_IMPORT):
133
+ legacy_data["imports"].append(self._convert_import_element(element))
134
+
135
+ # Update statistics
136
+ legacy_data["statistics"]["method_count"] = len(legacy_data["methods"])
137
+ legacy_data["statistics"]["field_count"] = len(legacy_data["fields"])
138
+ legacy_data["statistics"]["class_count"] = len(legacy_data["classes"])
139
+
140
+ # If no classes found, create a default one for proper formatting
141
+ if not legacy_data["classes"] and (
142
+ legacy_data["methods"] or legacy_data["fields"]
143
+ ):
144
+ legacy_data["classes"] = [
145
+ {
146
+ "name": "Unknown",
147
+ "type": "class",
148
+ "visibility": "public",
149
+ "line_range": {"start": 1, "end": 100},
150
+ }
151
+ ]
152
+
153
+ return legacy_data
154
+
155
+ def _convert_class_element(self, element: CodeElement) -> dict[str, Any]:
156
+ """Convert class CodeElement to legacy format"""
157
+ return {
158
+ "name": element.name,
159
+ "type": getattr(element, "class_type", "class"),
160
+ "visibility": getattr(element, "visibility", "public"),
161
+ "line_range": {"start": element.start_line, "end": element.end_line},
162
+ "modifiers": getattr(element, "modifiers", []),
163
+ }
164
+
165
+ def _convert_method_element(self, element: CodeElement) -> dict[str, Any]:
166
+ """Convert method CodeElement to legacy format"""
167
+ return {
168
+ "name": element.name,
169
+ "visibility": getattr(element, "visibility", "public"),
170
+ "return_type": getattr(element, "return_type", "void"),
171
+ "parameters": getattr(element, "parameters", []),
172
+ "line_range": {"start": element.start_line, "end": element.end_line},
173
+ "is_constructor": getattr(element, "is_constructor", False),
174
+ "is_static": getattr(element, "is_static", False),
175
+ "modifiers": getattr(element, "modifiers", []),
176
+ "complexity_score": getattr(element, "complexity_score", 0),
177
+ "javadoc": getattr(element, "documentation", ""),
178
+ }
179
+
180
+ def _convert_field_element(self, element: CodeElement) -> dict[str, Any]:
181
+ """Convert field CodeElement to legacy format"""
182
+ return {
183
+ "name": element.name,
184
+ "type": getattr(element, "field_type", "Object"),
185
+ "visibility": getattr(element, "visibility", "private"),
186
+ "line_range": {"start": element.start_line, "end": element.end_line},
187
+ "modifiers": getattr(element, "modifiers", []),
188
+ "javadoc": getattr(element, "documentation", ""),
189
+ }
190
+
191
+ def _convert_import_element(self, element: CodeElement) -> dict[str, Any]:
192
+ """Convert import CodeElement to legacy format"""
193
+ return {
194
+ "statement": getattr(element, "import_statement", f"import {element.name}")
195
+ }
196
+
197
+
198
+ class LegacyFullFormatter(LegacyFormatterAdapter):
199
+ """Legacy full formatter producing Markdown tables"""
200
+
201
+ def __init__(self, language: str = "java", include_javadoc: bool = False):
202
+ super().__init__("full", language, include_javadoc)
203
+
204
+ @staticmethod
205
+ def get_format_name() -> str:
206
+ return "full"
207
+
208
+
209
+ class LegacyCompactFormatter(LegacyFormatterAdapter):
210
+ """Legacy compact formatter with complexity scores"""
211
+
212
+ def __init__(self, language: str = "java", include_javadoc: bool = False):
213
+ super().__init__("compact", language, include_javadoc)
214
+
215
+ @staticmethod
216
+ def get_format_name() -> str:
217
+ return "compact"
218
+
219
+
220
+ class LegacyCsvFormatter(LegacyFormatterAdapter):
221
+ """Legacy CSV formatter with simple structure"""
222
+
223
+ def __init__(self, language: str = "java", include_javadoc: bool = False):
224
+ super().__init__("csv", language, include_javadoc)
225
+
226
+ @staticmethod
227
+ def get_format_name() -> str:
228
+ return "csv"