tree-sitter-analyzer 1.4.1__py3-none-any.whl → 1.6.0__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 +108 -8
- tree_sitter_analyzer/cli/commands/find_and_grep_cli.py +3 -2
- tree_sitter_analyzer/cli/commands/list_files_cli.py +0 -1
- tree_sitter_analyzer/cli/commands/search_content_cli.py +3 -2
- tree_sitter_analyzer/cli_main.py +3 -1
- tree_sitter_analyzer/encoding_utils.py +3 -3
- tree_sitter_analyzer/formatters/formatter_factory.py +3 -0
- tree_sitter_analyzer/formatters/javascript_formatter.py +467 -0
- tree_sitter_analyzer/formatters/python_formatter.py +161 -20
- tree_sitter_analyzer/language_loader.py +2 -2
- tree_sitter_analyzer/languages/javascript_plugin.py +1289 -238
- tree_sitter_analyzer/languages/python_plugin.py +581 -148
- tree_sitter_analyzer/mcp/server.py +17 -2
- tree_sitter_analyzer/mcp/tools/table_format_tool.py +106 -4
- tree_sitter_analyzer/mcp/utils/file_output_manager.py +257 -0
- tree_sitter_analyzer/mcp/utils/path_resolver.py +1 -1
- tree_sitter_analyzer/models.py +17 -0
- tree_sitter_analyzer/queries/javascript.py +592 -31
- tree_sitter_analyzer/queries/python.py +617 -58
- tree_sitter_analyzer/table_formatter.py +26 -2
- {tree_sitter_analyzer-1.4.1.dist-info → tree_sitter_analyzer-1.6.0.dist-info}/METADATA +165 -22
- {tree_sitter_analyzer-1.4.1.dist-info → tree_sitter_analyzer-1.6.0.dist-info}/RECORD +25 -23
- {tree_sitter_analyzer-1.4.1.dist-info → tree_sitter_analyzer-1.6.0.dist-info}/WHEEL +0 -0
- {tree_sitter_analyzer-1.4.1.dist-info → tree_sitter_analyzer-1.6.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
JavaScript-specific table formatter.
|
|
4
|
+
|
|
5
|
+
Provides specialized formatting for JavaScript code analysis results,
|
|
6
|
+
handling modern JavaScript features like ES6+ syntax, async/await,
|
|
7
|
+
classes, modules, and framework-specific patterns.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from .base_formatter import BaseTableFormatter
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class JavaScriptTableFormatter(BaseTableFormatter):
|
|
16
|
+
"""Table formatter specialized for JavaScript"""
|
|
17
|
+
|
|
18
|
+
def format(self, data: dict[str, Any]) -> str:
|
|
19
|
+
"""Format data using the configured format type"""
|
|
20
|
+
return self.format_structure(data)
|
|
21
|
+
|
|
22
|
+
def _format_full_table(self, data: dict[str, Any]) -> str:
|
|
23
|
+
"""Full table format for JavaScript"""
|
|
24
|
+
lines = []
|
|
25
|
+
|
|
26
|
+
# Header - JavaScript (module/file based)
|
|
27
|
+
file_path = data.get("file_path", "Unknown")
|
|
28
|
+
file_name = file_path.split("/")[-1].split("\\")[-1]
|
|
29
|
+
module_name = (
|
|
30
|
+
file_name.replace(".js", "").replace(".jsx", "").replace(".mjs", "")
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
# Check if this is a module (has exports)
|
|
34
|
+
exports = data.get("exports", [])
|
|
35
|
+
is_module = len(exports) > 0
|
|
36
|
+
|
|
37
|
+
if is_module:
|
|
38
|
+
lines.append(f"# Module: {module_name}")
|
|
39
|
+
else:
|
|
40
|
+
lines.append(f"# Script: {module_name}")
|
|
41
|
+
lines.append("")
|
|
42
|
+
|
|
43
|
+
# Imports
|
|
44
|
+
imports = data.get("imports", [])
|
|
45
|
+
if imports:
|
|
46
|
+
lines.append("## Imports")
|
|
47
|
+
lines.append("```javascript")
|
|
48
|
+
for imp in imports:
|
|
49
|
+
import_statement = imp.get("statement", "")
|
|
50
|
+
if not import_statement:
|
|
51
|
+
# Construct import statement from parts
|
|
52
|
+
source = imp.get("source", "")
|
|
53
|
+
name = imp.get("name", "")
|
|
54
|
+
if name and source:
|
|
55
|
+
import_statement = f"import {name} from {source};"
|
|
56
|
+
lines.append(import_statement)
|
|
57
|
+
lines.append("```")
|
|
58
|
+
lines.append("")
|
|
59
|
+
|
|
60
|
+
# Module Info
|
|
61
|
+
stats = data.get("statistics", {})
|
|
62
|
+
classes = data.get("classes", [])
|
|
63
|
+
|
|
64
|
+
lines.append("## Module Info")
|
|
65
|
+
lines.append("| Property | Value |")
|
|
66
|
+
lines.append("|----------|-------|")
|
|
67
|
+
lines.append(f"| File | {file_name} |")
|
|
68
|
+
lines.append(f"| Type | {'ES6 Module' if is_module else 'Script'} |")
|
|
69
|
+
lines.append(f"| Functions | {stats.get('function_count', 0)} |")
|
|
70
|
+
lines.append(f"| Classes | {len(classes)} |")
|
|
71
|
+
lines.append(f"| Variables | {stats.get('variable_count', 0)} |")
|
|
72
|
+
lines.append(f"| Exports | {len(exports)} |")
|
|
73
|
+
lines.append("")
|
|
74
|
+
|
|
75
|
+
# Classes (if any)
|
|
76
|
+
if classes:
|
|
77
|
+
lines.append("## Classes")
|
|
78
|
+
lines.append("| Class | Type | Extends | Lines | Methods | Properties |")
|
|
79
|
+
lines.append("|-------|------|---------|-------|---------|------------|")
|
|
80
|
+
|
|
81
|
+
for class_info in classes:
|
|
82
|
+
name = str(class_info.get("name", "Unknown"))
|
|
83
|
+
class_type = "class" # JavaScript only has classes
|
|
84
|
+
extends = str(class_info.get("superclass", "")) or "-"
|
|
85
|
+
line_range = class_info.get("line_range", {})
|
|
86
|
+
lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
|
|
87
|
+
|
|
88
|
+
# Count methods within the class
|
|
89
|
+
class_methods = [
|
|
90
|
+
m
|
|
91
|
+
for m in data.get("methods", [])
|
|
92
|
+
if line_range.get("start", 0)
|
|
93
|
+
<= m.get("line_range", {}).get("start", 0)
|
|
94
|
+
<= line_range.get("end", 0)
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
# Count properties (class fields)
|
|
98
|
+
class_properties = [
|
|
99
|
+
v
|
|
100
|
+
for v in data.get("variables", [])
|
|
101
|
+
if line_range.get("start", 0)
|
|
102
|
+
<= v.get("line_range", {}).get("start", 0)
|
|
103
|
+
<= line_range.get("end", 0)
|
|
104
|
+
]
|
|
105
|
+
|
|
106
|
+
lines.append(
|
|
107
|
+
f"| {name} | {class_type} | {extends} | {lines_str} | {len(class_methods)} | {len(class_properties)} |"
|
|
108
|
+
)
|
|
109
|
+
lines.append("")
|
|
110
|
+
|
|
111
|
+
# Variables/Constants
|
|
112
|
+
variables = data.get("variables", [])
|
|
113
|
+
if variables:
|
|
114
|
+
lines.append("## Variables")
|
|
115
|
+
lines.append("| Name | Type | Scope | Kind | Line | Value |")
|
|
116
|
+
lines.append("|------|------|-------|------|------|-------|")
|
|
117
|
+
|
|
118
|
+
for var in variables:
|
|
119
|
+
name = str(var.get("name", ""))
|
|
120
|
+
# Try to get value from initializer or value field
|
|
121
|
+
var_value = var.get("initializer") or var.get("value", "")
|
|
122
|
+
var_type = self._infer_js_type(var_value)
|
|
123
|
+
scope = self._determine_scope(var)
|
|
124
|
+
kind = self._get_variable_kind(var)
|
|
125
|
+
line = var.get("line_range", {}).get("start", 0)
|
|
126
|
+
value = str(var_value)[:30] + (
|
|
127
|
+
"..." if len(str(var_value)) > 30 else ""
|
|
128
|
+
)
|
|
129
|
+
value = value.replace("\n", " ").replace("|", "\\|")
|
|
130
|
+
|
|
131
|
+
lines.append(
|
|
132
|
+
f"| {name} | {var_type} | {scope} | {kind} | {line} | {value} |"
|
|
133
|
+
)
|
|
134
|
+
lines.append("")
|
|
135
|
+
|
|
136
|
+
# Functions
|
|
137
|
+
functions = data.get("functions", [])
|
|
138
|
+
if functions:
|
|
139
|
+
# Group functions by type
|
|
140
|
+
regular_functions = [
|
|
141
|
+
f
|
|
142
|
+
for f in functions
|
|
143
|
+
if not self._is_method(f) and not f.get("is_async", False)
|
|
144
|
+
]
|
|
145
|
+
async_functions = [
|
|
146
|
+
f
|
|
147
|
+
for f in functions
|
|
148
|
+
if not self._is_method(f) and f.get("is_async", False)
|
|
149
|
+
]
|
|
150
|
+
methods = [f for f in functions if self._is_method(f)]
|
|
151
|
+
|
|
152
|
+
# Regular Functions
|
|
153
|
+
if regular_functions:
|
|
154
|
+
lines.append("## Functions")
|
|
155
|
+
lines.append(
|
|
156
|
+
"| Function | Parameters | Type | Lines | Complexity | JSDoc |"
|
|
157
|
+
)
|
|
158
|
+
lines.append(
|
|
159
|
+
"|----------|------------|------|-------|------------|-------|"
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
for func in regular_functions:
|
|
163
|
+
lines.append(self._format_function_row(func))
|
|
164
|
+
lines.append("")
|
|
165
|
+
|
|
166
|
+
# Async Functions
|
|
167
|
+
if async_functions:
|
|
168
|
+
lines.append("## Async Functions")
|
|
169
|
+
lines.append(
|
|
170
|
+
"| Function | Parameters | Type | Lines | Complexity | JSDoc |"
|
|
171
|
+
)
|
|
172
|
+
lines.append(
|
|
173
|
+
"|----------|------------|------|-------|------------|-------|"
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
for func in async_functions:
|
|
177
|
+
lines.append(self._format_function_row(func))
|
|
178
|
+
lines.append("")
|
|
179
|
+
|
|
180
|
+
# Methods (class methods)
|
|
181
|
+
if methods:
|
|
182
|
+
lines.append("## Methods")
|
|
183
|
+
lines.append(
|
|
184
|
+
"| Method | Class | Parameters | Type | Lines | Complexity | JSDoc |"
|
|
185
|
+
)
|
|
186
|
+
lines.append(
|
|
187
|
+
"|--------|-------|------------|------|-------|------------|-------|"
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
for method in methods:
|
|
191
|
+
lines.append(self._format_method_row(method))
|
|
192
|
+
lines.append("")
|
|
193
|
+
|
|
194
|
+
# Exports
|
|
195
|
+
if exports:
|
|
196
|
+
lines.append("## Exports")
|
|
197
|
+
lines.append("| Export | Type | Name | Default |")
|
|
198
|
+
lines.append("|--------|------|------|---------|")
|
|
199
|
+
|
|
200
|
+
for export in exports:
|
|
201
|
+
export_type = self._get_export_type(export)
|
|
202
|
+
name = str(export.get("name", ""))
|
|
203
|
+
is_default = "✓" if export.get("is_default", False) else "-"
|
|
204
|
+
|
|
205
|
+
lines.append(f"| {export_type} | {name} | {is_default} |")
|
|
206
|
+
lines.append("")
|
|
207
|
+
|
|
208
|
+
# Trim trailing blank lines
|
|
209
|
+
while lines and lines[-1] == "":
|
|
210
|
+
lines.pop()
|
|
211
|
+
|
|
212
|
+
return "\n".join(lines)
|
|
213
|
+
|
|
214
|
+
def _format_compact_table(self, data: dict[str, Any]) -> str:
|
|
215
|
+
"""Compact table format for JavaScript"""
|
|
216
|
+
lines = []
|
|
217
|
+
|
|
218
|
+
# Header
|
|
219
|
+
file_path = data.get("file_path", "Unknown")
|
|
220
|
+
file_name = file_path.split("/")[-1].split("\\")[-1]
|
|
221
|
+
module_name = (
|
|
222
|
+
file_name.replace(".js", "").replace(".jsx", "").replace(".mjs", "")
|
|
223
|
+
)
|
|
224
|
+
lines.append(f"# {module_name}")
|
|
225
|
+
lines.append("")
|
|
226
|
+
|
|
227
|
+
# Info
|
|
228
|
+
stats = data.get("statistics", {})
|
|
229
|
+
lines.append("## Info")
|
|
230
|
+
lines.append("| Property | Value |")
|
|
231
|
+
lines.append("|----------|-------|")
|
|
232
|
+
lines.append(f"| Functions | {stats.get('function_count', 0)} |")
|
|
233
|
+
lines.append(f"| Classes | {len(data.get('classes', []))} |")
|
|
234
|
+
lines.append(f"| Variables | {stats.get('variable_count', 0)} |")
|
|
235
|
+
lines.append(f"| Exports | {len(data.get('exports', []))} |")
|
|
236
|
+
lines.append("")
|
|
237
|
+
|
|
238
|
+
# Functions (compact)
|
|
239
|
+
functions = data.get("functions", [])
|
|
240
|
+
if functions:
|
|
241
|
+
lines.append("## Functions")
|
|
242
|
+
lines.append("| Function | Params | Type | L | Cx | Doc |")
|
|
243
|
+
lines.append("|----------|--------|------|---|----|----|")
|
|
244
|
+
|
|
245
|
+
for func in functions:
|
|
246
|
+
name = str(func.get("name", ""))
|
|
247
|
+
params = self._create_compact_params(func)
|
|
248
|
+
func_type = self._get_function_type_short(func)
|
|
249
|
+
line_range = func.get("line_range", {})
|
|
250
|
+
lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
|
|
251
|
+
complexity = func.get("complexity_score", 0)
|
|
252
|
+
doc = self._clean_csv_text(
|
|
253
|
+
self._extract_doc_summary(str(func.get("jsdoc", "")))
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
lines.append(
|
|
257
|
+
f"| {name} | {params} | {func_type} | {lines_str} | {complexity} | {doc} |"
|
|
258
|
+
)
|
|
259
|
+
lines.append("")
|
|
260
|
+
|
|
261
|
+
# Trim trailing blank lines
|
|
262
|
+
while lines and lines[-1] == "":
|
|
263
|
+
lines.pop()
|
|
264
|
+
|
|
265
|
+
return "\n".join(lines)
|
|
266
|
+
|
|
267
|
+
def _format_function_row(self, func: dict[str, Any]) -> str:
|
|
268
|
+
"""Format a function table row for JavaScript"""
|
|
269
|
+
name = str(func.get("name", ""))
|
|
270
|
+
params = self._create_full_params(func)
|
|
271
|
+
func_type = self._get_function_type(func)
|
|
272
|
+
line_range = func.get("line_range", {})
|
|
273
|
+
lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
|
|
274
|
+
complexity = func.get("complexity_score", 0)
|
|
275
|
+
doc = self._clean_csv_text(
|
|
276
|
+
self._extract_doc_summary(str(func.get("jsdoc", "")))
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
return (
|
|
280
|
+
f"| {name} | {params} | {func_type} | {lines_str} | {complexity} | {doc} |"
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
def _format_method_row(self, method: dict[str, Any]) -> str:
|
|
284
|
+
"""Format a method table row for JavaScript"""
|
|
285
|
+
name = str(method.get("name", ""))
|
|
286
|
+
class_name = self._get_method_class(method)
|
|
287
|
+
params = self._create_full_params(method)
|
|
288
|
+
method_type = self._get_method_type(method)
|
|
289
|
+
line_range = method.get("line_range", {})
|
|
290
|
+
lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
|
|
291
|
+
complexity = method.get("complexity_score", 0)
|
|
292
|
+
doc = self._clean_csv_text(
|
|
293
|
+
self._extract_doc_summary(str(method.get("jsdoc", "")))
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
return f"| {name} | {class_name} | {params} | {method_type} | {lines_str} | {complexity} | {doc} |"
|
|
297
|
+
|
|
298
|
+
def _create_full_params(self, func: dict[str, Any]) -> str:
|
|
299
|
+
"""Create full parameter list for JavaScript functions"""
|
|
300
|
+
params = func.get("parameters", [])
|
|
301
|
+
if not params:
|
|
302
|
+
return "()"
|
|
303
|
+
|
|
304
|
+
param_strs = []
|
|
305
|
+
for param in params:
|
|
306
|
+
if isinstance(param, dict):
|
|
307
|
+
param_name = param.get("name", "")
|
|
308
|
+
param_type = param.get("type", "")
|
|
309
|
+
if param_type:
|
|
310
|
+
param_strs.append(f"{param_name}: {param_type}")
|
|
311
|
+
else:
|
|
312
|
+
param_strs.append(param_name)
|
|
313
|
+
else:
|
|
314
|
+
param_strs.append(str(param))
|
|
315
|
+
|
|
316
|
+
params_str = ", ".join(param_strs)
|
|
317
|
+
if len(params_str) > 50:
|
|
318
|
+
params_str = params_str[:47] + "..."
|
|
319
|
+
|
|
320
|
+
return f"({params_str})"
|
|
321
|
+
|
|
322
|
+
def _create_compact_params(self, func: dict[str, Any]) -> str:
|
|
323
|
+
"""Create compact parameter list for JavaScript functions"""
|
|
324
|
+
params = func.get("parameters", [])
|
|
325
|
+
if not params:
|
|
326
|
+
return "()"
|
|
327
|
+
|
|
328
|
+
param_count = len(params)
|
|
329
|
+
if param_count <= 3:
|
|
330
|
+
param_names = [
|
|
331
|
+
param.get("name", str(param)) if isinstance(param, dict) else str(param)
|
|
332
|
+
for param in params
|
|
333
|
+
]
|
|
334
|
+
return f"({','.join(param_names)})"
|
|
335
|
+
else:
|
|
336
|
+
return f"({param_count} params)"
|
|
337
|
+
|
|
338
|
+
def _get_function_type(self, func: dict[str, Any]) -> str:
|
|
339
|
+
"""Get full function type for JavaScript"""
|
|
340
|
+
if func.get("is_async", False):
|
|
341
|
+
return "async function"
|
|
342
|
+
elif func.get("is_generator", False):
|
|
343
|
+
return "generator"
|
|
344
|
+
elif func.get("is_arrow", False):
|
|
345
|
+
return "arrow"
|
|
346
|
+
elif self._is_method(func):
|
|
347
|
+
if func.get("is_constructor", False):
|
|
348
|
+
return "constructor"
|
|
349
|
+
elif func.get("is_getter", False):
|
|
350
|
+
return "getter"
|
|
351
|
+
elif func.get("is_setter", False):
|
|
352
|
+
return "setter"
|
|
353
|
+
elif func.get("is_static", False):
|
|
354
|
+
return "static method"
|
|
355
|
+
else:
|
|
356
|
+
return "method"
|
|
357
|
+
else:
|
|
358
|
+
return "function"
|
|
359
|
+
|
|
360
|
+
def _get_function_type_short(self, func: dict[str, Any]) -> str:
|
|
361
|
+
"""Get short function type for JavaScript"""
|
|
362
|
+
if func.get("is_async", False):
|
|
363
|
+
return "async"
|
|
364
|
+
elif func.get("is_generator", False):
|
|
365
|
+
return "gen"
|
|
366
|
+
elif func.get("is_arrow", False):
|
|
367
|
+
return "arrow"
|
|
368
|
+
elif self._is_method(func):
|
|
369
|
+
return "method"
|
|
370
|
+
else:
|
|
371
|
+
return "func"
|
|
372
|
+
|
|
373
|
+
def _get_method_type(self, method: dict[str, Any]) -> str:
|
|
374
|
+
"""Get method type for JavaScript"""
|
|
375
|
+
if method.get("is_constructor", False):
|
|
376
|
+
return "constructor"
|
|
377
|
+
elif method.get("is_getter", False):
|
|
378
|
+
return "getter"
|
|
379
|
+
elif method.get("is_setter", False):
|
|
380
|
+
return "setter"
|
|
381
|
+
elif method.get("is_static", False):
|
|
382
|
+
return "static"
|
|
383
|
+
elif method.get("is_async", False):
|
|
384
|
+
return "async"
|
|
385
|
+
else:
|
|
386
|
+
return "method"
|
|
387
|
+
|
|
388
|
+
def _is_method(self, func: dict[str, Any]) -> bool:
|
|
389
|
+
"""Check if function is a class method"""
|
|
390
|
+
return func.get("is_method", False) or func.get("class_name") is not None
|
|
391
|
+
|
|
392
|
+
def _get_method_class(self, method: dict[str, Any]) -> str:
|
|
393
|
+
"""Get the class name for a method"""
|
|
394
|
+
return str(method.get("class_name", "Unknown"))
|
|
395
|
+
|
|
396
|
+
def _infer_js_type(self, value: Any) -> str:
|
|
397
|
+
"""Infer JavaScript type from value"""
|
|
398
|
+
if value is None:
|
|
399
|
+
return "undefined"
|
|
400
|
+
|
|
401
|
+
value_str = str(value).strip()
|
|
402
|
+
|
|
403
|
+
# Check for specific patterns
|
|
404
|
+
if (
|
|
405
|
+
value_str.startswith('"')
|
|
406
|
+
or value_str.startswith("'")
|
|
407
|
+
or value_str.startswith("`")
|
|
408
|
+
):
|
|
409
|
+
return "string"
|
|
410
|
+
elif value_str in ["true", "false"]:
|
|
411
|
+
return "boolean"
|
|
412
|
+
elif value_str == "null":
|
|
413
|
+
return "null"
|
|
414
|
+
elif value_str.startswith("[") and value_str.endswith("]"):
|
|
415
|
+
return "array"
|
|
416
|
+
elif value_str.startswith("{") and value_str.endswith("}"):
|
|
417
|
+
return "object"
|
|
418
|
+
elif value_str.startswith("function") or "=>" in value_str:
|
|
419
|
+
return "function"
|
|
420
|
+
elif value_str.startswith("class"):
|
|
421
|
+
return "class"
|
|
422
|
+
elif value_str.replace(".", "").replace("-", "").isdigit():
|
|
423
|
+
return "number"
|
|
424
|
+
else:
|
|
425
|
+
return "unknown"
|
|
426
|
+
|
|
427
|
+
def _determine_scope(self, var: dict[str, Any]) -> str:
|
|
428
|
+
"""Determine variable scope"""
|
|
429
|
+
# This would need more context from the parser
|
|
430
|
+
# For now, return basic scope info
|
|
431
|
+
kind = self._get_variable_kind(var)
|
|
432
|
+
if kind == "const":
|
|
433
|
+
return "block"
|
|
434
|
+
elif kind == "let":
|
|
435
|
+
return "block"
|
|
436
|
+
elif kind == "var":
|
|
437
|
+
return "function"
|
|
438
|
+
else:
|
|
439
|
+
return "unknown"
|
|
440
|
+
|
|
441
|
+
def _get_variable_kind(self, var: dict[str, Any]) -> str:
|
|
442
|
+
"""Get variable declaration kind (const, let, var)"""
|
|
443
|
+
# Check if variable has is_constant flag
|
|
444
|
+
if var.get("is_constant", False):
|
|
445
|
+
return "const"
|
|
446
|
+
|
|
447
|
+
# Fall back to parsing raw text
|
|
448
|
+
raw_text = str(var.get("raw_text", "")).strip()
|
|
449
|
+
if raw_text.startswith("const"):
|
|
450
|
+
return "const"
|
|
451
|
+
elif raw_text.startswith("let"):
|
|
452
|
+
return "let"
|
|
453
|
+
elif raw_text.startswith("var"):
|
|
454
|
+
return "var"
|
|
455
|
+
else:
|
|
456
|
+
return "unknown"
|
|
457
|
+
|
|
458
|
+
def _get_export_type(self, export: dict[str, Any]) -> str:
|
|
459
|
+
"""Get export type"""
|
|
460
|
+
if export.get("is_default", False):
|
|
461
|
+
return "default"
|
|
462
|
+
elif export.get("is_named", False):
|
|
463
|
+
return "named"
|
|
464
|
+
elif export.get("is_all", False):
|
|
465
|
+
return "all"
|
|
466
|
+
else:
|
|
467
|
+
return "unknown"
|