gitnexus 1.4.7 → 1.4.8
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 +22 -1
- package/dist/cli/ai-context.d.ts +1 -1
- package/dist/cli/ai-context.js +1 -1
- package/dist/cli/analyze.d.ts +2 -0
- package/dist/cli/analyze.js +54 -21
- package/dist/cli/index.js +2 -1
- package/dist/cli/setup.js +78 -1
- package/dist/config/supported-languages.d.ts +30 -0
- package/dist/config/supported-languages.js +30 -0
- package/dist/core/embeddings/embedder.d.ts +6 -1
- package/dist/core/embeddings/embedder.js +65 -5
- package/dist/core/embeddings/embedding-pipeline.js +11 -9
- package/dist/core/embeddings/http-client.d.ts +31 -0
- package/dist/core/embeddings/http-client.js +179 -0
- package/dist/core/embeddings/index.d.ts +1 -0
- package/dist/core/embeddings/index.js +1 -0
- package/dist/core/embeddings/types.d.ts +1 -1
- package/dist/core/graph/types.d.ts +2 -1
- package/dist/core/ingestion/ast-helpers.d.ts +80 -0
- package/dist/core/ingestion/ast-helpers.js +738 -0
- package/dist/core/ingestion/call-analysis.d.ts +73 -0
- package/dist/core/ingestion/call-analysis.js +490 -0
- package/dist/core/ingestion/call-processor.d.ts +48 -1
- package/dist/core/ingestion/call-processor.js +368 -7
- package/dist/core/ingestion/call-routing.d.ts +6 -0
- package/dist/core/ingestion/entry-point-scoring.js +36 -26
- package/dist/core/ingestion/framework-detection.d.ts +10 -2
- package/dist/core/ingestion/framework-detection.js +49 -12
- package/dist/core/ingestion/heritage-processor.js +47 -49
- package/dist/core/ingestion/import-processor.d.ts +1 -1
- package/dist/core/ingestion/import-processor.js +103 -194
- package/dist/core/ingestion/import-resolution.d.ts +101 -0
- package/dist/core/ingestion/import-resolution.js +251 -0
- package/dist/core/ingestion/language-config.d.ts +3 -0
- package/dist/core/ingestion/language-config.js +13 -0
- package/dist/core/ingestion/markdown-processor.d.ts +17 -0
- package/dist/core/ingestion/markdown-processor.js +124 -0
- package/dist/core/ingestion/mro-processor.js +8 -3
- package/dist/core/ingestion/named-binding-extraction.d.ts +9 -43
- package/dist/core/ingestion/named-binding-extraction.js +89 -79
- package/dist/core/ingestion/parsing-processor.d.ts +2 -2
- package/dist/core/ingestion/parsing-processor.js +14 -73
- package/dist/core/ingestion/pipeline.d.ts +10 -0
- package/dist/core/ingestion/pipeline.js +421 -4
- package/dist/core/ingestion/resolution-context.d.ts +5 -0
- package/dist/core/ingestion/resolution-context.js +7 -4
- package/dist/core/ingestion/resolvers/index.d.ts +1 -1
- package/dist/core/ingestion/resolvers/index.js +1 -1
- package/dist/core/ingestion/resolvers/jvm.d.ts +2 -1
- package/dist/core/ingestion/resolvers/jvm.js +25 -9
- package/dist/core/ingestion/resolvers/php.d.ts +14 -0
- package/dist/core/ingestion/resolvers/php.js +43 -3
- package/dist/core/ingestion/resolvers/utils.d.ts +5 -0
- package/dist/core/ingestion/resolvers/utils.js +16 -0
- package/dist/core/ingestion/symbol-table.d.ts +16 -0
- package/dist/core/ingestion/symbol-table.js +20 -6
- package/dist/core/ingestion/tree-sitter-queries.d.ts +4 -4
- package/dist/core/ingestion/tree-sitter-queries.js +43 -2
- package/dist/core/ingestion/type-env.d.ts +28 -1
- package/dist/core/ingestion/type-env.js +419 -96
- package/dist/core/ingestion/type-extractors/c-cpp.d.ts +5 -0
- package/dist/core/ingestion/type-extractors/c-cpp.js +119 -0
- package/dist/core/ingestion/type-extractors/csharp.js +149 -16
- package/dist/core/ingestion/type-extractors/index.d.ts +1 -1
- package/dist/core/ingestion/type-extractors/index.js +1 -1
- package/dist/core/ingestion/type-extractors/jvm.js +169 -66
- package/dist/core/ingestion/type-extractors/rust.js +35 -1
- package/dist/core/ingestion/type-extractors/shared.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/shared.js +5 -10
- package/dist/core/ingestion/type-extractors/swift.js +7 -6
- package/dist/core/ingestion/type-extractors/types.d.ts +37 -7
- package/dist/core/ingestion/type-extractors/typescript.js +141 -9
- package/dist/core/ingestion/utils.d.ts +2 -120
- package/dist/core/ingestion/utils.js +3 -1051
- package/dist/core/ingestion/workers/parse-worker.d.ts +13 -4
- package/dist/core/ingestion/workers/parse-worker.js +66 -87
- package/dist/core/lbug/csv-generator.js +18 -1
- package/dist/core/lbug/lbug-adapter.d.ts +10 -0
- package/dist/core/lbug/lbug-adapter.js +69 -4
- package/dist/core/lbug/schema.d.ts +5 -3
- package/dist/core/lbug/schema.js +26 -2
- package/dist/mcp/core/embedder.js +11 -3
- package/dist/mcp/core/lbug-adapter.js +12 -1
- package/dist/mcp/local/local-backend.d.ts +22 -0
- package/dist/mcp/local/local-backend.js +133 -29
- package/dist/mcp/resources.js +2 -0
- package/dist/mcp/tools.js +2 -2
- package/dist/server/api.d.ts +19 -1
- package/dist/server/api.js +66 -6
- package/dist/storage/git.d.ts +12 -0
- package/dist/storage/git.js +21 -0
- package/package.json +10 -2
|
@@ -444,7 +444,8 @@ const extractForLoopBinding = (node, { scopeEnv, declarationTypeNodes, scope, re
|
|
|
444
444
|
if (loopVarName)
|
|
445
445
|
scopeEnv.set(loopVarName, elementType);
|
|
446
446
|
};
|
|
447
|
-
/** TS/JS: const alias = u → variable_declarator with name/value fields
|
|
447
|
+
/** TS/JS: const alias = u → variable_declarator with name/value fields.
|
|
448
|
+
* Also handles destructuring: `const { a, b } = obj` → N fieldAccess items. */
|
|
448
449
|
const extractPendingAssignment = (node, scopeEnv) => {
|
|
449
450
|
for (let i = 0; i < node.namedChildCount; i++) {
|
|
450
451
|
const child = node.namedChild(i);
|
|
@@ -454,6 +455,39 @@ const extractPendingAssignment = (node, scopeEnv) => {
|
|
|
454
455
|
const valueNode = child.childForFieldName('value');
|
|
455
456
|
if (!nameNode || !valueNode)
|
|
456
457
|
continue;
|
|
458
|
+
// Object destructuring: `const { address, name } = user`
|
|
459
|
+
// Emits N fieldAccess items — one per destructured binding.
|
|
460
|
+
if (nameNode.type === 'object_pattern' && valueNode.type === 'identifier') {
|
|
461
|
+
const receiver = valueNode.text;
|
|
462
|
+
const items = [];
|
|
463
|
+
for (let j = 0; j < nameNode.namedChildCount; j++) {
|
|
464
|
+
const prop = nameNode.namedChild(j);
|
|
465
|
+
if (!prop)
|
|
466
|
+
continue;
|
|
467
|
+
if (prop.type === 'shorthand_property_identifier_pattern') {
|
|
468
|
+
// `const { name } = user` → shorthand: varName = fieldName
|
|
469
|
+
const varName = prop.text;
|
|
470
|
+
if (!scopeEnv.has(varName)) {
|
|
471
|
+
items.push({ kind: 'fieldAccess', lhs: varName, receiver, field: varName });
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
else if (prop.type === 'pair_pattern') {
|
|
475
|
+
// `const { address: addr } = user` → pair_pattern: key=field, value=varName
|
|
476
|
+
const keyNode = prop.childForFieldName('key');
|
|
477
|
+
const valNode = prop.childForFieldName('value');
|
|
478
|
+
if (keyNode && valNode) {
|
|
479
|
+
const fieldName = keyNode.text;
|
|
480
|
+
const varName = valNode.text;
|
|
481
|
+
if (!scopeEnv.has(varName)) {
|
|
482
|
+
items.push({ kind: 'fieldAccess', lhs: varName, receiver, field: fieldName });
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
if (items.length > 0)
|
|
488
|
+
return items;
|
|
489
|
+
continue;
|
|
490
|
+
}
|
|
457
491
|
const lhs = nameNode.text;
|
|
458
492
|
if (scopeEnv.has(lhs))
|
|
459
493
|
continue;
|
|
@@ -492,22 +526,119 @@ const extractPendingAssignment = (node, scopeEnv) => {
|
|
|
492
526
|
}
|
|
493
527
|
return undefined;
|
|
494
528
|
};
|
|
529
|
+
/** Null-check keywords that indicate a null-comparison in binary expressions. */
|
|
530
|
+
const NULL_CHECK_KEYWORDS = new Set(['null', 'undefined']);
|
|
531
|
+
/**
|
|
532
|
+
* Find the if-body (consequence) block for a null-check binary_expression.
|
|
533
|
+
* Walks up from the binary_expression through parenthesized_expression to if_statement,
|
|
534
|
+
* then returns the consequence block (statement_block).
|
|
535
|
+
*
|
|
536
|
+
* AST structure: if_statement > parenthesized_expression > binary_expression
|
|
537
|
+
* if_statement > statement_block (consequence)
|
|
538
|
+
*/
|
|
539
|
+
const findIfConsequenceBlock = (binaryExpr) => {
|
|
540
|
+
// Walk up to find the if_statement (typically: binary_expression > parenthesized_expression > if_statement)
|
|
541
|
+
let current = binaryExpr.parent;
|
|
542
|
+
while (current) {
|
|
543
|
+
if (current.type === 'if_statement') {
|
|
544
|
+
// The consequence is the first statement_block child of if_statement
|
|
545
|
+
for (let i = 0; i < current.childCount; i++) {
|
|
546
|
+
const child = current.child(i);
|
|
547
|
+
if (child?.type === 'statement_block')
|
|
548
|
+
return child;
|
|
549
|
+
}
|
|
550
|
+
return undefined;
|
|
551
|
+
}
|
|
552
|
+
// Stop climbing at function/block boundaries — don't cross scope
|
|
553
|
+
if (current.type === 'function_declaration' || current.type === 'function_expression'
|
|
554
|
+
|| current.type === 'arrow_function' || current.type === 'method_definition')
|
|
555
|
+
return undefined;
|
|
556
|
+
current = current.parent;
|
|
557
|
+
}
|
|
558
|
+
return undefined;
|
|
559
|
+
};
|
|
495
560
|
/** TS instanceof narrowing: `x instanceof User` → bind x to User.
|
|
496
|
-
*
|
|
497
|
-
*
|
|
498
|
-
*
|
|
499
|
-
const extractPatternBinding = (node) => {
|
|
561
|
+
* Also handles null-check narrowing: `x !== null`, `x != undefined` etc.
|
|
562
|
+
* instanceof: first-writer-wins (no prior type binding).
|
|
563
|
+
* null-check: position-indexed narrowing via narrowingRange. */
|
|
564
|
+
const extractPatternBinding = (node, scopeEnv, declarationTypeNodes, scope) => {
|
|
500
565
|
if (node.type !== 'binary_expression')
|
|
501
566
|
return undefined;
|
|
502
|
-
|
|
567
|
+
// Check for instanceof first (existing behavior)
|
|
568
|
+
const instanceofOp = node.children.find(c => !c.isNamed && c.text === 'instanceof');
|
|
569
|
+
if (instanceofOp) {
|
|
570
|
+
const left = node.namedChild(0);
|
|
571
|
+
const right = node.namedChild(1);
|
|
572
|
+
if (left?.type !== 'identifier' || right?.type !== 'identifier')
|
|
573
|
+
return undefined;
|
|
574
|
+
return { varName: left.text, typeName: right.text };
|
|
575
|
+
}
|
|
576
|
+
// Null-check narrowing: x !== null, x != null, x !== undefined, x != undefined
|
|
577
|
+
const op = node.children.find(c => !c.isNamed && (c.text === '!==' || c.text === '!='));
|
|
503
578
|
if (!op)
|
|
504
579
|
return undefined;
|
|
505
|
-
// binary_expression children are positional — no left/right fields
|
|
506
580
|
const left = node.namedChild(0);
|
|
507
581
|
const right = node.namedChild(1);
|
|
508
|
-
if (left
|
|
582
|
+
if (!left || !right)
|
|
583
|
+
return undefined;
|
|
584
|
+
// Determine which side is the variable and which is null/undefined
|
|
585
|
+
let varNode;
|
|
586
|
+
let isNullCheck = false;
|
|
587
|
+
if (left.type === 'identifier' && NULL_CHECK_KEYWORDS.has(right.text)) {
|
|
588
|
+
varNode = left;
|
|
589
|
+
isNullCheck = true;
|
|
590
|
+
}
|
|
591
|
+
else if (right.type === 'identifier' && NULL_CHECK_KEYWORDS.has(left.text)) {
|
|
592
|
+
varNode = right;
|
|
593
|
+
isNullCheck = true;
|
|
594
|
+
}
|
|
595
|
+
if (!isNullCheck || !varNode)
|
|
509
596
|
return undefined;
|
|
510
|
-
|
|
597
|
+
const varName = varNode.text;
|
|
598
|
+
// Look up the variable's resolved type (already stripped of nullable by extractSimpleTypeName)
|
|
599
|
+
const resolvedType = scopeEnv.get(varName);
|
|
600
|
+
if (!resolvedType)
|
|
601
|
+
return undefined;
|
|
602
|
+
// Check if the original declaration type was nullable by looking at the raw AST type node.
|
|
603
|
+
// extractSimpleTypeName already strips nullable markers, so we need the original to know
|
|
604
|
+
// if narrowing is meaningful (i.e., the variable was declared as nullable).
|
|
605
|
+
const declTypeNode = declarationTypeNodes.get(`${scope}\0${varName}`);
|
|
606
|
+
if (!declTypeNode)
|
|
607
|
+
return undefined;
|
|
608
|
+
const declText = declTypeNode.text;
|
|
609
|
+
// Only narrow if the original declaration was nullable
|
|
610
|
+
if (!declText.includes('null') && !declText.includes('undefined'))
|
|
611
|
+
return undefined;
|
|
612
|
+
// Find the if-body block to scope the narrowing
|
|
613
|
+
const ifBody = findIfConsequenceBlock(node);
|
|
614
|
+
if (!ifBody)
|
|
615
|
+
return undefined;
|
|
616
|
+
return {
|
|
617
|
+
varName,
|
|
618
|
+
typeName: resolvedType,
|
|
619
|
+
narrowingRange: { startIndex: ifBody.startIndex, endIndex: ifBody.endIndex },
|
|
620
|
+
};
|
|
621
|
+
};
|
|
622
|
+
/** Infer the type of a literal AST node for TypeScript overload disambiguation. */
|
|
623
|
+
const inferTsLiteralType = (node) => {
|
|
624
|
+
switch (node.type) {
|
|
625
|
+
case 'number':
|
|
626
|
+
return 'number';
|
|
627
|
+
case 'string':
|
|
628
|
+
case 'template_string':
|
|
629
|
+
return 'string';
|
|
630
|
+
case 'true':
|
|
631
|
+
case 'false':
|
|
632
|
+
return 'boolean';
|
|
633
|
+
case 'null':
|
|
634
|
+
return 'null';
|
|
635
|
+
case 'undefined':
|
|
636
|
+
return 'undefined';
|
|
637
|
+
case 'regex':
|
|
638
|
+
return 'RegExp';
|
|
639
|
+
default:
|
|
640
|
+
return undefined;
|
|
641
|
+
}
|
|
511
642
|
};
|
|
512
643
|
export const typeConfig = {
|
|
513
644
|
declarationNodeTypes: DECLARATION_NODE_TYPES,
|
|
@@ -521,4 +652,5 @@ export const typeConfig = {
|
|
|
521
652
|
extractForLoopBinding,
|
|
522
653
|
extractPendingAssignment,
|
|
523
654
|
extractPatternBinding,
|
|
655
|
+
inferLiteralType: inferTsLiteralType,
|
|
524
656
|
};
|
|
@@ -1,24 +1,4 @@
|
|
|
1
|
-
import type Parser from 'tree-sitter';
|
|
2
1
|
import { SupportedLanguages } from '../../config/supported-languages.js';
|
|
3
|
-
/** Tree-sitter AST node. Re-exported for use across ingestion modules. */
|
|
4
|
-
export type SyntaxNode = Parser.SyntaxNode;
|
|
5
|
-
/**
|
|
6
|
-
* Ordered list of definition capture keys for tree-sitter query matches.
|
|
7
|
-
* Used to extract the definition node from a capture map.
|
|
8
|
-
*/
|
|
9
|
-
export declare const DEFINITION_CAPTURE_KEYS: readonly ["definition.function", "definition.class", "definition.interface", "definition.method", "definition.struct", "definition.enum", "definition.namespace", "definition.module", "definition.trait", "definition.impl", "definition.type", "definition.const", "definition.static", "definition.typedef", "definition.macro", "definition.union", "definition.property", "definition.record", "definition.delegate", "definition.annotation", "definition.constructor", "definition.template"];
|
|
10
|
-
/** Extract the definition node from a tree-sitter query capture map. */
|
|
11
|
-
export declare const getDefinitionNodeFromCaptures: (captureMap: Record<string, any>) => SyntaxNode | null;
|
|
12
|
-
/**
|
|
13
|
-
* Node types that represent function/method definitions across languages.
|
|
14
|
-
* Used to find the enclosing function for a call site.
|
|
15
|
-
*/
|
|
16
|
-
export declare const FUNCTION_NODE_TYPES: Set<string>;
|
|
17
|
-
/**
|
|
18
|
-
* Node types for standard function declarations that need C/C++ declarator handling.
|
|
19
|
-
* Used by extractFunctionName to determine how to extract the function name.
|
|
20
|
-
*/
|
|
21
|
-
export declare const FUNCTION_DECLARATION_TYPES: Set<string>;
|
|
22
2
|
/**
|
|
23
3
|
* Built-in function/method names that should not be tracked as call targets.
|
|
24
4
|
* Covers JS/TS, Python, Kotlin, C/C++, PHP, Swift standard library functions.
|
|
@@ -26,113 +6,15 @@ export declare const FUNCTION_DECLARATION_TYPES: Set<string>;
|
|
|
26
6
|
export declare const BUILT_IN_NAMES: Set<string>;
|
|
27
7
|
/** Check if a name is a built-in function or common noise that should be filtered out */
|
|
28
8
|
export declare const isBuiltInOrNoise: (name: string) => boolean;
|
|
29
|
-
/** AST node types that represent a class-like container (for HAS_METHOD edge extraction) */
|
|
30
|
-
export declare const CLASS_CONTAINER_TYPES: Set<string>;
|
|
31
|
-
export declare const CONTAINER_TYPE_TO_LABEL: Record<string, string>;
|
|
32
|
-
/** Walk up AST to find enclosing class/struct/interface/impl, return its generateId or null.
|
|
33
|
-
* For Go method_declaration nodes, extracts receiver type (e.g. `func (u *User) Save()` → User struct). */
|
|
34
|
-
export declare const findEnclosingClassId: (node: any, filePath: string) => string | null;
|
|
35
|
-
/**
|
|
36
|
-
* Extract function name and label from a function_definition or similar AST node.
|
|
37
|
-
* Handles C/C++ qualified_identifier (ClassName::MethodName) and other language patterns.
|
|
38
|
-
*/
|
|
39
|
-
export declare const extractFunctionName: (node: SyntaxNode) => {
|
|
40
|
-
funcName: string | null;
|
|
41
|
-
label: string;
|
|
42
|
-
};
|
|
43
9
|
/**
|
|
44
10
|
* Yield control to the event loop so spinners/progress can render.
|
|
45
11
|
* Call periodically in hot loops to prevent UI freezes.
|
|
46
12
|
*/
|
|
47
13
|
export declare const yieldToEventLoop: () => Promise<void>;
|
|
48
|
-
/**
|
|
49
|
-
* Find a child of `childType` within a sibling node of `siblingType`.
|
|
50
|
-
* Used for Kotlin AST traversal where visibility_modifier lives inside a modifiers sibling.
|
|
51
|
-
*/
|
|
52
|
-
export declare const findSiblingChild: (parent: any, siblingType: string, childType: string) => any | null;
|
|
53
14
|
/**
|
|
54
15
|
* Map file extension to SupportedLanguage enum
|
|
55
16
|
*/
|
|
56
17
|
export declare const getLanguageFromFilename: (filename: string) => SupportedLanguages | null;
|
|
57
|
-
export interface MethodSignature {
|
|
58
|
-
parameterCount: number | undefined;
|
|
59
|
-
returnType: string | undefined;
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Extract parameter count and return type text from an AST method/function node.
|
|
63
|
-
* Works across languages by looking for common AST patterns.
|
|
64
|
-
*/
|
|
65
|
-
export declare const extractMethodSignature: (node: SyntaxNode | null | undefined) => MethodSignature;
|
|
66
|
-
/**
|
|
67
|
-
* Count direct arguments for a call expression across common tree-sitter grammars.
|
|
68
|
-
* Returns undefined when the argument container cannot be located cheaply.
|
|
69
|
-
*/
|
|
70
|
-
export declare const countCallArguments: (callNode: SyntaxNode | null | undefined) => number | undefined;
|
|
71
|
-
type CallForm = 'free' | 'member' | 'constructor';
|
|
72
|
-
/**
|
|
73
|
-
* Infer whether a captured call site is a free call, member call, or constructor.
|
|
74
|
-
* Returns undefined if the form cannot be determined.
|
|
75
|
-
*
|
|
76
|
-
* Works by inspecting the AST structure between callNode (@call) and nameNode (@call.name).
|
|
77
|
-
* No tree-sitter query changes needed — the distinction is in the node types.
|
|
78
|
-
*/
|
|
79
|
-
export declare const inferCallForm: (callNode: SyntaxNode, nameNode: SyntaxNode) => CallForm | undefined;
|
|
80
|
-
export declare const extractReceiverName: (nameNode: SyntaxNode) => string | undefined;
|
|
81
|
-
/**
|
|
82
|
-
* Extract the raw receiver AST node for a member call.
|
|
83
|
-
* Unlike extractReceiverName, this returns the receiver node regardless of its type —
|
|
84
|
-
* including call_expression / method_invocation nodes that appear in chained calls
|
|
85
|
-
* like `svc.getUser().save()`.
|
|
86
|
-
*
|
|
87
|
-
* Returns undefined when the call is not a member call or when no receiver node
|
|
88
|
-
* can be found (e.g. top-level free calls).
|
|
89
|
-
*/
|
|
90
|
-
export declare const extractReceiverNode: (nameNode: SyntaxNode) => SyntaxNode | undefined;
|
|
91
18
|
export declare const isVerboseIngestionEnabled: () => boolean;
|
|
92
|
-
|
|
93
|
-
export
|
|
94
|
-
/**
|
|
95
|
-
* Hard limit on chain depth to prevent runaway recursion.
|
|
96
|
-
* For `a.b().c().d()`, the chain has depth 2 (b and c before d).
|
|
97
|
-
*/
|
|
98
|
-
export declare const MAX_CHAIN_DEPTH = 3;
|
|
99
|
-
/**
|
|
100
|
-
* Walk a receiver AST node that is itself a call expression, accumulating the
|
|
101
|
-
* chain of intermediate method names up to MAX_CHAIN_DEPTH.
|
|
102
|
-
*
|
|
103
|
-
* For `svc.getUser().save()`, called with the receiver of `save` (getUser() call):
|
|
104
|
-
* returns { chain: ['getUser'], baseReceiverName: 'svc' }
|
|
105
|
-
*
|
|
106
|
-
* For `a.b().c().d()`, called with the receiver of `d` (c() call):
|
|
107
|
-
* returns { chain: ['b', 'c'], baseReceiverName: 'a' }
|
|
108
|
-
*/
|
|
109
|
-
export declare function extractCallChain(receiverCallNode: SyntaxNode): {
|
|
110
|
-
chain: string[];
|
|
111
|
-
baseReceiverName: string | undefined;
|
|
112
|
-
} | undefined;
|
|
113
|
-
/** One step in a mixed receiver chain. */
|
|
114
|
-
export type MixedChainStep = {
|
|
115
|
-
kind: 'field' | 'call';
|
|
116
|
-
name: string;
|
|
117
|
-
};
|
|
118
|
-
/**
|
|
119
|
-
* Walk a receiver AST node that may interleave field accesses and method calls,
|
|
120
|
-
* building a unified chain of steps up to MAX_CHAIN_DEPTH.
|
|
121
|
-
*
|
|
122
|
-
* For `svc.getUser().address.save()`, called with the receiver of `save`
|
|
123
|
-
* (`svc.getUser().address`, a field access node):
|
|
124
|
-
* returns { chain: [{ kind:'call', name:'getUser' }, { kind:'field', name:'address' }],
|
|
125
|
-
* baseReceiverName: 'svc' }
|
|
126
|
-
*
|
|
127
|
-
* For `user.getAddress().city.getName()`, called with receiver of `getName`
|
|
128
|
-
* (`user.getAddress().city`):
|
|
129
|
-
* returns { chain: [{ kind:'call', name:'getAddress' }, { kind:'field', name:'city' }],
|
|
130
|
-
* baseReceiverName: 'user' }
|
|
131
|
-
*
|
|
132
|
-
* Pure field chains and pure call chains are special cases (all steps same kind).
|
|
133
|
-
*/
|
|
134
|
-
export declare function extractMixedChain(receiverNode: SyntaxNode): {
|
|
135
|
-
chain: MixedChainStep[];
|
|
136
|
-
baseReceiverName: string | undefined;
|
|
137
|
-
} | undefined;
|
|
138
|
-
export {};
|
|
19
|
+
export * from './ast-helpers.js';
|
|
20
|
+
export * from './call-analysis.js';
|