diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index 309d60b1b1ac29304927e5896612d666041add46..b95d1f60bf7bfdae0ad8647ecebb9b5d952b2676 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -5126,6 +5126,9 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { this.options.arkts2 && this.tsUtils.needToDeduceStructuralIdentity(targetType, exprType, tsAsExpr.expression, true) ) { + if (this.isExemptedAsExpression(tsAsExpr)) { + return; + } if (!this.tsUtils.isObject(exprType)) { this.incrementCounters(node, FaultID.StructuralIdentity); } @@ -5134,6 +5137,41 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { this.handleNoTuplesArrays(node, targetType, exprType); } + private isExemptedAsExpression(node: ts.AsExpression): boolean { + if (!ts.isElementAccessExpression(node.expression)) { + return false; + } + + const sourceType = this.tsTypeChecker.getTypeAtLocation(node.expression); + const targetType = this.tsTypeChecker.getTypeAtLocation(node.type); + const isRecordIndexAccess = (): boolean => { + const exprType = this.tsTypeChecker.getTypeAtLocation(node.expression); + const hasNumberIndex = !!exprType.getNumberIndexType(); + const hasStringIndex = !!exprType.getStringIndexType(); + const hasBooleanIndex = !!exprType.getProperty('true') || !!exprType.getProperty('false'); + + return hasNumberIndex || hasStringIndex || hasBooleanIndex; + }; + + if (isRecordIndexAccess()) { + const targetSymbol = targetType.getSymbol(); + if (targetSymbol && targetSymbol.getName() === 'Array') { + return true; + } + } + const primitiveFlags = ts.TypeFlags.Number | ts.TypeFlags.String | ts.TypeFlags.Boolean; + const objectFlag = ts.TypeFlags.Object; + return ( + sourceType.isUnion() && + sourceType.types.some((t) => { + return t.flags & primitiveFlags; + }) && + sourceType.types.some((t) => { + return t.flags & objectFlag; + }) + ); + } + private handleAsExpressionImport(tsAsExpr: ts.AsExpression): void { const type = tsAsExpr.type; const restrictedTypes = [ @@ -5884,6 +5922,9 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return; } if (this.tsUtils.needToDeduceStructuralIdentity(lhsType, rhsType, rhsExpr, isStrict)) { + if (ts.isNewExpression(rhsExpr) && ts.isIdentifier(rhsExpr.expression) && rhsExpr.expression.text === 'Promise') { + return; + } this.incrementCounters(field, FaultID.StructuralIdentity); } } diff --git a/ets2panda/linter/test/main/structural_identity.ets b/ets2panda/linter/test/main/structural_identity.ets index eae4133097d265060b89928949fb24982901a27b..406a7fee8edd059aa887b3e5d1f5e2eed7c97258 100644 --- a/ets2panda/linter/test/main/structural_identity.ets +++ b/ets2panda/linter/test/main/structural_identity.ets @@ -692,4 +692,15 @@ interface goodPerson extends IPerson { sayHello:()=> { return new MyObj2() } - } \ No newline at end of file + } + + async function foo1(): Promise{ + + return new Promise(()=>{ + + }); +} + +function foo2(rule:Record){ + let b:Array = rule['123'] as Array +} \ No newline at end of file