Skip to content

Commit fe2ea46

Browse files
angrychowclaude
andauthored
fix: self-reference detection and type alias dependency extraction (follow-up to #123) (#125)
* fix: use variable symbol instead of arrow function symbol for default export check Fixed an issue where arrow function default export detection was checking the arrow function's symbol instead of the variable declaration's symbol. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * upd version * fix: correct type alias symbol extraction from TypeReference nodes Fixed type dependency recognition for type aliases (especially union types) across all parsers by extracting symbols from TypeReference node's typeName child instead of the node itself. Changes: - DependencyUtils: capture union/intersection type aliases before recursing into members - TypeParser: extract symbols from typeName for TypeReference nodes, handle ExpressionWithTypeArguments, put type alias dependencies in InlineStruct instead of Implements - FunctionParser: extract symbols from TypeReference typeName for function parameter/return types - VarParser: extract symbols from TypeReference typeName for variable/property type annotations - Added comprehensive unit tests for all three parsers 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix type self-reference problem * filtering type parameters * support class parsing * fix: if a property in a class is defined as a function, categorize it as a method * fix bugs: construct symbol name by assignSymbolName * update version * add function parse --------- Co-authored-by: Claude <[email protected]>
1 parent 05af382 commit fe2ea46

File tree

7 files changed

+778
-142
lines changed

7 files changed

+778
-142
lines changed

ts-parser/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "abcoder-ts-parser",
3-
"version": "0.0.21",
3+
"version": "0.0.24",
44
"description": "TypeScript AST parser for UNIAST specification",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",

ts-parser/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const program = new Command();
1111
program
1212
.name('abcoder-ts-parser')
1313
.description('TypeScript AST parser for UNIAST specification')
14-
.version('0.0.21');
14+
.version('0.0.24');
1515

1616
program
1717
.command('parse')

ts-parser/src/parser/FunctionParser.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
MethodSignature,
1010
GetAccessorDeclaration,
1111
SetAccessorDeclaration,
12+
PropertyDeclaration,
1213
Node,
1314
SyntaxKind,
1415
ParameterDeclaration,
@@ -122,8 +123,23 @@ export class FunctionParser {
122123
console.error('Error processing setter:', setter, error);
123124
}
124125
}
126+
127+
// Parse properties with function initializers (arrow functions or function expressions)
128+
const properties = cls.getProperties();
129+
for (const prop of properties) {
130+
const initializer = prop.getInitializer();
131+
if (initializer && (Node.isArrowFunction(initializer) || Node.isFunctionExpression(initializer))) {
132+
try {
133+
const propObj = this.parsePropertyFunction(prop, initializer, moduleName, packagePath, sourceFile, className);
134+
functions[propObj.Name] = propObj;
135+
} catch (error) {
136+
console.error('Error processing property function:', prop, error);
137+
}
138+
}
139+
}
125140
}
126141

142+
127143
// Parse arrow functions assigned to variables
128144
const variableDeclarations = sourceFile.getVariableDeclarations();
129145
for (const varDecl of variableDeclarations) {
@@ -650,6 +666,88 @@ export class FunctionParser {
650666
};
651667
}
652668

669+
private parsePropertyFunction(
670+
prop: PropertyDeclaration,
671+
funcExpr: ArrowFunction | FunctionExpression,
672+
moduleName: string,
673+
packagePath: string,
674+
sourceFile: SourceFile,
675+
className: string
676+
): UniFunction {
677+
const symbol = prop.getSymbol();
678+
let propName = "";
679+
if (symbol) {
680+
propName = assignSymbolName(symbol);
681+
} else {
682+
propName = "anonymous_" + prop.getStart();
683+
}
684+
const startLine = prop.getStartLineNumber();
685+
const startOffset = prop.getStart();
686+
const endOffset = prop.getEnd();
687+
const content = prop.getFullText();
688+
const signature = this.extractSignature(funcExpr);
689+
690+
const parent = prop.getParent();
691+
const parentSym = parent.getSymbol();
692+
let isExported = false;
693+
if (Node.isClassDeclaration(parent)) {
694+
isExported = parent.isExported() || parent.isDefaultExport() || (this.defaultExportSymbol === parentSym && parentSym !== undefined);
695+
} else if (Node.isClassExpression(parent)) {
696+
const grandParent = parent.getParent();
697+
if (Node.isVariableDeclaration(grandParent)) {
698+
const varStatement = grandParent.getVariableStatement();
699+
const varSymbol = grandParent.getSymbol();
700+
isExported = varStatement ? (varStatement.isExported() || varStatement.isDefaultExport() || (this.defaultExportSymbol === varSymbol && varSymbol !== undefined)) : false;
701+
}
702+
}
703+
704+
// Parse receiver
705+
const receiver: Receiver = {
706+
IsPointer: false,
707+
Type: {
708+
ModPath: moduleName,
709+
PkgPath: this.getPkgPath(packagePath),
710+
Name: className
711+
}
712+
};
713+
714+
// Parse parameters
715+
const params = this.parseParameters(funcExpr.getParameters(), moduleName, packagePath, sourceFile);
716+
717+
// Parse return types
718+
const results = this.parseReturnTypes(funcExpr, moduleName, packagePath, sourceFile);
719+
720+
// Parse function calls
721+
const functionCalls = this.extractFunctionCalls(funcExpr, moduleName, packagePath, sourceFile);
722+
const methodCalls = this.extractMethodCalls(funcExpr, moduleName, packagePath, sourceFile);
723+
724+
// Extract type references and global variables
725+
const types = this.extractTypeReferences(funcExpr, moduleName, packagePath, sourceFile);
726+
const globalVars = this.extractGlobalVarReferences(funcExpr, moduleName, packagePath, sourceFile);
727+
728+
return {
729+
ModPath: moduleName,
730+
PkgPath: this.getPkgPath(packagePath),
731+
Name: propName,
732+
File: this.getRelativePath(sourceFile.getFilePath()),
733+
Line: startLine,
734+
StartOffset: startOffset,
735+
EndOffset: endOffset,
736+
Exported: isExported,
737+
IsMethod: true,
738+
IsInterfaceMethod: false,
739+
Content: content,
740+
Signature: signature,
741+
Receiver: receiver,
742+
Params: params,
743+
Results: results,
744+
FunctionCalls: functionCalls,
745+
MethodCalls: methodCalls,
746+
Types: types,
747+
GlobalVars: globalVars
748+
};
749+
}
750+
653751
// Parse parameters and extract type dependencies
654752
private parseParameters(parameters: ParameterDeclaration[], moduleName: string, packagePath: string, _sourceFile: SourceFile): Dependency[] {
655753
const dependencies: Dependency[] = [];

0 commit comments

Comments
 (0)