tree-sitter-analyzer 1.8.4__py3-none-any.whl → 1.9.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.
Potentially problematic release.
This version of tree-sitter-analyzer might be problematic. Click here for more details.
- tree_sitter_analyzer/__init__.py +1 -1
- tree_sitter_analyzer/api.py +4 -4
- tree_sitter_analyzer/cli/argument_validator.py +29 -17
- tree_sitter_analyzer/cli/commands/advanced_command.py +7 -5
- tree_sitter_analyzer/cli/commands/structure_command.py +7 -5
- tree_sitter_analyzer/cli/commands/summary_command.py +10 -6
- tree_sitter_analyzer/cli/commands/table_command.py +8 -7
- tree_sitter_analyzer/cli/info_commands.py +1 -1
- tree_sitter_analyzer/cli_main.py +3 -2
- tree_sitter_analyzer/core/analysis_engine.py +5 -5
- tree_sitter_analyzer/core/cache_service.py +3 -1
- tree_sitter_analyzer/core/query.py +17 -5
- tree_sitter_analyzer/core/query_service.py +1 -1
- tree_sitter_analyzer/encoding_utils.py +3 -3
- tree_sitter_analyzer/exceptions.py +61 -50
- tree_sitter_analyzer/file_handler.py +3 -0
- tree_sitter_analyzer/formatters/base_formatter.py +10 -5
- tree_sitter_analyzer/formatters/formatter_registry.py +83 -68
- tree_sitter_analyzer/formatters/html_formatter.py +90 -64
- tree_sitter_analyzer/formatters/javascript_formatter.py +21 -16
- tree_sitter_analyzer/formatters/language_formatter_factory.py +7 -6
- tree_sitter_analyzer/formatters/markdown_formatter.py +247 -124
- tree_sitter_analyzer/formatters/python_formatter.py +61 -38
- tree_sitter_analyzer/formatters/typescript_formatter.py +113 -45
- tree_sitter_analyzer/interfaces/mcp_server.py +2 -2
- tree_sitter_analyzer/language_detector.py +6 -6
- tree_sitter_analyzer/language_loader.py +3 -1
- tree_sitter_analyzer/languages/css_plugin.py +120 -61
- tree_sitter_analyzer/languages/html_plugin.py +159 -62
- tree_sitter_analyzer/languages/java_plugin.py +42 -34
- tree_sitter_analyzer/languages/javascript_plugin.py +59 -30
- tree_sitter_analyzer/languages/markdown_plugin.py +402 -368
- tree_sitter_analyzer/languages/python_plugin.py +111 -64
- tree_sitter_analyzer/languages/typescript_plugin.py +241 -132
- tree_sitter_analyzer/mcp/server.py +22 -18
- tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py +13 -8
- tree_sitter_analyzer/mcp/tools/base_tool.py +2 -2
- tree_sitter_analyzer/mcp/tools/fd_rg_utils.py +232 -26
- tree_sitter_analyzer/mcp/tools/find_and_grep_tool.py +31 -23
- tree_sitter_analyzer/mcp/tools/list_files_tool.py +21 -19
- tree_sitter_analyzer/mcp/tools/query_tool.py +17 -18
- tree_sitter_analyzer/mcp/tools/read_partial_tool.py +30 -31
- tree_sitter_analyzer/mcp/tools/search_content_tool.py +131 -77
- tree_sitter_analyzer/mcp/tools/table_format_tool.py +29 -16
- tree_sitter_analyzer/mcp/utils/file_output_factory.py +64 -51
- tree_sitter_analyzer/mcp/utils/file_output_manager.py +34 -24
- tree_sitter_analyzer/mcp/utils/gitignore_detector.py +8 -4
- tree_sitter_analyzer/models.py +7 -5
- tree_sitter_analyzer/plugins/base.py +9 -7
- tree_sitter_analyzer/plugins/manager.py +1 -0
- tree_sitter_analyzer/queries/css.py +2 -21
- tree_sitter_analyzer/queries/html.py +2 -15
- tree_sitter_analyzer/queries/markdown.py +30 -41
- tree_sitter_analyzer/queries/python.py +20 -5
- tree_sitter_analyzer/query_loader.py +5 -5
- tree_sitter_analyzer/security/validator.py +114 -86
- tree_sitter_analyzer/utils/__init__.py +58 -28
- tree_sitter_analyzer/utils/tree_sitter_compat.py +72 -65
- tree_sitter_analyzer/utils.py +26 -15
- {tree_sitter_analyzer-1.8.4.dist-info → tree_sitter_analyzer-1.9.1.dist-info}/METADATA +23 -6
- tree_sitter_analyzer-1.9.1.dist-info/RECORD +109 -0
- tree_sitter_analyzer-1.8.4.dist-info/RECORD +0 -109
- {tree_sitter_analyzer-1.8.4.dist-info → tree_sitter_analyzer-1.9.1.dist-info}/WHEEL +0 -0
- {tree_sitter_analyzer-1.8.4.dist-info → tree_sitter_analyzer-1.9.1.dist-info}/entry_points.txt +0 -0
|
@@ -20,21 +20,21 @@ class PythonTableFormatter(BaseTableFormatter):
|
|
|
20
20
|
# Handle None data - raise exception for edge case tests
|
|
21
21
|
if data is None:
|
|
22
22
|
raise TypeError("Cannot format None data")
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
# Ensure data is a dictionary - raise exception for edge case tests
|
|
25
25
|
if not isinstance(data, dict):
|
|
26
26
|
raise TypeError(f"Expected dict, got {type(data)}")
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
return self.format_structure(data)
|
|
29
29
|
|
|
30
30
|
def _format_full_table(self, data: dict[str, Any]) -> str:
|
|
31
31
|
"""Full table format for Python"""
|
|
32
32
|
if data is None:
|
|
33
33
|
return "# No data available\n"
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
if not isinstance(data, dict):
|
|
36
36
|
return f"# Invalid data type: {type(data)}\n"
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
lines = []
|
|
39
39
|
|
|
40
40
|
# Header - Python (module/package based)
|
|
@@ -42,17 +42,22 @@ class PythonTableFormatter(BaseTableFormatter):
|
|
|
42
42
|
if file_path is None:
|
|
43
43
|
file_path = "Unknown"
|
|
44
44
|
file_name = str(file_path).split("/")[-1].split("\\")[-1]
|
|
45
|
-
module_name =
|
|
45
|
+
module_name = (
|
|
46
|
+
file_name.replace(".py", "").replace(".pyw", "").replace(".pyi", "")
|
|
47
|
+
)
|
|
46
48
|
|
|
47
49
|
# Check if this is a package module
|
|
48
50
|
classes = data.get("classes", [])
|
|
49
51
|
functions = data.get("functions", [])
|
|
50
52
|
imports = data.get("imports", [])
|
|
51
|
-
|
|
53
|
+
|
|
52
54
|
# Determine module type
|
|
53
55
|
is_package = "__init__.py" in file_name
|
|
54
|
-
is_script = any(
|
|
55
|
-
|
|
56
|
+
is_script = any(
|
|
57
|
+
"if __name__ == '__main__'" in func.get("raw_text", "")
|
|
58
|
+
for func in functions
|
|
59
|
+
)
|
|
60
|
+
|
|
56
61
|
if is_package:
|
|
57
62
|
lines.append(f"# Package: {module_name}")
|
|
58
63
|
elif is_script:
|
|
@@ -96,7 +101,7 @@ class PythonTableFormatter(BaseTableFormatter):
|
|
|
96
101
|
# Handle None class_info
|
|
97
102
|
if class_info is None:
|
|
98
103
|
continue
|
|
99
|
-
|
|
104
|
+
|
|
100
105
|
name = str(class_info.get("name", "Unknown"))
|
|
101
106
|
class_type = str(class_info.get("type", "class"))
|
|
102
107
|
visibility = str(class_info.get("visibility", "public"))
|
|
@@ -136,14 +141,16 @@ class PythonTableFormatter(BaseTableFormatter):
|
|
|
136
141
|
stats = data.get("statistics") or {}
|
|
137
142
|
|
|
138
143
|
lines.append("| Package | (default) |")
|
|
139
|
-
lines.append(
|
|
144
|
+
lines.append(
|
|
145
|
+
f"| Type | {str(class_info.get('type', 'class') if class_info else 'class')} |"
|
|
146
|
+
)
|
|
140
147
|
lines.append(
|
|
141
148
|
f"| Visibility | {str(class_info.get('visibility', 'public') if class_info else 'public')} |"
|
|
142
149
|
)
|
|
143
|
-
|
|
150
|
+
|
|
144
151
|
# Handle None class_info for line range
|
|
145
|
-
if class_info and class_info.get(
|
|
146
|
-
line_range = class_info.get(
|
|
152
|
+
if class_info and class_info.get("line_range"):
|
|
153
|
+
line_range = class_info.get("line_range", {})
|
|
147
154
|
lines.append(
|
|
148
155
|
f"| Lines | {line_range.get('start', 0)}-{line_range.get('end', 0)} |"
|
|
149
156
|
)
|
|
@@ -176,11 +183,17 @@ class PythonTableFormatter(BaseTableFormatter):
|
|
|
176
183
|
lines.append("")
|
|
177
184
|
|
|
178
185
|
# Methods - Python (with decorators and async support)
|
|
179
|
-
methods =
|
|
186
|
+
methods = (
|
|
187
|
+
data.get("methods", []) or functions
|
|
188
|
+
) # Use functions if methods not available
|
|
180
189
|
if methods:
|
|
181
190
|
lines.append("## Methods")
|
|
182
|
-
lines.append(
|
|
183
|
-
|
|
191
|
+
lines.append(
|
|
192
|
+
"| Method | Signature | Vis | Lines | Cols | Cx | Decorators | Doc |"
|
|
193
|
+
)
|
|
194
|
+
lines.append(
|
|
195
|
+
"|--------|-----------|-----|-------|------|----|-----------|----|"
|
|
196
|
+
)
|
|
184
197
|
|
|
185
198
|
for method in methods:
|
|
186
199
|
lines.append(self._format_method_row(method))
|
|
@@ -249,16 +262,16 @@ class PythonTableFormatter(BaseTableFormatter):
|
|
|
249
262
|
"""Format a method table row for Python"""
|
|
250
263
|
name = str(method.get("name", ""))
|
|
251
264
|
signature = self._format_python_signature(method)
|
|
252
|
-
|
|
265
|
+
|
|
253
266
|
# Python-specific visibility handling
|
|
254
267
|
visibility = method.get("visibility", "public")
|
|
255
268
|
if name.startswith("__") and name.endswith("__"):
|
|
256
269
|
visibility = "magic"
|
|
257
270
|
elif name.startswith("_"):
|
|
258
271
|
visibility = "private"
|
|
259
|
-
|
|
272
|
+
|
|
260
273
|
vis_symbol = self._get_python_visibility_symbol(visibility)
|
|
261
|
-
|
|
274
|
+
|
|
262
275
|
line_range = method.get("line_range", {})
|
|
263
276
|
if not line_range or not isinstance(line_range, dict):
|
|
264
277
|
start_line = method.get("start_line", 0)
|
|
@@ -266,29 +279,29 @@ class PythonTableFormatter(BaseTableFormatter):
|
|
|
266
279
|
lines_str = f"{start_line}-{end_line}"
|
|
267
280
|
else:
|
|
268
281
|
lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
|
|
269
|
-
|
|
282
|
+
|
|
270
283
|
cols_str = "5-6" # default placeholder
|
|
271
284
|
complexity = method.get("complexity_score", 0)
|
|
272
|
-
|
|
285
|
+
|
|
273
286
|
# Use docstring instead of javadoc
|
|
274
287
|
doc = self._clean_csv_text(
|
|
275
288
|
self._extract_doc_summary(str(method.get("docstring", "")))
|
|
276
289
|
)
|
|
277
|
-
|
|
290
|
+
|
|
278
291
|
# Add decorators info
|
|
279
292
|
decorators = method.get("modifiers", []) or method.get("decorators", [])
|
|
280
293
|
decorator_str = self._format_decorators(decorators)
|
|
281
|
-
|
|
294
|
+
|
|
282
295
|
# Add async indicator
|
|
283
296
|
async_indicator = "🔄" if method.get("is_async", False) else ""
|
|
284
|
-
|
|
297
|
+
|
|
285
298
|
return f"| {name}{async_indicator} | {signature} | {vis_symbol} | {lines_str} | {cols_str} | {complexity} | {decorator_str} | {doc} |"
|
|
286
299
|
|
|
287
300
|
def _create_compact_signature(self, method: dict[str, Any]) -> str:
|
|
288
301
|
"""Create compact method signature for Python"""
|
|
289
302
|
if method is None or not isinstance(method, dict):
|
|
290
303
|
return "(Any,Any):A"
|
|
291
|
-
|
|
304
|
+
|
|
292
305
|
params = method.get("parameters", [])
|
|
293
306
|
param_types = []
|
|
294
307
|
|
|
@@ -347,7 +360,11 @@ class PythonTableFormatter(BaseTableFormatter):
|
|
|
347
360
|
|
|
348
361
|
# Optional[float] -> O[f], Optional[str] -> O[s]
|
|
349
362
|
if "Optional[" in type_name:
|
|
350
|
-
result =
|
|
363
|
+
result = (
|
|
364
|
+
type_name.replace("Optional[", "O[")
|
|
365
|
+
.replace("str", "s")
|
|
366
|
+
.replace("float", "f")
|
|
367
|
+
)
|
|
351
368
|
return str(result)
|
|
352
369
|
|
|
353
370
|
result = type_mapping.get(
|
|
@@ -361,17 +378,17 @@ class PythonTableFormatter(BaseTableFormatter):
|
|
|
361
378
|
source_code = data.get("source_code", "")
|
|
362
379
|
if not source_code:
|
|
363
380
|
return None
|
|
364
|
-
|
|
381
|
+
|
|
365
382
|
lines = source_code.split("\n")
|
|
366
383
|
for i, line in enumerate(lines[:10]): # Check first 10 lines
|
|
367
384
|
stripped = line.strip()
|
|
368
385
|
if stripped.startswith('"""') or stripped.startswith("'''"):
|
|
369
386
|
quote_type = '"""' if stripped.startswith('"""') else "'''"
|
|
370
|
-
|
|
387
|
+
|
|
371
388
|
# Single line docstring
|
|
372
389
|
if stripped.count(quote_type) >= 2:
|
|
373
390
|
return stripped.replace(quote_type, "").strip()
|
|
374
|
-
|
|
391
|
+
|
|
375
392
|
# Multi-line docstring
|
|
376
393
|
docstring_lines = [stripped.replace(quote_type, "")]
|
|
377
394
|
for j in range(i + 1, len(lines)):
|
|
@@ -380,9 +397,9 @@ class PythonTableFormatter(BaseTableFormatter):
|
|
|
380
397
|
docstring_lines.append(next_line.replace(quote_type, ""))
|
|
381
398
|
break
|
|
382
399
|
docstring_lines.append(next_line)
|
|
383
|
-
|
|
400
|
+
|
|
384
401
|
return "\n".join(docstring_lines).strip()
|
|
385
|
-
|
|
402
|
+
|
|
386
403
|
return None
|
|
387
404
|
|
|
388
405
|
def _format_python_signature(self, method: dict[str, Any]) -> str:
|
|
@@ -405,7 +422,7 @@ class PythonTableFormatter(BaseTableFormatter):
|
|
|
405
422
|
|
|
406
423
|
params_str = ", ".join(param_strs)
|
|
407
424
|
return_type = method.get("return_type", "")
|
|
408
|
-
|
|
425
|
+
|
|
409
426
|
if return_type and return_type != "Any":
|
|
410
427
|
return f"({params_str}) -> {return_type}"
|
|
411
428
|
else:
|
|
@@ -415,7 +432,7 @@ class PythonTableFormatter(BaseTableFormatter):
|
|
|
415
432
|
"""Get Python visibility symbol"""
|
|
416
433
|
visibility_map = {
|
|
417
434
|
"public": "🔓",
|
|
418
|
-
"private": "🔒",
|
|
435
|
+
"private": "🔒",
|
|
419
436
|
"protected": "🔐",
|
|
420
437
|
"magic": "✨",
|
|
421
438
|
}
|
|
@@ -425,18 +442,24 @@ class PythonTableFormatter(BaseTableFormatter):
|
|
|
425
442
|
"""Format Python decorators"""
|
|
426
443
|
if not decorators:
|
|
427
444
|
return "-"
|
|
428
|
-
|
|
445
|
+
|
|
429
446
|
# Show important decorators
|
|
430
|
-
important = [
|
|
447
|
+
important = [
|
|
448
|
+
"property",
|
|
449
|
+
"staticmethod",
|
|
450
|
+
"classmethod",
|
|
451
|
+
"dataclass",
|
|
452
|
+
"abstractmethod",
|
|
453
|
+
]
|
|
431
454
|
shown_decorators = []
|
|
432
|
-
|
|
455
|
+
|
|
433
456
|
for dec in decorators:
|
|
434
457
|
if any(imp in dec for imp in important):
|
|
435
458
|
shown_decorators.append(f"@{dec}")
|
|
436
|
-
|
|
459
|
+
|
|
437
460
|
if shown_decorators:
|
|
438
461
|
return ", ".join(shown_decorators)
|
|
439
462
|
elif len(decorators) == 1:
|
|
440
463
|
return f"@{decorators[0]}"
|
|
441
464
|
else:
|
|
442
|
-
return f"@{decorators[0]} (+{len(decorators)-1})"
|
|
465
|
+
return f"@{decorators[0]} (+{len(decorators) - 1})"
|
|
@@ -35,7 +35,12 @@ class TypeScriptTableFormatter(BaseTableFormatter):
|
|
|
35
35
|
classes = data.get("classes", [])
|
|
36
36
|
interfaces = data.get("interfaces", [])
|
|
37
37
|
functions = data.get("functions", [])
|
|
38
|
-
is_module =
|
|
38
|
+
is_module = (
|
|
39
|
+
len(exports) > 0
|
|
40
|
+
or len(classes) > 0
|
|
41
|
+
or len(interfaces) > 0
|
|
42
|
+
or len(functions) > 0
|
|
43
|
+
)
|
|
39
44
|
is_declaration_file = file_name.endswith(".d.ts")
|
|
40
45
|
is_tsx = file_name.endswith(".tsx")
|
|
41
46
|
|
|
@@ -74,13 +79,17 @@ class TypeScriptTableFormatter(BaseTableFormatter):
|
|
|
74
79
|
interfaces = [c for c in classes if c.get("class_type") == "interface"]
|
|
75
80
|
type_aliases = [c for c in classes if c.get("class_type") == "type"]
|
|
76
81
|
enums = [c for c in classes if c.get("class_type") == "enum"]
|
|
77
|
-
actual_classes = [
|
|
82
|
+
actual_classes = [
|
|
83
|
+
c for c in classes if c.get("class_type") in ["class", "abstract_class"]
|
|
84
|
+
]
|
|
78
85
|
|
|
79
86
|
lines.append("## Module Info")
|
|
80
87
|
lines.append("| Property | Value |")
|
|
81
88
|
lines.append("|----------|-------|")
|
|
82
89
|
lines.append(f"| File | {file_name} |")
|
|
83
|
-
lines.append(
|
|
90
|
+
lines.append(
|
|
91
|
+
f"| Type | {'Declaration File' if is_declaration_file else 'TSX Module' if is_tsx else 'TypeScript Module' if is_module else 'TypeScript Script'} |"
|
|
92
|
+
)
|
|
84
93
|
lines.append(f"| Functions | {stats.get('function_count', 0)} |")
|
|
85
94
|
lines.append(f"| Classes | {len(actual_classes)} |")
|
|
86
95
|
lines.append(f"| Interfaces | {len(interfaces)} |")
|
|
@@ -93,31 +102,43 @@ class TypeScriptTableFormatter(BaseTableFormatter):
|
|
|
93
102
|
# Interfaces (TypeScript specific)
|
|
94
103
|
if interfaces:
|
|
95
104
|
lines.append("## Interfaces")
|
|
96
|
-
lines.append(
|
|
97
|
-
|
|
105
|
+
lines.append(
|
|
106
|
+
"| Interface | Extends | Lines | Properties | Methods | Generics |"
|
|
107
|
+
)
|
|
108
|
+
lines.append(
|
|
109
|
+
"|-----------|---------|-------|------------|---------|----------|"
|
|
110
|
+
)
|
|
98
111
|
|
|
99
112
|
for interface in interfaces:
|
|
100
113
|
name = str(interface.get("name", "Unknown"))
|
|
101
114
|
extends = ", ".join(interface.get("interfaces", [])) or "-"
|
|
102
115
|
line_range = interface.get("line_range", {})
|
|
103
116
|
lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
|
|
104
|
-
|
|
117
|
+
|
|
105
118
|
# Count properties and methods within the interface
|
|
106
119
|
interface_properties = [
|
|
107
|
-
v
|
|
108
|
-
|
|
120
|
+
v
|
|
121
|
+
for v in data.get("variables", [])
|
|
122
|
+
if line_range.get("start", 0)
|
|
123
|
+
<= v.get("line_range", {}).get("start", 0)
|
|
124
|
+
<= line_range.get("end", 0)
|
|
109
125
|
and v.get("declaration_kind") == "property_signature"
|
|
110
126
|
]
|
|
111
|
-
|
|
127
|
+
|
|
112
128
|
interface_methods = [
|
|
113
|
-
m
|
|
114
|
-
|
|
129
|
+
m
|
|
130
|
+
for m in data.get("methods", [])
|
|
131
|
+
if line_range.get("start", 0)
|
|
132
|
+
<= m.get("line_range", {}).get("start", 0)
|
|
133
|
+
<= line_range.get("end", 0)
|
|
115
134
|
and m.get("is_signature", False)
|
|
116
135
|
]
|
|
117
|
-
|
|
136
|
+
|
|
118
137
|
generics = ", ".join(interface.get("generics", [])) or "-"
|
|
119
138
|
|
|
120
|
-
lines.append(
|
|
139
|
+
lines.append(
|
|
140
|
+
f"| {name} | {extends} | {lines_str} | {len(interface_properties)} | {len(interface_methods)} | {generics} |"
|
|
141
|
+
)
|
|
121
142
|
lines.append("")
|
|
122
143
|
|
|
123
144
|
# Type Aliases (TypeScript specific)
|
|
@@ -131,7 +152,7 @@ class TypeScriptTableFormatter(BaseTableFormatter):
|
|
|
131
152
|
line_range = type_alias.get("line_range", {})
|
|
132
153
|
lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
|
|
133
154
|
generics = ", ".join(type_alias.get("generics", [])) or "-"
|
|
134
|
-
|
|
155
|
+
|
|
135
156
|
# Extract type definition from raw text
|
|
136
157
|
raw_text = type_alias.get("raw_text", "")
|
|
137
158
|
if "=" in raw_text:
|
|
@@ -154,7 +175,7 @@ class TypeScriptTableFormatter(BaseTableFormatter):
|
|
|
154
175
|
name = str(enum.get("name", "Unknown"))
|
|
155
176
|
line_range = enum.get("line_range", {})
|
|
156
177
|
lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
|
|
157
|
-
|
|
178
|
+
|
|
158
179
|
# Count enum values (simplified)
|
|
159
180
|
raw_text = enum.get("raw_text", "")
|
|
160
181
|
value_count = raw_text.count(",") + 1 if raw_text.count("{") > 0 else 0
|
|
@@ -165,8 +186,12 @@ class TypeScriptTableFormatter(BaseTableFormatter):
|
|
|
165
186
|
# Classes
|
|
166
187
|
if actual_classes:
|
|
167
188
|
lines.append("## Classes")
|
|
168
|
-
lines.append(
|
|
169
|
-
|
|
189
|
+
lines.append(
|
|
190
|
+
"| Class | Type | Extends | Implements | Lines | Methods | Properties | Generics |"
|
|
191
|
+
)
|
|
192
|
+
lines.append(
|
|
193
|
+
"|-------|------|---------|------------|-------|---------|------------|----------|"
|
|
194
|
+
)
|
|
170
195
|
|
|
171
196
|
for class_info in actual_classes:
|
|
172
197
|
name = str(class_info.get("name", "Unknown"))
|
|
@@ -179,32 +204,52 @@ class TypeScriptTableFormatter(BaseTableFormatter):
|
|
|
179
204
|
|
|
180
205
|
# Count methods within the class
|
|
181
206
|
class_methods = [
|
|
182
|
-
m
|
|
183
|
-
|
|
207
|
+
m
|
|
208
|
+
for m in data.get("functions", [])
|
|
209
|
+
if (
|
|
210
|
+
line_range.get("start", 0)
|
|
211
|
+
<= m.get("line_range", {}).get("start", 0)
|
|
212
|
+
<= line_range.get("end", 0)
|
|
184
213
|
and m.get("is_method", False)
|
|
185
|
-
and not m.get("is_signature", False)
|
|
214
|
+
and not m.get("is_signature", False)
|
|
215
|
+
)
|
|
186
216
|
]
|
|
187
217
|
|
|
188
218
|
# Count properties (class fields)
|
|
189
219
|
class_properties = [
|
|
190
|
-
v
|
|
191
|
-
|
|
220
|
+
v
|
|
221
|
+
for v in data.get("variables", [])
|
|
222
|
+
if line_range.get("start", 0)
|
|
223
|
+
<= v.get("line_range", {}).get("start", 0)
|
|
224
|
+
<= line_range.get("end", 0)
|
|
192
225
|
and v.get("declaration_kind") == "property"
|
|
193
226
|
]
|
|
194
227
|
|
|
195
|
-
lines.append(
|
|
228
|
+
lines.append(
|
|
229
|
+
f"| {name} | {class_type} | {extends} | {implements} | {lines_str} | {len(class_methods)} | {len(class_properties)} | {generics} |"
|
|
230
|
+
)
|
|
196
231
|
lines.append("")
|
|
197
232
|
|
|
198
233
|
# Functions
|
|
199
234
|
functions = data.get("functions", [])
|
|
200
235
|
if functions:
|
|
201
236
|
lines.append("## Functions")
|
|
202
|
-
lines.append(
|
|
203
|
-
|
|
237
|
+
lines.append(
|
|
238
|
+
"| Function | Type | Return Type | Parameters | Async | Generic | Lines | Complexity |"
|
|
239
|
+
)
|
|
240
|
+
lines.append(
|
|
241
|
+
"|----------|------|-------------|------------|-------|---------|-------|------------|"
|
|
242
|
+
)
|
|
204
243
|
|
|
205
244
|
for func in functions:
|
|
206
245
|
name = str(func.get("name", "Unknown"))
|
|
207
|
-
func_type =
|
|
246
|
+
func_type = (
|
|
247
|
+
"arrow"
|
|
248
|
+
if func.get("is_arrow")
|
|
249
|
+
else "method"
|
|
250
|
+
if func.get("is_method")
|
|
251
|
+
else "function"
|
|
252
|
+
)
|
|
208
253
|
return_type = str(func.get("return_type", "any"))
|
|
209
254
|
params = func.get("parameters", [])
|
|
210
255
|
param_count = len(params)
|
|
@@ -214,15 +259,21 @@ class TypeScriptTableFormatter(BaseTableFormatter):
|
|
|
214
259
|
lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
|
|
215
260
|
complexity = func.get("complexity_score", 1)
|
|
216
261
|
|
|
217
|
-
lines.append(
|
|
262
|
+
lines.append(
|
|
263
|
+
f"| {name} | {func_type} | {return_type} | {param_count} | {is_async} | {has_generics} | {lines_str} | {complexity} |"
|
|
264
|
+
)
|
|
218
265
|
lines.append("")
|
|
219
266
|
|
|
220
267
|
# Variables/Properties
|
|
221
268
|
variables = data.get("variables", [])
|
|
222
269
|
if variables:
|
|
223
270
|
lines.append("## Variables & Properties")
|
|
224
|
-
lines.append(
|
|
225
|
-
|
|
271
|
+
lines.append(
|
|
272
|
+
"| Name | Type | Kind | Visibility | Static | Optional | Lines |"
|
|
273
|
+
)
|
|
274
|
+
lines.append(
|
|
275
|
+
"|------|------|------|------------|--------|----------|-------|"
|
|
276
|
+
)
|
|
226
277
|
|
|
227
278
|
for var in variables:
|
|
228
279
|
name = str(var.get("name", "Unknown"))
|
|
@@ -234,7 +285,9 @@ class TypeScriptTableFormatter(BaseTableFormatter):
|
|
|
234
285
|
line_range = var.get("line_range", {})
|
|
235
286
|
lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
|
|
236
287
|
|
|
237
|
-
lines.append(
|
|
288
|
+
lines.append(
|
|
289
|
+
f"| {name} | {var_type} | {kind} | {visibility} | {is_static} | {is_optional} | {lines_str} |"
|
|
290
|
+
)
|
|
238
291
|
lines.append("")
|
|
239
292
|
|
|
240
293
|
# Exports
|
|
@@ -265,7 +318,6 @@ class TypeScriptTableFormatter(BaseTableFormatter):
|
|
|
265
318
|
lines.append("")
|
|
266
319
|
|
|
267
320
|
# Summary
|
|
268
|
-
stats = data.get("statistics", {})
|
|
269
321
|
classes = data.get("classes", [])
|
|
270
322
|
functions = data.get("functions", [])
|
|
271
323
|
variables = data.get("variables", [])
|
|
@@ -273,7 +325,9 @@ class TypeScriptTableFormatter(BaseTableFormatter):
|
|
|
273
325
|
interfaces = len([c for c in classes if c.get("class_type") == "interface"])
|
|
274
326
|
type_aliases = len([c for c in classes if c.get("class_type") == "type"])
|
|
275
327
|
enums = len([c for c in classes if c.get("class_type") == "enum"])
|
|
276
|
-
actual_classes = len(
|
|
328
|
+
actual_classes = len(
|
|
329
|
+
[c for c in classes if c.get("class_type") in ["class", "abstract_class"]]
|
|
330
|
+
)
|
|
277
331
|
|
|
278
332
|
lines.append("## Summary")
|
|
279
333
|
lines.append(f"- **Classes**: {actual_classes}")
|
|
@@ -303,7 +357,9 @@ class TypeScriptTableFormatter(BaseTableFormatter):
|
|
|
303
357
|
line_range = func.get("line_range", {})
|
|
304
358
|
lines_str = f"L{line_range.get('start', 0)}-{line_range.get('end', 0)}"
|
|
305
359
|
async_marker = " (async)" if func.get("is_async") else ""
|
|
306
|
-
lines.append(
|
|
360
|
+
lines.append(
|
|
361
|
+
f"- **{name}**(): {return_type}{async_marker} - {lines_str}"
|
|
362
|
+
)
|
|
307
363
|
lines.append("")
|
|
308
364
|
|
|
309
365
|
return "\n".join(lines)
|
|
@@ -326,13 +382,21 @@ class TypeScriptTableFormatter(BaseTableFormatter):
|
|
|
326
382
|
is_static = "true" if class_info.get("is_static") else "false"
|
|
327
383
|
has_generics = "true" if class_info.get("generics") else "false"
|
|
328
384
|
|
|
329
|
-
lines.append(
|
|
385
|
+
lines.append(
|
|
386
|
+
f"Class,{name},{class_type},,{lines_str},{visibility},{is_static},,{has_generics}"
|
|
387
|
+
)
|
|
330
388
|
|
|
331
389
|
# Functions
|
|
332
390
|
functions = data.get("functions", [])
|
|
333
391
|
for func in functions:
|
|
334
392
|
name = func.get("name", "")
|
|
335
|
-
func_type =
|
|
393
|
+
func_type = (
|
|
394
|
+
"arrow"
|
|
395
|
+
if func.get("is_arrow")
|
|
396
|
+
else "method"
|
|
397
|
+
if func.get("is_method")
|
|
398
|
+
else "function"
|
|
399
|
+
)
|
|
336
400
|
return_type = func.get("return_type", "any")
|
|
337
401
|
line_range = func.get("line_range", {})
|
|
338
402
|
lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
|
|
@@ -341,7 +405,9 @@ class TypeScriptTableFormatter(BaseTableFormatter):
|
|
|
341
405
|
is_async = "true" if func.get("is_async") else "false"
|
|
342
406
|
has_generics = "true" if func.get("generics") else "false"
|
|
343
407
|
|
|
344
|
-
lines.append(
|
|
408
|
+
lines.append(
|
|
409
|
+
f"Function,{name},{func_type},{return_type},{lines_str},{visibility},{is_static},{is_async},{has_generics}"
|
|
410
|
+
)
|
|
345
411
|
|
|
346
412
|
# Variables
|
|
347
413
|
variables = data.get("variables", [])
|
|
@@ -354,14 +420,16 @@ class TypeScriptTableFormatter(BaseTableFormatter):
|
|
|
354
420
|
visibility = var.get("visibility", "public")
|
|
355
421
|
is_static = "true" if var.get("is_static") else "false"
|
|
356
422
|
|
|
357
|
-
lines.append(
|
|
423
|
+
lines.append(
|
|
424
|
+
f"Variable,{name},{kind},{var_type},{lines_str},{visibility},{is_static},,"
|
|
425
|
+
)
|
|
358
426
|
|
|
359
427
|
return "\n".join(lines)
|
|
360
428
|
|
|
361
429
|
def _get_element_type_name(self, element: dict[str, Any]) -> str:
|
|
362
430
|
"""Get human-readable type name for TypeScript elements"""
|
|
363
431
|
element_type = element.get("element_type", "unknown")
|
|
364
|
-
|
|
432
|
+
|
|
365
433
|
if element_type == "class":
|
|
366
434
|
class_type = element.get("class_type", "class")
|
|
367
435
|
if class_type == "interface":
|
|
@@ -399,21 +467,21 @@ class TypeScriptTableFormatter(BaseTableFormatter):
|
|
|
399
467
|
def _format_element_details(self, element: dict[str, Any]) -> str:
|
|
400
468
|
"""Format TypeScript-specific element details"""
|
|
401
469
|
details = []
|
|
402
|
-
|
|
470
|
+
|
|
403
471
|
# Type annotations
|
|
404
472
|
if element.get("has_type_annotations"):
|
|
405
473
|
details.append("typed")
|
|
406
|
-
|
|
474
|
+
|
|
407
475
|
# Generics
|
|
408
476
|
if element.get("generics"):
|
|
409
477
|
generics = ", ".join(element.get("generics", []))
|
|
410
478
|
details.append(f"<{generics}>")
|
|
411
|
-
|
|
479
|
+
|
|
412
480
|
# Visibility
|
|
413
481
|
visibility = element.get("visibility")
|
|
414
482
|
if visibility and visibility != "public":
|
|
415
483
|
details.append(visibility)
|
|
416
|
-
|
|
484
|
+
|
|
417
485
|
# Modifiers
|
|
418
486
|
if element.get("is_static"):
|
|
419
487
|
details.append("static")
|
|
@@ -423,10 +491,10 @@ class TypeScriptTableFormatter(BaseTableFormatter):
|
|
|
423
491
|
details.append("abstract")
|
|
424
492
|
if element.get("is_optional"):
|
|
425
493
|
details.append("optional")
|
|
426
|
-
|
|
494
|
+
|
|
427
495
|
# Framework specific
|
|
428
496
|
framework = element.get("framework_type")
|
|
429
497
|
if framework:
|
|
430
498
|
details.append(f"{framework}")
|
|
431
|
-
|
|
432
|
-
return " ".join(details) if details else ""
|
|
499
|
+
|
|
500
|
+
return " ".join(details) if details else ""
|
|
@@ -29,7 +29,7 @@ except ImportError:
|
|
|
29
29
|
pass
|
|
30
30
|
|
|
31
31
|
class InitializationOptions:
|
|
32
|
-
def __init__(self, **kwargs):
|
|
32
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
33
33
|
pass
|
|
34
34
|
|
|
35
35
|
class Tool:
|
|
@@ -41,7 +41,7 @@ except ImportError:
|
|
|
41
41
|
class TextContent:
|
|
42
42
|
pass
|
|
43
43
|
|
|
44
|
-
def stdio_server():
|
|
44
|
+
def stdio_server() -> None:
|
|
45
45
|
pass
|
|
46
46
|
|
|
47
47
|
|
|
@@ -266,14 +266,14 @@ class LanguageDetector:
|
|
|
266
266
|
# Handle invalid input
|
|
267
267
|
if not file_path or not isinstance(file_path, str):
|
|
268
268
|
return "unknown", 0.0
|
|
269
|
-
|
|
269
|
+
|
|
270
270
|
path = Path(file_path)
|
|
271
271
|
extension = path.suffix.lower()
|
|
272
272
|
|
|
273
273
|
# Direct mapping by extension
|
|
274
274
|
if extension in self.EXTENSION_MAPPING:
|
|
275
275
|
language = self.EXTENSION_MAPPING[extension]
|
|
276
|
-
|
|
276
|
+
|
|
277
277
|
# Ensure language is valid
|
|
278
278
|
if not language or language.strip() == "":
|
|
279
279
|
return "unknown", 0.0
|
|
@@ -313,7 +313,7 @@ class LanguageDetector:
|
|
|
313
313
|
# Handle invalid input
|
|
314
314
|
if not file_path or not isinstance(file_path, str):
|
|
315
315
|
return "unknown"
|
|
316
|
-
|
|
316
|
+
|
|
317
317
|
result = self.detect_language(file_path)
|
|
318
318
|
if isinstance(result, tuple):
|
|
319
319
|
language, _ = result
|
|
@@ -487,15 +487,15 @@ def detect_language_from_file(file_path: str) -> str:
|
|
|
487
487
|
# Handle invalid input
|
|
488
488
|
if not file_path or not isinstance(file_path, str):
|
|
489
489
|
return "unknown"
|
|
490
|
-
|
|
490
|
+
|
|
491
491
|
# Create a fresh instance to ensure latest configuration
|
|
492
492
|
fresh_detector = LanguageDetector()
|
|
493
493
|
result = fresh_detector.detect_from_extension(file_path)
|
|
494
|
-
|
|
494
|
+
|
|
495
495
|
# Ensure result is valid
|
|
496
496
|
if not result or result.strip() == "":
|
|
497
497
|
return "unknown"
|
|
498
|
-
|
|
498
|
+
|
|
499
499
|
return result
|
|
500
500
|
|
|
501
501
|
|
|
@@ -176,7 +176,9 @@ class LanguageLoader:
|
|
|
176
176
|
except Exception as inner_e: # noqa: F841
|
|
177
177
|
raise
|
|
178
178
|
else:
|
|
179
|
-
raise RuntimeError(
|
|
179
|
+
raise RuntimeError(
|
|
180
|
+
"Unsupported Parser API: no way to set language"
|
|
181
|
+
) from None
|
|
180
182
|
|
|
181
183
|
# Cache and return
|
|
182
184
|
self._parser_cache[language] = parser
|