@codeflow-map/core 0.1.0

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.
@@ -0,0 +1,358 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.tsxAnalyzer = void 0;
4
+ const extractorUtils_1 = require("../extractorUtils");
5
+ exports.tsxAnalyzer = {
6
+ functionQuery: `
7
+ (function_declaration
8
+ name: (identifier) @fn.name
9
+ parameters: (formal_parameters) @fn.params
10
+ return_type: (type_annotation)? @fn.return_type) @fn.decl
11
+
12
+ (lexical_declaration
13
+ (variable_declarator
14
+ name: (identifier) @fn.name
15
+ value: [(arrow_function) (function_expression)] @fn.decl))
16
+
17
+ (export_statement
18
+ declaration: (lexical_declaration
19
+ (variable_declarator
20
+ name: (identifier) @fn.name
21
+ value: [(arrow_function) (function_expression)] @fn.decl)))
22
+
23
+ (method_definition
24
+ name: (property_identifier) @fn.name
25
+ parameters: (formal_parameters) @fn.params
26
+ return_type: (type_annotation)? @fn.return_type) @fn.decl
27
+
28
+ (call_expression
29
+ function: (identifier) @hook.name
30
+ arguments: (arguments
31
+ [(arrow_function) (function_expression)] @fn.decl)
32
+ (#match? @hook.name "^use"))
33
+
34
+ (generator_function_declaration
35
+ name: (identifier) @fn.name
36
+ parameters: (formal_parameters) @fn.params
37
+ return_type: (type_annotation)? @fn.return_type) @fn.decl
38
+
39
+ (lexical_declaration
40
+ (variable_declarator
41
+ name: (identifier) @fn.name
42
+ value: (generator_function) @fn.decl))
43
+
44
+ (export_statement
45
+ declaration: (lexical_declaration
46
+ (variable_declarator
47
+ name: (identifier) @fn.name
48
+ value: (generator_function) @fn.decl)))
49
+
50
+ (function_expression
51
+ name: (identifier) @fn.name
52
+ parameters: (formal_parameters) @fn.params) @fn.decl
53
+
54
+ (lexical_declaration
55
+ (variable_declarator
56
+ name: (identifier) @fn.name
57
+ value: (call_expression
58
+ function: [(parenthesized_expression
59
+ [(function_expression)(arrow_function)] @fn.decl)
60
+ (arrow_function) @fn.decl
61
+ (function_expression) @fn.decl])))
62
+
63
+ (expression_statement
64
+ (call_expression
65
+ function: (parenthesized_expression
66
+ [(function_expression)(arrow_function)] @fn.decl)))
67
+
68
+ (assignment_expression
69
+ left: (member_expression
70
+ object: (identifier) @worker.obj
71
+ property: (property_identifier) @worker.prop)
72
+ right: [(arrow_function) (function_expression)] @worker.fn
73
+ (#match? @worker.obj "^self$")
74
+ (#match? @worker.prop "^onmessage$"))
75
+
76
+ (call_expression
77
+ function: (member_expression
78
+ object: (identifier) @worker.obj
79
+ property: (property_identifier) @worker.method)
80
+ arguments: (arguments
81
+ (string) @worker.event
82
+ [(arrow_function) (function_expression)] @worker.fn)
83
+ (#match? @worker.obj "^self$")
84
+ (#match? @worker.method "^addEventListener$")
85
+ (#match? @worker.event "message"))
86
+
87
+ (lexical_declaration
88
+ (variable_declarator
89
+ name: (identifier) @fn.name
90
+ value: (call_expression
91
+ function: (identifier) @wrapper.name
92
+ arguments: (arguments
93
+ [(arrow_function) (function_expression)] @fn.decl)
94
+ (#match? @wrapper.name "^(forwardRef|memo)$"))))
95
+
96
+ (lexical_declaration
97
+ (variable_declarator
98
+ name: (identifier) @fn.name
99
+ value: (call_expression
100
+ function: (identifier) @wrapper.outer
101
+ arguments: (arguments
102
+ (call_expression
103
+ function: (identifier) @wrapper.inner
104
+ arguments: (arguments
105
+ [(arrow_function) (function_expression)] @fn.decl)))
106
+ (#match? @wrapper.outer "^(memo|forwardRef)$"))))
107
+
108
+ (export_statement
109
+ declaration: (lexical_declaration
110
+ (variable_declarator
111
+ name: (identifier) @fn.name
112
+ value: (call_expression
113
+ function: (identifier) @wrapper.name
114
+ arguments: (arguments
115
+ [(arrow_function) (function_expression)] @fn.decl)
116
+ (#match? @wrapper.name "^(forwardRef|memo)$")))))
117
+
118
+ (export_statement
119
+ declaration: (lexical_declaration
120
+ (variable_declarator
121
+ name: (identifier) @fn.name
122
+ value: (call_expression
123
+ function: (identifier) @wrapper.outer
124
+ arguments: (arguments
125
+ (call_expression
126
+ function: (identifier) @wrapper.inner
127
+ arguments: (arguments
128
+ [(arrow_function) (function_expression)] @fn.decl)))
129
+ (#match? @wrapper.outer "^(memo|forwardRef)$")))))
130
+
131
+ (public_field_definition
132
+ name: (property_identifier) @fn.name
133
+ value: [(arrow_function)(function_expression)] @fn.decl)
134
+ `,
135
+ callQuery: `
136
+ (call_expression
137
+ function: [(identifier)(member_expression)] @call.name) @call.expr
138
+
139
+ (jsx_element
140
+ open_tag: (jsx_opening_element
141
+ name: (identifier) @call.name
142
+ (#match? @call.name "^[A-Z]"))) @call.expr
143
+
144
+ (jsx_self_closing_element
145
+ name: (identifier) @call.name
146
+ (#match? @call.name "^[A-Z]")) @call.expr
147
+
148
+ (new_expression
149
+ constructor: (identifier) @call.name) @call.expr
150
+
151
+ (call_expression
152
+ function: (member_expression
153
+ property: (property_identifier) @call.name
154
+ (#match? @call.name "^(then|catch|finally)$"))) @call.expr
155
+ `,
156
+ extractFunction(match, filePath, languageId) {
157
+ const declCapture = match.captures.find((c) => c.name === 'fn.decl');
158
+ if (!declCapture) {
159
+ const workerFn = match.captures.find((c) => c.name === 'worker.fn');
160
+ if (workerFn) {
161
+ const workerProp = match.captures.find((c) => c.name === 'worker.prop');
162
+ const node = workerFn.node;
163
+ const rawName = workerProp ? 'onmessage_handler' : `message_handler_${node.startPosition.row}`;
164
+ const paramsList = (0, extractorUtils_1.getParamsFromFunctionNode)(node, true);
165
+ return {
166
+ id: `${filePath}::${rawName}::${node.startPosition.row}`,
167
+ name: rawName,
168
+ filePath,
169
+ startLine: node.startPosition.row,
170
+ endLine: node.endPosition.row,
171
+ params: paramsList,
172
+ returnType: null,
173
+ isAsync: (0, extractorUtils_1.checkIsAsync)(node),
174
+ isExported: false,
175
+ isEntryPoint: true,
176
+ language: languageId,
177
+ kind: 'function'
178
+ };
179
+ }
180
+ return null;
181
+ }
182
+ const nameCapture = match.captures.find((c) => c.name === 'fn.name');
183
+ const hookNameCapture = match.captures.find((c) => c.name === 'hook.name');
184
+ // For wrapper patterns (memo, forwardRef), only capture the first argument
185
+ const wrapperCapture = match.captures.find((c) => c.name === 'wrapper.name' || c.name === 'wrapper.outer');
186
+ if (wrapperCapture) {
187
+ const argsParent = declCapture.node.parent;
188
+ if (argsParent?.type === 'arguments') {
189
+ const firstArg = argsParent.namedChildren[0];
190
+ if (firstArg.id !== declCapture.node.id) {
191
+ return null;
192
+ }
193
+ }
194
+ }
195
+ let rawName = "anonymous";
196
+ let kind = 'function';
197
+ let parentFunctionId;
198
+ if (nameCapture) {
199
+ rawName = nameCapture.node.text;
200
+ if (declCapture.node.type === 'function_expression' && nameCapture.node.parent?.id === declCapture.node.id) {
201
+ if (declCapture.node.parent?.type === 'variable_declarator') {
202
+ return null;
203
+ }
204
+ parentFunctionId = (0, extractorUtils_1.getEnclosingFunctionId)(declCapture.node, filePath) ?? undefined;
205
+ }
206
+ if (declCapture.node.type === 'method_definition') {
207
+ kind = 'method';
208
+ }
209
+ else if (rawName.length > 0 && rawName[0] === rawName[0].toUpperCase())
210
+ kind = 'component';
211
+ }
212
+ else if (hookNameCapture) {
213
+ const startLine = declCapture.node.startPosition.row;
214
+ rawName = `${hookNameCapture.node.text}_callback_${startLine}`;
215
+ kind = 'hook';
216
+ }
217
+ // Detect IIFE: fn.decl is inside a call_expression (the IIFE invocation)
218
+ // Skip IIFE detection for wrapper patterns (forwardRef, memo)
219
+ const declParent = declCapture.node.parent;
220
+ const isParenWrapped = declParent?.type === 'parenthesized_expression';
221
+ const callParent = isParenWrapped ? declParent.parent : declParent;
222
+ if (callParent?.type === 'call_expression' && !wrapperCapture) {
223
+ if (rawName === 'anonymous') {
224
+ rawName = `iife_${declCapture.node.startPosition.row}`;
225
+ }
226
+ kind = 'iife';
227
+ }
228
+ else if (rawName === "anonymous" && !hookNameCapture) {
229
+ return null;
230
+ }
231
+ // Prefix with enclosing scope chain (parent functions, classes, and object literals)
232
+ const scopeChain = (0, extractorUtils_1.getEnclosingScopeChain)(declCapture.node, extractorUtils_1.JS_FN_SCOPE_TYPES, extractorUtils_1.JS_CLASS_SCOPE_TYPES);
233
+ if (scopeChain.length > 0) {
234
+ rawName = `${scopeChain.map(s => s.name).join('.')}.${rawName}`;
235
+ }
236
+ // For wrapper patterns, use the outermost wrapper call_expression range
237
+ let rangeNode = declCapture.node;
238
+ if (wrapperCapture) {
239
+ let target = declCapture.node.parent;
240
+ while (target?.type === 'arguments') {
241
+ const callExpr = target.parent;
242
+ if (callExpr?.type !== 'call_expression')
243
+ break;
244
+ const fn = callExpr.childForFieldName('function');
245
+ const isKnownWrapper = fn && ((fn.type === 'identifier' && /^(forwardRef|memo)$/.test(fn.text)) ||
246
+ (fn.type === 'member_expression' && /^(forwardRef|memo)$/.test(fn.childForFieldName('property')?.text ?? '')));
247
+ if (!isKnownWrapper)
248
+ break;
249
+ rangeNode = callExpr;
250
+ target = callExpr.parent;
251
+ }
252
+ }
253
+ const paramsCapture = match.captures.find((c) => c.name === 'fn.params');
254
+ const returnCapture = match.captures.find((c) => c.name === 'fn.return_type');
255
+ const isExported = (0, extractorUtils_1.checkExportedByParentWalk)(declCapture.node);
256
+ const paramsList = paramsCapture
257
+ ? (0, extractorUtils_1.buildJsParams)(paramsCapture.node, true)
258
+ : (0, extractorUtils_1.getParamsFromFunctionNode)(declCapture.node, true);
259
+ let finalReturnType = returnCapture ? returnCapture.node.text.replace(/^:\s*/, '') : null;
260
+ if (!finalReturnType) {
261
+ const returnValues = (0, extractorUtils_1.getReturnValues)(declCapture.node, extractorUtils_1.JS_NESTED_FN_TYPES);
262
+ if (returnValues.length > 0) {
263
+ finalReturnType = returnValues.join(' | ');
264
+ }
265
+ }
266
+ return {
267
+ id: `${filePath}::${rawName}::${rangeNode.startPosition.row}`,
268
+ name: rawName,
269
+ filePath,
270
+ startLine: rangeNode.startPosition.row,
271
+ endLine: rangeNode.endPosition.row,
272
+ params: paramsList,
273
+ returnType: finalReturnType,
274
+ isAsync: (0, extractorUtils_1.checkIsAsync)(declCapture.node),
275
+ isExported,
276
+ isEntryPoint: false,
277
+ language: languageId,
278
+ kind,
279
+ ...(parentFunctionId ? { parentFunctionId } : {})
280
+ };
281
+ },
282
+ extractCall(match, filePath) {
283
+ const nameCapture = match.captures.find((c) => c.name === 'call.name');
284
+ const exprCapture = match.captures.find((c) => c.name === 'call.expr');
285
+ if (nameCapture && exprCapture) {
286
+ let calleeName = nameCapture.node.text;
287
+ if (nameCapture.node.type === 'member_expression') {
288
+ const prop = nameCapture.node.childForFieldName('property');
289
+ if (prop)
290
+ calleeName = prop.text;
291
+ }
292
+ // Unwrap .bind(): handleWorkerMessage.bind(this) → ref to handleWorkerMessage
293
+ if (calleeName === 'bind' && nameCapture.node.type === 'member_expression') {
294
+ const obj = nameCapture.node.childForFieldName('object');
295
+ if (obj?.type === 'identifier') {
296
+ return {
297
+ callerFilePath: filePath,
298
+ calleeName: obj.text,
299
+ line: exprCapture.node.startPosition.row,
300
+ callType: (0, extractorUtils_1.isInsidePromiseCombinator)(exprCapture.node) ? 'concurrent' : 'ref',
301
+ isRef: true
302
+ };
303
+ }
304
+ }
305
+ const callType = (0, extractorUtils_1.isInsidePromiseCombinator)(exprCapture.node) ? 'concurrent' : undefined;
306
+ const directCall = {
307
+ callerFilePath: filePath,
308
+ calleeName,
309
+ line: exprCapture.node.startPosition.row,
310
+ ...(callType ? { callType } : {})
311
+ };
312
+ // Extract function reference arguments from any call
313
+ const refCalls = [];
314
+ const callNode = exprCapture.node;
315
+ const argsNode = callNode.childForFieldName('arguments');
316
+ if (argsNode) {
317
+ for (const arg of argsNode.namedChildren) {
318
+ let refName = null;
319
+ if (arg.type === 'identifier') {
320
+ refName = arg.text;
321
+ }
322
+ else if (arg.type === 'member_expression') {
323
+ const obj = arg.childForFieldName('object');
324
+ const prop = arg.childForFieldName('property');
325
+ if (obj?.type === 'this' && prop) {
326
+ refName = prop.text;
327
+ }
328
+ }
329
+ else if (arg.type === 'call_expression') {
330
+ const fn = arg.childForFieldName('function');
331
+ if (fn?.type === 'member_expression') {
332
+ const prop = fn.childForFieldName('property');
333
+ const obj = fn.childForFieldName('object');
334
+ if (prop?.text === 'bind' && obj?.type === 'identifier') {
335
+ refName = obj.text;
336
+ }
337
+ }
338
+ }
339
+ if (refName) {
340
+ const refCallType = (0, extractorUtils_1.isInsidePromiseCombinator)(callNode) ? 'concurrent' : 'ref';
341
+ refCalls.push({
342
+ callerFilePath: filePath,
343
+ calleeName: refName,
344
+ line: callNode.startPosition.row,
345
+ callType: refCallType,
346
+ isRef: true
347
+ });
348
+ }
349
+ }
350
+ }
351
+ if (refCalls.length > 0) {
352
+ return [directCall, ...refCalls];
353
+ }
354
+ return directCall;
355
+ }
356
+ return null;
357
+ }
358
+ };
@@ -0,0 +1,2 @@
1
+ import { LanguageAnalyzer } from '../../types';
2
+ export declare const typescriptAnalyzer: LanguageAnalyzer;