diff --git a/src/core/common/TypeInference.ts b/src/core/common/TypeInference.ts index cd2e0312746ac8ca9153a9fa8824dd63e6141b99..ad199128f50073d843a1cf06f714b443357c9ab4 100644 --- a/src/core/common/TypeInference.ts +++ b/src/core/common/TypeInference.ts @@ -56,7 +56,6 @@ import { ArkNamespace } from '../model/ArkNamespace'; import { CONSTRUCTOR_NAME, SUPER_NAME } from './TSConst'; import { ModelUtils } from './ModelUtils'; import { Builtin } from './Builtin'; -import { MethodSignature, MethodSubSignature } from '../model/ArkSignature'; import { UNKNOWN_FILE_NAME } from './Const'; import { EMPTY_STRING } from './ValueUtil'; @@ -377,14 +376,9 @@ export class TypeInference { } public static inferMethodReturnType(method: ArkMethod) { - const oldMethodSignature = method.getSignature(); - const oldMethodSubSignature = oldMethodSignature.getMethodSubSignature(); if (method.getName() === CONSTRUCTOR_NAME) { const newReturnType = new ClassType(method.getDeclaringArkClass().getSignature()); - const newMethodSubSignature = new MethodSubSignature(oldMethodSubSignature.getMethodName(), - oldMethodSubSignature.getParameters(), newReturnType, oldMethodSubSignature.isStatic()); - method.setSignature( - new MethodSignature(oldMethodSignature.getDeclaringClassSignature(), newMethodSubSignature)); + method.setReturnType(newReturnType); return; } const returnType = method.getReturnType(); @@ -393,10 +387,32 @@ export class TypeInference { inferType = this.inferUnclearReferenceType(returnType.getName(), method.getDeclaringArkClass()); } if (inferType) { - const newMethodSubSignature = new MethodSubSignature(oldMethodSubSignature.getMethodName(), - oldMethodSubSignature.getParameters(), inferType, oldMethodSubSignature.isStatic()); - method.setSignature( - new MethodSignature(oldMethodSignature.getDeclaringClassSignature(), newMethodSubSignature)); + method.setReturnType(returnType); + return; + } + + // 基本数据类型, 根据return语句推断返回值类型 + const returnValues: Value[] = method.getReturnValues(); + if (returnValues.length === 0) { + method.setReturnType(VoidType.getInstance()); + } else if (returnValues.length === 1) { + method.setReturnType(returnValues[0].getType()); + } else { + let typeMap: Map = new Map(); + for (let returnValue of returnValues) { + typeMap.set(returnValue.getType().toString(), returnValue.getType()); + } + if (typeMap.size === 1) { + for (let type of typeMap.values()) { + method.setReturnType(type); + } + } else { + let types: Type[] = []; + for (let type of typeMap.values()) { + types.push(type); + } + method.setReturnType(new UnionType(types)); + } } } diff --git a/src/core/model/ArkMethod.ts b/src/core/model/ArkMethod.ts index a95170cfadb33afe18c43387f9e6f764f34ce10d..c238c33395d62094326b59e7b25af1f0b13e31dc 100644 --- a/src/core/model/ArkMethod.ts +++ b/src/core/model/ArkMethod.ts @@ -15,13 +15,13 @@ import { ArkParameterRef, ArkThisRef } from '../base/Ref'; import { ArkAssignStmt, ArkReturnStmt, Stmt } from '../base/Stmt'; -import { GenericType } from '../base/Type'; +import { GenericType, Type } from '../base/Type'; import { Value } from '../base/Value'; import { Cfg } from '../graph/Cfg'; import { ViewTree } from '../graph/ViewTree'; import { ArkBody } from './ArkBody'; import { ArkClass } from './ArkClass'; -import { MethodSignature } from './ArkSignature'; +import { MethodSignature, MethodSubSignature } from './ArkSignature'; import { Decorator } from '../base/Decorator'; import { BodyBuilder } from '../common/BodyBuilder'; import { ArkExport, ExportType } from './ArkExport'; @@ -127,6 +127,14 @@ export class ArkMethod implements ArkExport { return this.methodSignature.getType(); } + public setReturnType(newReturnType: Type): void { + const oldMethodSignature = this.getSignature(); + const oldMethodSubSignature = oldMethodSignature.getMethodSubSignature(); + const newMethodSubSignature = new MethodSubSignature(oldMethodSubSignature.getMethodName(), + oldMethodSubSignature.getParameters(), newReturnType, oldMethodSubSignature.isStatic()); + this.setSignature(new MethodSignature(oldMethodSignature.getDeclaringClassSignature(), newMethodSubSignature)); + } + public getSignature() { return this.methodSignature; }