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,367 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ C#-specific table formatter.
4
+ """
5
+
6
+ from typing import Any
7
+
8
+ from .base_formatter import BaseTableFormatter
9
+
10
+
11
+ class CSharpTableFormatter(BaseTableFormatter):
12
+ """Table formatter specialized for C#"""
13
+
14
+ def _format_full_table(self, data: dict[str, Any]) -> str:
15
+ """Full table format for C#"""
16
+ lines = []
17
+
18
+ # Header - C# (multi-class supported)
19
+ classes = data.get("classes", [])
20
+ namespace_name = self._extract_namespace(data)
21
+
22
+ if len(classes) > 1:
23
+ # If multiple classes exist, use filename
24
+ file_name = data.get("file_path", "Unknown").split("/")[-1].split("\\")[-1]
25
+ if namespace_name == "unknown":
26
+ lines.append(f"# {file_name}")
27
+ else:
28
+ lines.append(f"# {namespace_name}.{file_name}")
29
+ else:
30
+ # Single class: use class name
31
+ class_name = classes[0].get("name", "Unknown") if classes else "Unknown"
32
+ if namespace_name == "unknown":
33
+ lines.append(f"# {class_name}")
34
+ else:
35
+ lines.append(f"# {namespace_name}.{class_name}")
36
+ lines.append("")
37
+
38
+ # Using directives (imports)
39
+ imports = data.get("imports", [])
40
+ if imports:
41
+ lines.append("## Imports")
42
+ lines.append("```csharp")
43
+ for imp in imports:
44
+ import_text = imp.get("raw_text", "").strip()
45
+ if import_text:
46
+ lines.append(import_text)
47
+ lines.append("```")
48
+ lines.append("")
49
+
50
+ # Class Info - C# (multi-class aware)
51
+ if len(classes) > 1:
52
+ lines.append("## Classes Overview")
53
+ lines.append("| Class | Type | Visibility | Lines | Methods | Fields |")
54
+ lines.append("|-------|------|------------|-------|---------|--------|")
55
+
56
+ for class_info in classes:
57
+ name = str(class_info.get("name", "Unknown"))
58
+ class_type = str(class_info.get("class_type", "class"))
59
+ visibility = str(class_info.get("visibility", "internal"))
60
+ line_range = class_info.get("line_range", {})
61
+ lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
62
+
63
+ # Count methods/fields within the class range
64
+ class_methods = [
65
+ m
66
+ for m in data.get("methods", [])
67
+ if line_range.get("start", 0)
68
+ <= m.get("line_range", {}).get("start", 0)
69
+ <= line_range.get("end", 0)
70
+ ]
71
+ class_fields = [
72
+ f
73
+ for f in data.get("fields", [])
74
+ if line_range.get("start", 0)
75
+ <= f.get("line_range", {}).get("start", 0)
76
+ <= line_range.get("end", 0)
77
+ ]
78
+
79
+ lines.append(
80
+ f"| {name} | {class_type} | {visibility} | {lines_str} | {len(class_methods)} | {len(class_fields)} |"
81
+ )
82
+ else:
83
+ # Single class details
84
+ lines.append("## Info")
85
+ lines.append("| Property | Value |")
86
+ lines.append("|----------|-------|")
87
+
88
+ class_info = data.get("classes", [{}])[0] if data.get("classes") else {}
89
+ stats = data.get("statistics") or {}
90
+
91
+ lines.append(f"| Namespace | {namespace_name} |")
92
+ lines.append(f"| Type | {str(class_info.get('class_type', 'class'))} |")
93
+ lines.append(
94
+ f"| Visibility | {str(class_info.get('visibility', 'internal'))} |"
95
+ )
96
+ lines.append(f"| Methods | {stats.get('method_count', 0)} |")
97
+ lines.append(f"| Fields | {stats.get('field_count', 0)} |")
98
+
99
+ lines.append("")
100
+
101
+ # Methods section
102
+ methods = data.get("methods", [])
103
+ if methods:
104
+ # Group methods by class if multiple classes
105
+ if len(classes) > 1:
106
+ for class_info in classes:
107
+ class_name = class_info.get("name", "Unknown")
108
+ line_range = class_info.get("line_range", {})
109
+ class_methods = [
110
+ m
111
+ for m in methods
112
+ if line_range.get("start", 0)
113
+ <= m.get("line_range", {}).get("start", 0)
114
+ <= line_range.get("end", 0)
115
+ ]
116
+
117
+ if class_methods:
118
+ lines.append(f"## {class_name} Methods")
119
+ self._add_methods_table(lines, class_methods)
120
+ lines.append("")
121
+ else:
122
+ lines.append("## Methods")
123
+ self._add_methods_table(lines, methods)
124
+ lines.append("")
125
+
126
+ # Fields section
127
+ fields = data.get("fields", [])
128
+ if fields:
129
+ # Group fields by class if multiple classes
130
+ if len(classes) > 1:
131
+ for class_info in classes:
132
+ class_name = class_info.get("name", "Unknown")
133
+ line_range = class_info.get("line_range", {})
134
+ class_fields = [
135
+ f
136
+ for f in fields
137
+ if line_range.get("start", 0)
138
+ <= f.get("line_range", {}).get("start", 0)
139
+ <= line_range.get("end", 0)
140
+ ]
141
+
142
+ if class_fields:
143
+ lines.append(f"## {class_name} Fields")
144
+ self._add_fields_table(lines, class_fields)
145
+ lines.append("")
146
+ else:
147
+ lines.append("## Fields")
148
+ self._add_fields_table(lines, fields)
149
+ lines.append("")
150
+
151
+ return "\n".join(lines)
152
+
153
+ def _format_compact_table(self, data: dict[str, Any]) -> str:
154
+ """Compact table format for C#"""
155
+ lines = []
156
+
157
+ # Header
158
+ file_name = data.get("file_path", "Unknown").split("/")[-1].split("\\")[-1]
159
+ lines.append(f"# {file_name}")
160
+ lines.append("")
161
+
162
+ # Info
163
+ lines.append("## Info")
164
+ lines.append("| Property | Value |")
165
+ lines.append("|----------|-------|")
166
+
167
+ namespace_name = self._extract_namespace(data)
168
+ stats = data.get("statistics") or {}
169
+
170
+ lines.append(f"| Namespace | {namespace_name} |")
171
+ lines.append(f"| Methods | {stats.get('method_count', 0)} |")
172
+ lines.append(f"| Fields | {stats.get('field_count', 0)} |")
173
+ lines.append("")
174
+
175
+ # Methods
176
+ methods = data.get("methods", [])
177
+ if methods:
178
+ lines.append("## Methods")
179
+ lines.append("| Method | Sig | V | L | Cx | Doc |")
180
+ lines.append("|--------|-----|---|---|----|----|")
181
+
182
+ for method in methods:
183
+ name = str(method.get("name", ""))
184
+ params = method.get("parameters", [])
185
+ return_type = str(method.get("return_type", "void"))
186
+
187
+ # Format parameters
188
+ if params:
189
+ param_str = ",".join(
190
+ [self._format_param_type(p) for p in params[:2]]
191
+ )
192
+ if len(params) > 2:
193
+ param_str += ",..."
194
+ else:
195
+ param_str = ""
196
+
197
+ # Format return type (abbreviated)
198
+ ret_str = self._abbreviate_type(return_type)
199
+
200
+ signature = f"({param_str}):{ret_str}"
201
+ visibility = self._get_visibility_symbol(
202
+ method.get("visibility", "private")
203
+ )
204
+ line_range = method.get("line_range", {})
205
+ lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
206
+ complexity = method.get("complexity_score", 1)
207
+ has_doc = "✓" if method.get("documentation") else "-"
208
+
209
+ lines.append(
210
+ f"| {name} | {signature} | {visibility} | {lines_str} | {complexity} | {has_doc} |"
211
+ )
212
+
213
+ return "\n".join(lines)
214
+
215
+ def _add_methods_table(
216
+ self, lines: list[str], methods: list[dict[str, Any]]
217
+ ) -> None:
218
+ """Add methods table to lines"""
219
+ lines.append("| Method | Signature | Vis | Lines | Cx | Doc |")
220
+ lines.append("|--------|-----------|-----|-------|----|----|")
221
+
222
+ for method in methods:
223
+ name = str(method.get("name", ""))
224
+ params = method.get("parameters", [])
225
+ return_type = str(method.get("return_type", "void"))
226
+
227
+ # Format parameters
228
+ param_strs = []
229
+ for param in params:
230
+ param_strs.append(self._format_parameter(param))
231
+
232
+ signature = f"({', '.join(param_strs)}):{return_type}"
233
+ visibility = self._get_visibility_symbol(
234
+ method.get("visibility", "private")
235
+ )
236
+ line_range = method.get("line_range", {})
237
+ lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
238
+ complexity = method.get("complexity_score", 1)
239
+ has_doc = "✓" if method.get("documentation") else "-"
240
+
241
+ lines.append(
242
+ f"| {name} | {signature} | {visibility} | {lines_str} | {complexity} | {has_doc} |"
243
+ )
244
+
245
+ def _add_fields_table(self, lines: list[str], fields: list[dict[str, Any]]) -> None:
246
+ """Add fields table to lines"""
247
+ lines.append("| Name | Type | Vis | Modifiers | Line | Doc |")
248
+ lines.append("|------|------|-----|-----------|------|-----|")
249
+
250
+ for field in fields:
251
+ name = str(field.get("name", ""))
252
+ field_type = str(field.get("variable_type", "unknown"))
253
+ visibility = self._get_visibility_symbol(field.get("visibility", "private"))
254
+ modifiers = ",".join(field.get("modifiers", []))
255
+ line = field.get("line_range", {}).get("start", 0)
256
+ has_doc = "✓" if field.get("documentation") else "-"
257
+
258
+ lines.append(
259
+ f"| {name} | {field_type} | {visibility} | {modifiers} | {line} | {has_doc} |"
260
+ )
261
+
262
+ def _extract_namespace(self, data: dict[str, Any]) -> str:
263
+ """Extract namespace from data"""
264
+ # Try to get namespace from classes
265
+ classes = data.get("classes", [])
266
+ if classes:
267
+ full_name = classes[0].get("full_qualified_name", "")
268
+ if full_name and "." in full_name:
269
+ # Extract namespace from full qualified name
270
+ parts = full_name.rsplit(".", 1)
271
+ if len(parts) == 2:
272
+ return parts[0]
273
+
274
+ return "unknown"
275
+
276
+ def _format_parameter(self, param: str) -> str:
277
+ """Format a parameter string"""
278
+ # Parameter is already formatted as "type name" or just "type"
279
+ return param
280
+
281
+ def _format_param_type(self, param: str) -> str:
282
+ """Extract and abbreviate parameter type"""
283
+ # Extract type from "type name" format
284
+ parts = param.strip().split()
285
+ if parts:
286
+ return self._abbreviate_type(parts[0])
287
+ return "?"
288
+
289
+ def _abbreviate_type(self, type_str: str) -> str:
290
+ """Abbreviate type name for compact display"""
291
+ # Remove namespace qualifiers
292
+ if "." in type_str:
293
+ type_str = type_str.split(".")[-1]
294
+
295
+ # Common abbreviations
296
+ abbrev_map = {
297
+ "String": "string",
298
+ "Int32": "int",
299
+ "Int64": "long",
300
+ "Boolean": "bool",
301
+ "Double": "double",
302
+ "Decimal": "decimal",
303
+ "DateTime": "DateTime",
304
+ "Object": "object",
305
+ }
306
+
307
+ # Handle generic types
308
+ if "<" in type_str:
309
+ base_type = type_str.split("<")[0]
310
+ base_type = abbrev_map.get(base_type, base_type)
311
+ # Simplify generic parameters
312
+ return f"{base_type}<T>"
313
+
314
+ return abbrev_map.get(type_str, type_str)
315
+
316
+ def _get_visibility_symbol(self, visibility: str) -> str:
317
+ """Convert visibility to symbol"""
318
+ symbols = {
319
+ "public": "+",
320
+ "private": "-",
321
+ "protected": "#",
322
+ "internal": "~",
323
+ }
324
+ return symbols.get(visibility.lower(), "-")
325
+
326
+ def _format_csv(self, data: dict[str, Any]) -> str:
327
+ """CSV format for C#"""
328
+ lines = []
329
+
330
+ # Header
331
+ lines.append("Type,Name,Visibility,Lines,Signature,Complexity")
332
+
333
+ # Classes
334
+ for class_info in data.get("classes", []):
335
+ name = class_info.get("name", "")
336
+ visibility = class_info.get("visibility", "internal")
337
+ line_range = class_info.get("line_range", {})
338
+ lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
339
+ class_type = class_info.get("class_type", "class")
340
+
341
+ lines.append(f"Class,{name},{visibility},{lines_str},{class_type},")
342
+
343
+ # Methods
344
+ for method in data.get("methods", []):
345
+ name = method.get("name", "")
346
+ visibility = method.get("visibility", "private")
347
+ line_range = method.get("line_range", {})
348
+ lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
349
+ params = method.get("parameters", [])
350
+ return_type = method.get("return_type", "void")
351
+ signature = f"({len(params)} params):{return_type}"
352
+ complexity = method.get("complexity_score", 1)
353
+
354
+ lines.append(
355
+ f"Method,{name},{visibility},{lines_str},{signature},{complexity}"
356
+ )
357
+
358
+ # Fields
359
+ for field in data.get("fields", []):
360
+ name = field.get("name", "")
361
+ visibility = field.get("visibility", "private")
362
+ line = field.get("line_range", {}).get("start", 0)
363
+ field_type = field.get("variable_type", "unknown")
364
+
365
+ lines.append(f"Field,{name},{visibility},{line},{field_type},")
366
+
367
+ return "\n".join(lines)
@@ -0,0 +1,197 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Formatter configuration for language-specific formatting.
4
+
5
+ This configuration determines which formatter system (legacy or new)
6
+ should be used for each language and format type combination.
7
+ """
8
+
9
+ from typing import Literal
10
+
11
+ FormatType = Literal["table", "compact", "full", "csv", "json"]
12
+ FormatterStrategy = Literal["legacy", "new"]
13
+
14
+ # Configuration mapping: language → format_type → strategy
15
+ LANGUAGE_FORMATTER_CONFIG: dict[str, dict[str, str]] = {
16
+ # Legacy languages - use original TableFormatter
17
+ "java": {
18
+ "table": "legacy",
19
+ "compact": "legacy",
20
+ "full": "legacy",
21
+ "csv": "legacy",
22
+ "json": "legacy",
23
+ },
24
+ "kotlin": {
25
+ "table": "new",
26
+ "compact": "new",
27
+ "full": "new",
28
+ "csv": "new",
29
+ "json": "new",
30
+ },
31
+ "kt": { # Alias for Kotlin
32
+ "table": "new",
33
+ "compact": "new",
34
+ "full": "new",
35
+ "csv": "new",
36
+ "json": "new",
37
+ },
38
+ "kts": { # Alias for Kotlin script
39
+ "table": "new",
40
+ "compact": "new",
41
+ "full": "new",
42
+ "csv": "new",
43
+ "json": "new",
44
+ },
45
+ "python": {
46
+ "table": "legacy",
47
+ "compact": "legacy",
48
+ "full": "legacy",
49
+ "csv": "legacy",
50
+ "json": "legacy",
51
+ },
52
+ "py": { # Alias for Python
53
+ "table": "legacy",
54
+ "compact": "legacy",
55
+ "full": "legacy",
56
+ "csv": "legacy",
57
+ "json": "legacy",
58
+ },
59
+ "javascript": {
60
+ "table": "legacy",
61
+ "compact": "legacy",
62
+ "full": "legacy",
63
+ "csv": "legacy",
64
+ "json": "legacy",
65
+ },
66
+ "js": { # Alias for JavaScript
67
+ "table": "legacy",
68
+ "compact": "legacy",
69
+ "full": "legacy",
70
+ "csv": "legacy",
71
+ "json": "legacy",
72
+ },
73
+ "typescript": {
74
+ "table": "legacy",
75
+ "compact": "legacy",
76
+ "full": "legacy",
77
+ "csv": "legacy",
78
+ "json": "legacy",
79
+ },
80
+ "ts": { # Alias for TypeScript
81
+ "table": "legacy",
82
+ "compact": "legacy",
83
+ "full": "legacy",
84
+ "csv": "legacy",
85
+ "json": "legacy",
86
+ },
87
+ # New languages - use language-specific formatters
88
+ "sql": {
89
+ "table": "new",
90
+ "compact": "new",
91
+ "full": "new",
92
+ "csv": "new",
93
+ "json": "new",
94
+ },
95
+ "html": {
96
+ "table": "new",
97
+ "compact": "new",
98
+ "full": "new",
99
+ "csv": "new",
100
+ "json": "new",
101
+ },
102
+ "css": {
103
+ "table": "new",
104
+ "compact": "new",
105
+ "full": "new",
106
+ "csv": "new",
107
+ "json": "new",
108
+ },
109
+ "markdown": {
110
+ "table": "new",
111
+ "compact": "new",
112
+ "full": "new",
113
+ "csv": "new",
114
+ "json": "new",
115
+ },
116
+ "md": { # Alias for Markdown
117
+ "table": "new",
118
+ "compact": "new",
119
+ "full": "new",
120
+ "csv": "new",
121
+ "json": "new",
122
+ },
123
+ "rust": {
124
+ "table": "new",
125
+ "compact": "new",
126
+ "full": "new",
127
+ "csv": "new",
128
+ "json": "new",
129
+ },
130
+ "rs": { # Alias for Rust
131
+ "table": "new",
132
+ "compact": "new",
133
+ "full": "new",
134
+ "csv": "new",
135
+ "json": "new",
136
+ },
137
+ "go": {
138
+ "table": "new",
139
+ "compact": "new",
140
+ "full": "new",
141
+ "csv": "new",
142
+ "json": "new",
143
+ },
144
+ "csharp": {
145
+ "table": "legacy",
146
+ "compact": "legacy",
147
+ "full": "legacy",
148
+ "csv": "legacy",
149
+ "json": "legacy",
150
+ },
151
+ "cs": { # Alias for C#
152
+ "table": "legacy",
153
+ "compact": "legacy",
154
+ "full": "legacy",
155
+ "csv": "legacy",
156
+ "json": "legacy",
157
+ },
158
+ "php": {
159
+ "table": "legacy",
160
+ "compact": "legacy",
161
+ "full": "legacy",
162
+ "csv": "legacy",
163
+ "json": "legacy",
164
+ },
165
+ "ruby": {
166
+ "table": "legacy",
167
+ "compact": "legacy",
168
+ "full": "legacy",
169
+ "csv": "legacy",
170
+ "json": "legacy",
171
+ },
172
+ "rb": { # Alias for Ruby
173
+ "table": "legacy",
174
+ "compact": "legacy",
175
+ "full": "legacy",
176
+ "csv": "legacy",
177
+ "json": "legacy",
178
+ },
179
+ }
180
+
181
+ # Default strategy for unknown languages
182
+ DEFAULT_STRATEGY: str = "legacy"
183
+
184
+
185
+ def get_formatter_strategy(language: str, format_type: str) -> str:
186
+ """
187
+ Get formatter strategy for language and format type.
188
+
189
+ Args:
190
+ language: Programming language name
191
+ format_type: Output format type
192
+
193
+ Returns:
194
+ Formatter strategy ("legacy" or "new")
195
+ """
196
+ lang_config = LANGUAGE_FORMATTER_CONFIG.get(language.lower(), {})
197
+ return lang_config.get(format_type, DEFAULT_STRATEGY)
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Factory for creating language-specific table formatters.
4
+ """
5
+
6
+ from .base_formatter import BaseTableFormatter
7
+ from .java_formatter import JavaTableFormatter
8
+ from .javascript_formatter import JavaScriptTableFormatter
9
+ from .python_formatter import PythonTableFormatter
10
+ from .typescript_formatter import TypeScriptTableFormatter
11
+
12
+
13
+ class TableFormatterFactory:
14
+ """Factory for creating language-specific table formatters"""
15
+
16
+ _formatters: dict[str, type[BaseTableFormatter]] = {
17
+ "java": JavaTableFormatter,
18
+ "javascript": JavaScriptTableFormatter,
19
+ "js": JavaScriptTableFormatter, # Alias
20
+ "python": PythonTableFormatter,
21
+ "typescript": TypeScriptTableFormatter,
22
+ "ts": TypeScriptTableFormatter, # Alias
23
+ }
24
+
25
+ @classmethod
26
+ def create_formatter(
27
+ cls, language: str, format_type: str = "full"
28
+ ) -> BaseTableFormatter:
29
+ """
30
+ Create table formatter for specified language
31
+
32
+ Args:
33
+ language: Programming language name
34
+ format_type: Format type (full, compact, csv)
35
+
36
+ Returns:
37
+ Language-specific table formatter
38
+ """
39
+ formatter_class = cls._formatters.get(language.lower())
40
+
41
+ if formatter_class is None:
42
+ # Use Java formatter as default
43
+ formatter_class = JavaTableFormatter
44
+
45
+ return formatter_class(format_type)
46
+
47
+ @classmethod
48
+ def register_formatter(
49
+ cls, language: str, formatter_class: type[BaseTableFormatter]
50
+ ) -> None:
51
+ """
52
+ Register new language formatter
53
+
54
+ Args:
55
+ language: Programming language name
56
+ formatter_class: Formatter class
57
+ """
58
+ cls._formatters[language.lower()] = formatter_class
59
+
60
+ @classmethod
61
+ def get_supported_languages(cls) -> list[str]:
62
+ """
63
+ Get list of supported languages
64
+
65
+ Returns:
66
+ List of supported languages
67
+ """
68
+ return list(cls._formatters.keys())
69
+
70
+
71
+ def create_table_formatter(
72
+ format_type: str, language: str = "java"
73
+ ) -> BaseTableFormatter:
74
+ """
75
+ Create table formatter (function for compatibility)
76
+
77
+ Args:
78
+ format_type: Format type
79
+ language: Programming language name
80
+
81
+ Returns:
82
+ Table formatter
83
+ """
84
+ return TableFormatterFactory.create_formatter(language, format_type)