diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index 7a6dd23d96c159848928bf3d1454328e93c1db4e..9231894edec07fde91f9dc1861c40fb5f6487f7d 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -1398,14 +1398,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { const typeMap = new Map(); if (commonPropertyType.length === allType.length) { allType.forEach((type) => { - const propertySymbol = this.tsUtils.findProperty(type, propertyAccessNode.name.getText()); - if (propertySymbol?.declarations) { - const propertyType = this.tsTypeChecker.getTypeOfSymbolAtLocation( - propertySymbol, - propertySymbol.declarations[0] - ); - typeMap.set(propertyType, propertyAccessNode.name.getText()); - } + this.handleTypeMember(type, propertyAccessNode.name.getText(), typeMap); }); if (typeMap.size > 1) { this.incrementCounters(propertyAccessNode, FaultID.AvoidUnionTypes); @@ -1413,6 +1406,42 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } } + private handleTypeMember( + type: ts.Type, + memberName: string, + typeMap: Map + ): void { + const propertySymbol = this.tsUtils.findProperty(type, memberName); + if (!propertySymbol?.declarations) { + return; + } + const propertyType = this.tsTypeChecker.getTypeOfSymbolAtLocation(propertySymbol, propertySymbol.declarations[0]); + const symbol = propertySymbol.valueDeclaration; + if (!symbol) { + return; + } + if (ts.isMethodDeclaration(symbol)) { + const returnType = this.getMethodReturnType(propertySymbol); + typeMap.set(returnType, memberName); + } else { + typeMap.set(propertyType, memberName); + } + } + + private getMethodReturnType(symbol: ts.Symbol): string | undefined { + const declaration = symbol.valueDeclaration ?? (symbol.declarations?.[0] as ts.Node | undefined); + if (!declaration) { + return undefined; + } + const methodType = this.tsTypeChecker.getTypeOfSymbolAtLocation(symbol, declaration); + const signatures = methodType.getCallSignatures(); + if (signatures.length === 0) { + return 'void'; + } + const returnType = signatures[0].getReturnType(); + return this.tsTypeChecker.typeToString(returnType); + } + private handleLiteralAsPropertyName(node: ts.PropertyDeclaration | ts.PropertySignature): void { const propName = node.name; if (!!propName && (ts.isNumericLiteral(propName) || this.options.arkts2 && ts.isStringLiteral(propName))) { diff --git a/ets2panda/linter/test/main/avoid_using_union_types.ets b/ets2panda/linter/test/main/avoid_using_union_types.ets index 4b633916d9b3e45a0a9abcb39b92ebda00f9abe4..da1290b868f322e04231a4cc1d9aacc847f4e590 100644 --- a/ets2panda/linter/test/main/avoid_using_union_types.ets +++ b/ets2panda/linter/test/main/avoid_using_union_types.ets @@ -36,4 +36,12 @@ function foo(a: A | B | C) { } let data: Uint8Array = new Uint8Array(); -let reqPb = data.buffer.slice(data.byteOffset, data.byteLength + data.byteOffset); \ No newline at end of file +let reqPb = data.buffer.slice(data.byteOffset, data.byteLength + data.byteOffset); +class D { + tt() {} +} +class E { + tt() {} +} +let ab: D|E = new D(); +ab.tt(); \ No newline at end of file