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.
- tree_sitter_analyzer/__init__.py +132 -0
- tree_sitter_analyzer/__main__.py +11 -0
- tree_sitter_analyzer/api.py +853 -0
- tree_sitter_analyzer/cli/__init__.py +39 -0
- tree_sitter_analyzer/cli/__main__.py +12 -0
- tree_sitter_analyzer/cli/argument_validator.py +89 -0
- tree_sitter_analyzer/cli/commands/__init__.py +26 -0
- tree_sitter_analyzer/cli/commands/advanced_command.py +226 -0
- tree_sitter_analyzer/cli/commands/base_command.py +181 -0
- tree_sitter_analyzer/cli/commands/default_command.py +18 -0
- tree_sitter_analyzer/cli/commands/find_and_grep_cli.py +188 -0
- tree_sitter_analyzer/cli/commands/list_files_cli.py +133 -0
- tree_sitter_analyzer/cli/commands/partial_read_command.py +139 -0
- tree_sitter_analyzer/cli/commands/query_command.py +109 -0
- tree_sitter_analyzer/cli/commands/search_content_cli.py +161 -0
- tree_sitter_analyzer/cli/commands/structure_command.py +156 -0
- tree_sitter_analyzer/cli/commands/summary_command.py +116 -0
- tree_sitter_analyzer/cli/commands/table_command.py +414 -0
- tree_sitter_analyzer/cli/info_commands.py +124 -0
- tree_sitter_analyzer/cli_main.py +472 -0
- tree_sitter_analyzer/constants.py +85 -0
- tree_sitter_analyzer/core/__init__.py +15 -0
- tree_sitter_analyzer/core/analysis_engine.py +580 -0
- tree_sitter_analyzer/core/cache_service.py +333 -0
- tree_sitter_analyzer/core/engine.py +585 -0
- tree_sitter_analyzer/core/parser.py +293 -0
- tree_sitter_analyzer/core/query.py +605 -0
- tree_sitter_analyzer/core/query_filter.py +200 -0
- tree_sitter_analyzer/core/query_service.py +340 -0
- tree_sitter_analyzer/encoding_utils.py +530 -0
- tree_sitter_analyzer/exceptions.py +747 -0
- tree_sitter_analyzer/file_handler.py +246 -0
- tree_sitter_analyzer/formatters/__init__.py +1 -0
- tree_sitter_analyzer/formatters/base_formatter.py +201 -0
- tree_sitter_analyzer/formatters/csharp_formatter.py +367 -0
- tree_sitter_analyzer/formatters/formatter_config.py +197 -0
- tree_sitter_analyzer/formatters/formatter_factory.py +84 -0
- tree_sitter_analyzer/formatters/formatter_registry.py +377 -0
- tree_sitter_analyzer/formatters/formatter_selector.py +96 -0
- tree_sitter_analyzer/formatters/go_formatter.py +368 -0
- tree_sitter_analyzer/formatters/html_formatter.py +498 -0
- tree_sitter_analyzer/formatters/java_formatter.py +423 -0
- tree_sitter_analyzer/formatters/javascript_formatter.py +611 -0
- tree_sitter_analyzer/formatters/kotlin_formatter.py +268 -0
- tree_sitter_analyzer/formatters/language_formatter_factory.py +123 -0
- tree_sitter_analyzer/formatters/legacy_formatter_adapters.py +228 -0
- tree_sitter_analyzer/formatters/markdown_formatter.py +725 -0
- tree_sitter_analyzer/formatters/php_formatter.py +301 -0
- tree_sitter_analyzer/formatters/python_formatter.py +830 -0
- tree_sitter_analyzer/formatters/ruby_formatter.py +278 -0
- tree_sitter_analyzer/formatters/rust_formatter.py +233 -0
- tree_sitter_analyzer/formatters/sql_formatter_wrapper.py +689 -0
- tree_sitter_analyzer/formatters/sql_formatters.py +536 -0
- tree_sitter_analyzer/formatters/typescript_formatter.py +543 -0
- tree_sitter_analyzer/formatters/yaml_formatter.py +462 -0
- tree_sitter_analyzer/interfaces/__init__.py +9 -0
- tree_sitter_analyzer/interfaces/cli.py +535 -0
- tree_sitter_analyzer/interfaces/cli_adapter.py +359 -0
- tree_sitter_analyzer/interfaces/mcp_adapter.py +224 -0
- tree_sitter_analyzer/interfaces/mcp_server.py +428 -0
- tree_sitter_analyzer/language_detector.py +553 -0
- tree_sitter_analyzer/language_loader.py +271 -0
- tree_sitter_analyzer/languages/__init__.py +10 -0
- tree_sitter_analyzer/languages/csharp_plugin.py +1076 -0
- tree_sitter_analyzer/languages/css_plugin.py +449 -0
- tree_sitter_analyzer/languages/go_plugin.py +836 -0
- tree_sitter_analyzer/languages/html_plugin.py +496 -0
- tree_sitter_analyzer/languages/java_plugin.py +1299 -0
- tree_sitter_analyzer/languages/javascript_plugin.py +1622 -0
- tree_sitter_analyzer/languages/kotlin_plugin.py +656 -0
- tree_sitter_analyzer/languages/markdown_plugin.py +1928 -0
- tree_sitter_analyzer/languages/php_plugin.py +862 -0
- tree_sitter_analyzer/languages/python_plugin.py +1636 -0
- tree_sitter_analyzer/languages/ruby_plugin.py +757 -0
- tree_sitter_analyzer/languages/rust_plugin.py +673 -0
- tree_sitter_analyzer/languages/sql_plugin.py +2444 -0
- tree_sitter_analyzer/languages/typescript_plugin.py +1892 -0
- tree_sitter_analyzer/languages/yaml_plugin.py +695 -0
- tree_sitter_analyzer/legacy_table_formatter.py +860 -0
- tree_sitter_analyzer/mcp/__init__.py +34 -0
- tree_sitter_analyzer/mcp/resources/__init__.py +43 -0
- tree_sitter_analyzer/mcp/resources/code_file_resource.py +208 -0
- tree_sitter_analyzer/mcp/resources/project_stats_resource.py +586 -0
- tree_sitter_analyzer/mcp/server.py +869 -0
- tree_sitter_analyzer/mcp/tools/__init__.py +28 -0
- tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py +779 -0
- tree_sitter_analyzer/mcp/tools/analyze_scale_tool_cli_compatible.py +291 -0
- tree_sitter_analyzer/mcp/tools/base_tool.py +139 -0
- tree_sitter_analyzer/mcp/tools/fd_rg_utils.py +816 -0
- tree_sitter_analyzer/mcp/tools/find_and_grep_tool.py +686 -0
- tree_sitter_analyzer/mcp/tools/list_files_tool.py +413 -0
- tree_sitter_analyzer/mcp/tools/output_format_validator.py +148 -0
- tree_sitter_analyzer/mcp/tools/query_tool.py +443 -0
- tree_sitter_analyzer/mcp/tools/read_partial_tool.py +464 -0
- tree_sitter_analyzer/mcp/tools/search_content_tool.py +836 -0
- tree_sitter_analyzer/mcp/tools/table_format_tool.py +572 -0
- tree_sitter_analyzer/mcp/tools/universal_analyze_tool.py +653 -0
- tree_sitter_analyzer/mcp/utils/__init__.py +113 -0
- tree_sitter_analyzer/mcp/utils/error_handler.py +569 -0
- tree_sitter_analyzer/mcp/utils/file_output_factory.py +217 -0
- tree_sitter_analyzer/mcp/utils/file_output_manager.py +322 -0
- tree_sitter_analyzer/mcp/utils/gitignore_detector.py +358 -0
- tree_sitter_analyzer/mcp/utils/path_resolver.py +414 -0
- tree_sitter_analyzer/mcp/utils/search_cache.py +343 -0
- tree_sitter_analyzer/models.py +840 -0
- tree_sitter_analyzer/mypy_current_errors.txt +2 -0
- tree_sitter_analyzer/output_manager.py +255 -0
- tree_sitter_analyzer/platform_compat/__init__.py +3 -0
- tree_sitter_analyzer/platform_compat/adapter.py +324 -0
- tree_sitter_analyzer/platform_compat/compare.py +224 -0
- tree_sitter_analyzer/platform_compat/detector.py +67 -0
- tree_sitter_analyzer/platform_compat/fixtures.py +228 -0
- tree_sitter_analyzer/platform_compat/profiles.py +217 -0
- tree_sitter_analyzer/platform_compat/record.py +55 -0
- tree_sitter_analyzer/platform_compat/recorder.py +155 -0
- tree_sitter_analyzer/platform_compat/report.py +92 -0
- tree_sitter_analyzer/plugins/__init__.py +280 -0
- tree_sitter_analyzer/plugins/base.py +647 -0
- tree_sitter_analyzer/plugins/manager.py +384 -0
- tree_sitter_analyzer/project_detector.py +328 -0
- tree_sitter_analyzer/queries/__init__.py +27 -0
- tree_sitter_analyzer/queries/csharp.py +216 -0
- tree_sitter_analyzer/queries/css.py +615 -0
- tree_sitter_analyzer/queries/go.py +275 -0
- tree_sitter_analyzer/queries/html.py +543 -0
- tree_sitter_analyzer/queries/java.py +402 -0
- tree_sitter_analyzer/queries/javascript.py +724 -0
- tree_sitter_analyzer/queries/kotlin.py +192 -0
- tree_sitter_analyzer/queries/markdown.py +258 -0
- tree_sitter_analyzer/queries/php.py +95 -0
- tree_sitter_analyzer/queries/python.py +859 -0
- tree_sitter_analyzer/queries/ruby.py +92 -0
- tree_sitter_analyzer/queries/rust.py +223 -0
- tree_sitter_analyzer/queries/sql.py +555 -0
- tree_sitter_analyzer/queries/typescript.py +871 -0
- tree_sitter_analyzer/queries/yaml.py +236 -0
- tree_sitter_analyzer/query_loader.py +272 -0
- tree_sitter_analyzer/security/__init__.py +22 -0
- tree_sitter_analyzer/security/boundary_manager.py +277 -0
- tree_sitter_analyzer/security/regex_checker.py +297 -0
- tree_sitter_analyzer/security/validator.py +599 -0
- tree_sitter_analyzer/table_formatter.py +782 -0
- tree_sitter_analyzer/utils/__init__.py +53 -0
- tree_sitter_analyzer/utils/logging.py +433 -0
- tree_sitter_analyzer/utils/tree_sitter_compat.py +289 -0
- tree_sitter_analyzer-1.9.17.1.dist-info/METADATA +485 -0
- tree_sitter_analyzer-1.9.17.1.dist-info/RECORD +149 -0
- tree_sitter_analyzer-1.9.17.1.dist-info/WHEEL +4 -0
- 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)
|