@@ -174,6 +174,7 @@ export interface VariableAllocatorContext {
174174 setCurrentDeclaredInterfaceType ( type : string | undefined ) : void ;
175175 getCurrentDeclaredInterfaceType ( ) : string | undefined ;
176176 getCurrentClassName ( ) : string | null ;
177+ getMethodReturnType ( className : string , methodName : string ) : string | null ;
177178 getParameterTypeFromAST ( paramName : string ) : string | null ;
178179 resolveImportAlias ( localName : string ) : string ;
179180 typeResolverGetInterface ( name : string ) : InterfaceDeclaration | null ;
@@ -1223,33 +1224,70 @@ export class VariableAllocator {
12231224 if ( exprBase . type !== "member_access" ) return null ;
12241225 const memberExpr = expr as MemberAccessNode ;
12251226 const objBase = memberExpr . object as ExprBase ;
1226- if ( objBase . type !== "variable" ) return null ;
1227- const varName = ( memberExpr . object as VariableNode ) . name ;
1228- if ( ! varName ) return null ;
12291227 let objectInterfaceType : string | null = null ;
1230- const ifaceType = this . ctx . symbolTable . getInterfaceType ( varName ) ;
1231- if ( ifaceType ) {
1232- objectInterfaceType = ifaceType ;
1233- } else {
1234- const objMeta = this . ctx . symbolTable . getObjectMetadata ( varName ) ;
1235- if ( objMeta && objMeta . tsTypes ) {
1236- if ( ! objMeta . keys || ! memberExpr . property ) return null ;
1237- const keyIdx = objMeta . keys . indexOf ( memberExpr . property ) ;
1238- if ( keyIdx >= 0 && objMeta . tsTypes ) {
1239- const propType = objMeta . tsTypes [ keyIdx ] ;
1240- if (
1241- propType &&
1242- ! propType . endsWith ( "[]" ) &&
1243- propType !== "string" &&
1244- propType !== "number" &&
1245- propType !== "boolean"
1246- ) {
1247- const iface = this . getInterface ( propType ) ;
1248- if ( iface ) return propType ;
1228+ if ( objBase . type === "method_call" ) {
1229+ const mc = memberExpr . object as MethodCallNode ;
1230+ const mcObjBase = mc . object as ExprBase ;
1231+ let mcClassName : string | null = null ;
1232+ if ( mcObjBase . type === "variable" ) {
1233+ const mcVar = mc . object as VariableNode ;
1234+ const concrete = this . ctx . symbolTable . getConcreteClass ( mcVar . name ) ;
1235+ if ( concrete ) mcClassName = concrete ;
1236+ else if ( this . ctx . symbolTable . isClass ( mcVar . name ) ) {
1237+ const ci = this . ctx . symbolTable . getClassInfo ( mcVar . name ) ;
1238+ if ( ci ) mcClassName = ci . className ;
1239+ }
1240+ } else if ( mcObjBase . type === "this" ) {
1241+ mcClassName = this . ctx . getCurrentClassName ( ) ;
1242+ }
1243+ if ( mcClassName ) {
1244+ const rt = this . ctx . getMethodReturnType ( mcClassName , mc . method ) ;
1245+ if ( rt && ! rt . endsWith ( "[]" ) ) {
1246+ objectInterfaceType = stripNullable ( rt ) ;
1247+ }
1248+ }
1249+ } else if ( objBase . type === "call" ) {
1250+ const ce = memberExpr . object as CallNode ;
1251+ const ast = this . ctx . getAst ( ) ;
1252+ if ( ast && ce . name ) {
1253+ const funcs = ast . functions || [ ] ;
1254+ for ( let i = 0 ; i < funcs . length ; i ++ ) {
1255+ const fn = funcs [ i ] ;
1256+ if ( fn . name === ce . name && fn . returnType && ! fn . returnType . endsWith ( "[]" ) ) {
1257+ objectInterfaceType = stripNullable ( fn . returnType ) ;
1258+ break ;
12491259 }
12501260 }
1251- return null ;
12521261 }
1262+ } else if ( objBase . type === "variable" ) {
1263+ const varName = ( memberExpr . object as VariableNode ) . name ;
1264+ if ( ! varName ) return null ;
1265+ const ifaceType = this . ctx . symbolTable . getInterfaceType ( varName ) ;
1266+ if ( ifaceType ) {
1267+ objectInterfaceType = ifaceType ;
1268+ } else {
1269+ const objMeta = this . ctx . symbolTable . getObjectMetadata ( varName ) ;
1270+ if ( objMeta && objMeta . tsTypes ) {
1271+ if ( ! objMeta . keys || ! memberExpr . property ) return null ;
1272+ const keyIdx = objMeta . keys . indexOf ( memberExpr . property ) ;
1273+ if ( keyIdx >= 0 && objMeta . tsTypes ) {
1274+ const propType = objMeta . tsTypes [ keyIdx ] ;
1275+ if (
1276+ propType &&
1277+ ! propType . endsWith ( "[]" ) &&
1278+ propType !== "string" &&
1279+ propType !== "number" &&
1280+ propType !== "boolean"
1281+ ) {
1282+ const iface = this . getInterface ( propType ) ;
1283+ if ( iface ) return propType ;
1284+ }
1285+ }
1286+ return null ;
1287+ }
1288+ }
1289+ } else {
1290+ return null ;
12531291 }
12541292 if ( ! objectInterfaceType ) return null ;
12551293 const objectInterface = this . getInterface ( objectInterfaceType ) ;
0 commit comments