diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index 309d60b1b1ac29304927e5896612d666041add46..3912d2edde80958991665d0fea245c069e81c2cf 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -5122,9 +5122,15 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (this.tsUtils.isWrongSendableFunctionAssignment(targetType, exprType)) { this.incrementCounters(tsAsExpr, FaultID.SendableFunctionAsExpr); } + const initialType = this.addCondForStructuralIdentity(tsAsExpr); if ( this.options.arkts2 && - this.tsUtils.needToDeduceStructuralIdentity(targetType, exprType, tsAsExpr.expression, true) + this.tsUtils.needToDeduceStructuralIdentity( + targetType, + initialType ? initialType : exprType, + tsAsExpr.expression, + true + ) ) { if (!this.tsUtils.isObject(exprType)) { this.incrementCounters(node, FaultID.StructuralIdentity); @@ -5134,6 +5140,24 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { this.handleNoTuplesArrays(node, targetType, exprType); } + private addCondForStructuralIdentity(express: ts.AsExpression): ts.Type | undefined { + if (!express) { + return undefined; + } + let varType: ts.Type | undefined; + const targetSym = this.tsUtils.trueSymbolAtLocation(express.expression); + const targetDecl = TsUtils.getDeclaration(targetSym); + if ( + targetDecl && + ts.isVariableDeclaration(targetDecl) && + targetDecl.initializer && + !ts.isObjectLiteralExpression(targetDecl.initializer) + ) { + varType = this.tsTypeChecker.getTypeAtLocation(targetDecl.initializer); + } + return varType; + } + private handleAsExpressionImport(tsAsExpr: ts.AsExpression): void { const type = tsAsExpr.type; const restrictedTypes = [ diff --git a/ets2panda/linter/test/main/structural_identity.ets b/ets2panda/linter/test/main/structural_identity.ets index eae4133097d265060b89928949fb24982901a27b..b80250a4acdef3455426d1b6dd6463dd2b34205d 100644 --- a/ets2panda/linter/test/main/structural_identity.ets +++ b/ets2panda/linter/test/main/structural_identity.ets @@ -692,4 +692,60 @@ interface goodPerson extends IPerson { sayHello:()=> { return new MyObj2() } - } \ No newline at end of file + } + + +class Animal { + constructor(public name: string) {} + move(distance: number = 0) { + console.log(`${this.name} moved ${distance}m.`); + } +} + +class Dog extends Animal { + bark() { + console.log('Woof! Woof!'); + } +} + +class Cat extends Animal { + meow() { + console.log('Meow!'); + } +} + +const myPet: Animal = new Dog("Buddy"); + +const myDog = myPet as Dog; +myDog.bark(); + +const myCat = myPet as Cat; //error +myCat.meow(); + +function isDog(animal: Animal): animal is Dog { + return (animal as Dog).bark !== undefined; //error +} + +if (isDog(myPet)) { + myPet.bark(); +} +const dog:Dog=new Dog("Buddy"); +function isAnimal(dog: Dog){ + (dog as Animal).move(1); +} + + +class AAA {} +class BBB extends AAA {} + +let aaa : AAA = new BBB(); +aaa as BBB; +function getB(){ + return new BBB(); +} +const bbb = new BBB(); +aaa = bbb; +let aaa1:AAA = bbb; +aaa1 as BBB; +let aaa2:AAA = getB(); +aaa2 as BBB; \ No newline at end of file diff --git a/ets2panda/linter/test/main/structural_identity.ets.arkts2.json b/ets2panda/linter/test/main/structural_identity.ets.arkts2.json index 1a9ca3c7cfd29082482d0da6d3c02b04726fdfde..568dbfb7eef02d4759b12da6db42ca2b23fe71f6 100644 --- a/ets2panda/linter/test/main/structural_identity.ets.arkts2.json +++ b/ets2panda/linter/test/main/structural_identity.ets.arkts2.json @@ -1583,6 +1583,66 @@ "suggest": "", "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" + }, + { + "line": 699, + "column": 15, + "endLine": 699, + "endColumn": 21, + "problem": "ParameterProperties", + "suggest": "", + "rule": "Declaring fields in \"constructor\" is not supported (arkts-no-ctor-prop-decls)", + "severity": "ERROR" + }, + { + "line": 700, + "column": 27, + "endLine": 700, + "endColumn": 28, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 722, + "column": 15, + "endLine": 722, + "endColumn": 27, + "problem": "StructuralIdentity", + "suggest": "", + "rule": "Structural typing is not supported (arkts-no-structural-typing)", + "severity": "ERROR" + }, + { + "line": 725, + "column": 33, + "endLine": 725, + "endColumn": 46, + "problem": "IsOperator", + "suggest": "", + "rule": "Type guarding is supported with \"instanceof\" and \"as\" (arkts-no-is)", + "severity": "ERROR" + }, + { + "line": 726, + "column": 11, + "endLine": 726, + "endColumn": 24, + "problem": "StructuralIdentity", + "suggest": "", + "rule": "Structural typing is not supported (arkts-no-structural-typing)", + "severity": "ERROR" + }, + { + "line": 734, + "column": 24, + "endLine": 734, + "endColumn": 25, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/main/structural_identity.ets.json b/ets2panda/linter/test/main/structural_identity.ets.json index ba557cfd4379bc3548161375e6ea09a280971c97..e0c28887d7c5daf8acc106022c93ddf6f60a71a1 100644 --- a/ets2panda/linter/test/main/structural_identity.ets.json +++ b/ets2panda/linter/test/main/structural_identity.ets.json @@ -653,6 +653,26 @@ "suggest": "", "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" + }, + { + "line": 699, + "column": 15, + "endLine": 699, + "endColumn": 21, + "problem": "ParameterProperties", + "suggest": "", + "rule": "Declaring fields in \"constructor\" is not supported (arkts-no-ctor-prop-decls)", + "severity": "ERROR" + }, + { + "line": 725, + "column": 33, + "endLine": 725, + "endColumn": 46, + "problem": "IsOperator", + "suggest": "", + "rule": "Type guarding is supported with \"instanceof\" and \"as\" (arkts-no-is)", + "severity": "ERROR" } ] } \ No newline at end of file