@optave/codegraph 3.1.5 → 3.2.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.
- package/README.md +3 -2
- package/package.json +7 -7
- package/src/ast-analysis/engine.js +252 -258
- package/src/ast-analysis/shared.js +0 -12
- package/src/ast-analysis/visitors/cfg-visitor.js +635 -649
- package/src/ast-analysis/visitors/complexity-visitor.js +135 -139
- package/src/ast-analysis/visitors/dataflow-visitor.js +230 -224
- package/src/cli/commands/ast.js +2 -1
- package/src/cli/commands/audit.js +2 -1
- package/src/cli/commands/batch.js +2 -1
- package/src/cli/commands/brief.js +12 -0
- package/src/cli/commands/cfg.js +2 -1
- package/src/cli/commands/check.js +20 -23
- package/src/cli/commands/children.js +6 -1
- package/src/cli/commands/complexity.js +2 -1
- package/src/cli/commands/context.js +6 -1
- package/src/cli/commands/dataflow.js +2 -1
- package/src/cli/commands/deps.js +8 -3
- package/src/cli/commands/flow.js +2 -1
- package/src/cli/commands/fn-impact.js +6 -1
- package/src/cli/commands/owners.js +4 -2
- package/src/cli/commands/query.js +6 -1
- package/src/cli/commands/roles.js +2 -1
- package/src/cli/commands/search.js +8 -2
- package/src/cli/commands/sequence.js +2 -1
- package/src/cli/commands/triage.js +38 -27
- package/src/db/connection.js +18 -12
- package/src/db/migrations.js +41 -64
- package/src/db/query-builder.js +60 -4
- package/src/db/repository/in-memory-repository.js +27 -16
- package/src/db/repository/nodes.js +8 -10
- package/src/domain/analysis/brief.js +155 -0
- package/src/domain/analysis/context.js +174 -190
- package/src/domain/analysis/dependencies.js +200 -146
- package/src/domain/analysis/exports.js +3 -2
- package/src/domain/analysis/impact.js +267 -152
- package/src/domain/analysis/module-map.js +247 -221
- package/src/domain/analysis/roles.js +8 -5
- package/src/domain/analysis/symbol-lookup.js +7 -5
- package/src/domain/graph/builder/helpers.js +1 -1
- package/src/domain/graph/builder/incremental.js +116 -90
- package/src/domain/graph/builder/pipeline.js +106 -80
- package/src/domain/graph/builder/stages/build-edges.js +318 -239
- package/src/domain/graph/builder/stages/detect-changes.js +198 -177
- package/src/domain/graph/builder/stages/insert-nodes.js +147 -139
- package/src/domain/graph/watcher.js +2 -2
- package/src/domain/parser.js +20 -11
- package/src/domain/queries.js +1 -0
- package/src/domain/search/search/filters.js +9 -5
- package/src/domain/search/search/keyword.js +12 -5
- package/src/domain/search/search/prepare.js +13 -5
- package/src/extractors/csharp.js +224 -207
- package/src/extractors/go.js +176 -172
- package/src/extractors/hcl.js +94 -78
- package/src/extractors/java.js +213 -207
- package/src/extractors/javascript.js +274 -304
- package/src/extractors/php.js +234 -221
- package/src/extractors/python.js +252 -250
- package/src/extractors/ruby.js +192 -185
- package/src/extractors/rust.js +182 -167
- package/src/features/ast.js +5 -3
- package/src/features/audit.js +4 -2
- package/src/features/boundaries.js +98 -83
- package/src/features/cfg.js +134 -143
- package/src/features/communities.js +68 -53
- package/src/features/complexity.js +143 -132
- package/src/features/dataflow.js +146 -149
- package/src/features/export.js +3 -3
- package/src/features/graph-enrichment.js +2 -2
- package/src/features/manifesto.js +9 -6
- package/src/features/owners.js +4 -3
- package/src/features/sequence.js +152 -141
- package/src/features/shared/find-nodes.js +31 -0
- package/src/features/structure.js +130 -99
- package/src/features/triage.js +83 -68
- package/src/graph/classifiers/risk.js +3 -2
- package/src/graph/classifiers/roles.js +6 -3
- package/src/index.js +1 -0
- package/src/mcp/server.js +65 -56
- package/src/mcp/tool-registry.js +13 -0
- package/src/mcp/tools/brief.js +8 -0
- package/src/mcp/tools/index.js +2 -0
- package/src/presentation/brief.js +51 -0
- package/src/presentation/queries-cli/exports.js +21 -14
- package/src/presentation/queries-cli/impact.js +55 -39
- package/src/presentation/queries-cli/inspect.js +184 -189
- package/src/presentation/queries-cli/overview.js +57 -58
- package/src/presentation/queries-cli/path.js +36 -29
- package/src/presentation/table.js +0 -8
- package/src/shared/generators.js +7 -3
- package/src/shared/kinds.js +1 -1
|
@@ -320,333 +320,303 @@ function handleCommonJSAssignment(left, right, node, imports) {
|
|
|
320
320
|
// ── Manual tree walk (fallback when Query not available) ────────────────────
|
|
321
321
|
|
|
322
322
|
function extractSymbolsWalk(tree) {
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
const fnChildren = extractParameters(node);
|
|
335
|
-
definitions.push({
|
|
336
|
-
name: nameNode.text,
|
|
337
|
-
kind: 'function',
|
|
338
|
-
line: node.startPosition.row + 1,
|
|
339
|
-
endLine: nodeEndLine(node),
|
|
340
|
-
children: fnChildren.length > 0 ? fnChildren : undefined,
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
break;
|
|
344
|
-
}
|
|
323
|
+
const ctx = {
|
|
324
|
+
definitions: [],
|
|
325
|
+
calls: [],
|
|
326
|
+
imports: [],
|
|
327
|
+
classes: [],
|
|
328
|
+
exports: [],
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
walkJavaScriptNode(tree.rootNode, ctx);
|
|
332
|
+
return ctx;
|
|
333
|
+
}
|
|
345
334
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
335
|
+
function walkJavaScriptNode(node, ctx) {
|
|
336
|
+
switch (node.type) {
|
|
337
|
+
case 'function_declaration':
|
|
338
|
+
handleFunctionDecl(node, ctx);
|
|
339
|
+
break;
|
|
340
|
+
case 'class_declaration':
|
|
341
|
+
handleClassDecl(node, ctx);
|
|
342
|
+
break;
|
|
343
|
+
case 'method_definition':
|
|
344
|
+
handleMethodDef(node, ctx);
|
|
345
|
+
break;
|
|
346
|
+
case 'interface_declaration':
|
|
347
|
+
handleInterfaceDecl(node, ctx);
|
|
348
|
+
break;
|
|
349
|
+
case 'type_alias_declaration':
|
|
350
|
+
handleTypeAliasDecl(node, ctx);
|
|
351
|
+
break;
|
|
352
|
+
case 'lexical_declaration':
|
|
353
|
+
case 'variable_declaration':
|
|
354
|
+
handleVariableDecl(node, ctx);
|
|
355
|
+
break;
|
|
356
|
+
case 'enum_declaration':
|
|
357
|
+
handleEnumDecl(node, ctx);
|
|
358
|
+
break;
|
|
359
|
+
case 'call_expression':
|
|
360
|
+
handleCallExpr(node, ctx);
|
|
361
|
+
break;
|
|
362
|
+
case 'import_statement':
|
|
363
|
+
handleImportStmt(node, ctx);
|
|
364
|
+
break;
|
|
365
|
+
case 'export_statement':
|
|
366
|
+
handleExportStmt(node, ctx);
|
|
367
|
+
break;
|
|
368
|
+
case 'expression_statement':
|
|
369
|
+
handleExpressionStmt(node, ctx);
|
|
370
|
+
break;
|
|
371
|
+
}
|
|
373
372
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
const fullName = parentClass ? `${parentClass}.${nameNode.text}` : nameNode.text;
|
|
379
|
-
const methChildren = extractParameters(node);
|
|
380
|
-
const methVis = extractVisibility(node);
|
|
381
|
-
definitions.push({
|
|
382
|
-
name: fullName,
|
|
383
|
-
kind: 'method',
|
|
384
|
-
line: node.startPosition.row + 1,
|
|
385
|
-
endLine: nodeEndLine(node),
|
|
386
|
-
children: methChildren.length > 0 ? methChildren : undefined,
|
|
387
|
-
visibility: methVis,
|
|
388
|
-
});
|
|
389
|
-
}
|
|
390
|
-
break;
|
|
391
|
-
}
|
|
373
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
374
|
+
walkJavaScriptNode(node.child(i), ctx);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
392
377
|
|
|
393
|
-
|
|
394
|
-
const nameNode = node.childForFieldName('name');
|
|
395
|
-
if (nameNode) {
|
|
396
|
-
definitions.push({
|
|
397
|
-
name: nameNode.text,
|
|
398
|
-
kind: 'interface',
|
|
399
|
-
line: node.startPosition.row + 1,
|
|
400
|
-
endLine: nodeEndLine(node),
|
|
401
|
-
});
|
|
402
|
-
const body =
|
|
403
|
-
node.childForFieldName('body') ||
|
|
404
|
-
findChild(node, 'interface_body') ||
|
|
405
|
-
findChild(node, 'object_type');
|
|
406
|
-
if (body) {
|
|
407
|
-
extractInterfaceMethods(body, nameNode.text, definitions);
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
break;
|
|
411
|
-
}
|
|
378
|
+
// ── Walk-path per-node-type handlers ────────────────────────────────────────
|
|
412
379
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
380
|
+
function handleFunctionDecl(node, ctx) {
|
|
381
|
+
const nameNode = node.childForFieldName('name');
|
|
382
|
+
if (nameNode) {
|
|
383
|
+
const fnChildren = extractParameters(node);
|
|
384
|
+
ctx.definitions.push({
|
|
385
|
+
name: nameNode.text,
|
|
386
|
+
kind: 'function',
|
|
387
|
+
line: node.startPosition.row + 1,
|
|
388
|
+
endLine: nodeEndLine(node),
|
|
389
|
+
children: fnChildren.length > 0 ? fnChildren : undefined,
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
}
|
|
425
393
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
name: nameN.text,
|
|
452
|
-
kind: 'constant',
|
|
453
|
-
line: node.startPosition.row + 1,
|
|
454
|
-
endLine: nodeEndLine(node),
|
|
455
|
-
});
|
|
456
|
-
}
|
|
457
|
-
} else if (isConst && nameN && nameN.type === 'identifier' && !valueN) {
|
|
458
|
-
// const with no value (shouldn't happen but be safe)
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
break;
|
|
463
|
-
}
|
|
394
|
+
function handleClassDecl(node, ctx) {
|
|
395
|
+
const nameNode = node.childForFieldName('name');
|
|
396
|
+
if (!nameNode) return;
|
|
397
|
+
const className = nameNode.text;
|
|
398
|
+
const startLine = node.startPosition.row + 1;
|
|
399
|
+
const clsChildren = extractClassProperties(node);
|
|
400
|
+
ctx.definitions.push({
|
|
401
|
+
name: className,
|
|
402
|
+
kind: 'class',
|
|
403
|
+
line: startLine,
|
|
404
|
+
endLine: nodeEndLine(node),
|
|
405
|
+
children: clsChildren.length > 0 ? clsChildren : undefined,
|
|
406
|
+
});
|
|
407
|
+
const heritage = node.childForFieldName('heritage') || findChild(node, 'class_heritage');
|
|
408
|
+
if (heritage) {
|
|
409
|
+
const superName = extractSuperclass(heritage);
|
|
410
|
+
if (superName) {
|
|
411
|
+
ctx.classes.push({ name: className, extends: superName, line: startLine });
|
|
412
|
+
}
|
|
413
|
+
const implementsList = extractImplements(heritage);
|
|
414
|
+
for (const iface of implementsList) {
|
|
415
|
+
ctx.classes.push({ name: className, implements: iface, line: startLine });
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
464
419
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
});
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
definitions.push({
|
|
488
|
-
name: nameNode.text,
|
|
489
|
-
kind: 'enum',
|
|
490
|
-
line: node.startPosition.row + 1,
|
|
491
|
-
endLine: nodeEndLine(node),
|
|
492
|
-
children: enumChildren.length > 0 ? enumChildren : undefined,
|
|
493
|
-
});
|
|
494
|
-
}
|
|
495
|
-
break;
|
|
496
|
-
}
|
|
420
|
+
function handleMethodDef(node, ctx) {
|
|
421
|
+
const nameNode = node.childForFieldName('name');
|
|
422
|
+
if (nameNode) {
|
|
423
|
+
const parentClass = findParentClass(node);
|
|
424
|
+
const fullName = parentClass ? `${parentClass}.${nameNode.text}` : nameNode.text;
|
|
425
|
+
const methChildren = extractParameters(node);
|
|
426
|
+
const methVis = extractVisibility(node);
|
|
427
|
+
ctx.definitions.push({
|
|
428
|
+
name: fullName,
|
|
429
|
+
kind: 'method',
|
|
430
|
+
line: node.startPosition.row + 1,
|
|
431
|
+
endLine: nodeEndLine(node),
|
|
432
|
+
children: methChildren.length > 0 ? methChildren : undefined,
|
|
433
|
+
visibility: methVis,
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
}
|
|
497
437
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
line: node.startPosition.row + 1,
|
|
516
|
-
dynamicImport: true,
|
|
517
|
-
});
|
|
518
|
-
} else {
|
|
519
|
-
debug(
|
|
520
|
-
`Skipping non-static dynamic import() at line ${node.startPosition.row + 1} (template literal or variable)`,
|
|
521
|
-
);
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
} else {
|
|
525
|
-
const callInfo = extractCallInfo(fn, node);
|
|
526
|
-
if (callInfo) calls.push(callInfo);
|
|
527
|
-
if (fn.type === 'member_expression') {
|
|
528
|
-
const cbDef = extractCallbackDefinition(node, fn);
|
|
529
|
-
if (cbDef) definitions.push(cbDef);
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
break;
|
|
534
|
-
}
|
|
438
|
+
function handleInterfaceDecl(node, ctx) {
|
|
439
|
+
const nameNode = node.childForFieldName('name');
|
|
440
|
+
if (!nameNode) return;
|
|
441
|
+
ctx.definitions.push({
|
|
442
|
+
name: nameNode.text,
|
|
443
|
+
kind: 'interface',
|
|
444
|
+
line: node.startPosition.row + 1,
|
|
445
|
+
endLine: nodeEndLine(node),
|
|
446
|
+
});
|
|
447
|
+
const body =
|
|
448
|
+
node.childForFieldName('body') ||
|
|
449
|
+
findChild(node, 'interface_body') ||
|
|
450
|
+
findChild(node, 'object_type');
|
|
451
|
+
if (body) {
|
|
452
|
+
extractInterfaceMethods(body, nameNode.text, ctx.definitions);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
535
455
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
456
|
+
function handleTypeAliasDecl(node, ctx) {
|
|
457
|
+
const nameNode = node.childForFieldName('name');
|
|
458
|
+
if (nameNode) {
|
|
459
|
+
ctx.definitions.push({
|
|
460
|
+
name: nameNode.text,
|
|
461
|
+
kind: 'type',
|
|
462
|
+
line: node.startPosition.row + 1,
|
|
463
|
+
endLine: nodeEndLine(node),
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
function handleVariableDecl(node, ctx) {
|
|
469
|
+
const isConst = node.text.startsWith('const ');
|
|
470
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
471
|
+
const declarator = node.child(i);
|
|
472
|
+
if (declarator && declarator.type === 'variable_declarator') {
|
|
473
|
+
const nameN = declarator.childForFieldName('name');
|
|
474
|
+
const valueN = declarator.childForFieldName('value');
|
|
475
|
+
if (nameN && valueN) {
|
|
476
|
+
const valType = valueN.type;
|
|
477
|
+
if (
|
|
478
|
+
valType === 'arrow_function' ||
|
|
479
|
+
valType === 'function_expression' ||
|
|
480
|
+
valType === 'function'
|
|
481
|
+
) {
|
|
482
|
+
const varFnChildren = extractParameters(valueN);
|
|
483
|
+
ctx.definitions.push({
|
|
484
|
+
name: nameN.text,
|
|
485
|
+
kind: 'function',
|
|
486
|
+
line: node.startPosition.row + 1,
|
|
487
|
+
endLine: nodeEndLine(valueN),
|
|
488
|
+
children: varFnChildren.length > 0 ? varFnChildren : undefined,
|
|
489
|
+
});
|
|
490
|
+
} else if (isConst && nameN.type === 'identifier' && isConstantValue(valueN)) {
|
|
491
|
+
ctx.definitions.push({
|
|
492
|
+
name: nameN.text,
|
|
493
|
+
kind: 'constant',
|
|
545
494
|
line: node.startPosition.row + 1,
|
|
546
|
-
|
|
495
|
+
endLine: nodeEndLine(node),
|
|
547
496
|
});
|
|
548
497
|
}
|
|
549
|
-
break;
|
|
550
498
|
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
551
502
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
}
|
|
569
|
-
const source = node.childForFieldName('source') || findChild(node, 'string');
|
|
570
|
-
if (source && !decl) {
|
|
571
|
-
const modPath = source.text.replace(/['"]/g, '');
|
|
572
|
-
const reexportNames = extractImportNames(node);
|
|
573
|
-
const nodeText = node.text;
|
|
574
|
-
const isWildcard = nodeText.includes('export *') || nodeText.includes('export*');
|
|
575
|
-
imports.push({
|
|
576
|
-
source: modPath,
|
|
577
|
-
names: reexportNames,
|
|
578
|
-
line: exportLine,
|
|
579
|
-
reexport: true,
|
|
580
|
-
wildcardReexport: isWildcard && reexportNames.length === 0,
|
|
503
|
+
function handleEnumDecl(node, ctx) {
|
|
504
|
+
const nameNode = node.childForFieldName('name');
|
|
505
|
+
if (!nameNode) return;
|
|
506
|
+
const enumChildren = [];
|
|
507
|
+
const body = node.childForFieldName('body') || findChild(node, 'enum_body');
|
|
508
|
+
if (body) {
|
|
509
|
+
for (let i = 0; i < body.childCount; i++) {
|
|
510
|
+
const member = body.child(i);
|
|
511
|
+
if (!member) continue;
|
|
512
|
+
if (member.type === 'enum_assignment' || member.type === 'property_identifier') {
|
|
513
|
+
const mName = member.childForFieldName('name') || member.child(0);
|
|
514
|
+
if (mName) {
|
|
515
|
+
enumChildren.push({
|
|
516
|
+
name: mName.text,
|
|
517
|
+
kind: 'constant',
|
|
518
|
+
line: member.startPosition.row + 1,
|
|
581
519
|
});
|
|
582
520
|
}
|
|
583
|
-
break;
|
|
584
521
|
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
ctx.definitions.push({
|
|
525
|
+
name: nameNode.text,
|
|
526
|
+
kind: 'enum',
|
|
527
|
+
line: node.startPosition.row + 1,
|
|
528
|
+
endLine: nodeEndLine(node),
|
|
529
|
+
children: enumChildren.length > 0 ? enumChildren : undefined,
|
|
530
|
+
});
|
|
531
|
+
}
|
|
585
532
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
});
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
if (right.type === 'object') {
|
|
611
|
-
for (let ci = 0; ci < right.childCount; ci++) {
|
|
612
|
-
const child = right.child(ci);
|
|
613
|
-
if (child && child.type === 'spread_element') {
|
|
614
|
-
const spreadExpr = child.child(1) || child.childForFieldName('value');
|
|
615
|
-
if (spreadExpr && spreadExpr.type === 'call_expression') {
|
|
616
|
-
const fn2 = spreadExpr.childForFieldName('function');
|
|
617
|
-
const args2 =
|
|
618
|
-
spreadExpr.childForFieldName('arguments') ||
|
|
619
|
-
findChild(spreadExpr, 'arguments');
|
|
620
|
-
if (fn2 && fn2.text === 'require' && args2) {
|
|
621
|
-
const strArg2 = findChild(args2, 'string');
|
|
622
|
-
if (strArg2) {
|
|
623
|
-
imports.push({
|
|
624
|
-
source: strArg2.text.replace(/['"]/g, ''),
|
|
625
|
-
names: [],
|
|
626
|
-
line: node.startPosition.row + 1,
|
|
627
|
-
reexport: true,
|
|
628
|
-
wildcardReexport: true,
|
|
629
|
-
});
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
break;
|
|
533
|
+
function handleCallExpr(node, ctx) {
|
|
534
|
+
const fn = node.childForFieldName('function');
|
|
535
|
+
if (!fn) return;
|
|
536
|
+
if (fn.type === 'import') {
|
|
537
|
+
const args = node.childForFieldName('arguments') || findChild(node, 'arguments');
|
|
538
|
+
if (args) {
|
|
539
|
+
const strArg = findChild(args, 'string');
|
|
540
|
+
if (strArg) {
|
|
541
|
+
const modPath = strArg.text.replace(/['"]/g, '');
|
|
542
|
+
const names = extractDynamicImportNames(node);
|
|
543
|
+
ctx.imports.push({
|
|
544
|
+
source: modPath,
|
|
545
|
+
names,
|
|
546
|
+
line: node.startPosition.row + 1,
|
|
547
|
+
dynamicImport: true,
|
|
548
|
+
});
|
|
549
|
+
} else {
|
|
550
|
+
debug(
|
|
551
|
+
`Skipping non-static dynamic import() at line ${node.startPosition.row + 1} (template literal or variable)`,
|
|
552
|
+
);
|
|
640
553
|
}
|
|
641
554
|
}
|
|
555
|
+
} else {
|
|
556
|
+
const callInfo = extractCallInfo(fn, node);
|
|
557
|
+
if (callInfo) ctx.calls.push(callInfo);
|
|
558
|
+
if (fn.type === 'member_expression') {
|
|
559
|
+
const cbDef = extractCallbackDefinition(node, fn);
|
|
560
|
+
if (cbDef) ctx.definitions.push(cbDef);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
642
564
|
|
|
643
|
-
|
|
644
|
-
|
|
565
|
+
function handleImportStmt(node, ctx) {
|
|
566
|
+
const isTypeOnly = node.text.startsWith('import type');
|
|
567
|
+
const source = node.childForFieldName('source') || findChild(node, 'string');
|
|
568
|
+
if (source) {
|
|
569
|
+
const modPath = source.text.replace(/['"]/g, '');
|
|
570
|
+
const names = extractImportNames(node);
|
|
571
|
+
ctx.imports.push({
|
|
572
|
+
source: modPath,
|
|
573
|
+
names,
|
|
574
|
+
line: node.startPosition.row + 1,
|
|
575
|
+
typeOnly: isTypeOnly,
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
function handleExportStmt(node, ctx) {
|
|
581
|
+
const exportLine = node.startPosition.row + 1;
|
|
582
|
+
const decl = node.childForFieldName('declaration');
|
|
583
|
+
if (decl) {
|
|
584
|
+
const declType = decl.type;
|
|
585
|
+
const kindMap = {
|
|
586
|
+
function_declaration: 'function',
|
|
587
|
+
class_declaration: 'class',
|
|
588
|
+
interface_declaration: 'interface',
|
|
589
|
+
type_alias_declaration: 'type',
|
|
590
|
+
};
|
|
591
|
+
const kind = kindMap[declType];
|
|
592
|
+
if (kind) {
|
|
593
|
+
const n = decl.childForFieldName('name');
|
|
594
|
+
if (n) ctx.exports.push({ name: n.text, kind, line: exportLine });
|
|
645
595
|
}
|
|
646
596
|
}
|
|
597
|
+
const source = node.childForFieldName('source') || findChild(node, 'string');
|
|
598
|
+
if (source && !decl) {
|
|
599
|
+
const modPath = source.text.replace(/['"]/g, '');
|
|
600
|
+
const reexportNames = extractImportNames(node);
|
|
601
|
+
const nodeText = node.text;
|
|
602
|
+
const isWildcard = nodeText.includes('export *') || nodeText.includes('export*');
|
|
603
|
+
ctx.imports.push({
|
|
604
|
+
source: modPath,
|
|
605
|
+
names: reexportNames,
|
|
606
|
+
line: exportLine,
|
|
607
|
+
reexport: true,
|
|
608
|
+
wildcardReexport: isWildcard && reexportNames.length === 0,
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
}
|
|
647
612
|
|
|
648
|
-
|
|
649
|
-
|
|
613
|
+
function handleExpressionStmt(node, ctx) {
|
|
614
|
+
const expr = node.child(0);
|
|
615
|
+
if (expr && expr.type === 'assignment_expression') {
|
|
616
|
+
const left = expr.childForFieldName('left');
|
|
617
|
+
const right = expr.childForFieldName('right');
|
|
618
|
+
handleCommonJSAssignment(left, right, node, ctx.imports);
|
|
619
|
+
}
|
|
650
620
|
}
|
|
651
621
|
|
|
652
622
|
// ── Child extraction helpers ────────────────────────────────────────────────
|