From a6f84bd7934464a4bb37b312807f364fa4fbb22d Mon Sep 17 00:00:00 2001 From: zhongning5 Date: Fri, 4 Jul 2025 14:56:54 +0800 Subject: [PATCH 01/13] fix arkts-incompatible-function-types Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICJ5G9 Test scenarios:Fix bugs for arkts-incompatible-function-types Signed-off-by: zhongning5 --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 124 ++++++++++++++---- .../test/main/incompatible_function.ets | 14 +- .../incompatible_function.ets.arkts2.json | 20 +++ 3 files changed, 133 insertions(+), 25 deletions(-) diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index dcb878796d..ec25be1f63 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -3317,28 +3317,69 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return; } const methodName = node.name.text; - for (const baseType of allBaseTypes) { - const baseMethod = baseType.getProperty(methodName); - if (!baseMethod) { - continue; - } - - const baseMethodDecl = baseMethod.declarations?.find((d) => { - return (ts.isMethodDeclaration(d) || ts.isMethodSignature(d)) && - this.isDeclarationInType(d, baseType, isStatic); - }) as ts.MethodDeclaration | ts.MethodSignature; + if (allBaseTypes && allBaseTypes.length > 0) { + for (const baseType of allBaseTypes) { + const baseMethod = baseType.getProperty(methodName); + if (!baseMethod) { + continue; + } - if (!baseMethodDecl) { - continue; - } + const baseMethodDecl = baseMethod.declarations?.find((d) => { + return ( + (ts.isMethodDeclaration(d) || ts.isMethodSignature(d)) && + this.tsTypeChecker.getTypeAtLocation(d.parent) === baseType + ); + }) as ts.MethodDeclaration | ts.MethodSignature; + + if (!baseMethodDecl) { + continue; + } - this.checkMethodParameters(node, baseMethodDecl); - this.checkMethodReturnType(node, baseMethodDecl); + this.checkMethodParameters(node, baseMethodDecl); + + this.checkMethodReturnType(node, baseMethodDecl); break; } } + private checkIncompatibleFunctionTypes(method: ts.MethodDeclaration): void { + const declaredReturnType = this.getActualReturnType(method); + if (!declaredReturnType) { + return; + } + const returnStatements = this.collectReturnStatements(method); + const declaredReturnTypeStr = this.tsTypeChecker.typeToString(declaredReturnType); + for (const returnStmt of returnStatements) { + if (!returnStmt.expression) { + continue; + } + const actualReturnType = this.tsTypeChecker.getTypeAtLocation(returnStmt.expression); + const actualReturnTypeStr = this.tsTypeChecker.typeToString(actualReturnType); + if (declaredReturnTypeStr === actualReturnTypeStr) { + return; + } + if (this.isSubtypeByBaseTypesList(actualReturnType, declaredReturnType)) { + this.incrementCounters(returnStmt.expression, FaultID.IncompationbleFunctionType); + return; + } + } + } + + private collectReturnStatements(node: ts.Node): ts.ReturnStatement[] { + const result: ts.ReturnStatement[] = []; + + ts.forEachChild(node, (child) => { + if (ts.isReturnStatement(child)) { + result.push(child); + } else { + result.push(...this.collectReturnStatements(child)); + } + }); + + return result; + } + private getClassType( classDecl: ts.ClassDeclaration, isStatic?: boolean): ts.Type | undefined { let classType: ts.Type; @@ -3661,7 +3702,12 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { const baseTypeNode = baseDeclarations[0]; const derivedTypeNode = derivedDeclarations[0]; - if (ts.isClassDeclaration(baseTypeNode) && ts.isClassDeclaration(derivedTypeNode)) { + if ( + baseTypeNode && + derivedTypeNode && + ts.isClassDeclaration(baseTypeNode) && + ts.isClassDeclaration(derivedTypeNode) + ) { const baseTypes = this.tsTypeChecker.getTypeAtLocation(derivedTypeNode).getBaseTypes(); const baseTypesExtends = baseTypes?.some((t) => { return t === baseType; @@ -6953,15 +6999,12 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (!this.options.arkts2) { return; } - const isArray = - this.tsUtils.isOrDerivedFrom(lhsType, this.tsUtils.isArray) && - this.tsUtils.isOrDerivedFrom(rhsType, this.tsUtils.isArray); + const isArray = this.tsUtils.isArray(lhsType) && this.tsUtils.isArray(rhsType); const isTuple = this.tsUtils.isOrDerivedFrom(lhsType, TsUtils.isTuple) && this.tsUtils.isOrDerivedFrom(rhsType, TsUtils.isTuple); if (!((isArray || isTuple) && lhsType !== rhsType)) { return; } - const rhsTypeStr = this.tsTypeChecker.typeToString(rhsType); let lhsTypeStr = this.tsTypeChecker.typeToString(lhsType); if (rhsExpr && (this.isNullOrEmptyArray(rhsExpr) || ts.isArrayLiteralExpression(rhsExpr))) { @@ -6980,6 +7023,16 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } } + private isSubtypeByBaseTypesList(baseType: ts.Type, actualType: ts.Type): boolean { + if (this.isTypeAssignable(actualType, baseType)) { + return true; + } + const actualBaseTypes = actualType.getBaseTypes() || []; + return actualBaseTypes.some((base) => { + return this.isSubtypeByBaseTypesList(baseType, base); + }); + } + private isNullOrEmptyArray(expr: ts.Expression): boolean { if (ts.isNewExpression(expr)) { const constructorSym = this.tsTypeChecker.getSymbolAtLocation(expr.expression); @@ -10376,11 +10429,34 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { private isExactlySameType(type1: ts.Type, type2: ts.Type): boolean { if (type2.getCallSignatures().length > 0) { const returnType = TsUtils.getFunctionReturnType(type2); - return returnType ? - this.tsTypeChecker.typeToString(type1) === this.tsTypeChecker.typeToString(returnType) : - false; + return returnType ? this.isExactlySameType(type1, returnType) : false; } - return this.tsTypeChecker.typeToString(type1) === this.tsTypeChecker.typeToString(type2); + + const type1String = this.tsTypeChecker.typeToString(type1); + const type2String = this.tsTypeChecker.typeToString(type2); + if (type1String === type2String) { + return true; + } + + if (this.checkBaseTypes(type1, type2) || this.checkBaseTypes(type2, type1)) { + return true; + } + return type1String === type2String; + } + + private checkBaseTypes(type1: ts.Type, type2: ts.Type): boolean { + const isClassType = + (type1.getFlags() & ts.TypeFlags.Object) !== 0 && + ((type1 as ts.ObjectType).objectFlags & ts.ObjectFlags.Class) !== 0; + if (isClassType) { + const baseTypes = (type1 as any).getBaseTypes?.() || []; + for (const baseType of baseTypes) { + if (this.isExactlySameType(baseType, type2)) { + return true; + } + } + } + return false; } private handleNumericBigintCompare(node: ts.BinaryExpression): void { diff --git a/ets2panda/linter/test/main/incompatible_function.ets b/ets2panda/linter/test/main/incompatible_function.ets index e137fe5ecc..687a6bb89a 100644 --- a/ets2panda/linter/test/main/incompatible_function.ets +++ b/ets2panda/linter/test/main/incompatible_function.ets @@ -79,4 +79,16 @@ type FuncTypeNoParams = () => void; let fNoParams: FuncTypeNoParams = () => { return 0; -}; \ No newline at end of file +}; + +class A {} + +class C extends Array {} + +class B { + private arr: Array = []; + + test(): C { + return this.arr; + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/incompatible_function.ets.arkts2.json b/ets2panda/linter/test/main/incompatible_function.ets.arkts2.json index da908095d3..2757f6f80c 100644 --- a/ets2panda/linter/test/main/incompatible_function.ets.arkts2.json +++ b/ets2panda/linter/test/main/incompatible_function.ets.arkts2.json @@ -203,6 +203,26 @@ "suggest": "", "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" + }, + { + "line": 92, + "column": 12, + "endLine": 92, + "endColumn": 20, + "problem": "IncompationbleFunctionType", + "suggest": "", + "rule": "Stricter assignments into variables of function type (arkts-incompatible-function-types)", + "severity": "ERROR" + }, + { + "line": 92, + "column": 12, + "endLine": 92, + "endColumn": 20, + "problem": "StructuralIdentity", + "suggest": "", + "rule": "Structural typing is not supported (arkts-no-structural-typing)", + "severity": "ERROR" } ] } \ No newline at end of file -- Gitee From b28c9018006f9053ceae64988a409aae2f3b3c39 Mon Sep 17 00:00:00 2001 From: ZhongNing Date: Wed, 9 Jul 2025 18:23:52 +0800 Subject: [PATCH 02/13] Fix for UnsupportPropNameFromValue Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICKW0F Test scenarios: fix bug Signed-off-by: ZhongNing --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 29 +++++++++++++++++-- .../test/main/literals_as_prop_names.ets | 17 ++++++++++- .../literals_as_prop_names.ets.arkts2.json | 20 +++++++++++++ .../literals_as_prop_names.ets.autofix.json | 20 +++++++++++++ .../literals_as_prop_names.ets.migrate.ets | 17 ++++++++++- .../literals_as_prop_names.ets.migrate.json | 20 +++++++++++++ 6 files changed, 118 insertions(+), 5 deletions(-) diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index ec25be1f63..4b7865526d 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -9921,9 +9921,32 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (ts.isStringLiteral(indexExpr) || ts.isNumericLiteral(indexExpr)) { return true; } - const type = this.tsTypeChecker.getTypeAtLocation(indexExpr); - const typeString = this.tsTypeChecker.typeToString(type); - return typeString === 'number' || typeString === 'string'; + const indexType = this.tsTypeChecker.getTypeAtLocation(indexExpr); + const typeString = this.tsTypeChecker.typeToString(indexType); + if (typeString === 'number' || typeString === 'string') { + return true; + } + const baseExprSym = this.tsUtils.trueSymbolAtLocation(node.expression); + if (indexType.isUnion()) { + return indexType.types.some((t) => { + return this.isInvalidEnumMemberType(t, baseExprSym); + }); + } + return this.isInvalidEnumMemberType(indexType, baseExprSym); + } + + private isInvalidEnumMemberType(indexType: ts.Type, baseExprSym: ts.Symbol | undefined): boolean { + const indexSym = indexType.getSymbol(); + if (!indexSym) { + return false; + } + return !indexSym.declarations?.some((decl) => { + if (decl && ts.isEnumDeclaration(decl.parent) && ts.isEnumMember(decl)) { + const enumDeclSym = this.tsUtils.trueSymbolAtLocation(decl.parent.name); + return enumDeclSym === baseExprSym; + } + return false; + }); } private handleMakeObserved(node: ts.PropertyAccessExpression): void { diff --git a/ets2panda/linter/test/main/literals_as_prop_names.ets b/ets2panda/linter/test/main/literals_as_prop_names.ets index 114339394c..0f2781e90b 100755 --- a/ets2panda/linter/test/main/literals_as_prop_names.ets +++ b/ets2panda/linter/test/main/literals_as_prop_names.ets @@ -147,4 +147,19 @@ let compPropObj = { ['CompProp']: 1, // Error in arkts 2.0 [2]: 'CompProp2', // Error in arkts 2.0 [LiteralAsPropertyNameEnum.One]: 3 // Error in arkts 2.0 -}; \ No newline at end of file +}; + +enum TEST { + A, + B, + C, +} +enum TEST2 { + A, + B, + C, +} + +let de3 = TEST2[TEST.A] //error +let de4 = TEST2[TEST.A| TEST.B] //error +let de5 = TEST[TEST.C] //ok \ No newline at end of file diff --git a/ets2panda/linter/test/main/literals_as_prop_names.ets.arkts2.json b/ets2panda/linter/test/main/literals_as_prop_names.ets.arkts2.json index 5062fc598a..a1c3a4b972 100644 --- a/ets2panda/linter/test/main/literals_as_prop_names.ets.arkts2.json +++ b/ets2panda/linter/test/main/literals_as_prop_names.ets.arkts2.json @@ -724,6 +724,26 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 163, + "column": 11, + "endLine": 163, + "endColumn": 24, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-enum-no-props-by-index)", + "severity": "ERROR" + }, + { + "line": 164, + "column": 11, + "endLine": 164, + "endColumn": 32, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-enum-no-props-by-index)", + "severity": "ERROR" + }, { "line": 115, "column": 2, diff --git a/ets2panda/linter/test/main/literals_as_prop_names.ets.autofix.json b/ets2panda/linter/test/main/literals_as_prop_names.ets.autofix.json index b16fee9cc9..5d84566f2e 100644 --- a/ets2panda/linter/test/main/literals_as_prop_names.ets.autofix.json +++ b/ets2panda/linter/test/main/literals_as_prop_names.ets.autofix.json @@ -1248,6 +1248,26 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 163, + "column": 11, + "endLine": 163, + "endColumn": 24, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-enum-no-props-by-index)", + "severity": "ERROR" + }, + { + "line": 164, + "column": 11, + "endLine": 164, + "endColumn": 32, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-enum-no-props-by-index)", + "severity": "ERROR" + }, { "line": 115, "column": 2, diff --git a/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.ets b/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.ets index 735fe00359..0cbab448d6 100644 --- a/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.ets +++ b/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.ets @@ -156,4 +156,19 @@ let compPropObj = { ['CompProp']: 1.0, // Error in arkts 2.0 [2.0]: 'CompProp2', // Error in arkts 2.0 [LiteralAsPropertyNameEnum.One]: 3.0 // Error in arkts 2.0 -}; \ No newline at end of file +}; + +enum TEST { + A, + B, + C, +} +enum TEST2 { + A, + B, + C, +} + +let de3 = TEST2[TEST.A] //error +let de4 = TEST2[TEST.A| TEST.B] //error +let de5 = TEST[TEST.C] //ok \ No newline at end of file diff --git a/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.json b/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.json index 61d1781a5e..40d660f102 100644 --- a/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.json +++ b/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.json @@ -314,6 +314,26 @@ "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", "severity": "ERROR" }, + { + "line": 172, + "column": 11, + "endLine": 172, + "endColumn": 24, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-enum-no-props-by-index)", + "severity": "ERROR" + }, + { + "line": 173, + "column": 11, + "endLine": 173, + "endColumn": 32, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-enum-no-props-by-index)", + "severity": "ERROR" + }, { "line": 31, "column": 11, -- Gitee From ade060e6f3d3f65a76355ca07c1101d911a858ca Mon Sep 17 00:00:00 2001 From: ZhongNing Date: Wed, 9 Jul 2025 16:30:53 +0800 Subject: [PATCH 03/13] fix arkts-no-ts-like-smart-type Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICKXXU Test scenarios: fix bug Signed-off-by: ZhongNing --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 8 ++++++++ ets2panda/linter/test/main/no_ts_like_smart_type.ets | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index 4b7865526d..c834dcfbfc 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -10231,6 +10231,14 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (!this.options.arkts2) { return; } + + if (ts.isIdentifier(tsCallExpr.expression)) { + const funcName = tsCallExpr.expression.text; + if (funcName === 'setTimeout') { + return; + } + } + const isContinue = ts.isCallExpression(tsCallExpr) && ts.isIdentifier(tsCallExpr.expression) && diff --git a/ets2panda/linter/test/main/no_ts_like_smart_type.ets b/ets2panda/linter/test/main/no_ts_like_smart_type.ets index 3bcd3fae8c..9c49b8c43c 100755 --- a/ets2panda/linter/test/main/no_ts_like_smart_type.ets +++ b/ets2panda/linter/test/main/no_ts_like_smart_type.ets @@ -162,3 +162,10 @@ class AA { } } } + + +function sleep(ms: number): PromiseLike { + return new Promise( + (resolve: (value: T | PromiseLike) => void): number => setTimeout(resolve, ms) + ); +} \ No newline at end of file -- Gitee From 447faa9616425e385b735e674c2e9d7ca2ab7efa Mon Sep 17 00:00:00 2001 From: ZhongNing Date: Thu, 10 Jul 2025 20:34:24 +0800 Subject: [PATCH 04/13] fix issue for arkts-no-structural-typing Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICKXWC Test scenarios: new tests added to the linter Signed-off-by: ZhongNing --- .../src/lib/utils/consts/ExtendedBaseTypes.ts | 3 ++- .../test/main/structural_identity_promise.ets | 6 +++++ ...tructural_identity_promise.ets.arkts2.json | 23 ++++++++++++++++++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/ets2panda/linter/src/lib/utils/consts/ExtendedBaseTypes.ts b/ets2panda/linter/src/lib/utils/consts/ExtendedBaseTypes.ts index 198e45afb1..de0c40e186 100644 --- a/ets2panda/linter/src/lib/utils/consts/ExtendedBaseTypes.ts +++ b/ets2panda/linter/src/lib/utils/consts/ExtendedBaseTypes.ts @@ -33,5 +33,6 @@ export const EXTENDED_BASE_TYPES = new Map([ ['ReadonlyArray', ['ConcatArray']], ['Array', ['ReadonlyArray']], ['Map', ['ReadonlyMap']], - ['Set', ['ReadonlySet']] + ['Set', ['ReadonlySet']], + ['Promise', ['PromiseLike']] ]); diff --git a/ets2panda/linter/test/main/structural_identity_promise.ets b/ets2panda/linter/test/main/structural_identity_promise.ets index e9fe68fd17..59edca4ff0 100644 --- a/ets2panda/linter/test/main/structural_identity_promise.ets +++ b/ets2panda/linter/test/main/structural_identity_promise.ets @@ -32,4 +32,10 @@ class PromiseTest { public async bar(): Promise { return this.foo(); // No error in ArkTS 1.2 } +} + +function sleep(ms: number): PromiseLike { + return new Promise( + (resolve: (value: T | PromiseLike) => void): number => setTimeout(resolve, ms) + ); } \ No newline at end of file diff --git a/ets2panda/linter/test/main/structural_identity_promise.ets.arkts2.json b/ets2panda/linter/test/main/structural_identity_promise.ets.arkts2.json index ca88f857e9..239919cb52 100644 --- a/ets2panda/linter/test/main/structural_identity_promise.ets.arkts2.json +++ b/ets2panda/linter/test/main/structural_identity_promise.ets.arkts2.json @@ -13,5 +13,26 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [] + "result": [ + { + "line": 39, + "column": 74, + "endLine": 39, + "endColumn": 81, + "problem": "NoTsLikeSmartType", + "suggest": "", + "rule": "Smart type differences (arkts-no-ts-like-smart-type)", + "severity": "ERROR" + }, + { + "line": 39, + "column": 83, + "endLine": 39, + "endColumn": 85, + "problem": "NoTsLikeSmartType", + "suggest": "", + "rule": "Smart type differences (arkts-no-ts-like-smart-type)", + "severity": "ERROR" + } + ] } \ No newline at end of file -- Gitee From aebb063931c199c432bbaff066de743ff10efc96 Mon Sep 17 00:00:00 2001 From: cihatfurkaneken Date: Wed, 9 Jul 2025 09:12:42 +0300 Subject: [PATCH 05/13] update arkts-obj-literal-props rule check Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICKVEW Signed-off-by: cihatfurkaneken --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 40 +- ...upport_property_descriptor.ets.arkts2.json | 40 -- .../test/main/object_literals_properties.ets | 25 ++ ...object_literals_properties.ets.arkts2.json | 170 ++------- ...bject_literals_properties.ets.autofix.json | 356 ++++-------------- .../main/object_literals_properties.ets.json | 10 + ...object_literals_properties.ets.migrate.ets | 69 ++-- ...bject_literals_properties.ets.migrate.json | 118 +++--- 8 files changed, 284 insertions(+), 544 deletions(-) diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index c834dcfbfc..a694f5cc8a 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -651,11 +651,43 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } for (const prop of invalidProps) { - const autofix = ts.isShorthandPropertyAssignment(prop) ? - this.autofixer?.fixShorthandPropertyAssignment(prop) : - objLiteralAutofix; - this.incrementCounters(prop, FaultID.ObjectLiteralProperty, autofix); + if (objectLiteralType) { + const typeDecl = TsUtils.getDeclaration(objectLiteralType.getSymbol()); + if (typeDecl && ts.isInterfaceDeclaration(typeDecl) && ts.isMethodDeclaration(prop)) { + continue; + } + } + if (ts.isShorthandPropertyAssignment(prop)) { + if (this.checkShorthandInObjectLiteral(prop, objectLiteralType)) { + const autofix = this.autofixer?.fixShorthandPropertyAssignment(prop); + this.incrementCounters(prop, FaultID.ObjectLiteralProperty, autofix); + } + } else { + this.incrementCounters(prop, FaultID.ObjectLiteralProperty, objLiteralAutofix); + } + } + } + + private checkShorthandInObjectLiteral(prop: ts.ShorthandPropertyAssignment, type: ts.Type | undefined): boolean { + if (!type) { + return true; } + const propName = prop.name.text; + const expectedProp = type.getProperty(propName); + if (!expectedProp) { + return false; + } + const expectedPropType = this.tsTypeChecker.getTypeOfSymbolAtLocation(expectedProp, prop.name); + const symbol = this.tsTypeChecker.getSymbolAtLocation(prop.name); + const varDecl = symbol?.valueDeclaration; + if (!varDecl) { + return false; + } + const actualType = this.tsTypeChecker.getTypeAtLocation(varDecl); + if (!this.isTypeAssignable(actualType, expectedPropType)) { + return true; + } + return false; } private handleArrayLiteralExpression(node: ts.Node): void { diff --git a/ets2panda/linter/test/builtin/builtin_not_support_property_descriptor.ets.arkts2.json b/ets2panda/linter/test/builtin/builtin_not_support_property_descriptor.ets.arkts2.json index 79538ccf9b..dcb5f51ada 100644 --- a/ets2panda/linter/test/builtin/builtin_not_support_property_descriptor.ets.arkts2.json +++ b/ets2panda/linter/test/builtin/builtin_not_support_property_descriptor.ets.arkts2.json @@ -124,26 +124,6 @@ "rule": "Not support propertydescriptor (arkts-builtin-no-property-descriptor)", "severity": "ERROR" }, - { - "line": 27, - "column": 3, - "endLine": 27, - "endColumn": 35, - "problem": "ObjectLiteralProperty", - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, - { - "line": 28, - "column": 3, - "endLine": 28, - "endColumn": 32, - "problem": "ObjectLiteralProperty", - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, { "line": 26, "column": 9, @@ -244,26 +224,6 @@ "rule": "Not support propertydescriptor (arkts-builtin-no-property-descriptor)", "severity": "ERROR" }, - { - "line": 48, - "column": 5, - "endLine": 48, - "endColumn": 41, - "problem": "ObjectLiteralProperty", - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, - { - "line": 49, - "column": 5, - "endLine": 49, - "endColumn": 34, - "problem": "ObjectLiteralProperty", - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, { "line": 47, "column": 12, diff --git a/ets2panda/linter/test/main/object_literals_properties.ets b/ets2panda/linter/test/main/object_literals_properties.ets index 1944ed2ef9..5c88953eb0 100644 --- a/ets2panda/linter/test/main/object_literals_properties.ets +++ b/ets2panda/linter/test/main/object_literals_properties.ets @@ -295,3 +295,28 @@ function baz(fooBar: Map) { function baz2(fooBarBaz: FooBarBaz) { } + +class JJ { + mm?: Map + aa?: string +} +const mm: Map = new Map(); +let nn: JJ = {mm} // no error + + +class DD { + tt?: Map + gg?: string +} +const tt: Map = new Map(); +let gg: DD = {tt} // error + +interface Q { + a:number; + foo():void; +} + +let w: Q = { + a:1.0, + foo(){} // no error +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/object_literals_properties.ets.arkts2.json b/ets2panda/linter/test/main/object_literals_properties.ets.arkts2.json index 8ed64f688b..a63a7a849d 100644 --- a/ets2panda/linter/test/main/object_literals_properties.ets.arkts2.json +++ b/ets2panda/linter/test/main/object_literals_properties.ets.arkts2.json @@ -474,16 +474,6 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, - { - "line": 81, - "column": 3, - "endLine": 83, - "endColumn": 4, - "problem": "ObjectLiteralProperty", - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, { "line": 82, "column": 17, @@ -634,36 +624,6 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, - { - "line": 110, - "column": 3, - "endLine": 110, - "endColumn": 5, - "problem": "ObjectLiteralProperty", - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, - { - "line": 111, - "column": 3, - "endLine": 111, - "endColumn": 5, - "problem": "ObjectLiteralProperty", - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, - { - "line": 112, - "column": 3, - "endLine": 112, - "endColumn": 5, - "problem": "ObjectLiteralProperty", - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, { "line": 113, "column": 3, @@ -694,36 +654,6 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, - { - "line": 117, - "column": 3, - "endLine": 117, - "endColumn": 5, - "problem": "ObjectLiteralProperty", - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, - { - "line": 118, - "column": 3, - "endLine": 118, - "endColumn": 5, - "problem": "ObjectLiteralProperty", - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, - { - "line": 119, - "column": 3, - "endLine": 119, - "endColumn": 5, - "problem": "ObjectLiteralProperty", - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, { "line": 120, "column": 3, @@ -834,36 +764,6 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, - { - "line": 134, - "column": 3, - "endLine": 134, - "endColumn": 5, - "problem": "ObjectLiteralProperty", - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, - { - "line": 135, - "column": 3, - "endLine": 135, - "endColumn": 5, - "problem": "ObjectLiteralProperty", - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, - { - "line": 136, - "column": 3, - "endLine": 136, - "endColumn": 5, - "problem": "ObjectLiteralProperty", - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, { "line": 137, "column": 3, @@ -1144,16 +1044,6 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, - { - "line": 209, - "column": 3, - "endLine": 209, - "endColumn": 9, - "problem": "ObjectLiteralProperty", - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, { "line": 208, "column": 6, @@ -1284,26 +1174,6 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, - { - "line": 251, - "column": 15, - "endLine": 251, - "endColumn": 18, - "problem": "ObjectLiteralProperty", - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, - { - "line": 258, - "column": 15, - "endLine": 258, - "endColumn": 19, - "problem": "ObjectLiteralProperty", - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, { "line": 274, "column": 16, @@ -1335,15 +1205,45 @@ "severity": "ERROR" }, { - "line": 281, - "column": 5, - "endLine": 283, - "endColumn": 6, + "line": 303, + "column": 32, + "endLine": 303, + "endColumn": 41, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 311, + "column": 32, + "endLine": 311, + "endColumn": 41, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 312, + "column": 15, + "endLine": 312, + "endColumn": 17, "problem": "ObjectLiteralProperty", "suggest": "", "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", "severity": "ERROR" }, + { + "line": 319, + "column": 12, + "endLine": 319, + "endColumn": 13, + "problem": "ObjectLiteralNoContextType", + "suggest": "", + "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", + "severity": "ERROR" + }, { "line": 187, "column": 3, @@ -1355,4 +1255,4 @@ "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/object_literals_properties.ets.autofix.json b/ets2panda/linter/test/main/object_literals_properties.ets.autofix.json index bbb319af18..afb110b1af 100644 --- a/ets2panda/linter/test/main/object_literals_properties.ets.autofix.json +++ b/ets2panda/linter/test/main/object_literals_properties.ets.autofix.json @@ -851,36 +851,6 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, - { - "line": 81, - "column": 3, - "endLine": 83, - "endColumn": 4, - "problem": "ObjectLiteralProperty", - "autofix": [ - { - "start": 1599, - "end": 1599, - "replacementText": "class GeneratedObjectLiteralClass_5 implements I {\n m() {\n console.log(100);\n }\n}\n\n", - "line": 81, - "column": 3, - "endLine": 83, - "endColumn": 4 - }, - { - "start": 1610, - "end": 1658, - "replacementText": "new GeneratedObjectLiteralClass_5()", - "line": 81, - "column": 3, - "endLine": 83, - "endColumn": 4 - } - ], - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, { "line": 82, "column": 17, @@ -1181,69 +1151,6 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, - { - "line": 110, - "column": 3, - "endLine": 110, - "endColumn": 5, - "problem": "ObjectLiteralProperty", - "autofix": [ - { - "start": 1926, - "end": 1928, - "replacementText": "x2: x2", - "line": 110, - "column": 3, - "endLine": 110, - "endColumn": 5 - } - ], - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, - { - "line": 111, - "column": 3, - "endLine": 111, - "endColumn": 5, - "problem": "ObjectLiteralProperty", - "autofix": [ - { - "start": 1943, - "end": 1945, - "replacementText": "y2: y2", - "line": 111, - "column": 3, - "endLine": 111, - "endColumn": 5 - } - ], - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, - { - "line": 112, - "column": 3, - "endLine": 112, - "endColumn": 5, - "problem": "ObjectLiteralProperty", - "autofix": [ - { - "start": 1960, - "end": 1962, - "replacementText": "z2: z2", - "line": 112, - "column": 3, - "endLine": 112, - "endColumn": 5 - } - ], - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, { "line": 113, "column": 3, @@ -1305,69 +1212,6 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, - { - "line": 117, - "column": 3, - "endLine": 117, - "endColumn": 5, - "problem": "ObjectLiteralProperty", - "autofix": [ - { - "start": 2034, - "end": 2036, - "replacementText": "x2: x2", - "line": 117, - "column": 3, - "endLine": 117, - "endColumn": 5 - } - ], - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, - { - "line": 118, - "column": 3, - "endLine": 118, - "endColumn": 5, - "problem": "ObjectLiteralProperty", - "autofix": [ - { - "start": 2051, - "end": 2053, - "replacementText": "y2: y2", - "line": 118, - "column": 3, - "endLine": 118, - "endColumn": 5 - } - ], - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, - { - "line": 119, - "column": 3, - "endLine": 119, - "endColumn": 5, - "problem": "ObjectLiteralProperty", - "autofix": [ - { - "start": 2068, - "end": 2070, - "replacementText": "z2: z2", - "line": 119, - "column": 3, - "endLine": 119, - "endColumn": 5 - } - ], - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, { "line": 120, "column": 3, @@ -1555,69 +1399,6 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, - { - "line": 134, - "column": 3, - "endLine": 134, - "endColumn": 5, - "problem": "ObjectLiteralProperty", - "autofix": [ - { - "start": 2289, - "end": 2291, - "replacementText": "x2: x2", - "line": 134, - "column": 3, - "endLine": 134, - "endColumn": 5 - } - ], - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, - { - "line": 135, - "column": 3, - "endLine": 135, - "endColumn": 5, - "problem": "ObjectLiteralProperty", - "autofix": [ - { - "start": 2306, - "end": 2308, - "replacementText": "y2: y2", - "line": 135, - "column": 3, - "endLine": 135, - "endColumn": 5 - } - ], - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, - { - "line": 136, - "column": 3, - "endLine": 136, - "endColumn": 5, - "problem": "ObjectLiteralProperty", - "autofix": [ - { - "start": 2323, - "end": 2325, - "replacementText": "z2: z2", - "line": 136, - "column": 3, - "endLine": 136, - "endColumn": 5 - } - ], - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, { "line": 137, "column": 3, @@ -2041,16 +1822,6 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, - { - "line": 209, - "column": 3, - "endLine": 209, - "endColumn": 9, - "problem": "ObjectLiteralProperty", - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, { "line": 208, "column": 6, @@ -2276,48 +2047,6 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, - { - "line": 251, - "column": 15, - "endLine": 251, - "endColumn": 18, - "problem": "ObjectLiteralProperty", - "autofix": [ - { - "start": 4619, - "end": 4622, - "replacementText": "map: map", - "line": 251, - "column": 15, - "endLine": 251, - "endColumn": 18 - } - ], - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, - { - "line": 258, - "column": 15, - "endLine": 258, - "endColumn": 19, - "problem": "ObjectLiteralProperty", - "autofix": [ - { - "start": 4766, - "end": 4770, - "replacementText": "map1: map1", - "line": 258, - "column": 15, - "endLine": 258, - "endColumn": 19 - } - ], - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, { "line": 274, "column": 16, @@ -2369,35 +2098,78 @@ "severity": "ERROR" }, { - "line": 281, - "column": 5, - "endLine": 283, - "endColumn": 6, - "problem": "ObjectLiteralProperty", + "line": 303, + "column": 32, + "endLine": 303, + "endColumn": 41, + "problem": "GenericCallNoTypeArgs", "autofix": [ { - "start": 4956, - "end": 4956, - "replacementText": "class GeneratedObjectLiteralClass_12 implements X.I {\n m(): void {\n console.log(\"I\");\n }\n}\n\n", - "line": 281, - "column": 5, - "endLine": 283, - "endColumn": 6 - }, + "start": 5382, + "end": 5382, + "replacementText": "", + "line": 303, + "column": 32, + "endLine": 303, + "endColumn": 41 + } + ], + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 311, + "column": 32, + "endLine": 311, + "endColumn": 41, + "problem": "GenericCallNoTypeArgs", + "autofix": [ { - "start": 5055, - "end": 5106, - "replacementText": "new GeneratedObjectLiteralClass_12()", - "line": 281, - "column": 5, - "endLine": 283, - "endColumn": 6 + "start": 5514, + "end": 5514, + "replacementText": "", + "line": 311, + "column": 32, + "endLine": 311, + "endColumn": 41 + } + ], + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 312, + "column": 15, + "endLine": 312, + "endColumn": 17, + "problem": "ObjectLiteralProperty", + "autofix": [ + { + "start": 5532, + "end": 5534, + "replacementText": "tt: tt", + "line": 312, + "column": 15, + "endLine": 312, + "endColumn": 17 } ], "suggest": "", "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", "severity": "ERROR" }, + { + "line": 319, + "column": 12, + "endLine": 319, + "endColumn": 13, + "problem": "ObjectLiteralNoContextType", + "suggest": "", + "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", + "severity": "ERROR" + }, { "line": 187, "column": 3, @@ -2409,4 +2181,4 @@ "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/object_literals_properties.ets.json b/ets2panda/linter/test/main/object_literals_properties.ets.json index 97cb35867c..bd4222ae87 100644 --- a/ets2panda/linter/test/main/object_literals_properties.ets.json +++ b/ets2panda/linter/test/main/object_literals_properties.ets.json @@ -314,6 +314,16 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, + { + "line": 319, + "column": 12, + "endLine": 319, + "endColumn": 13, + "problem": "ObjectLiteralNoContextType", + "suggest": "", + "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", + "severity": "ERROR" + }, { "line": 187, "column": 3, diff --git a/ets2panda/linter/test/main/object_literals_properties.ets.migrate.ets b/ets2panda/linter/test/main/object_literals_properties.ets.migrate.ets index ef4628d62a..fb644f560c 100644 --- a/ets2panda/linter/test/main/object_literals_properties.ets.migrate.ets +++ b/ets2panda/linter/test/main/object_literals_properties.ets.migrate.ets @@ -108,13 +108,11 @@ let mixedBad = { // Not fixable interface I { m(): void; } -class GeneratedObjectLiteralClass_5 implements I { - m() { - console.log(100.0); - } -} - -let i: I = new GeneratedObjectLiteralClass_5(); +let i: I = { + m() { // Fixable + console.log(100.0); + } +}; class C { m(): void { @@ -147,7 +145,7 @@ class GeneratedObjectLiteralClass_8 extends C2 { x2: number; y2: number; z2: number; - constructor(init: GeneratedObjectLiteralInitInterface_1) { + constructor(init: GeneratedObjectLiteralInitInterface_8) { super(); this.x2 = init.x2; this.y2 = init.y2; @@ -156,7 +154,7 @@ class GeneratedObjectLiteralClass_8 extends C2 { m() { console.log(1.0); } // Fixable } -interface GeneratedObjectLiteralInitInterface_1 { +interface GeneratedObjectLiteralInitInterface_8 { x2: number; y2: number; z2: number; @@ -169,9 +167,9 @@ let c2: C2 = new GeneratedObjectLiteralClass_8({ }); let c22: C2 = { - x2: x2, // Fixable - y2: y2, // Fixable - z2: z2, // Fixable + x2, // Fixable + y2, // Fixable + z2, // Fixable m() { console.log(1.0); }, // Not fixable, object has spread property ...shorthand // Not fixable }; @@ -186,9 +184,9 @@ class C3 { constructor(a: number) {} } let c3: C3 = { - x2: x2, // Fixable - y2: y2, // Fixable - z2: z2, // Fixable + x2, // Fixable + y2, // Fixable + z2, // Fixable m() { console.log(1.0); } // Not fixable, class type has constructor with parameters }; @@ -310,14 +308,14 @@ interface I4 { map: Map; } let map:Map = new Map(); -let i4: I4 = {map: map}; +let i4: I4 = {map}; class C6 { map1: Map = new Map(); } let map1:Map = new Map(); -let c6: C6 = {map1: map1}; +let c6: C6 = {map1}; // Namespace typed object literals namespace X { @@ -338,16 +336,14 @@ class GeneratedObjectLiteralClass_11 extends X.C { } } -class GeneratedObjectLiteralClass_12 implements X.I { - m(): void { - console.log("I"); - } -} - function test() { let c: X.C = new GeneratedObjectLiteralClass_11() - let i: X.I = new GeneratedObjectLiteralClass_12() + let i: X.I = { + m(): void { + console.log("I"); + } + } } class FooBarBaz { @@ -361,3 +357,28 @@ function baz(fooBar: Map) { function baz2(fooBarBaz: FooBarBaz) { } + +class JJ { + mm?: Map + aa?: string +} +const mm: Map = new Map(); +let nn: JJ = {mm} // no error + + +class DD { + tt?: Map + gg?: string +} +const tt: Map = new Map(); +let gg: DD = {tt: tt} // error + +interface Q { + a:number; + foo():void; +} + +let w: Q = { + a:1.0, + foo(){} // no error +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/object_literals_properties.ets.migrate.json b/ets2panda/linter/test/main/object_literals_properties.ets.migrate.json index 675cc2476a..07599351fa 100644 --- a/ets2panda/linter/test/main/object_literals_properties.ets.migrate.json +++ b/ets2panda/linter/test/main/object_literals_properties.ets.migrate.json @@ -85,9 +85,19 @@ "severity": "ERROR" }, { - "line": 171, + "line": 111, + "column": 12, + "endLine": 111, + "endColumn": 13, + "problem": "ObjectLiteralNoContextType", + "suggest": "", + "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", + "severity": "ERROR" + }, + { + "line": 169, "column": 15, - "endLine": 171, + "endLine": 169, "endColumn": 16, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -95,9 +105,9 @@ "severity": "ERROR" }, { - "line": 175, + "line": 173, "column": 3, - "endLine": 175, + "endLine": 173, "endColumn": 28, "problem": "ObjectLiteralProperty", "suggest": "", @@ -105,9 +115,9 @@ "severity": "ERROR" }, { - "line": 176, + "line": 174, "column": 3, - "endLine": 176, + "endLine": 174, "endColumn": 15, "problem": "ObjectLiteralProperty", "suggest": "", @@ -115,9 +125,9 @@ "severity": "ERROR" }, { - "line": 176, + "line": 174, "column": 3, - "endLine": 176, + "endLine": 174, "endColumn": 15, "problem": "SpreadOperator", "suggest": "", @@ -125,9 +135,9 @@ "severity": "ERROR" }, { - "line": 188, + "line": 186, "column": 14, - "endLine": 188, + "endLine": 186, "endColumn": 15, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -135,9 +145,9 @@ "severity": "ERROR" }, { - "line": 192, + "line": 190, "column": 3, - "endLine": 192, + "endLine": 190, "endColumn": 28, "problem": "ObjectLiteralProperty", "suggest": "", @@ -145,9 +155,9 @@ "severity": "ERROR" }, { - "line": 197, + "line": 195, "column": 25, - "endLine": 197, + "endLine": 195, "endColumn": 26, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -155,9 +165,9 @@ "severity": "ERROR" }, { - "line": 198, + "line": 196, "column": 5, - "endLine": 200, + "endLine": 198, "endColumn": 6, "problem": "ObjectLiteralProperty", "suggest": "", @@ -165,9 +175,9 @@ "severity": "ERROR" }, { - "line": 203, + "line": 201, "column": 29, - "endLine": 203, + "endLine": 201, "endColumn": 30, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -175,9 +185,9 @@ "severity": "ERROR" }, { - "line": 204, + "line": 202, "column": 5, - "endLine": 206, + "endLine": 204, "endColumn": 6, "problem": "ObjectLiteralProperty", "suggest": "", @@ -185,9 +195,9 @@ "severity": "ERROR" }, { - "line": 214, + "line": 212, "column": 26, - "endLine": 214, + "endLine": 212, "endColumn": 27, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -195,9 +205,9 @@ "severity": "ERROR" }, { - "line": 215, + "line": 213, "column": 5, - "endLine": 217, + "endLine": 215, "endColumn": 6, "problem": "ObjectLiteralProperty", "suggest": "", @@ -205,9 +215,9 @@ "severity": "ERROR" }, { - "line": 219, + "line": 217, "column": 27, - "endLine": 219, + "endLine": 217, "endColumn": 28, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -215,9 +225,9 @@ "severity": "ERROR" }, { - "line": 220, + "line": 218, "column": 5, - "endLine": 222, + "endLine": 220, "endColumn": 6, "problem": "ObjectLiteralProperty", "suggest": "", @@ -225,9 +235,9 @@ "severity": "ERROR" }, { - "line": 226, + "line": 224, "column": 27, - "endLine": 226, + "endLine": 224, "endColumn": 28, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -235,9 +245,9 @@ "severity": "ERROR" }, { - "line": 227, + "line": 225, "column": 5, - "endLine": 229, + "endLine": 227, "endColumn": 6, "problem": "ObjectLiteralProperty", "suggest": "", @@ -245,9 +255,9 @@ "severity": "ERROR" }, { - "line": 238, + "line": 236, "column": 14, - "endLine": 238, + "endLine": 236, "endColumn": 15, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -255,9 +265,9 @@ "severity": "ERROR" }, { - "line": 249, + "line": 247, "column": 3, - "endLine": 249, + "endLine": 247, "endColumn": 9, "problem": "ObjectLiteralProperty", "suggest": "", @@ -265,9 +275,9 @@ "severity": "ERROR" }, { - "line": 256, + "line": 254, "column": 14, - "endLine": 256, + "endLine": 254, "endColumn": 15, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -305,9 +315,9 @@ "severity": "ERROR" }, { - "line": 289, + "line": 287, "column": 20, - "endLine": 289, + "endLine": 287, "endColumn": 21, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -315,9 +325,9 @@ "severity": "ERROR" }, { - "line": 290, + "line": 288, "column": 3, - "endLine": 290, + "endLine": 288, "endColumn": 28, "problem": "ObjectLiteralProperty", "suggest": "", @@ -336,18 +346,28 @@ }, { "line": 342, - "column": 5, + "column": 16, "endLine": 342, - "endColumn": 6, - "problem": "MethodInheritRule", + "endColumn": 17, + "problem": "ObjectLiteralNoContextType", + "suggest": "", + "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", + "severity": "ERROR" + }, + { + "line": 381, + "column": 12, + "endLine": 381, + "endColumn": 13, + "problem": "ObjectLiteralNoContextType", "suggest": "", - "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", + "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, { - "line": 245, + "line": 243, "column": 3, - "endLine": 245, + "endLine": 243, "endColumn": 4, "problem": "StrictDiagnostic", "suggest": "Property 'b' has no initializer and is not definitely assigned in the constructor.", @@ -355,4 +375,4 @@ "severity": "ERROR" } ] -} +} \ No newline at end of file -- Gitee From 821ff98699d4a5bbaa52e0a62010f5bf5c8785e8 Mon Sep 17 00:00:00 2001 From: sefayilmazunal Date: Tue, 8 Jul 2025 08:49:52 +0300 Subject: [PATCH 06/13] AsyncLock autofix Description: autofix added for arkts-limited-stdlib-no-import-concurrency Issue: #ICKQYO Signed-off-by: sefayilmazunal --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 3 +- .../linter/src/lib/autofixes/Autofixer.ts | 54 +++++++++++------ ...rktsutils_locks_asynclock.ets.autofix.json | 38 ------------ ...rktsutils_locks_asynclock.ets.migrate.json | 38 ------------ ...no_support_arktsutils_locks_asynclock.ets} | 4 +- ...t_arktsutils_locks_asynclock.ets.args.json | 21 +++++++ ...rktsutils_locks_asynclock.ets.arkts2.json} | 0 ...rktsutils_locks_asynclock.ets.autofix.json | 60 +++++++++++++++++++ ...pport_arktsutils_locks_asynclock.ets.json} | 0 ...rktsutils_locks_asynclock.ets.migrate.ets} | 6 +- ...rktsutils_locks_asynclock.ets.migrate.json | 58 ++++++++++++++++++ 11 files changed, 182 insertions(+), 100 deletions(-) delete mode 100644 ets2panda/linter/test/concurrent/ no_support_arktsutils_locks_asynclock.ets.autofix.json delete mode 100644 ets2panda/linter/test/concurrent/ no_support_arktsutils_locks_asynclock.ets.migrate.json rename ets2panda/linter/test/concurrent/{ no_support_arktsutils_locks_asynclock.ets => no_support_arktsutils_locks_asynclock.ets} (87%) create mode 100644 ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets.args.json rename ets2panda/linter/test/concurrent/{ no_support_arktsutils_locks_asynclock.ets.arkts2.json => no_support_arktsutils_locks_asynclock.ets.arkts2.json} (100%) create mode 100644 ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets.autofix.json rename ets2panda/linter/test/concurrent/{ no_support_arktsutils_locks_asynclock.ets.json => no_support_arktsutils_locks_asynclock.ets.json} (100%) rename ets2panda/linter/test/concurrent/{ no_support_arktsutils_locks_asynclock.ets.migrate.ets => no_support_arktsutils_locks_asynclock.ets.migrate.ets} (87%) create mode 100644 ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets.migrate.json diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index a694f5cc8a..fea8ce06ee 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -7517,7 +7517,8 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return; } if (parent.name.text === ARKTSUTILS_LOCKS_MEMBER) { - this.incrementCounters(node, FaultID.LimitedStdLibNoImportConcurrency); + const autofix = this.autofixer?.fixConcurrencyLock(parent); + this.incrementCounters(node, FaultID.LimitedStdLibNoImportConcurrency, autofix); } }; diff --git a/ets2panda/linter/src/lib/autofixes/Autofixer.ts b/ets2panda/linter/src/lib/autofixes/Autofixer.ts index bca8d8304e..560c4727e2 100644 --- a/ets2panda/linter/src/lib/autofixes/Autofixer.ts +++ b/ets2panda/linter/src/lib/autofixes/Autofixer.ts @@ -981,11 +981,11 @@ export class Autofixer { const propertyChain: string[] = [propertyName]; let current: ts.Node = node; - + while (current.parent && ts.isElementAccessExpression(current.parent)) { const parentArg = current.parent.argumentExpression; if (ts.isStringLiteral(parentArg)) { - propertyChain.push(parentArg.text); + propertyChain.push(parentArg.text); } current = current.parent; } @@ -2468,17 +2468,15 @@ export class Autofixer { const prev = allSpecifiers[specIndex - 1]; start = prev.getEnd(); } - fixes.push({ - start: start, - end: end, - replacementText: '' - }); + fixes.push({ start: start, end: end, replacementText: '' }); } const alias = specToRemove.name; - const original = specToRemove.propertyName ?? specToRemove.name; - const replacements = this.replaceIdentifierUsages(alias, original.getText()); - fixes.push(...replacements); + const original = specToRemove.propertyName; + if (original) { + const replacements = this.replaceIdentifierUsages(alias, original.getText()); + fixes.push(...replacements); + } return fixes; } @@ -4081,6 +4079,26 @@ export class Autofixer { return { replacementText, start: identifier.getStart(), end: identifier.getEnd() }; } + fixConcurrencyLock(locksProp: ts.PropertyAccessExpression): Autofix[] | undefined { + // 1) Ensure the next property is `.AsyncLock` + const asyncLockProp = locksProp.parent; + if (!ts.isPropertyAccessExpression(asyncLockProp)) { + return undefined; + } + + // 2) Find the enclosing `new` expression + const newExpr = asyncLockProp.parent; + if (!ts.isNewExpression(newExpr)) { + return undefined; + } + + const className = asyncLockProp.name.getText(); + const replacement = ts.factory.createNewExpression(ts.factory.createIdentifier(className), undefined, []); + const replacementText = this.printer.printNode(ts.EmitHint.Unspecified, replacement, newExpr.getSourceFile()); + + return [{ start: newExpr.getStart(), end: newExpr.getEnd(), replacementText }]; + } + fixSharedArrayBufferConstructor(node: ts.NewExpression): Autofix[] | undefined { void this; @@ -4731,13 +4749,13 @@ export class Autofixer { `${expr.getText()}${callExpr.questionDotToken.getText()}unsafeCall` : `${expr.getText()}.unsafeCall`; - return [ - { - start: expr.getStart(), - end: hasOptionalChain ? callExpr.questionDotToken.getEnd() : expr.getEnd(), - replacementText - } - ]; + return [{ + start: expr.getStart(), + end: hasOptionalChain ? + callExpr.questionDotToken.getEnd() : + expr.getEnd(), + replacementText + }]; } private static createBuiltInTypeInitializer(type: ts.TypeReferenceNode): ts.Expression | undefined { @@ -5152,7 +5170,7 @@ export class Autofixer { fixNumericPublicStatic(node: ts.PropertyDeclaration): Autofix[] | undefined { if (!node?.name || node.type) { - return undefined + return undefined; }; const typeNode = ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword); const modifiers = ts.getModifiers(node) || []; diff --git a/ets2panda/linter/test/concurrent/ no_support_arktsutils_locks_asynclock.ets.autofix.json b/ets2panda/linter/test/concurrent/ no_support_arktsutils_locks_asynclock.ets.autofix.json deleted file mode 100644 index 31d218b8f0..0000000000 --- a/ets2panda/linter/test/concurrent/ no_support_arktsutils_locks_asynclock.ets.autofix.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", - "Licensed under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - "http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an 'AS IS' BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." - ], - "result": [ - { - "line": 18, - "column": 28, - "endLine": 18, - "endColumn": 33, - "problem": "LimitedStdLibNoImportConcurrency", - "suggest": "", - "rule": "Import Concurrency is not required (arkts-limited-stdlib-no-import-concurrency)", - "severity": "ERROR" - }, - { - "line": 20, - "column": 28, - "endLine": 20, - "endColumn": 33, - "problem": "LimitedStdLibNoImportConcurrency", - "suggest": "", - "rule": "Import Concurrency is not required (arkts-limited-stdlib-no-import-concurrency)", - "severity": "ERROR" - } - ] -} \ No newline at end of file diff --git a/ets2panda/linter/test/concurrent/ no_support_arktsutils_locks_asynclock.ets.migrate.json b/ets2panda/linter/test/concurrent/ no_support_arktsutils_locks_asynclock.ets.migrate.json deleted file mode 100644 index 31d218b8f0..0000000000 --- a/ets2panda/linter/test/concurrent/ no_support_arktsutils_locks_asynclock.ets.migrate.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", - "Licensed under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - "http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an 'AS IS' BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." - ], - "result": [ - { - "line": 18, - "column": 28, - "endLine": 18, - "endColumn": 33, - "problem": "LimitedStdLibNoImportConcurrency", - "suggest": "", - "rule": "Import Concurrency is not required (arkts-limited-stdlib-no-import-concurrency)", - "severity": "ERROR" - }, - { - "line": 20, - "column": 28, - "endLine": 20, - "endColumn": 33, - "problem": "LimitedStdLibNoImportConcurrency", - "suggest": "", - "rule": "Import Concurrency is not required (arkts-limited-stdlib-no-import-concurrency)", - "severity": "ERROR" - } - ] -} \ No newline at end of file diff --git a/ets2panda/linter/test/concurrent/ no_support_arktsutils_locks_asynclock.ets b/ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets similarity index 87% rename from ets2panda/linter/test/concurrent/ no_support_arktsutils_locks_asynclock.ets rename to ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets index 3ad92e0865..d94d1d8c0e 100644 --- a/ets2panda/linter/test/concurrent/ no_support_arktsutils_locks_asynclock.ets +++ b/ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets @@ -15,6 +15,6 @@ import { ArkTSUtils } from '../main/oh_modules/@kit.ArkTS'; -let lock1 = new ArkTSUtils.locks.AsyncLock(); +let lock1 = new ArkTSUtils.locks.AsyncLock(); -let lock2 = new ArkTSUtils.locks.AsyncLock(); \ No newline at end of file +let lock2 = new ArkTSUtils.locks.AsyncLock(); diff --git a/ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets.args.json b/ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets.args.json new file mode 100644 index 0000000000..6958168fef --- /dev/null +++ b/ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets.args.json @@ -0,0 +1,21 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "mode": { + "arkts2": "", + "autofix": "--arkts-2", + "migrate": "--arkts-2" + } +} diff --git a/ets2panda/linter/test/concurrent/ no_support_arktsutils_locks_asynclock.ets.arkts2.json b/ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets.arkts2.json similarity index 100% rename from ets2panda/linter/test/concurrent/ no_support_arktsutils_locks_asynclock.ets.arkts2.json rename to ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets.arkts2.json diff --git a/ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets.autofix.json b/ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets.autofix.json new file mode 100644 index 0000000000..34839afbd9 --- /dev/null +++ b/ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets.autofix.json @@ -0,0 +1,60 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 18, + "column": 28, + "endLine": 18, + "endColumn": 33, + "problem": "LimitedStdLibNoImportConcurrency", + "autofix": [ + { + "start": 678, + "end": 710, + "replacementText": "new AsyncLock()", + "line": 18, + "column": 28, + "endLine": 18, + "endColumn": 33 + } + ], + "suggest": "", + "rule": "Import Concurrency is not required (arkts-limited-stdlib-no-import-concurrency)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 28, + "endLine": 20, + "endColumn": 33, + "problem": "LimitedStdLibNoImportConcurrency", + "autofix": [ + { + "start": 725, + "end": 757, + "replacementText": "new AsyncLock()", + "line": 20, + "column": 28, + "endLine": 20, + "endColumn": 33 + } + ], + "suggest": "", + "rule": "Import Concurrency is not required (arkts-limited-stdlib-no-import-concurrency)", + "severity": "ERROR" + } + ] +} diff --git a/ets2panda/linter/test/concurrent/ no_support_arktsutils_locks_asynclock.ets.json b/ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets.json similarity index 100% rename from ets2panda/linter/test/concurrent/ no_support_arktsutils_locks_asynclock.ets.json rename to ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets.json diff --git a/ets2panda/linter/test/concurrent/ no_support_arktsutils_locks_asynclock.ets.migrate.ets b/ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets.migrate.ets similarity index 87% rename from ets2panda/linter/test/concurrent/ no_support_arktsutils_locks_asynclock.ets.migrate.ets rename to ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets.migrate.ets index c8cd4f5b48..e4b1c6ec60 100644 --- a/ets2panda/linter/test/concurrent/ no_support_arktsutils_locks_asynclock.ets.migrate.ets +++ b/ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets.migrate.ets @@ -12,9 +12,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + import { ArkTSUtils } from '../main/oh_modules/@kit.ArkTS'; -let lock1 = new ArkTSUtils.locks.AsyncLock(); +let lock1 = new AsyncLock(); -let lock2 = new ArkTSUtils.locks.AsyncLock(); \ No newline at end of file +let lock2 = new AsyncLock(); diff --git a/ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets.migrate.json b/ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets.migrate.json new file mode 100644 index 0000000000..7b88b28ed4 --- /dev/null +++ b/ets2panda/linter/test/concurrent/no_support_arktsutils_locks_asynclock.ets.migrate.json @@ -0,0 +1,58 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 18, + "column": 5, + "endLine": 18, + "endColumn": 28, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 18, + "column": 17, + "endLine": 18, + "endColumn": 26, + "problem": "DynamicCtorCall", + "suggest": "", + "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 5, + "endLine": 20, + "endColumn": 28, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 17, + "endLine": 20, + "endColumn": 26, + "problem": "DynamicCtorCall", + "suggest": "", + "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", + "severity": "ERROR" + } + ] +} -- Gitee From cb9d441f8dd12d4f293d15c46778f647409c04cf Mon Sep 17 00:00:00 2001 From: sefayilmazunal Date: Wed, 9 Jul 2025 14:11:03 +0300 Subject: [PATCH 07/13] autofix added for interop for of array Description: autofix added for interop array usages inside for of loop on arkts-interop-js2s-traverse-js-instance rule Issue: #ICLEA5 Signed-off-by: sefayilmazunal --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 3 +- .../linter/src/lib/autofixes/Autofixer.ts | 224 +++++++++--------- .../test/interop/interop_import_js_index.ets | 2 +- .../interop_import_js_index.ets.autofix.json | 20 ++ .../interop_import_js_index.ets.migrate.ets | 6 +- .../interop_import_js_index.ets.migrate.json | 12 +- .../interop_import_js_rules.ets.autofix.json | 22 +- 7 files changed, 162 insertions(+), 127 deletions(-) diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index fea8ce06ee..3dec24b467 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -9114,7 +9114,8 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return; } - this.incrementCounters(node, FaultID.InteropJsObjectTraverseJsInstance); + const autofix = this.autofixer?.applyForOfJsArrayFix(node); + this.incrementCounters(node, FaultID.InteropJsObjectTraverseJsInstance, autofix); } private checkStdLibConcurrencyImport(importDeclaration: ts.ImportDeclaration): void { diff --git a/ets2panda/linter/src/lib/autofixes/Autofixer.ts b/ets2panda/linter/src/lib/autofixes/Autofixer.ts index 560c4727e2..1b7526353d 100644 --- a/ets2panda/linter/src/lib/autofixes/Autofixer.ts +++ b/ets2panda/linter/src/lib/autofixes/Autofixer.ts @@ -61,7 +61,6 @@ import { LENGTH, IS_INSTANCE_OF } from '../utils/consts/InteropAPI'; -import { ESLIB_SHAREDARRAYBUFFER } from '../utils/consts/ConcurrentAPI'; const UNDEFINED_NAME = 'undefined'; @@ -3471,6 +3470,119 @@ export class Autofixer { return [{ start: expression.getStart(), end: expression.getEnd(), replacementText }]; } + /** + * Convert a JS-imported `for...of` over an array into an indexed `for` loop. + * + * @param forOf - The `ForOfStatement` node to transform. + */ + applyForOfJsArrayFix(forOf: ts.ForOfStatement): Autofix[] | undefined { + const loopDecl = (forOf.initializer as ts.VariableDeclarationList).declarations[0]; + const elementName = (loopDecl.name as ts.Identifier).text; + + const indexName = TsUtils.generateUniqueName(this.tmpVariableNameGenerator, forOf.getSourceFile()) ?? '_i'; + + const fixes: Autofix[] = []; + fixes.push(this.buildForOfHeaderFix(forOf, indexName)); + fixes.push(...this.buildForOfBodyFixes(forOf, elementName, indexName)); + return fixes.length > 0 ? fixes : undefined; + } + + /** + * Build an Autofix for replacing the for-of loop header. + */ + private buildForOfHeaderFix(forOf: ts.ForOfStatement, indexName: string): Autofix { + const arrText = forOf.expression.getText(); + + const initializer = ts.factory.createVariableDeclarationList( + [ + ts.factory.createVariableDeclaration( + ts.factory.createIdentifier(indexName), + undefined, + undefined, + ts.factory.createNumericLiteral('0') + ) + ], + ts.NodeFlags.Let + ); + + // condition: i < arr.getProperty('length').toNumber() + const condition = ts.factory.createBinaryExpression( + ts.factory.createIdentifier(indexName), + ts.SyntaxKind.LessThanToken, + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(arrText), + ts.factory.createIdentifier(GET_PROPERTY) + ), + undefined, + [ts.factory.createStringLiteral(LENGTH, true)] + ), + ts.factory.createIdentifier('toNumber') + ), + undefined, + [] + ) + ); + + const incrementor = ts.factory.createPrefixUnaryExpression( + ts.SyntaxKind.PlusPlusToken, + ts.factory.createIdentifier(indexName) + ); + + return this.createReplacementTextForOfHeader(forOf, initializer, condition, incrementor); + } + + private createReplacementTextForOfHeader( + forOf: ts.ForOfStatement, + initializer: ts.VariableDeclarationList, + condition: ts.BinaryExpression, + incrementor: ts.PrefixUnaryExpression + ): Autofix { + // Render just the "(initializer; condition; incrementor)" text: + const replacementText = [ + this.printer.printNode(ts.EmitHint.Unspecified, initializer, forOf.getSourceFile()), + '; ', + this.printer.printNode(ts.EmitHint.Unspecified, condition, forOf.getSourceFile()), + '; ', + this.printer.printNode(ts.EmitHint.Unspecified, incrementor, forOf.getSourceFile()) + ].join(''); + + return { start: forOf.initializer.getStart(), end: forOf.expression.getEnd(), replacementText }; + } + + /** + * Build fixes for replacing loop-variable references inside the for-of body. + */ + private buildForOfBodyFixes(forOf: ts.ForOfStatement, elementName: string, indexName: string): Autofix[] { + const fixes: Autofix[] = []; + const arrExpr = forOf.expression; + + const visit = (node: ts.Node): void => { + if (ts.isIdentifier(node) && node.text === elementName) { + const callExpr = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(arrExpr.getText()), + ts.factory.createIdentifier(GET_PROPERTY) + ), + undefined, + [ts.factory.createIdentifier(indexName)] + ); + + // Print and append proper conversion suffix + const printed = this.printer.printNode(ts.EmitHint.Unspecified, callExpr, forOf.getSourceFile()); + const replacementText = printed + this.utils.findTypeOfNodeForConversion(node); + + fixes.push({ start: node.getStart(), end: node.getEnd(), replacementText }); + } + ts.forEachChild(node, visit); + }; + + visit(forOf.statement); + return fixes; + } + fixInteropInstantiateExpression( express: ts.NewExpression, args: ts.NodeArray | undefined @@ -4054,31 +4166,6 @@ export class Autofixer { return [{ replacementText, start, end }]; } - /** - * Replace each loop‐variable reference (e.g. `element`) with - * `array.getProperty(i)` plus appropriate conversion. - * - * @param identifier The Identifier node of the loop variable usage. - * @param arrayName The name of the array being iterated. - */ - fixInteropArrayElementUsage(identifier: ts.Identifier, arrayName: string): Autofix { - // arr.getProperty(i) - const callExpr = ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier(arrayName), - ts.factory.createIdentifier(GET_PROPERTY) - ), - undefined, - [ts.factory.createIdentifier('i')] - ); - - // Print and append proper conversion suffix - const printed = this.printer.printNode(ts.EmitHint.Unspecified, callExpr, identifier.getSourceFile()); - const replacementText = printed + this.utils.findTypeOfNodeForConversion(identifier); - - return { replacementText, start: identifier.getStart(), end: identifier.getEnd() }; - } - fixConcurrencyLock(locksProp: ts.PropertyAccessExpression): Autofix[] | undefined { // 1) Ensure the next property is `.AsyncLock` const asyncLockProp = locksProp.parent; @@ -4098,90 +4185,7 @@ export class Autofixer { return [{ start: newExpr.getStart(), end: newExpr.getEnd(), replacementText }]; } - - fixSharedArrayBufferConstructor(node: ts.NewExpression): Autofix[] | undefined { - void this; - - // Ensure it's a constructor call to SharedArrayBuffer - if (!ts.isIdentifier(node.expression) || node.expression.text !== ESLIB_SHAREDARRAYBUFFER) { - return undefined; - } - - // Construct replacement - const replacementText = 'ArrayBuffer'; - - return [{ replacementText, start: node.expression.getStart(), end: node.expression.getEnd() }]; - } - - fixSharedArrayBufferTypeReference(node: ts.TypeReferenceNode): Autofix[] | undefined { - void this; - - if (!ts.isIdentifier(node.typeName) || node.typeName.text !== ESLIB_SHAREDARRAYBUFFER) { - return undefined; - } - - const replacementText = 'ArrayBuffer'; - - return [{ replacementText, start: node.getStart(), end: node.getEnd() }]; - } - - /** - * Converts a `for...of` over an interop array into - * an index-based `for` loop using `getProperty("length")`. - * - * @param node The `ForOfStatement` node to fix. - * @returns A single Autofix for the loop header replacement. - */ - fixInteropArrayForOf(node: ts.ForOfStatement): Autofix { - const iterableName = node.expression.getText(); - - const initializer = ts.factory.createVariableDeclarationList( - [ - ts.factory.createVariableDeclaration( - ts.factory.createIdentifier('i'), - undefined, - undefined, - ts.factory.createNumericLiteral('0') - ) - ], - ts.NodeFlags.Let - ); - - const lengthAccess = ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier(iterableName), - ts.factory.createIdentifier(GET_PROPERTY) - ), - undefined, - [ts.factory.createStringLiteral(LENGTH)] - ); - const condition = ts.factory.createBinaryExpression( - ts.factory.createIdentifier('i'), - ts.SyntaxKind.LessThanToken, - lengthAccess - ); - - const incrementor = ts.factory.createPrefixUnaryExpression( - ts.SyntaxKind.PlusPlusToken, - ts.factory.createIdentifier('i') - ); - - // Render just the "(initializer; condition; incrementor)" text: - const headerText = [ - this.printer.printNode(ts.EmitHint.Unspecified, initializer, node.getSourceFile()), - '; ', - this.printer.printNode(ts.EmitHint.Unspecified, condition, node.getSourceFile()), - '; ', - this.printer.printNode(ts.EmitHint.Unspecified, incrementor, node.getSourceFile()) - ].join(''); - - // Only replace from the start of the initializer to the end of the 'of' expression - const start = node.initializer.getStart(); - const end = node.expression.getEnd(); - - return { start, end, replacementText: headerText }; - } - + fixAppStorageCallExpression(callExpr: ts.CallExpression): Autofix[] | undefined { const varDecl = Autofixer.findParentVariableDeclaration(callExpr); if (!varDecl || varDecl.type) { diff --git a/ets2panda/linter/test/interop/interop_import_js_index.ets b/ets2panda/linter/test/interop/interop_import_js_index.ets index a4ffabe660..411f8c70a6 100644 --- a/ets2panda/linter/test/interop/interop_import_js_index.ets +++ b/ets2panda/linter/test/interop/interop_import_js_index.ets @@ -31,4 +31,4 @@ for (let element of arr1) { //error if (element == 8) { console.log("hi"); } -} \ No newline at end of file +} diff --git a/ets2panda/linter/test/interop/interop_import_js_index.ets.autofix.json b/ets2panda/linter/test/interop/interop_import_js_index.ets.autofix.json index 8b38c2c03f..1fe5631167 100644 --- a/ets2panda/linter/test/interop/interop_import_js_index.ets.autofix.json +++ b/ets2panda/linter/test/interop/interop_import_js_index.ets.autofix.json @@ -478,6 +478,26 @@ "endLine": 34, "endColumn": 2, "problem": "InteropJsObjectTraverseJsInstance", + "autofix": [ + { + "start": 970, + "end": 989, + "replacementText": "let tmp_1 = 0; tmp_1 < arr1.getProperty('length').toNumber(); ++tmp_1", + "line": 30, + "column": 1, + "endLine": 34, + "endColumn": 2 + }, + { + "start": 1008, + "end": 1015, + "replacementText": "arr1.getProperty(tmp_1).toNumber()", + "line": 30, + "column": 1, + "endLine": 34, + "endColumn": 2 + } + ], "suggest": "", "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", "severity": "ERROR" diff --git a/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.ets b/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.ets index 7cac462bbc..989d010fbf 100644 --- a/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.ets +++ b/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.ets @@ -30,8 +30,8 @@ for (let i: number = 0.0; i < arr1.getProperty("length"); ++i) { console.log(arr1.getProperty(i).toNumber()+''); //error } -for (let element of arr1) { //error - if (element == 8.0) { +for (let tmp_1: number = 0.0; tmp_1 < arr1.getProperty('length').toNumber(); ++tmp_1) { //error + if (arr1.getProperty(tmp_1).toNumber() == 8.0) { console.log("hi"); } -} \ No newline at end of file +} diff --git a/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.json b/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.json index bc80aa171a..7c8632a14d 100644 --- a/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.json +++ b/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.json @@ -63,16 +63,6 @@ "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", "severity": "ERROR" - }, - { - "line": 33, - "column": 10, - "endLine": 33, - "endColumn": 17, - "problem": "AnyType", - "suggest": "", - "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", - "severity": "ERROR" } ] -} \ No newline at end of file +} diff --git a/ets2panda/linter/test/interop/interop_import_js_rules.ets.autofix.json b/ets2panda/linter/test/interop/interop_import_js_rules.ets.autofix.json index e160d4c3d0..e83cca5906 100644 --- a/ets2panda/linter/test/interop/interop_import_js_rules.ets.autofix.json +++ b/ets2panda/linter/test/interop/interop_import_js_rules.ets.autofix.json @@ -1110,6 +1110,26 @@ "endLine": 92, "endColumn": 2, "problem": "InteropJsObjectTraverseJsInstance", + "autofix": [ + { + "start": 1882, + "end": 1900, + "replacementText": "let tmp_1 = 0; tmp_1 < arr.getProperty('length').toNumber(); ++tmp_1", + "line": 88, + "column": 1, + "endLine": 92, + "endColumn": 2 + }, + { + "start": 1910, + "end": 1917, + "replacementText": "arr.getProperty(tmp_1).toNumber()", + "line": 88, + "column": 1, + "endLine": 92, + "endColumn": 2 + } + ], "suggest": "", "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", "severity": "ERROR" @@ -1136,4 +1156,4 @@ "severity": "ERROR" } ] -} \ No newline at end of file +} -- Gitee From 298f92526d95dd2fd031549754b2fe857c982a35 Mon Sep 17 00:00:00 2001 From: zengyuan Date: Thu, 3 Jul 2025 17:25:06 +0800 Subject: [PATCH 08/13] Add scanning scenarios for arkts-no-sparse-array Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICKJLD Signed-off-by: zengyuan Change-Id: Iba8843d15e1464762fcaff011bdbb275104088ce --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 55 +++++-- .../src/lib/utils/consts/BuiltinWhiteList.ts | 17 ++- .../linter/test/main/no_sparse_array.ets | 22 +++ .../linter/test/main/no_sparse_array2.ets | 22 +++ .../main/no_sparse_array2.ets.arkts2.json | 140 ++++++++++++++++++ ...tructural_identity_promise.ets.arkts2.json | 23 +-- 6 files changed, 241 insertions(+), 38 deletions(-) diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index 3dec24b467..3aec0eae29 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -55,7 +55,7 @@ import { } from './utils/consts/SendableAPI'; import { DEFAULT_COMPATIBLE_SDK_VERSION, DEFAULT_COMPATIBLE_SDK_VERSION_STAGE } from './utils/consts/VersionInfo'; import { TYPED_ARRAYS } from './utils/consts/TypedArrays'; -import { BUILTIN_CONSTRUCTORS } from './utils/consts/BuiltinWhiteList'; +import { BUILTIN_CONSTRUCTORS, COLLECTION_METHODS, COLLECTION_TYPES } from './utils/consts/BuiltinWhiteList'; import { forEachNodeInSubtree } from './utils/functions/ForEachNodeInSubtree'; import { hasPredecessor } from './utils/functions/HasPredecessor'; import { isStdLibrarySymbol, isStdLibraryType } from './utils/functions/IsStdLibrary'; @@ -724,12 +724,12 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { * check that array literal consists of inferrable types * e.g. there is no element which is untyped object literals */ - const isPromiseCallExpression = TypeScriptLinter.checkPromiseCallExpression(parent); + const isCallExpression = this.checkMethodCallForSparseArray(parent); const isTypedArrayOrBuiltInConstructor = TypeScriptLinter.checkTypedArrayOrBuiltInConstructor(parent); if (this.options.arkts2 && arrayElementIsEmpty) { if (!arrayLitType) { this.incrementCounters(node, FaultID.NosparseArray); - } else if (isPromiseCallExpression || isTypedArrayOrBuiltInConstructor) { + } else if (isCallExpression || isTypedArrayOrBuiltInConstructor) { this.incrementCounters(arrayLitNode, FaultID.NosparseArray); } } @@ -759,25 +759,49 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } private static checkTypedArrayOrBuiltInConstructor(parent: ts.Node): boolean { - if (ts.isNewExpression(parent)) { - const newExpr = parent as ts.NewExpression; - const typeName = newExpr.expression.getText(); + if (!ts.isNewExpression(parent)) { + return false; + } + const newExpr = parent as ts.NewExpression; + const typeName = newExpr.expression.getText(); + + return TYPED_ARRAYS.includes(typeName) || BUILTIN_CONSTRUCTORS.includes(typeName); + } - return TYPED_ARRAYS.includes(typeName) || BUILTIN_CONSTRUCTORS.includes(typeName); + private checkMethodCallForSparseArray(parent: ts.Node): boolean { + if (!ts.isCallExpression(parent)) { + return false; + } + + const callExpr = parent as ts.CallExpression; + const promiseMethodName = TypeScriptLinter.getPromiseMethodName(callExpr.expression); + if (promiseMethodName && PROMISE_METHODS.has(promiseMethodName)) { + return true; + } + + const collectionMethodName = this.getCollectionMethodName(callExpr.expression); + if (collectionMethodName && COLLECTION_METHODS.has(collectionMethodName)) { + return true; } + return false; } - private static checkPromiseCallExpression(parent: ts.Node): boolean { - if (ts.isCallExpression(parent)) { - const callExpr = parent; - const methodName = TypeScriptLinter.getPromiseMethodName(callExpr.expression); - if (methodName && PROMISE_METHODS.has(methodName)) { - return true; + private getCollectionMethodName(node: ts.Expression): string | undefined { + if (!ts.isPropertyAccessExpression(node)) { + return undefined; + } + + const expr = node.expression; + if (ts.isIdentifier(expr) || ts.isPropertyAccessExpression(expr)) { + const type = this.tsTypeChecker.getTypeAtLocation(expr); + const typeName = type.symbol?.getName(); + if (typeName && COLLECTION_TYPES.has(typeName)) { + return node.name.text; } - return false; } - return false; + + return undefined; } private static getPromiseMethodName(node: ts.Expression): string | undefined { @@ -3372,6 +3396,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { this.checkMethodReturnType(node, baseMethodDecl); break; + } } } diff --git a/ets2panda/linter/src/lib/utils/consts/BuiltinWhiteList.ts b/ets2panda/linter/src/lib/utils/consts/BuiltinWhiteList.ts index a491289280..080bcfa5e4 100644 --- a/ets2panda/linter/src/lib/utils/consts/BuiltinWhiteList.ts +++ b/ets2panda/linter/src/lib/utils/consts/BuiltinWhiteList.ts @@ -51,4 +51,19 @@ export const BUILTIN_CONSTRUCTORS = [ 'Number', 'Object', 'String' -]; \ No newline at end of file +]; + +export const COLLECTION_TYPES = new Set([ + 'Map', + 'Set', + 'WeakMap', + 'WeakSet' +]); + +export const COLLECTION_METHODS = new Set([ + 'add', + 'delete', + 'get', + 'has', + 'set' +]); \ No newline at end of file diff --git a/ets2panda/linter/test/main/no_sparse_array.ets b/ets2panda/linter/test/main/no_sparse_array.ets index e8e2ef3ba4..39116898df 100644 --- a/ets2panda/linter/test/main/no_sparse_array.ets +++ b/ets2panda/linter/test/main/no_sparse_array.ets @@ -77,3 +77,25 @@ function foo5(a: T[]) { return; } foo5([]); + +let set1 = new WeakSet(); +set1.has(['1']); +set1.add(['1']); +set1.delete(['1']); + +let map1 = new WeakMap(); +map1.has(['1']); +map1.set(['1'], ""); +map1.delete(['1']); +map1.get(['1']); + +let set2 = new Set(); +set2.has(['1']); +set2.add(['1']); +set2.delete(['1']); + +let map2 = new Map(); +map2.has(['1']); +map2.set(['1'], ""); +map2.delete(['1']); +map2.get(['1']); \ No newline at end of file diff --git a/ets2panda/linter/test/main/no_sparse_array2.ets b/ets2panda/linter/test/main/no_sparse_array2.ets index 5e923a25cb..1bc89431c2 100644 --- a/ets2panda/linter/test/main/no_sparse_array2.ets +++ b/ets2panda/linter/test/main/no_sparse_array2.ets @@ -48,3 +48,25 @@ let str1 = new String([]); let bool1 = new Boolean([]); let num1 = new Number([]); let obj1 = new Object([]); + +let set1 = new WeakSet(); +set1.has([]); +set1.add([]); +set1.delete([]); + +let map1 = new WeakMap(); +map1.has([]); +map1.set([], ""); +map1.delete([]); +map1.get([]); + +let set2 = new Set(); +set2.has([]); +set2.add([]); +set2.delete([]); + +let map2 = new Map(); +map2.has([]); +map2.set([], ""); +map2.delete([]); +map2.get([]); \ No newline at end of file diff --git a/ets2panda/linter/test/main/no_sparse_array2.ets.arkts2.json b/ets2panda/linter/test/main/no_sparse_array2.ets.arkts2.json index c9499abe6c..b7f01e7ef6 100644 --- a/ets2panda/linter/test/main/no_sparse_array2.ets.arkts2.json +++ b/ets2panda/linter/test/main/no_sparse_array2.ets.arkts2.json @@ -343,6 +343,146 @@ "suggest": "", "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", "severity": "ERROR" + }, + { + "line": 53, + "column": 10, + "endLine": 53, + "endColumn": 12, + "problem": "NosparseArray", + "suggest": "", + "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", + "severity": "ERROR" + }, + { + "line": 54, + "column": 10, + "endLine": 54, + "endColumn": 12, + "problem": "NosparseArray", + "suggest": "", + "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", + "severity": "ERROR" + }, + { + "line": 55, + "column": 13, + "endLine": 55, + "endColumn": 15, + "problem": "NosparseArray", + "suggest": "", + "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", + "severity": "ERROR" + }, + { + "line": 58, + "column": 10, + "endLine": 58, + "endColumn": 12, + "problem": "NosparseArray", + "suggest": "", + "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", + "severity": "ERROR" + }, + { + "line": 59, + "column": 10, + "endLine": 59, + "endColumn": 12, + "problem": "NosparseArray", + "suggest": "", + "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", + "severity": "ERROR" + }, + { + "line": 60, + "column": 13, + "endLine": 60, + "endColumn": 15, + "problem": "NosparseArray", + "suggest": "", + "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", + "severity": "ERROR" + }, + { + "line": 61, + "column": 10, + "endLine": 61, + "endColumn": 12, + "problem": "NosparseArray", + "suggest": "", + "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", + "severity": "ERROR" + }, + { + "line": 64, + "column": 10, + "endLine": 64, + "endColumn": 12, + "problem": "NosparseArray", + "suggest": "", + "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", + "severity": "ERROR" + }, + { + "line": 65, + "column": 10, + "endLine": 65, + "endColumn": 12, + "problem": "NosparseArray", + "suggest": "", + "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", + "severity": "ERROR" + }, + { + "line": 66, + "column": 13, + "endLine": 66, + "endColumn": 15, + "problem": "NosparseArray", + "suggest": "", + "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", + "severity": "ERROR" + }, + { + "line": 69, + "column": 10, + "endLine": 69, + "endColumn": 12, + "problem": "NosparseArray", + "suggest": "", + "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", + "severity": "ERROR" + }, + { + "line": 70, + "column": 10, + "endLine": 70, + "endColumn": 12, + "problem": "NosparseArray", + "suggest": "", + "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", + "severity": "ERROR" + }, + { + "line": 71, + "column": 13, + "endLine": 71, + "endColumn": 15, + "problem": "NosparseArray", + "suggest": "", + "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", + "severity": "ERROR" + }, + { + "line": 72, + "column": 10, + "endLine": 72, + "endColumn": 12, + "problem": "NosparseArray", + "suggest": "", + "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", + "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/main/structural_identity_promise.ets.arkts2.json b/ets2panda/linter/test/main/structural_identity_promise.ets.arkts2.json index 239919cb52..ca88f857e9 100644 --- a/ets2panda/linter/test/main/structural_identity_promise.ets.arkts2.json +++ b/ets2panda/linter/test/main/structural_identity_promise.ets.arkts2.json @@ -13,26 +13,5 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [ - { - "line": 39, - "column": 74, - "endLine": 39, - "endColumn": 81, - "problem": "NoTsLikeSmartType", - "suggest": "", - "rule": "Smart type differences (arkts-no-ts-like-smart-type)", - "severity": "ERROR" - }, - { - "line": 39, - "column": 83, - "endLine": 39, - "endColumn": 85, - "problem": "NoTsLikeSmartType", - "suggest": "", - "rule": "Smart type differences (arkts-no-ts-like-smart-type)", - "severity": "ERROR" - } - ] + "result": [] } \ No newline at end of file -- Gitee From f91f3ea11bc2a2498f6144f567afe71fdad79d5b Mon Sep 17 00:00:00 2001 From: Raif Mirza Erten Date: Wed, 9 Jul 2025 13:36:02 +0300 Subject: [PATCH 09/13] Missed case for equality judgment Issue: #ICL4PD Description: Fixed some missed test cases for equality judgment rule. Signed-off-by: Raif Mirza Erten --- ets2panda/linter/src/cli/CommandLineParser.ts | 77 ++- ets2panda/linter/src/lib/CookBookMsg.ts | 10 +- ets2panda/linter/src/lib/TypeScriptLinter.ts | 63 ++- .../linter/src/lib/autofixes/Autofixer.ts | 41 +- .../scan/ProblemStatisticsCommonFunction.ts | 2 +- .../src/lib/utils/consts/BuiltinWhiteList.ts | 8 +- .../interop/interop_equality_judgment.ets | 8 +- .../interop_equality_judgment.ets.arkts2.json | 224 +++++++-- ...interop_equality_judgment.ets.autofix.json | 472 ++++++++++++++---- .../interop_equality_judgment.ets.migrate.ets | 8 +- ...interop_equality_judgment.ets.migrate.json | 66 ++- .../interop/interop_equality_judgment_js.js | 10 +- .../interop_import_js_rules.ets.autofix.json | 2 +- ..._not_have_property_arkts2.ets.autofix.json | 16 +- 14 files changed, 717 insertions(+), 290 deletions(-) diff --git a/ets2panda/linter/src/cli/CommandLineParser.ts b/ets2panda/linter/src/cli/CommandLineParser.ts index 88efd14adf..04f6792b4d 100644 --- a/ets2panda/linter/src/cli/CommandLineParser.ts +++ b/ets2panda/linter/src/cli/CommandLineParser.ts @@ -206,57 +206,56 @@ function formCommandLineOptions(parsedCmd: ParsedCommand): CommandLineOptions { } function processRuleConfig(commandLineOptions: CommandLineOptions, options: OptionValues): void { - const configureRulePath = getConfigureRulePath(options); - const configuredRulesMap = getRulesFromConfig(configureRulePath); - const arkTSRulesMap = extractRuleTags(cookBookTag); - commandLineOptions.linterOptions.ruleConfigTags = getConfiguredRuleTags(arkTSRulesMap, configuredRulesMap); + const configureRulePath = getConfigureRulePath(options); + const configuredRulesMap = getRulesFromConfig(configureRulePath); + const arkTSRulesMap = extractRuleTags(cookBookTag); + commandLineOptions.linterOptions.ruleConfigTags = getConfiguredRuleTags(arkTSRulesMap, configuredRulesMap); } -function getConfigureRulePath(options: OptionValues) : string { - if (!options.ruleConfig) { - return getDefaultConfigurePath(); - } else { - const stats = fs.statSync(path.normalize(options.ruleConfig)); - if (!stats.isFile()) { - Logger.error(`The file at ${options.ruleConfigPath} path does not exist! +function getConfigureRulePath(options: OptionValues): string { + if (!options.ruleConfig) { + return getDefaultConfigurePath(); + } + const stats = fs.statSync(path.normalize(options.ruleConfig)); + if (!stats.isFile()) { + Logger.error(`The file at ${options.ruleConfigPath} path does not exist! And will use the default configure rule`); - return getDefaultConfigurePath(); - } else { - return options.ruleConfig; - } - } + return getDefaultConfigurePath(); + } + return options.ruleConfig; } -function getDefaultConfigurePath() : string { +function getDefaultConfigurePath(): string { const defaultConfigPath = path.join(process.cwd(), 'rule-config.json'); try { fs.accessSync(defaultConfigPath, fs.constants.F_OK); } catch (error: any) { if (error.code === 'ENOENT') { - Logger.error(`The default rule configuration file does not exist, please add the file named rule-config.json in the migration-helper folder!`); + Logger.error( + 'The default rule configuration file does not exist, please add the file named rule-config.json in the migration-helper folder!' + ); process.exit(1); } } return defaultConfigPath; } - function processAutofixRuleConfig(commandLineOptions: CommandLineOptions, options: OptionValues): void { - if (options.ruleConfig) { - return; - } - const autofixConfigureRulePath = options.autofixRuleConfig; - if (!autofixConfigureRulePath || autofixConfigureRulePath.length === 0) { - return; - } - const stats = fs.statSync(path.normalize(options.autofixRuleConfig)); - if (!stats.isFile()) { - Logger.error(`The file at ${options.autofixRuleConfig} path does not exist!`); - return; - } - const configuredRulesMap = getRulesFromConfig(autofixConfigureRulePath); - const arkTSRulesMap = extractRuleTags(cookBookTag); - commandLineOptions.linterOptions.autofixRuleConfigTags = getConfiguredRuleTags(arkTSRulesMap, configuredRulesMap); + if (options.ruleConfig) { + return; + } + const autofixConfigureRulePath = options.autofixRuleConfig; + if (!autofixConfigureRulePath || autofixConfigureRulePath.length === 0) { + return; + } + const stats = fs.statSync(path.normalize(options.autofixRuleConfig)); + if (!stats.isFile()) { + Logger.error(`The file at ${options.autofixRuleConfig} path does not exist!`); + return; + } + const configuredRulesMap = getRulesFromConfig(autofixConfigureRulePath); + const arkTSRulesMap = extractRuleTags(cookBookTag); + commandLineOptions.linterOptions.autofixRuleConfigTags = getConfiguredRuleTags(arkTSRulesMap, configuredRulesMap); } function createCommand(): Command { @@ -342,11 +341,11 @@ function processResponseFiles(parsedCmd: ParsedCommand): void { const rspFiles = parsedCmd.args.responseFiles; for (const rspFile of rspFiles) { try { - const rspArgs = fs - .readFileSync(rspFile) - .toString() - .split('\n') - .filter((e) => { + const rspArgs = fs. + readFileSync(rspFile). + toString(). + split('\n'). + filter((e) => { return e.trimEnd(); }); const cmdArgs = ['dummy', 'dummy']; diff --git a/ets2panda/linter/src/lib/CookBookMsg.ts b/ets2panda/linter/src/lib/CookBookMsg.ts index d94ca19217..c9f5b69115 100644 --- a/ets2panda/linter/src/lib/CookBookMsg.ts +++ b/ets2panda/linter/src/lib/CookBookMsg.ts @@ -17,14 +17,14 @@ export const cookBookMsg: string[] = []; export const cookBookTag: string[] = []; /** - * @note If the value contains multiple parentheses groups, + * @note If the value contains multiple parentheses groups, * the rule name must be placed in the last group. - * - * @example + * + * @example * // Correct (rule name in last parentheses): * 'cookBookTag[352] = "1.2 Void conflict...(sdk-ability-asynchronous-lifecycle)"' - * -*/ + * + */ cookBookTag[1] = 'Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)'; diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index 3aec0eae29..7485e67bbc 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -762,7 +762,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (!ts.isNewExpression(parent)) { return false; } - const newExpr = parent as ts.NewExpression; + const newExpr = parent; const typeName = newExpr.expression.getText(); return TYPED_ARRAYS.includes(typeName) || BUILTIN_CONSTRUCTORS.includes(typeName); @@ -3728,19 +3728,18 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { // Check if a type string has an equivalent primitive/wrapper type in a set private static areWrapperAndPrimitiveTypesEqual(typeStr: string, typeSet: Set): boolean { - const typePairs = [ - ['String', 'string'], - ['Number', 'number'], - ['Boolean', 'boolean'] - ]; + const typePairs = [ + ['String', 'string'], + ['Number', 'number'], + ['Boolean', 'boolean'] + ]; - for (const [wrapper, primitive] of typePairs) { - if ((typeStr === wrapper && typeSet.has(primitive)) || - (typeStr === primitive && typeSet.has(wrapper))) { - return true; - } + for (const [wrapper, primitive] of typePairs) { + if (typeStr === wrapper && typeSet.has(primitive) || typeStr === primitive && typeSet.has(wrapper)) { + return true; } - return false; + } + return false; } private isDerivedTypeAssignable(derivedType: ts.Type, baseType: ts.Type): boolean { @@ -3779,29 +3778,29 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { // Converts union types into an array of type strings for easy comparison. private flattenUnionTypes(type: ts.Type): string[] { - if (type.isUnion()) { - return type.types.map((t) => { - return TypeScriptLinter.normalizeTypeString(this.tsTypeChecker.typeToString(t)); - }); - } - return [TypeScriptLinter.normalizeTypeString(this.tsTypeChecker.typeToString(type))]; + if (type.isUnion()) { + return type.types.map((t) => { + return TypeScriptLinter.normalizeTypeString(this.tsTypeChecker.typeToString(t)); + }); + } + return [TypeScriptLinter.normalizeTypeString(this.tsTypeChecker.typeToString(type))]; } // Normalize type string to handle primitive wrapper types consistently private static normalizeTypeString(typeStr: string): string { - // Handle all primitive wrapper types - const wrapperToPrimitive: Record = { - 'String': 'string', - 'Number': 'number', - 'Boolean': 'boolean' - }; + // Handle all primitive wrapper types + const wrapperToPrimitive: Record = { + String: 'string', + Number: 'number', + Boolean: 'boolean' + }; - // Replace wrapper types with their primitive counterparts - let normalized = typeStr; - for (const [wrapper, primitive] of Object.entries(wrapperToPrimitive)) { - normalized = normalized.replace(new RegExp(wrapper, 'g'), primitive); - } - return normalized; + // Replace wrapper types with their primitive counterparts + let normalized = typeStr; + for (const [wrapper, primitive] of Object.entries(wrapperToPrimitive)) { + normalized = normalized.replace(new RegExp(wrapper, 'g'), primitive); + } + return normalized; } private checkClassImplementsMethod(classDecl: ts.ClassDeclaration, methodName: string): boolean { @@ -4640,7 +4639,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return; } if (ts.isCallExpression(tsCallExpr) && tsCallExpr.expression.kind === ts.SyntaxKind.SuperKeyword) { - return; + return; } const node = ts.isCallExpression(tsCallExpr) ? tsCallExpr.expression : tsCallExpr.typeName; const constructorType = this.tsTypeChecker.getTypeAtLocation(node); @@ -11435,7 +11434,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return false; } - const ifStatement = accessExpr.parent.parent.parent as ts.IfStatement; + const ifStatement = accessExpr.parent.parent.parent; if (!ts.isBinaryExpression(ifStatement.expression)) { return false; diff --git a/ets2panda/linter/src/lib/autofixes/Autofixer.ts b/ets2panda/linter/src/lib/autofixes/Autofixer.ts index 1b7526353d..36ff8421dc 100644 --- a/ets2panda/linter/src/lib/autofixes/Autofixer.ts +++ b/ets2panda/linter/src/lib/autofixes/Autofixer.ts @@ -4664,7 +4664,7 @@ export class Autofixer { fixImportClause(tsImportClause: ts.ImportClause): Autofix[] { void this; - const replacementText = tsImportClause.getText().replace(/\blazy\b\s*/, ""); + const replacementText = tsImportClause.getText().replace(/\blazy\b\s*/, ''); return [{ start: tsImportClause.getStart(), end: tsImportClause.getEnd(), replacementText }]; } @@ -4679,6 +4679,21 @@ export class Autofixer { return undefined; } + createInteropPropertyAccess(exp: ts.Expression): string { + let text: string; + if (!ts.isPropertyAccessExpression(exp)) { + text = exp.getText(); + return text; + } + const statements = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(exp.expression, ts.factory.createIdentifier(GET_PROPERTY)), + undefined, + [ts.factory.createStringLiteral(exp.name.getText())] + ); + text = this.printer.printNode(ts.EmitHint.Unspecified, statements, exp.getSourceFile()); + return text; + } + replaceInteropEqualityOperator( tsBinaryExpr: ts.BinaryExpression, binaryOperator: ts.BinaryOperator @@ -4689,14 +4704,20 @@ export class Autofixer { } const tsLhsExpr = tsBinaryExpr.left; + const left = this.createInteropPropertyAccess(tsLhsExpr); const tsRhsExpr = tsBinaryExpr.right; + const right = this.createInteropPropertyAccess(tsRhsExpr); + if (!left || !right) { + return undefined; + } + const callExpression = ts.factory.createCallExpression( ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier(tsLhsExpr.getText()), + ts.factory.createIdentifier(left), ts.factory.createIdentifier(info.functionName) ), undefined, - [ts.factory.createIdentifier(tsRhsExpr.getText())] + [ts.factory.createIdentifier(right)] ); let text = this.printer.printNode(ts.EmitHint.Unspecified, callExpression, tsBinaryExpr.getSourceFile()); @@ -5175,7 +5196,7 @@ export class Autofixer { fixNumericPublicStatic(node: ts.PropertyDeclaration): Autofix[] | undefined { if (!node?.name || node.type) { return undefined; - }; + } const typeNode = ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword); const modifiers = ts.getModifiers(node) || []; const updatedProperty = ts.factory.updatePropertyDeclaration( @@ -5188,11 +5209,13 @@ export class Autofixer { ); const newText = this.printer.printNode(ts.EmitHint.Unspecified, updatedProperty, node.getSourceFile()); - return [{ - start: node.getStart(), - end: node.getEnd(), - replacementText: newText - }]; + return [ + { + start: node.getStart(), + end: node.getEnd(), + replacementText: newText + } + ]; } fixRepeat(stmt: ts.ExpressionStatement): Autofix[] { diff --git a/ets2panda/linter/src/lib/statistics/scan/ProblemStatisticsCommonFunction.ts b/ets2panda/linter/src/lib/statistics/scan/ProblemStatisticsCommonFunction.ts index 1dbd42bcd1..cbe8c04e23 100644 --- a/ets2panda/linter/src/lib/statistics/scan/ProblemStatisticsCommonFunction.ts +++ b/ets2panda/linter/src/lib/statistics/scan/ProblemStatisticsCommonFunction.ts @@ -119,7 +119,7 @@ export function generateReportFileSync(reportName: string, reportData: any, repo fs.mkdirSync(path.dirname(reportFilePath), { recursive: true }); fs.writeFileSync(reportFilePath, JSON.stringify(reportData, null, 2)); } catch (error) { - Logger.error(`Error generating report file:${error}`); + Logger.error(`Error generating report file:${error}`); } } diff --git a/ets2panda/linter/src/lib/utils/consts/BuiltinWhiteList.ts b/ets2panda/linter/src/lib/utils/consts/BuiltinWhiteList.ts index 080bcfa5e4..db5078a676 100644 --- a/ets2panda/linter/src/lib/utils/consts/BuiltinWhiteList.ts +++ b/ets2panda/linter/src/lib/utils/consts/BuiltinWhiteList.ts @@ -46,12 +46,8 @@ export const BUILTIN_DISABLE_CALLSIGNATURE = [ 'URIError' ]; -export const BUILTIN_CONSTRUCTORS = [ - 'Boolean', - 'Number', - 'Object', - 'String' -]; +export const BUILTIN_CONSTRUCTORS = ['Boolean', 'Number', 'Object', 'String']; + export const COLLECTION_TYPES = new Set([ 'Map', diff --git a/ets2panda/linter/test/interop/interop_equality_judgment.ets b/ets2panda/linter/test/interop/interop_equality_judgment.ets index 65ce20fddc..aebc647fbe 100644 --- a/ets2panda/linter/test/interop/interop_equality_judgment.ets +++ b/ets2panda/linter/test/interop/interop_equality_judgment.ets @@ -13,8 +13,12 @@ * limitations under the License. */ -import {a, b} from "./interop_equality_judgment_js" +import {a, b, c, d} from "./interop_equality_judgment_js" a == b a != b a === b -a !== b \ No newline at end of file +a !== b +c.num1 == d.num1 +c.num1 != d.num2 +c.num1 === d.num1 +c.num1 !== d.num2 diff --git a/ets2panda/linter/test/interop/interop_equality_judgment.ets.arkts2.json b/ets2panda/linter/test/interop/interop_equality_judgment.ets.arkts2.json index 920de865a7..24b5949ab2 100644 --- a/ets2panda/linter/test/interop/interop_equality_judgment.ets.arkts2.json +++ b/ets2panda/linter/test/interop/interop_equality_judgment.ets.arkts2.json @@ -14,55 +14,175 @@ "limitations under the License." ], "result": [ - { - "line": 16, - "column": 1, - "endLine": 16, - "endColumn": 52, - "problem": "InterOpImportJs", - "suggest": "", - "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", - "severity": "ERROR" - }, - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 7, - "problem": "InteropEqualityJudgment", - "suggest": "", - "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", - "severity": "ERROR" - }, - { - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 7, - "problem": "InteropEqualityJudgment", - "suggest": "", - "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 1, - "endLine": 19, - "endColumn": 8, - "problem": "InteropEqualityJudgment", - "suggest": "", - "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", - "severity": "ERROR" - }, - { - "line": 20, - "column": 1, - "endLine": 20, - "endColumn": 8, - "problem": "InteropEqualityJudgment", - "suggest": "", - "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", - "severity": "ERROR" - } - ] -} \ No newline at end of file + { + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 58, + "problem": "InterOpImportJs", + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, + { + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 7, + "problem": "InteropEqualityJudgment", + "suggest": "", + "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", + "severity": "ERROR" + }, + { + "line": 18, + "column": 1, + "endLine": 18, + "endColumn": 7, + "problem": "InteropEqualityJudgment", + "suggest": "", + "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", + "severity": "ERROR" + }, + { + "line": 19, + "column": 1, + "endLine": 19, + "endColumn": 8, + "problem": "InteropEqualityJudgment", + "suggest": "", + "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 8, + "problem": "InteropEqualityJudgment", + "suggest": "", + "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 1, + "endLine": 21, + "endColumn": 17, + "problem": "InteropEqualityJudgment", + "suggest": "", + "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 1, + "endLine": 21, + "endColumn": 7, + "problem": "InteropObjectProperty", + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 11, + "endLine": 21, + "endColumn": 17, + "problem": "InteropObjectProperty", + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 1, + "endLine": 22, + "endColumn": 17, + "problem": "InteropEqualityJudgment", + "suggest": "", + "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 1, + "endLine": 22, + "endColumn": 7, + "problem": "InteropObjectProperty", + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 11, + "endLine": 22, + "endColumn": 17, + "problem": "InteropObjectProperty", + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 1, + "endLine": 23, + "endColumn": 18, + "problem": "InteropEqualityJudgment", + "suggest": "", + "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 1, + "endLine": 23, + "endColumn": 7, + "problem": "InteropObjectProperty", + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 12, + "endLine": 23, + "endColumn": 18, + "problem": "InteropObjectProperty", + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 1, + "endLine": 24, + "endColumn": 18, + "problem": "InteropEqualityJudgment", + "suggest": "", + "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 1, + "endLine": 24, + "endColumn": 7, + "problem": "InteropObjectProperty", + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 12, + "endLine": 24, + "endColumn": 18, + "problem": "InteropObjectProperty", + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + } + ] +} diff --git a/ets2panda/linter/test/interop/interop_equality_judgment.ets.autofix.json b/ets2panda/linter/test/interop/interop_equality_judgment.ets.autofix.json index d38814d67c..92a6f21d60 100644 --- a/ets2panda/linter/test/interop/interop_equality_judgment.ets.autofix.json +++ b/ets2panda/linter/test/interop/interop_equality_judgment.ets.autofix.json @@ -14,119 +14,371 @@ "limitations under the License." ], "result": [ + { + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 58, + "problem": "InterOpImportJs", + "autofix": [ { - "line": 16, - "column": 1, - "endLine": 16, - "endColumn": 52, - "problem": "InterOpImportJs", - "autofix": [ - { - "start": 605, - "end": 656, - "replacementText": "", - "line": 16, - "column": 1, - "endLine": 16, - "endColumn": 52 - }, - { - "start": 656, - "end": 656, - "replacementText": "let a = ESValue.load('./interop_equality_judgment_js').getProperty('a');\nlet b = ESValue.load('./interop_equality_judgment_js').getProperty('b');\n", - "line": 16, - "column": 1, - "endLine": 16, - "endColumn": 52 - } - ], - "suggest": "", - "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", - "severity": "ERROR" + "start": 605, + "end": 662, + "replacementText": "", + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 58 }, { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 7, - "problem": "InteropEqualityJudgment", - "autofix": [ - { - "start": 657, - "end": 663, - "replacementText": "a.areEqual(b)", - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 7 - } - ], - "suggest": "", - "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", - "severity": "ERROR" - }, + "start": 662, + "end": 662, + "replacementText": "let a = ESValue.load('./interop_equality_judgment_js').getProperty('a');\nlet b = ESValue.load('./interop_equality_judgment_js').getProperty('b');\nlet c = ESValue.load('./interop_equality_judgment_js').getProperty('c');\nlet d = ESValue.load('./interop_equality_judgment_js').getProperty('d');\n", + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 58 + } + ], + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, + { + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 7, + "problem": "InteropEqualityJudgment", + "autofix": [ { - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 7, - "problem": "InteropEqualityJudgment", - "autofix": [ - { - "start": 664, - "end": 670, - "replacementText": "!a.areEqual(b)", - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 7 - } - ], - "suggest": "", - "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", - "severity": "ERROR" - }, + "start": 663, + "end": 669, + "replacementText": "a.areEqual(b)", + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 7 + } + ], + "suggest": "", + "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", + "severity": "ERROR" + }, + { + "line": 18, + "column": 1, + "endLine": 18, + "endColumn": 7, + "problem": "InteropEqualityJudgment", + "autofix": [ { - "line": 19, - "column": 1, - "endLine": 19, - "endColumn": 8, - "problem": "InteropEqualityJudgment", - "autofix": [ - { - "start": 671, - "end": 678, - "replacementText": "a.areStrictlyEqual(b)", - "line": 19, - "column": 1, - "endLine": 19, - "endColumn": 8 - } - ], - "suggest": "", - "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", - "severity": "ERROR" - }, + "start": 670, + "end": 676, + "replacementText": "!a.areEqual(b)", + "line": 18, + "column": 1, + "endLine": 18, + "endColumn": 7 + } + ], + "suggest": "", + "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", + "severity": "ERROR" + }, + { + "line": 19, + "column": 1, + "endLine": 19, + "endColumn": 8, + "problem": "InteropEqualityJudgment", + "autofix": [ + { + "start": 677, + "end": 684, + "replacementText": "a.areStrictlyEqual(b)", + "line": 19, + "column": 1, + "endLine": 19, + "endColumn": 8 + } + ], + "suggest": "", + "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 8, + "problem": "InteropEqualityJudgment", + "autofix": [ { - "line": 20, - "column": 1, - "endLine": 20, - "endColumn": 8, - "problem": "InteropEqualityJudgment", - "autofix": [ - { - "start": 679, - "end": 686, - "replacementText": "!a.areStrictlyEqual(b)", - "line": 20, - "column": 1, - "endLine": 20, - "endColumn": 8 - } - ], - "suggest": "", - "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", - "severity": "ERROR" - } - ] -} \ No newline at end of file + "start": 685, + "end": 692, + "replacementText": "!a.areStrictlyEqual(b)", + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 8 + } + ], + "suggest": "", + "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 1, + "endLine": 21, + "endColumn": 17, + "problem": "InteropEqualityJudgment", + "autofix": [ + { + "start": 693, + "end": 709, + "replacementText": "c.getProperty(\"num1\").areEqual(d.getProperty(\"num1\"))", + "line": 21, + "column": 1, + "endLine": 21, + "endColumn": 17 + } + ], + "suggest": "", + "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 1, + "endLine": 21, + "endColumn": 7, + "problem": "InteropObjectProperty", + "autofix": [ + { + "start": 693, + "end": 699, + "replacementText": "c.getProperty(\"num1\")", + "line": 21, + "column": 1, + "endLine": 21, + "endColumn": 7 + } + ], + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 11, + "endLine": 21, + "endColumn": 17, + "problem": "InteropObjectProperty", + "autofix": [ + { + "start": 703, + "end": 709, + "replacementText": "d.getProperty(\"num1\")", + "line": 21, + "column": 11, + "endLine": 21, + "endColumn": 17 + } + ], + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 1, + "endLine": 22, + "endColumn": 17, + "problem": "InteropEqualityJudgment", + "autofix": [ + { + "start": 710, + "end": 726, + "replacementText": "!c.getProperty(\"num1\").areEqual(d.getProperty(\"num2\"))", + "line": 22, + "column": 1, + "endLine": 22, + "endColumn": 17 + } + ], + "suggest": "", + "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 1, + "endLine": 22, + "endColumn": 7, + "problem": "InteropObjectProperty", + "autofix": [ + { + "start": 710, + "end": 716, + "replacementText": "c.getProperty(\"num1\")", + "line": 22, + "column": 1, + "endLine": 22, + "endColumn": 7 + } + ], + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 11, + "endLine": 22, + "endColumn": 17, + "problem": "InteropObjectProperty", + "autofix": [ + { + "start": 720, + "end": 726, + "replacementText": "d.getProperty(\"num2\")", + "line": 22, + "column": 11, + "endLine": 22, + "endColumn": 17 + } + ], + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 1, + "endLine": 23, + "endColumn": 18, + "problem": "InteropEqualityJudgment", + "autofix": [ + { + "start": 727, + "end": 744, + "replacementText": "c.getProperty(\"num1\").areStrictlyEqual(d.getProperty(\"num1\"))", + "line": 23, + "column": 1, + "endLine": 23, + "endColumn": 18 + } + ], + "suggest": "", + "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 1, + "endLine": 23, + "endColumn": 7, + "problem": "InteropObjectProperty", + "autofix": [ + { + "start": 727, + "end": 733, + "replacementText": "c.getProperty(\"num1\")", + "line": 23, + "column": 1, + "endLine": 23, + "endColumn": 7 + } + ], + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 12, + "endLine": 23, + "endColumn": 18, + "problem": "InteropObjectProperty", + "autofix": [ + { + "start": 738, + "end": 744, + "replacementText": "d.getProperty(\"num1\")", + "line": 23, + "column": 12, + "endLine": 23, + "endColumn": 18 + } + ], + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 1, + "endLine": 24, + "endColumn": 18, + "problem": "InteropEqualityJudgment", + "autofix": [ + { + "start": 745, + "end": 762, + "replacementText": "!c.getProperty(\"num1\").areStrictlyEqual(d.getProperty(\"num2\"))", + "line": 24, + "column": 1, + "endLine": 24, + "endColumn": 18 + } + ], + "suggest": "", + "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 1, + "endLine": 24, + "endColumn": 7, + "problem": "InteropObjectProperty", + "autofix": [ + { + "start": 745, + "end": 751, + "replacementText": "c.getProperty(\"num1\")", + "line": 24, + "column": 1, + "endLine": 24, + "endColumn": 7 + } + ], + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 12, + "endLine": 24, + "endColumn": 18, + "problem": "InteropObjectProperty", + "autofix": [ + { + "start": 756, + "end": 762, + "replacementText": "d.getProperty(\"num2\")", + "line": 24, + "column": 12, + "endLine": 24, + "endColumn": 18 + } + ], + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + } + ] +} diff --git a/ets2panda/linter/test/interop/interop_equality_judgment.ets.migrate.ets b/ets2panda/linter/test/interop/interop_equality_judgment.ets.migrate.ets index 75dfa93e70..4280a2dfb4 100644 --- a/ets2panda/linter/test/interop/interop_equality_judgment.ets.migrate.ets +++ b/ets2panda/linter/test/interop/interop_equality_judgment.ets.migrate.ets @@ -15,8 +15,14 @@ let a = ESValue.load('./interop_equality_judgment_js').getProperty('a'); let b = ESValue.load('./interop_equality_judgment_js').getProperty('b'); +let c = ESValue.load('./interop_equality_judgment_js').getProperty('c'); +let d = ESValue.load('./interop_equality_judgment_js').getProperty('d'); a.areEqual(b) !a.areEqual(b) a.areStrictlyEqual(b) -!a.areStrictlyEqual(b) \ No newline at end of file +!a.areStrictlyEqual(b) +c.getProperty("num1").areEqual(d.getProperty("num1")) +!c.getProperty("num1").areEqual(d.getProperty("num2")) +c.getProperty("num1").areStrictlyEqual(d.getProperty("num1")) +!c.getProperty("num1").areStrictlyEqual(d.getProperty("num2")) diff --git a/ets2panda/linter/test/interop/interop_equality_judgment.ets.migrate.json b/ets2panda/linter/test/interop/interop_equality_judgment.ets.migrate.json index c8a37393a6..165b58c9e8 100644 --- a/ets2panda/linter/test/interop/interop_equality_judgment.ets.migrate.json +++ b/ets2panda/linter/test/interop/interop_equality_judgment.ets.migrate.json @@ -13,26 +13,46 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [ - { - "line": 16, - "column": 5, - "endLine": 16, - "endColumn": 72, - "problem": "AnyType", - "suggest": "", - "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", - "severity": "ERROR" - }, - { - "line": 17, - "column": 5, - "endLine": 17, - "endColumn": 72, - "problem": "AnyType", - "suggest": "", - "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", - "severity": "ERROR" - } - ] -} \ No newline at end of file + "result": [ + { + "line": 16, + "column": 5, + "endLine": 16, + "endColumn": 72, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 17, + "column": 5, + "endLine": 17, + "endColumn": 72, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 18, + "column": 5, + "endLine": 18, + "endColumn": 72, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 19, + "column": 5, + "endLine": 19, + "endColumn": 72, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + } + ] +} diff --git a/ets2panda/linter/test/interop/interop_equality_judgment_js.js b/ets2panda/linter/test/interop/interop_equality_judgment_js.js index 6461191d68..036eb5a333 100644 --- a/ets2panda/linter/test/interop/interop_equality_judgment_js.js +++ b/ets2panda/linter/test/interop/interop_equality_judgment_js.js @@ -15,4 +15,12 @@ class A {} export let a = new A() -export let b = new A() \ No newline at end of file +export let b = new A() +export let c = { + num1:1, + num2:2, +} +export let d = { + num1: 1, + num2: 2, +} diff --git a/ets2panda/linter/test/interop/interop_import_js_rules.ets.autofix.json b/ets2panda/linter/test/interop/interop_import_js_rules.ets.autofix.json index e83cca5906..3d0767dc09 100644 --- a/ets2panda/linter/test/interop/interop_import_js_rules.ets.autofix.json +++ b/ets2panda/linter/test/interop/interop_import_js_rules.ets.autofix.json @@ -1051,7 +1051,7 @@ { "start": 1831, "end": 1858, - "replacementText": "orange.isVegetable1.areStrictlyEqual(123)", + "replacementText": "orange.getProperty(\"isVegetable1\").areStrictlyEqual(123)", "line": 84, "column": 5, "endLine": 84, diff --git a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.autofix.json b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.autofix.json index a4046013b9..b04c0809f2 100644 --- a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.autofix.json +++ b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.autofix.json @@ -431,7 +431,7 @@ { "start": 1005, "end": 1031, - "replacementText": "machine.name.areStrictlyEqual(\"machine\")", + "replacementText": "machine.getProperty(\"name\").areStrictlyEqual(\"machine\")", "line": 32, "column": 12, "endLine": 32, @@ -515,7 +515,7 @@ { "start": 1173, "end": 1190, - "replacementText": "user.id.areStrictlyEqual(\"Bob\")", + "replacementText": "user.getProperty(\"id\").areStrictlyEqual(\"Bob\")", "line": 37, "column": 12, "endLine": 37, @@ -620,7 +620,7 @@ { "start": 1312, "end": 1326, - "replacementText": "user.id.areStrictlyEqual(10)", + "replacementText": "user.getProperty(\"id\").areStrictlyEqual(10)", "line": 42, "column": 8, "endLine": 42, @@ -725,7 +725,7 @@ { "start": 1454, "end": 1470, - "replacementText": "user.id.areStrictlyEqual(123n)", + "replacementText": "user.getProperty(\"id\").areStrictlyEqual(123n)", "line": 47, "column": 12, "endLine": 47, @@ -809,7 +809,7 @@ { "start": 1601, "end": 1617, - "replacementText": "user.id.areStrictlyEqual(true)", + "replacementText": "user.getProperty(\"id\").areStrictlyEqual(true)", "line": 52, "column": 12, "endLine": 52, @@ -914,7 +914,7 @@ { "start": 1758, "end": 1784, - "replacementText": "machine.name.areStrictlyEqual(\"machine\")", + "replacementText": "machine.getProperty(\"name\").areStrictlyEqual(\"machine\")", "line": 57, "column": 12, "endLine": 57, @@ -998,7 +998,7 @@ { "start": 1929, "end": 1957, - "replacementText": "employee.name.areStrictlyEqual(\"employee\")", + "replacementText": "employee.getProperty(\"name\").areStrictlyEqual(\"employee\")", "line": 62, "column": 12, "endLine": 62, @@ -1031,4 +1031,4 @@ "severity": "ERROR" } ] -} \ No newline at end of file +} -- Gitee From 2c1c905768eb29bc094437e73c76e5a9b8c72939 Mon Sep 17 00:00:00 2001 From: beratagaca_9a91 Date: Fri, 11 Jul 2025 10:07:57 +0300 Subject: [PATCH 10/13] fix interop-ts2s-static-access-ts-type rule Description: added isMixedEnum check Issue: #ICLO03 Signed-off-by: beratagaca_9a91 --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 155 +++++----- .../test/interop/ignore_files/unique_types.ts | 6 + .../linter/test/interop/unique_types.ets | 2 + .../test/interop/unique_types.ets.arkts2.json | 226 +++++++------- .../interop/unique_types.ets.autofix.json | 285 ++++++++++-------- .../linter/test/interop/unique_types.ets.json | 44 +-- .../test/interop/unique_types.ets.migrate.ets | 2 + .../interop/unique_types.ets.migrate.json | 188 ++++++------ .../incompatible_function.ets.arkts2.json | 10 - .../main/method_inheritance2.ets.arkts2.json | 30 -- .../no_ts_like_smart_type.ets.arkts2.json | 10 + ...bject_literals_properties.ets.migrate.json | 22 +- 12 files changed, 497 insertions(+), 483 deletions(-) diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index 7485e67bbc..7f045f08d6 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -160,7 +160,7 @@ import { ERROR_PROP_LIST } from './utils/consts/ErrorProp'; import { D_ETS, D_TS } from './utils/consts/TsSuffix'; import { arkTsBuiltInTypeName } from './utils/consts/ArkuiImportList'; import { ERROR_TASKPOOL_PROP_LIST } from './utils/consts/ErrorProp'; -import { COMMON_UNION_MEMBER_ACCESS_WHITELIST} from './utils/consts/ArktsWhiteApiPaths'; +import { COMMON_UNION_MEMBER_ACCESS_WHITELIST } from './utils/consts/ArktsWhiteApiPaths'; import type { BaseClassConstructorInfo, ConstructorParameter, ExtendedIdentifierInfo } from './utils/consts/Types'; import { ExtendedIdentifierType } from './utils/consts/Types'; import { STRING_ERROR_LITERAL } from './utils/consts/Literals'; @@ -629,7 +629,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return ( ts.isPropertyAssignment(prop) || ts.isShorthandPropertyAssignment(prop) && - (ts.isCallExpression(objLitExpr.parent) || ts.isNewExpression(objLitExpr.parent)) + (ts.isCallExpression(objLitExpr.parent) || ts.isNewExpression(objLitExpr.parent)) ); } @@ -773,7 +773,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return false; } - const callExpr = parent as ts.CallExpression; + const callExpr = parent; const promiseMethodName = TypeScriptLinter.getPromiseMethodName(callExpr.expression); if (promiseMethodName && PROMISE_METHODS.has(promiseMethodName)) { return true; @@ -3364,9 +3364,10 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return; } - const isStatic = node.modifiers?.some(mod => { - return mod.kind === ts.SyntaxKind.StaticKeyword; - }) || false; + const isStatic = + node.modifiers?.some((mod) => { + return mod.kind === ts.SyntaxKind.StaticKeyword; + }) || false; const classType: ts.Type | undefined = this.getClassType(classDecl, isStatic); const allBaseTypes = classType && this.getAllBaseTypes(classType, classDecl, isStatic); if (!allBaseTypes || allBaseTypes.length === 0) { @@ -3374,29 +3375,34 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } const methodName = node.name.text; if (allBaseTypes && allBaseTypes.length > 0) { - for (const baseType of allBaseTypes) { - const baseMethod = baseType.getProperty(methodName); - if (!baseMethod) { - continue; - } + this.checkMethodType(allBaseTypes, methodName, node); + } + this.checkIncompatibleFunctionTypes(node); + } - const baseMethodDecl = baseMethod.declarations?.find((d) => { - return ( - (ts.isMethodDeclaration(d) || ts.isMethodSignature(d)) && - this.tsTypeChecker.getTypeAtLocation(d.parent) === baseType - ); - }) as ts.MethodDeclaration | ts.MethodSignature; + private checkMethodType(allBaseTypes: ts.Type[], methodName: string, node: ts.MethodDeclaration): void { + for (const baseType of allBaseTypes) { + const baseMethod = baseType.getProperty(methodName); + if (!baseMethod) { + continue; + } - if (!baseMethodDecl) { - continue; - } + const baseMethodDecl = baseMethod.declarations?.find((d) => { + return ( + (ts.isMethodDeclaration(d) || ts.isMethodSignature(d)) && + this.tsTypeChecker.getTypeAtLocation(d.parent) === baseType + ); + }) as ts.MethodDeclaration | ts.MethodSignature; + + if (!baseMethodDecl) { + continue; + } - this.checkMethodParameters(node, baseMethodDecl); + this.checkMethodParameters(node, baseMethodDecl); - this.checkMethodReturnType(node, baseMethodDecl); + this.checkMethodReturnType(node, baseMethodDecl); break; - } } } @@ -3437,7 +3443,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return result; } - private getClassType( classDecl: ts.ClassDeclaration, isStatic?: boolean): ts.Type | undefined { + private getClassType(classDecl: ts.ClassDeclaration, isStatic?: boolean): ts.Type | undefined { let classType: ts.Type; if (isStatic) { @@ -3457,7 +3463,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (!declParent) { return false; } - + let declParentType: ts.Type; if (isStatic && ts.isClassDeclaration(declParent)) { if (!declParent.symbol) { @@ -3467,7 +3473,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } else { declParentType = this.tsTypeChecker.getTypeAtLocation(declParent); } - + return this.isSameType(declParentType, type); } @@ -3498,7 +3504,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } return true; } - + return this.tsTypeChecker.typeToString(type1) === this.tsTypeChecker.typeToString(type2); } @@ -3517,7 +3523,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { baseTypes.push(baseType); } } - + return baseTypes; } @@ -4187,7 +4193,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { this.tsUtils.isOrDerivedFrom(type, this.tsUtils.isStdRecordType) || this.tsUtils.isOrDerivedFrom(type, this.tsUtils.isStringType) || !this.options.arkts2 && - (this.tsUtils.isOrDerivedFrom(type, this.tsUtils.isStdMapType) || TsUtils.isIntrinsicObjectType(type)) || + (this.tsUtils.isOrDerivedFrom(type, this.tsUtils.isStdMapType) || TsUtils.isIntrinsicObjectType(type)) || TsUtils.isEnumType(type) || // we allow EsObject here beacuse it is reported later using FaultId.EsObjectType TsUtils.isEsValueType(typeNode) @@ -4533,9 +4539,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return; } if (ts.isAsExpression(initializer) || ts.isTypeAssertionExpression(initializer)) { - const typeNode = ts.isAsExpression(initializer) - ? initializer.type - : initializer.type; + const typeNode = ts.isAsExpression(initializer) ? initializer.type : initializer.type; if (typeNode.kind === ts.SyntaxKind.NumberKeyword) { this.incrementCounters(enumMember, FaultID.EnumMemberNonConstInit); @@ -4744,7 +4748,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } else { const autofix = this.autofixer?.fixNoTsLikeFunctionCall(callExpr); this.incrementCounters(expression, FaultID.ExplicitFunctionType, autofix); - } + } } private handleAppStorageCallExpression(tsCallExpr: ts.CallExpression): void { @@ -6542,7 +6546,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if ( this.compatibleSdkVersion > SENDBALE_FUNCTION_START_VERSION || this.compatibleSdkVersion === SENDBALE_FUNCTION_START_VERSION && - !SENDABLE_FUNCTION_UNSUPPORTED_STAGES_IN_API12.includes(this.compatibleSdkVersionStage) + !SENDABLE_FUNCTION_UNSUPPORTED_STAGES_IN_API12.includes(this.compatibleSdkVersionStage) ) { return true; } @@ -6756,10 +6760,10 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { const typeText = this.tsTypeChecker.typeToString(t); return Boolean( t.flags & ts.TypeFlags.StringLike || - typeText === 'String' || - t.flags & ts.TypeFlags.NumberLike && (/^\d+$/).test(typeText) || - isLiteralInitialized && !hasExplicitTypeAnnotation && !isFloatLiteral || - t.flags & ts.TypeFlags.EnumLike + typeText === 'String' || + t.flags & ts.TypeFlags.NumberLike && (/^\d+$/).test(typeText) || + isLiteralInitialized && !hasExplicitTypeAnnotation && !isFloatLiteral || + t.flags & ts.TypeFlags.EnumLike ); }; @@ -7031,9 +7035,9 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } if ( this.tsUtils.isOrDerivedFrom(lhsType, this.tsUtils.isArray) && - this.tsUtils.isOrDerivedFrom(rhsType, TsUtils.isTuple) || + this.tsUtils.isOrDerivedFrom(rhsType, TsUtils.isTuple) || this.tsUtils.isOrDerivedFrom(rhsType, this.tsUtils.isArray) && - this.tsUtils.isOrDerivedFrom(lhsType, TsUtils.isTuple) + this.tsUtils.isOrDerivedFrom(lhsType, TsUtils.isTuple) ) { this.incrementCounters(node, FaultID.NoTuplesArrays); } @@ -10289,7 +10293,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (!this.options.arkts2) { return; } - + if (ts.isIdentifier(tsCallExpr.expression)) { const funcName = tsCallExpr.expression.text; if (funcName === 'setTimeout') { @@ -10319,26 +10323,30 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { const expectedType = parameterTypes[index]; let expectedUnionType: string[] = []; if (expectedType.includes('|')) { - expectedUnionType = expectedType.split('|').map((item) => { - return item.trim(); + expectedUnionType = expectedType.split('|').map((item) => { + return item.trim(); }); } - const actualSym = this.tsTypeChecker.getSymbolAtLocation(arg); - const decl = TsUtils.getDeclaration(actualSym); - if (decl && ts.isParameter(decl) && decl.type) { - const actualType = this.tsTypeChecker.getTypeFromTypeNode(decl.type); - const actualTypeName = this.tsTypeChecker.typeToString(actualType); - if (expectedUnionType.length > 0) { - if (!expectedUnionType.includes(actualTypeName)) { - this.incrementCounters(arg, FaultID.NoTsLikeSmartType); - } - return; - } - if (actualTypeName !== expectedType) { + this.checkParameterTypeCompatibility(arg, expectedUnionType, expectedType); + }); + } + + private checkParameterTypeCompatibility(arg: ts.Expression, expectedUnionType: string[], expectedType: string): void { + const actualSym = this.tsTypeChecker.getSymbolAtLocation(arg); + const decl = TsUtils.getDeclaration(actualSym); + if (decl && ts.isParameter(decl) && decl.type) { + const actualType = this.tsTypeChecker.getTypeFromTypeNode(decl.type); + const actualTypeName = this.tsTypeChecker.typeToString(actualType); + if (expectedUnionType.length > 0) { + if (!expectedUnionType.includes(actualTypeName)) { this.incrementCounters(arg, FaultID.NoTsLikeSmartType); } + return; } - }); + if (actualTypeName !== expectedType) { + this.incrementCounters(arg, FaultID.NoTsLikeSmartType); + } + } } private handleNotsLikeSmartTypeOnAsExpression(tsAsExpr: ts.AsExpression): void { @@ -11170,9 +11178,9 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return ( (argType.flags & ts.TypeFlags.NumberLike) !== 0 || argType.isUnionOrIntersection() && - argType.types.some((t) => { - return t.flags & ts.TypeFlags.NumberLike; - }) + argType.types.some((t) => { + return t.flags & ts.TypeFlags.NumberLike; + }) ); }; @@ -11649,8 +11657,8 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { parent = parent.parent; } if (!parent) { - return false - }; + return false; + } const forStmt = parent; @@ -11659,12 +11667,11 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } const condition = forStmt.condition; - const isStandardLoop = ( + const isStandardLoop = (condition.operatorToken.kind === ts.SyntaxKind.LessThanToken || condition.operatorToken.kind === ts.SyntaxKind.LessThanEqualsToken) && ts.isPropertyAccessExpression(condition.right) && - condition.right.name.text === LENGTH_IDENTIFIER - ); + condition.right.name.text === LENGTH_IDENTIFIER; if (!isStandardLoop) { return false; @@ -11691,9 +11698,10 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return false; } + private checkArrayModifications(node: ts.Node, arrayName: string): boolean { let hasModification = false; - ts.forEachChild(node, child => { + ts.forEachChild(node, (child) => { if (TypeScriptLinter.isArrayModification(child, arrayName)) { hasModification = true; } @@ -11706,11 +11714,13 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { private checkIndexModifications(node: ts.Node, indexVar: string): boolean { let hasModification = false; - ts.forEachChild(node, child => { - if (ts.isBinaryExpression(child) && + ts.forEachChild(node, (child) => { + if ( + ts.isBinaryExpression(child) && child.operatorToken.kind === ts.SyntaxKind.EqualsToken && ts.isIdentifier(child.left) && - child.left.text === indexVar) { + child.left.text === indexVar + ) { hasModification = true; } if (!hasModification) { @@ -11722,11 +11732,13 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { private checkOutOfBoundAccess(node: ts.Node, arrayName: string): boolean { let hasOutOfBound = false; - ts.forEachChild(node, child => { - if (ts.isElementAccessExpression(child) && + ts.forEachChild(node, (child) => { + if ( + ts.isElementAccessExpression(child) && ts.isIdentifier(child.expression) && child.expression.text === arrayName && - ts.isNumericLiteral(child.argumentExpression)) { + ts.isNumericLiteral(child.argumentExpression) + ) { hasOutOfBound = true; } if (!hasOutOfBound) { @@ -11735,6 +11747,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { }); return hasOutOfBound; } + private handleCallExpressionForRepeat(node: ts.CallExpression): void { if (!this.options.arkts2) { return; diff --git a/ets2panda/linter/test/interop/ignore_files/unique_types.ts b/ets2panda/linter/test/interop/ignore_files/unique_types.ts index f56856f73a..60cf239e96 100644 --- a/ets2panda/linter/test/interop/ignore_files/unique_types.ts +++ b/ets2panda/linter/test/interop/ignore_files/unique_types.ts @@ -30,6 +30,12 @@ export let function_var: Function = function() { return true; }; +//mixed enum +export enum enum_var { + a = 0, + b = '1', +} + export class A { static instance = new A(); } diff --git a/ets2panda/linter/test/interop/unique_types.ets b/ets2panda/linter/test/interop/unique_types.ets index 9c16a54d2b..10b1d97c33 100644 --- a/ets2panda/linter/test/interop/unique_types.ets +++ b/ets2panda/linter/test/interop/unique_types.ets @@ -18,6 +18,7 @@ import { unknown_var, symbol_var, function_var, + enum_var, A, B, TestHelper, @@ -71,6 +72,7 @@ typeof symbol_var === 'object'; function_var() === true; A.instance; let obj: B = { name: "hello" }; +enum_var.a === 0; export function test_ts_non_standard_exception(testCaseRet: Array) { let test_helper = new TestHelper("TEST_TS_NON_STANDARD_EXCEPTION"); diff --git a/ets2panda/linter/test/interop/unique_types.ets.arkts2.json b/ets2panda/linter/test/interop/unique_types.ets.arkts2.json index 7fb34afcb3..3f87d2a6a4 100644 --- a/ets2panda/linter/test/interop/unique_types.ets.arkts2.json +++ b/ets2panda/linter/test/interop/unique_types.ets.arkts2.json @@ -15,9 +15,9 @@ ], "result": [ { - "line": 68, + "line": 69, "column": 8, - "endLine": 68, + "endLine": 69, "endColumn": 15, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -25,9 +25,9 @@ "severity": "ERROR" }, { - "line": 69, + "line": 70, "column": 8, - "endLine": 69, + "endLine": 70, "endColumn": 19, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -35,9 +35,9 @@ "severity": "ERROR" }, { - "line": 70, + "line": 71, "column": 8, - "endLine": 70, + "endLine": 71, "endColumn": 18, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -45,9 +45,9 @@ "severity": "ERROR" }, { - "line": 71, + "line": 72, "column": 1, - "endLine": 71, + "endLine": 72, "endColumn": 13, "problem": "ExplicitFunctionType", "suggest": "", @@ -55,9 +55,9 @@ "severity": "ERROR" }, { - "line": 71, + "line": 72, "column": 1, - "endLine": 71, + "endLine": 72, "endColumn": 13, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -65,9 +65,19 @@ "severity": "ERROR" }, { - "line": 76, + "line": 75, + "column": 16, + "endLine": 75, + "endColumn": 17, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 78, "column": 7, - "endLine": 76, + "endLine": 78, "endColumn": 69, "problem": "AnyType", "suggest": "", @@ -75,9 +85,9 @@ "severity": "ERROR" }, { - "line": 76, + "line": 78, "column": 25, - "endLine": 76, + "endLine": 78, "endColumn": 35, "problem": "DynamicCtorCall", "suggest": "", @@ -85,9 +95,9 @@ "severity": "ERROR" }, { - "line": 80, + "line": 82, "column": 7, - "endLine": 80, + "endLine": 82, "endColumn": 21, "problem": "InteropTSFunctionInvoke", "suggest": "", @@ -95,9 +105,9 @@ "severity": "ERROR" }, { - "line": 82, + "line": 84, "column": 30, - "endLine": 82, + "endLine": 84, "endColumn": 33, "problem": "NumericSemantics", "suggest": "", @@ -105,9 +115,9 @@ "severity": "ERROR" }, { - "line": 89, + "line": 91, "column": 7, - "endLine": 89, + "endLine": 91, "endColumn": 22, "problem": "InteropTSFunctionInvoke", "suggest": "", @@ -115,9 +125,9 @@ "severity": "ERROR" }, { - "line": 98, + "line": 100, "column": 7, - "endLine": 98, + "endLine": 100, "endColumn": 21, "problem": "InteropTSFunctionInvoke", "suggest": "", @@ -125,9 +135,9 @@ "severity": "ERROR" }, { - "line": 107, + "line": 109, "column": 7, - "endLine": 107, + "endLine": 109, "endColumn": 21, "problem": "InteropTSFunctionInvoke", "suggest": "", @@ -135,9 +145,9 @@ "severity": "ERROR" }, { - "line": 116, + "line": 118, "column": 7, - "endLine": 116, + "endLine": 118, "endColumn": 18, "problem": "InteropTSFunctionInvoke", "suggest": "", @@ -145,9 +155,9 @@ "severity": "ERROR" }, { - "line": 138, + "line": 140, "column": 36, - "endLine": 138, + "endLine": 140, "endColumn": 39, "problem": "NumericSemantics", "suggest": "", @@ -155,9 +165,9 @@ "severity": "ERROR" }, { - "line": 138, + "line": 140, "column": 60, - "endLine": 138, + "endLine": 140, "endColumn": 63, "problem": "NumericSemantics", "suggest": "", @@ -165,9 +175,9 @@ "severity": "ERROR" }, { - "line": 158, + "line": 160, "column": 7, - "endLine": 158, + "endLine": 160, "endColumn": 58, "problem": "AnyType", "suggest": "", @@ -175,9 +185,9 @@ "severity": "ERROR" }, { - "line": 158, + "line": 160, "column": 25, - "endLine": 158, + "endLine": 160, "endColumn": 35, "problem": "DynamicCtorCall", "suggest": "", @@ -185,9 +195,9 @@ "severity": "ERROR" }, { - "line": 176, + "line": 178, "column": 1, - "endLine": 176, + "endLine": 178, "endColumn": 18, "problem": "DecoratorsNotSupported", "suggest": "", @@ -195,9 +205,9 @@ "severity": "ERROR" }, { - "line": 181, + "line": 183, "column": 3, - "endLine": 181, + "endLine": 183, "endColumn": 21, "problem": "DecoratorsNotSupported", "suggest": "", @@ -205,9 +215,9 @@ "severity": "ERROR" }, { - "line": 187, + "line": 189, "column": 3, - "endLine": 187, + "endLine": 189, "endColumn": 19, "problem": "DecoratorsNotSupported", "suggest": "", @@ -215,9 +225,9 @@ "severity": "ERROR" }, { - "line": 195, + "line": 197, "column": 22, - "endLine": 195, + "endLine": 197, "endColumn": 41, "problem": "DecoratorsNotSupported", "suggest": "", @@ -225,9 +235,9 @@ "severity": "ERROR" }, { - "line": 195, + "line": 197, "column": 52, - "endLine": 195, + "endLine": 197, "endColumn": 55, "problem": "AnyType", "suggest": "", @@ -235,9 +245,9 @@ "severity": "ERROR" }, { - "line": 203, + "line": 205, "column": 3, - "endLine": 203, + "endLine": 205, "endColumn": 21, "problem": "DecoratorsNotSupported", "suggest": "", @@ -245,9 +255,9 @@ "severity": "ERROR" }, { - "line": 215, + "line": 217, "column": 3, - "endLine": 215, + "endLine": 217, "endColumn": 18, "problem": "DecoratorsNotSupported", "suggest": "", @@ -255,9 +265,9 @@ "severity": "ERROR" }, { - "line": 226, + "line": 228, "column": 3, - "endLine": 226, + "endLine": 228, "endColumn": 20, "problem": "DecoratorsNotSupported", "suggest": "", @@ -265,9 +275,9 @@ "severity": "ERROR" }, { - "line": 231, + "line": 233, "column": 5, - "endLine": 231, + "endLine": 233, "endColumn": 23, "problem": "DecoratorsNotSupported", "suggest": "", @@ -275,9 +285,9 @@ "severity": "ERROR" }, { - "line": 237, + "line": 239, "column": 5, - "endLine": 237, + "endLine": 239, "endColumn": 21, "problem": "DecoratorsNotSupported", "suggest": "", @@ -285,9 +295,9 @@ "severity": "ERROR" }, { - "line": 245, + "line": 247, "column": 24, - "endLine": 245, + "endLine": 247, "endColumn": 43, "problem": "DecoratorsNotSupported", "suggest": "", @@ -295,9 +305,9 @@ "severity": "ERROR" }, { - "line": 245, + "line": 247, "column": 54, - "endLine": 245, + "endLine": 247, "endColumn": 57, "problem": "AnyType", "suggest": "", @@ -305,9 +315,9 @@ "severity": "ERROR" }, { - "line": 256, + "line": 258, "column": 5, - "endLine": 256, + "endLine": 258, "endColumn": 23, "problem": "DecoratorsNotSupported", "suggest": "", @@ -315,9 +325,9 @@ "severity": "ERROR" }, { - "line": 271, + "line": 273, "column": 5, - "endLine": 271, + "endLine": 273, "endColumn": 21, "problem": "DecoratorsNotSupported", "suggest": "", @@ -325,9 +335,9 @@ "severity": "ERROR" }, { - "line": 282, + "line": 284, "column": 7, - "endLine": 282, + "endLine": 284, "endColumn": 57, "problem": "AnyType", "suggest": "", @@ -335,9 +345,9 @@ "severity": "ERROR" }, { - "line": 282, + "line": 284, "column": 25, - "endLine": 282, + "endLine": 284, "endColumn": 35, "problem": "DynamicCtorCall", "suggest": "", @@ -345,9 +355,9 @@ "severity": "ERROR" }, { - "line": 303, + "line": 305, "column": 7, - "endLine": 303, + "endLine": 305, "endColumn": 60, "problem": "AnyType", "suggest": "", @@ -355,9 +365,9 @@ "severity": "ERROR" }, { - "line": 303, + "line": 305, "column": 25, - "endLine": 303, + "endLine": 305, "endColumn": 35, "problem": "DynamicCtorCall", "suggest": "", @@ -365,9 +375,9 @@ "severity": "ERROR" }, { - "line": 306, + "line": 308, "column": 26, - "endLine": 306, + "endLine": 308, "endColumn": 33, "problem": "DynamicCtorCall", "suggest": "", @@ -375,9 +385,9 @@ "severity": "ERROR" }, { - "line": 307, + "line": 309, "column": 51, - "endLine": 307, + "endLine": 309, "endColumn": 58, "problem": "DynamicCtorCall", "suggest": "", @@ -385,9 +395,9 @@ "severity": "ERROR" }, { - "line": 308, + "line": 310, "column": 52, - "endLine": 308, + "endLine": 310, "endColumn": 59, "problem": "DynamicCtorCall", "suggest": "", @@ -395,9 +405,9 @@ "severity": "ERROR" }, { - "line": 309, + "line": 311, "column": 46, - "endLine": 309, + "endLine": 311, "endColumn": 53, "problem": "DynamicCtorCall", "suggest": "", @@ -405,9 +415,9 @@ "severity": "ERROR" }, { - "line": 310, + "line": 312, "column": 33, - "endLine": 310, + "endLine": 312, "endColumn": 40, "problem": "DynamicCtorCall", "suggest": "", @@ -415,9 +425,9 @@ "severity": "ERROR" }, { - "line": 311, + "line": 313, "column": 39, - "endLine": 311, + "endLine": 313, "endColumn": 46, "problem": "DynamicCtorCall", "suggest": "", @@ -425,9 +435,9 @@ "severity": "ERROR" }, { - "line": 312, + "line": 314, "column": 35, - "endLine": 312, + "endLine": 314, "endColumn": 42, "problem": "DynamicCtorCall", "suggest": "", @@ -435,9 +445,9 @@ "severity": "ERROR" }, { - "line": 313, + "line": 315, "column": 35, - "endLine": 313, + "endLine": 315, "endColumn": 42, "problem": "DynamicCtorCall", "suggest": "", @@ -445,9 +455,9 @@ "severity": "ERROR" }, { - "line": 314, + "line": 316, "column": 31, - "endLine": 314, + "endLine": 316, "endColumn": 38, "problem": "DynamicCtorCall", "suggest": "", @@ -455,9 +465,9 @@ "severity": "ERROR" }, { - "line": 315, + "line": 317, "column": 31, - "endLine": 315, + "endLine": 317, "endColumn": 38, "problem": "DynamicCtorCall", "suggest": "", @@ -465,9 +475,9 @@ "severity": "ERROR" }, { - "line": 316, + "line": 318, "column": 33, - "endLine": 316, + "endLine": 318, "endColumn": 40, "problem": "DynamicCtorCall", "suggest": "", @@ -475,9 +485,9 @@ "severity": "ERROR" }, { - "line": 324, + "line": 326, "column": 23, - "endLine": 324, + "endLine": 326, "endColumn": 24, "problem": "NumericSemantics", "suggest": "", @@ -485,9 +495,9 @@ "severity": "ERROR" }, { - "line": 355, + "line": 357, "column": 7, - "endLine": 355, + "endLine": 357, "endColumn": 61, "problem": "AnyType", "suggest": "", @@ -495,9 +505,9 @@ "severity": "ERROR" }, { - "line": 355, + "line": 357, "column": 25, - "endLine": 355, + "endLine": 357, "endColumn": 35, "problem": "DynamicCtorCall", "suggest": "", @@ -505,9 +515,9 @@ "severity": "ERROR" }, { - "line": 373, + "line": 375, "column": 23, - "endLine": 373, + "endLine": 375, "endColumn": 24, "problem": "NumericSemantics", "suggest": "", @@ -515,9 +525,9 @@ "severity": "ERROR" }, { - "line": 182, + "line": 184, "column": 3, - "endLine": 182, + "endLine": 184, "endColumn": 13, "problem": "StrictDiagnostic", "suggest": "Property 'myProperty' has no initializer and is not definitely assigned in the constructor.", @@ -525,9 +535,9 @@ "severity": "ERROR" }, { - "line": 202, + "line": 204, "column": 11, - "endLine": 202, + "endLine": 204, "endColumn": 16, "problem": "StrictDiagnostic", "suggest": "Property '_name' has no initializer and is not definitely assigned in the constructor.", @@ -535,9 +545,9 @@ "severity": "ERROR" }, { - "line": 214, + "line": 216, "column": 11, - "endLine": 214, + "endLine": 216, "endColumn": 15, "problem": "StrictDiagnostic", "suggest": "Property '_age' has no initializer and is not definitely assigned in the constructor.", @@ -545,9 +555,9 @@ "severity": "ERROR" }, { - "line": 232, + "line": 234, "column": 5, - "endLine": 232, + "endLine": 234, "endColumn": 15, "problem": "StrictDiagnostic", "suggest": "Property 'myProperty' has no initializer and is not definitely assigned in the constructor.", diff --git a/ets2panda/linter/test/interop/unique_types.ets.autofix.json b/ets2panda/linter/test/interop/unique_types.ets.autofix.json index bdb124b2ed..3cce68fecd 100644 --- a/ets2panda/linter/test/interop/unique_types.ets.autofix.json +++ b/ets2panda/linter/test/interop/unique_types.ets.autofix.json @@ -15,9 +15,9 @@ ], "result": [ { - "line": 68, + "line": 69, "column": 8, - "endLine": 68, + "endLine": 69, "endColumn": 15, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -25,9 +25,9 @@ "severity": "ERROR" }, { - "line": 69, + "line": 70, "column": 8, - "endLine": 69, + "endLine": 70, "endColumn": 19, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -35,9 +35,9 @@ "severity": "ERROR" }, { - "line": 70, + "line": 71, "column": 8, - "endLine": 70, + "endLine": 71, "endColumn": 18, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -45,19 +45,19 @@ "severity": "ERROR" }, { - "line": 71, + "line": 72, "column": 1, - "endLine": 71, + "endLine": 72, "endColumn": 13, "problem": "ExplicitFunctionType", "autofix": [ { - "start": 1767, - "end": 1779, + "start": 1778, + "end": 1790, "replacementText": "function_var.unsafeCall", - "line": 71, + "line": 72, "column": 1, - "endLine": 71, + "endLine": 72, "endColumn": 13 } ], @@ -66,9 +66,9 @@ "severity": "ERROR" }, { - "line": 71, + "line": 72, "column": 1, - "endLine": 71, + "endLine": 72, "endColumn": 13, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -76,9 +76,30 @@ "severity": "ERROR" }, { - "line": 76, + "line": 75, + "column": 16, + "endLine": 75, + "endColumn": 17, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1862, + "end": 1863, + "replacementText": "0.0", + "line": 75, + "column": 16, + "endLine": 75, + "endColumn": 17 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 78, "column": 7, - "endLine": 76, + "endLine": 78, "endColumn": 69, "problem": "AnyType", "suggest": "", @@ -86,9 +107,9 @@ "severity": "ERROR" }, { - "line": 76, + "line": 78, "column": 25, - "endLine": 76, + "endLine": 78, "endColumn": 35, "problem": "DynamicCtorCall", "suggest": "", @@ -96,9 +117,9 @@ "severity": "ERROR" }, { - "line": 80, + "line": 82, "column": 7, - "endLine": 80, + "endLine": 82, "endColumn": 21, "problem": "InteropTSFunctionInvoke", "suggest": "", @@ -106,19 +127,19 @@ "severity": "ERROR" }, { - "line": 82, + "line": 84, "column": 30, - "endLine": 82, + "endLine": 84, "endColumn": 33, "problem": "NumericSemantics", "autofix": [ { - "start": 2118, - "end": 2121, + "start": 2147, + "end": 2150, "replacementText": "123.0", - "line": 82, + "line": 84, "column": 30, - "endLine": 82, + "endLine": 84, "endColumn": 33 } ], @@ -127,9 +148,9 @@ "severity": "ERROR" }, { - "line": 89, + "line": 91, "column": 7, - "endLine": 89, + "endLine": 91, "endColumn": 22, "problem": "InteropTSFunctionInvoke", "suggest": "", @@ -137,9 +158,9 @@ "severity": "ERROR" }, { - "line": 98, + "line": 100, "column": 7, - "endLine": 98, + "endLine": 100, "endColumn": 21, "problem": "InteropTSFunctionInvoke", "suggest": "", @@ -147,9 +168,9 @@ "severity": "ERROR" }, { - "line": 107, + "line": 109, "column": 7, - "endLine": 107, + "endLine": 109, "endColumn": 21, "problem": "InteropTSFunctionInvoke", "suggest": "", @@ -157,9 +178,9 @@ "severity": "ERROR" }, { - "line": 116, + "line": 118, "column": 7, - "endLine": 116, + "endLine": 118, "endColumn": 18, "problem": "InteropTSFunctionInvoke", "suggest": "", @@ -167,19 +188,19 @@ "severity": "ERROR" }, { - "line": 138, + "line": 140, "column": 36, - "endLine": 138, + "endLine": 140, "endColumn": 39, "problem": "NumericSemantics", "autofix": [ { - "start": 3384, - "end": 3387, + "start": 3413, + "end": 3416, "replacementText": "123.0", - "line": 138, + "line": 140, "column": 36, - "endLine": 138, + "endLine": 140, "endColumn": 39 } ], @@ -188,19 +209,19 @@ "severity": "ERROR" }, { - "line": 138, + "line": 140, "column": 60, - "endLine": 138, + "endLine": 140, "endColumn": 63, "problem": "NumericSemantics", "autofix": [ { - "start": 3408, - "end": 3411, + "start": 3437, + "end": 3440, "replacementText": "456.0", - "line": 138, + "line": 140, "column": 60, - "endLine": 138, + "endLine": 140, "endColumn": 63 } ], @@ -209,9 +230,9 @@ "severity": "ERROR" }, { - "line": 158, + "line": 160, "column": 7, - "endLine": 158, + "endLine": 160, "endColumn": 58, "problem": "AnyType", "suggest": "", @@ -219,9 +240,9 @@ "severity": "ERROR" }, { - "line": 158, + "line": 160, "column": 25, - "endLine": 158, + "endLine": 160, "endColumn": 35, "problem": "DynamicCtorCall", "suggest": "", @@ -229,9 +250,9 @@ "severity": "ERROR" }, { - "line": 176, + "line": 178, "column": 1, - "endLine": 176, + "endLine": 178, "endColumn": 18, "problem": "DecoratorsNotSupported", "suggest": "", @@ -239,9 +260,9 @@ "severity": "ERROR" }, { - "line": 181, + "line": 183, "column": 3, - "endLine": 181, + "endLine": 183, "endColumn": 21, "problem": "DecoratorsNotSupported", "suggest": "", @@ -249,9 +270,9 @@ "severity": "ERROR" }, { - "line": 187, + "line": 189, "column": 3, - "endLine": 187, + "endLine": 189, "endColumn": 19, "problem": "DecoratorsNotSupported", "suggest": "", @@ -259,9 +280,9 @@ "severity": "ERROR" }, { - "line": 195, + "line": 197, "column": 22, - "endLine": 195, + "endLine": 197, "endColumn": 41, "problem": "DecoratorsNotSupported", "suggest": "", @@ -269,9 +290,9 @@ "severity": "ERROR" }, { - "line": 195, + "line": 197, "column": 52, - "endLine": 195, + "endLine": 197, "endColumn": 55, "problem": "AnyType", "suggest": "", @@ -279,9 +300,9 @@ "severity": "ERROR" }, { - "line": 203, + "line": 205, "column": 3, - "endLine": 203, + "endLine": 205, "endColumn": 21, "problem": "DecoratorsNotSupported", "suggest": "", @@ -289,9 +310,9 @@ "severity": "ERROR" }, { - "line": 215, + "line": 217, "column": 3, - "endLine": 215, + "endLine": 217, "endColumn": 18, "problem": "DecoratorsNotSupported", "suggest": "", @@ -299,9 +320,9 @@ "severity": "ERROR" }, { - "line": 226, + "line": 228, "column": 3, - "endLine": 226, + "endLine": 228, "endColumn": 20, "problem": "DecoratorsNotSupported", "suggest": "", @@ -309,9 +330,9 @@ "severity": "ERROR" }, { - "line": 231, + "line": 233, "column": 5, - "endLine": 231, + "endLine": 233, "endColumn": 23, "problem": "DecoratorsNotSupported", "suggest": "", @@ -319,9 +340,9 @@ "severity": "ERROR" }, { - "line": 237, + "line": 239, "column": 5, - "endLine": 237, + "endLine": 239, "endColumn": 21, "problem": "DecoratorsNotSupported", "suggest": "", @@ -329,9 +350,9 @@ "severity": "ERROR" }, { - "line": 245, + "line": 247, "column": 24, - "endLine": 245, + "endLine": 247, "endColumn": 43, "problem": "DecoratorsNotSupported", "suggest": "", @@ -339,9 +360,9 @@ "severity": "ERROR" }, { - "line": 245, + "line": 247, "column": 54, - "endLine": 245, + "endLine": 247, "endColumn": 57, "problem": "AnyType", "suggest": "", @@ -349,9 +370,9 @@ "severity": "ERROR" }, { - "line": 256, + "line": 258, "column": 5, - "endLine": 256, + "endLine": 258, "endColumn": 23, "problem": "DecoratorsNotSupported", "suggest": "", @@ -359,9 +380,9 @@ "severity": "ERROR" }, { - "line": 271, + "line": 273, "column": 5, - "endLine": 271, + "endLine": 273, "endColumn": 21, "problem": "DecoratorsNotSupported", "suggest": "", @@ -369,9 +390,9 @@ "severity": "ERROR" }, { - "line": 282, + "line": 284, "column": 7, - "endLine": 282, + "endLine": 284, "endColumn": 57, "problem": "AnyType", "suggest": "", @@ -379,9 +400,9 @@ "severity": "ERROR" }, { - "line": 282, + "line": 284, "column": 25, - "endLine": 282, + "endLine": 284, "endColumn": 35, "problem": "DynamicCtorCall", "suggest": "", @@ -389,9 +410,9 @@ "severity": "ERROR" }, { - "line": 303, + "line": 305, "column": 7, - "endLine": 303, + "endLine": 305, "endColumn": 60, "problem": "AnyType", "suggest": "", @@ -399,9 +420,9 @@ "severity": "ERROR" }, { - "line": 303, + "line": 305, "column": 25, - "endLine": 303, + "endLine": 305, "endColumn": 35, "problem": "DynamicCtorCall", "suggest": "", @@ -409,9 +430,9 @@ "severity": "ERROR" }, { - "line": 306, + "line": 308, "column": 26, - "endLine": 306, + "endLine": 308, "endColumn": 33, "problem": "DynamicCtorCall", "suggest": "", @@ -419,9 +440,9 @@ "severity": "ERROR" }, { - "line": 307, + "line": 309, "column": 51, - "endLine": 307, + "endLine": 309, "endColumn": 58, "problem": "DynamicCtorCall", "suggest": "", @@ -429,9 +450,9 @@ "severity": "ERROR" }, { - "line": 308, + "line": 310, "column": 52, - "endLine": 308, + "endLine": 310, "endColumn": 59, "problem": "DynamicCtorCall", "suggest": "", @@ -439,9 +460,9 @@ "severity": "ERROR" }, { - "line": 309, + "line": 311, "column": 46, - "endLine": 309, + "endLine": 311, "endColumn": 53, "problem": "DynamicCtorCall", "suggest": "", @@ -449,9 +470,9 @@ "severity": "ERROR" }, { - "line": 310, + "line": 312, "column": 33, - "endLine": 310, + "endLine": 312, "endColumn": 40, "problem": "DynamicCtorCall", "suggest": "", @@ -459,9 +480,9 @@ "severity": "ERROR" }, { - "line": 311, + "line": 313, "column": 39, - "endLine": 311, + "endLine": 313, "endColumn": 46, "problem": "DynamicCtorCall", "suggest": "", @@ -469,9 +490,9 @@ "severity": "ERROR" }, { - "line": 312, + "line": 314, "column": 35, - "endLine": 312, + "endLine": 314, "endColumn": 42, "problem": "DynamicCtorCall", "suggest": "", @@ -479,9 +500,9 @@ "severity": "ERROR" }, { - "line": 313, + "line": 315, "column": 35, - "endLine": 313, + "endLine": 315, "endColumn": 42, "problem": "DynamicCtorCall", "suggest": "", @@ -489,9 +510,9 @@ "severity": "ERROR" }, { - "line": 314, + "line": 316, "column": 31, - "endLine": 314, + "endLine": 316, "endColumn": 38, "problem": "DynamicCtorCall", "suggest": "", @@ -499,9 +520,9 @@ "severity": "ERROR" }, { - "line": 315, + "line": 317, "column": 31, - "endLine": 315, + "endLine": 317, "endColumn": 38, "problem": "DynamicCtorCall", "suggest": "", @@ -509,9 +530,9 @@ "severity": "ERROR" }, { - "line": 316, + "line": 318, "column": 33, - "endLine": 316, + "endLine": 318, "endColumn": 40, "problem": "DynamicCtorCall", "suggest": "", @@ -519,19 +540,19 @@ "severity": "ERROR" }, { - "line": 324, + "line": 326, "column": 23, - "endLine": 324, + "endLine": 326, "endColumn": 24, "problem": "NumericSemantics", "autofix": [ { - "start": 7971, - "end": 7972, + "start": 8000, + "end": 8001, "replacementText": "1.0", - "line": 324, + "line": 326, "column": 23, - "endLine": 324, + "endLine": 326, "endColumn": 24 } ], @@ -540,9 +561,9 @@ "severity": "ERROR" }, { - "line": 355, + "line": 357, "column": 7, - "endLine": 355, + "endLine": 357, "endColumn": 61, "problem": "AnyType", "suggest": "", @@ -550,9 +571,9 @@ "severity": "ERROR" }, { - "line": 355, + "line": 357, "column": 25, - "endLine": 355, + "endLine": 357, "endColumn": 35, "problem": "DynamicCtorCall", "suggest": "", @@ -560,19 +581,19 @@ "severity": "ERROR" }, { - "line": 373, + "line": 375, "column": 23, - "endLine": 373, + "endLine": 375, "endColumn": 24, "problem": "NumericSemantics", "autofix": [ { - "start": 9425, - "end": 9426, + "start": 9454, + "end": 9455, "replacementText": "1.0", - "line": 373, + "line": 375, "column": 23, - "endLine": 373, + "endLine": 375, "endColumn": 24 } ], @@ -581,9 +602,9 @@ "severity": "ERROR" }, { - "line": 182, + "line": 184, "column": 3, - "endLine": 182, + "endLine": 184, "endColumn": 13, "problem": "StrictDiagnostic", "suggest": "Property 'myProperty' has no initializer and is not definitely assigned in the constructor.", @@ -591,9 +612,9 @@ "severity": "ERROR" }, { - "line": 202, + "line": 204, "column": 11, - "endLine": 202, + "endLine": 204, "endColumn": 16, "problem": "StrictDiagnostic", "suggest": "Property '_name' has no initializer and is not definitely assigned in the constructor.", @@ -601,9 +622,9 @@ "severity": "ERROR" }, { - "line": 214, + "line": 216, "column": 11, - "endLine": 214, + "endLine": 216, "endColumn": 15, "problem": "StrictDiagnostic", "suggest": "Property '_age' has no initializer and is not definitely assigned in the constructor.", @@ -611,9 +632,9 @@ "severity": "ERROR" }, { - "line": 232, + "line": 234, "column": 5, - "endLine": 232, + "endLine": 234, "endColumn": 15, "problem": "StrictDiagnostic", "suggest": "Property 'myProperty' has no initializer and is not definitely assigned in the constructor.", diff --git a/ets2panda/linter/test/interop/unique_types.ets.json b/ets2panda/linter/test/interop/unique_types.ets.json index 017acb4fb6..b8a27de873 100644 --- a/ets2panda/linter/test/interop/unique_types.ets.json +++ b/ets2panda/linter/test/interop/unique_types.ets.json @@ -15,9 +15,9 @@ ], "result": [ { - "line": 76, + "line": 78, "column": 7, - "endLine": 76, + "endLine": 78, "endColumn": 69, "problem": "AnyType", "suggest": "", @@ -25,9 +25,9 @@ "severity": "ERROR" }, { - "line": 158, + "line": 160, "column": 7, - "endLine": 158, + "endLine": 160, "endColumn": 58, "problem": "AnyType", "suggest": "", @@ -35,9 +35,9 @@ "severity": "ERROR" }, { - "line": 195, + "line": 197, "column": 52, - "endLine": 195, + "endLine": 197, "endColumn": 55, "problem": "AnyType", "suggest": "", @@ -45,9 +45,9 @@ "severity": "ERROR" }, { - "line": 245, + "line": 247, "column": 54, - "endLine": 245, + "endLine": 247, "endColumn": 57, "problem": "AnyType", "suggest": "", @@ -55,9 +55,9 @@ "severity": "ERROR" }, { - "line": 282, + "line": 284, "column": 7, - "endLine": 282, + "endLine": 284, "endColumn": 57, "problem": "AnyType", "suggest": "", @@ -65,9 +65,9 @@ "severity": "ERROR" }, { - "line": 303, + "line": 305, "column": 7, - "endLine": 303, + "endLine": 305, "endColumn": 60, "problem": "AnyType", "suggest": "", @@ -75,9 +75,9 @@ "severity": "ERROR" }, { - "line": 355, + "line": 357, "column": 7, - "endLine": 355, + "endLine": 357, "endColumn": 61, "problem": "AnyType", "suggest": "", @@ -85,9 +85,9 @@ "severity": "ERROR" }, { - "line": 182, + "line": 184, "column": 3, - "endLine": 182, + "endLine": 184, "endColumn": 13, "problem": "StrictDiagnostic", "suggest": "Property 'myProperty' has no initializer and is not definitely assigned in the constructor.", @@ -95,9 +95,9 @@ "severity": "ERROR" }, { - "line": 202, + "line": 204, "column": 11, - "endLine": 202, + "endLine": 204, "endColumn": 16, "problem": "StrictDiagnostic", "suggest": "Property '_name' has no initializer and is not definitely assigned in the constructor.", @@ -105,9 +105,9 @@ "severity": "ERROR" }, { - "line": 214, + "line": 216, "column": 11, - "endLine": 214, + "endLine": 216, "endColumn": 15, "problem": "StrictDiagnostic", "suggest": "Property '_age' has no initializer and is not definitely assigned in the constructor.", @@ -115,9 +115,9 @@ "severity": "ERROR" }, { - "line": 232, + "line": 234, "column": 5, - "endLine": 232, + "endLine": 234, "endColumn": 15, "problem": "StrictDiagnostic", "suggest": "Property 'myProperty' has no initializer and is not definitely assigned in the constructor.", diff --git a/ets2panda/linter/test/interop/unique_types.ets.migrate.ets b/ets2panda/linter/test/interop/unique_types.ets.migrate.ets index 6f0585bf51..9aed01dd79 100644 --- a/ets2panda/linter/test/interop/unique_types.ets.migrate.ets +++ b/ets2panda/linter/test/interop/unique_types.ets.migrate.ets @@ -18,6 +18,7 @@ import { unknown_var, symbol_var, function_var, + enum_var, A, B, TestHelper, @@ -71,6 +72,7 @@ typeof symbol_var === 'object'; function_var.unsafeCall() === true; A.instance; let obj: B = { name: "hello" }; +enum_var.a === 0.0; export function test_ts_non_standard_exception(testCaseRet: Array) { let test_helper = new TestHelper("TEST_TS_NON_STANDARD_EXCEPTION"); diff --git a/ets2panda/linter/test/interop/unique_types.ets.migrate.json b/ets2panda/linter/test/interop/unique_types.ets.migrate.json index e78688989e..c5e5bd5229 100644 --- a/ets2panda/linter/test/interop/unique_types.ets.migrate.json +++ b/ets2panda/linter/test/interop/unique_types.ets.migrate.json @@ -15,9 +15,9 @@ ], "result": [ { - "line": 68, + "line": 69, "column": 8, - "endLine": 68, + "endLine": 69, "endColumn": 15, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -25,9 +25,9 @@ "severity": "ERROR" }, { - "line": 69, + "line": 70, "column": 8, - "endLine": 69, + "endLine": 70, "endColumn": 19, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -35,9 +35,9 @@ "severity": "ERROR" }, { - "line": 70, + "line": 71, "column": 8, - "endLine": 70, + "endLine": 71, "endColumn": 18, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -45,9 +45,9 @@ "severity": "ERROR" }, { - "line": 76, + "line": 78, "column": 7, - "endLine": 76, + "endLine": 78, "endColumn": 69, "problem": "AnyType", "suggest": "", @@ -55,9 +55,9 @@ "severity": "ERROR" }, { - "line": 76, + "line": 78, "column": 25, - "endLine": 76, + "endLine": 78, "endColumn": 35, "problem": "DynamicCtorCall", "suggest": "", @@ -65,9 +65,9 @@ "severity": "ERROR" }, { - "line": 80, + "line": 82, "column": 7, - "endLine": 80, + "endLine": 82, "endColumn": 21, "problem": "InteropTSFunctionInvoke", "suggest": "", @@ -75,9 +75,9 @@ "severity": "ERROR" }, { - "line": 89, + "line": 91, "column": 7, - "endLine": 89, + "endLine": 91, "endColumn": 22, "problem": "InteropTSFunctionInvoke", "suggest": "", @@ -85,9 +85,9 @@ "severity": "ERROR" }, { - "line": 98, + "line": 100, "column": 7, - "endLine": 98, + "endLine": 100, "endColumn": 21, "problem": "InteropTSFunctionInvoke", "suggest": "", @@ -95,9 +95,9 @@ "severity": "ERROR" }, { - "line": 107, + "line": 109, "column": 7, - "endLine": 107, + "endLine": 109, "endColumn": 21, "problem": "InteropTSFunctionInvoke", "suggest": "", @@ -105,9 +105,9 @@ "severity": "ERROR" }, { - "line": 116, + "line": 118, "column": 7, - "endLine": 116, + "endLine": 118, "endColumn": 18, "problem": "InteropTSFunctionInvoke", "suggest": "", @@ -115,9 +115,9 @@ "severity": "ERROR" }, { - "line": 158, + "line": 160, "column": 7, - "endLine": 158, + "endLine": 160, "endColumn": 58, "problem": "AnyType", "suggest": "", @@ -125,9 +125,9 @@ "severity": "ERROR" }, { - "line": 158, + "line": 160, "column": 25, - "endLine": 158, + "endLine": 160, "endColumn": 35, "problem": "DynamicCtorCall", "suggest": "", @@ -135,9 +135,9 @@ "severity": "ERROR" }, { - "line": 176, + "line": 178, "column": 1, - "endLine": 176, + "endLine": 178, "endColumn": 18, "problem": "DecoratorsNotSupported", "suggest": "", @@ -145,9 +145,9 @@ "severity": "ERROR" }, { - "line": 181, + "line": 183, "column": 3, - "endLine": 181, + "endLine": 183, "endColumn": 21, "problem": "DecoratorsNotSupported", "suggest": "", @@ -155,9 +155,9 @@ "severity": "ERROR" }, { - "line": 187, + "line": 189, "column": 3, - "endLine": 187, + "endLine": 189, "endColumn": 19, "problem": "DecoratorsNotSupported", "suggest": "", @@ -165,9 +165,9 @@ "severity": "ERROR" }, { - "line": 195, + "line": 197, "column": 22, - "endLine": 195, + "endLine": 197, "endColumn": 41, "problem": "DecoratorsNotSupported", "suggest": "", @@ -175,9 +175,9 @@ "severity": "ERROR" }, { - "line": 195, + "line": 197, "column": 52, - "endLine": 195, + "endLine": 197, "endColumn": 55, "problem": "AnyType", "suggest": "", @@ -185,9 +185,9 @@ "severity": "ERROR" }, { - "line": 203, + "line": 205, "column": 3, - "endLine": 203, + "endLine": 205, "endColumn": 21, "problem": "DecoratorsNotSupported", "suggest": "", @@ -195,9 +195,9 @@ "severity": "ERROR" }, { - "line": 215, + "line": 217, "column": 3, - "endLine": 215, + "endLine": 217, "endColumn": 18, "problem": "DecoratorsNotSupported", "suggest": "", @@ -205,9 +205,9 @@ "severity": "ERROR" }, { - "line": 226, + "line": 228, "column": 3, - "endLine": 226, + "endLine": 228, "endColumn": 20, "problem": "DecoratorsNotSupported", "suggest": "", @@ -215,9 +215,9 @@ "severity": "ERROR" }, { - "line": 231, + "line": 233, "column": 5, - "endLine": 231, + "endLine": 233, "endColumn": 23, "problem": "DecoratorsNotSupported", "suggest": "", @@ -225,9 +225,9 @@ "severity": "ERROR" }, { - "line": 237, + "line": 239, "column": 5, - "endLine": 237, + "endLine": 239, "endColumn": 21, "problem": "DecoratorsNotSupported", "suggest": "", @@ -235,9 +235,9 @@ "severity": "ERROR" }, { - "line": 245, + "line": 247, "column": 24, - "endLine": 245, + "endLine": 247, "endColumn": 43, "problem": "DecoratorsNotSupported", "suggest": "", @@ -245,9 +245,9 @@ "severity": "ERROR" }, { - "line": 245, + "line": 247, "column": 54, - "endLine": 245, + "endLine": 247, "endColumn": 57, "problem": "AnyType", "suggest": "", @@ -255,9 +255,9 @@ "severity": "ERROR" }, { - "line": 256, + "line": 258, "column": 5, - "endLine": 256, + "endLine": 258, "endColumn": 23, "problem": "DecoratorsNotSupported", "suggest": "", @@ -265,9 +265,9 @@ "severity": "ERROR" }, { - "line": 271, + "line": 273, "column": 5, - "endLine": 271, + "endLine": 273, "endColumn": 21, "problem": "DecoratorsNotSupported", "suggest": "", @@ -275,9 +275,9 @@ "severity": "ERROR" }, { - "line": 282, + "line": 284, "column": 7, - "endLine": 282, + "endLine": 284, "endColumn": 57, "problem": "AnyType", "suggest": "", @@ -285,9 +285,9 @@ "severity": "ERROR" }, { - "line": 282, + "line": 284, "column": 25, - "endLine": 282, + "endLine": 284, "endColumn": 35, "problem": "DynamicCtorCall", "suggest": "", @@ -295,9 +295,9 @@ "severity": "ERROR" }, { - "line": 303, + "line": 305, "column": 7, - "endLine": 303, + "endLine": 305, "endColumn": 60, "problem": "AnyType", "suggest": "", @@ -305,9 +305,9 @@ "severity": "ERROR" }, { - "line": 303, + "line": 305, "column": 25, - "endLine": 303, + "endLine": 305, "endColumn": 35, "problem": "DynamicCtorCall", "suggest": "", @@ -315,9 +315,9 @@ "severity": "ERROR" }, { - "line": 306, + "line": 308, "column": 26, - "endLine": 306, + "endLine": 308, "endColumn": 33, "problem": "DynamicCtorCall", "suggest": "", @@ -325,9 +325,9 @@ "severity": "ERROR" }, { - "line": 307, + "line": 309, "column": 51, - "endLine": 307, + "endLine": 309, "endColumn": 58, "problem": "DynamicCtorCall", "suggest": "", @@ -335,9 +335,9 @@ "severity": "ERROR" }, { - "line": 308, + "line": 310, "column": 52, - "endLine": 308, + "endLine": 310, "endColumn": 59, "problem": "DynamicCtorCall", "suggest": "", @@ -345,9 +345,9 @@ "severity": "ERROR" }, { - "line": 309, + "line": 311, "column": 46, - "endLine": 309, + "endLine": 311, "endColumn": 53, "problem": "DynamicCtorCall", "suggest": "", @@ -355,9 +355,9 @@ "severity": "ERROR" }, { - "line": 310, + "line": 312, "column": 33, - "endLine": 310, + "endLine": 312, "endColumn": 40, "problem": "DynamicCtorCall", "suggest": "", @@ -365,9 +365,9 @@ "severity": "ERROR" }, { - "line": 311, + "line": 313, "column": 39, - "endLine": 311, + "endLine": 313, "endColumn": 46, "problem": "DynamicCtorCall", "suggest": "", @@ -375,9 +375,9 @@ "severity": "ERROR" }, { - "line": 312, + "line": 314, "column": 35, - "endLine": 312, + "endLine": 314, "endColumn": 42, "problem": "DynamicCtorCall", "suggest": "", @@ -385,9 +385,9 @@ "severity": "ERROR" }, { - "line": 313, + "line": 315, "column": 35, - "endLine": 313, + "endLine": 315, "endColumn": 42, "problem": "DynamicCtorCall", "suggest": "", @@ -395,9 +395,9 @@ "severity": "ERROR" }, { - "line": 314, + "line": 316, "column": 31, - "endLine": 314, + "endLine": 316, "endColumn": 38, "problem": "DynamicCtorCall", "suggest": "", @@ -405,9 +405,9 @@ "severity": "ERROR" }, { - "line": 315, + "line": 317, "column": 31, - "endLine": 315, + "endLine": 317, "endColumn": 38, "problem": "DynamicCtorCall", "suggest": "", @@ -415,9 +415,9 @@ "severity": "ERROR" }, { - "line": 316, + "line": 318, "column": 33, - "endLine": 316, + "endLine": 318, "endColumn": 40, "problem": "DynamicCtorCall", "suggest": "", @@ -425,9 +425,9 @@ "severity": "ERROR" }, { - "line": 355, + "line": 357, "column": 7, - "endLine": 355, + "endLine": 357, "endColumn": 61, "problem": "AnyType", "suggest": "", @@ -435,9 +435,9 @@ "severity": "ERROR" }, { - "line": 355, + "line": 357, "column": 25, - "endLine": 355, + "endLine": 357, "endColumn": 35, "problem": "DynamicCtorCall", "suggest": "", @@ -445,9 +445,9 @@ "severity": "ERROR" }, { - "line": 182, + "line": 184, "column": 3, - "endLine": 182, + "endLine": 184, "endColumn": 13, "problem": "StrictDiagnostic", "suggest": "Property 'myProperty' has no initializer and is not definitely assigned in the constructor.", @@ -455,9 +455,9 @@ "severity": "ERROR" }, { - "line": 202, + "line": 204, "column": 11, - "endLine": 202, + "endLine": 204, "endColumn": 16, "problem": "StrictDiagnostic", "suggest": "Property '_name' has no initializer and is not definitely assigned in the constructor.", @@ -465,9 +465,9 @@ "severity": "ERROR" }, { - "line": 214, + "line": 216, "column": 11, - "endLine": 214, + "endLine": 216, "endColumn": 15, "problem": "StrictDiagnostic", "suggest": "Property '_age' has no initializer and is not definitely assigned in the constructor.", @@ -475,9 +475,9 @@ "severity": "ERROR" }, { - "line": 232, + "line": 234, "column": 5, - "endLine": 232, + "endLine": 234, "endColumn": 15, "problem": "StrictDiagnostic", "suggest": "Property 'myProperty' has no initializer and is not definitely assigned in the constructor.", diff --git a/ets2panda/linter/test/main/incompatible_function.ets.arkts2.json b/ets2panda/linter/test/main/incompatible_function.ets.arkts2.json index 2757f6f80c..83f24a944f 100644 --- a/ets2panda/linter/test/main/incompatible_function.ets.arkts2.json +++ b/ets2panda/linter/test/main/incompatible_function.ets.arkts2.json @@ -204,16 +204,6 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, - { - "line": 92, - "column": 12, - "endLine": 92, - "endColumn": 20, - "problem": "IncompationbleFunctionType", - "suggest": "", - "rule": "Stricter assignments into variables of function type (arkts-incompatible-function-types)", - "severity": "ERROR" - }, { "line": 92, "column": 12, diff --git a/ets2panda/linter/test/main/method_inheritance2.ets.arkts2.json b/ets2panda/linter/test/main/method_inheritance2.ets.arkts2.json index 30c37afc53..0a8b389c11 100755 --- a/ets2panda/linter/test/main/method_inheritance2.ets.arkts2.json +++ b/ets2panda/linter/test/main/method_inheritance2.ets.arkts2.json @@ -94,36 +94,6 @@ "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", "severity": "ERROR" }, - { - "line": 66, - "column": 10, - "endLine": 66, - "endColumn": 16, - "problem": "MethodInheritRule", - "suggest": "", - "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", - "severity": "ERROR" - }, - { - "line": 69, - "column": 3, - "endLine": 69, - "endColumn": 7, - "problem": "MethodInheritRule", - "suggest": "", - "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", - "severity": "ERROR" - }, - { - "line": 72, - "column": 11, - "endLine": 72, - "endColumn": 21, - "problem": "MethodInheritRule", - "suggest": "", - "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", - "severity": "ERROR" - }, { "line": 98, "column": 17, diff --git a/ets2panda/linter/test/main/no_ts_like_smart_type.ets.arkts2.json b/ets2panda/linter/test/main/no_ts_like_smart_type.ets.arkts2.json index 7ee5337c99..2c467f12f3 100755 --- a/ets2panda/linter/test/main/no_ts_like_smart_type.ets.arkts2.json +++ b/ets2panda/linter/test/main/no_ts_like_smart_type.ets.arkts2.json @@ -334,6 +334,16 @@ "rule": "Smart type differences (arkts-no-ts-like-smart-type)", "severity": "ERROR" }, + { + "line": 168, + "column": 10, + "endLine": 170, + "endColumn": 4, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, { "line": 137, "column": 5, diff --git a/ets2panda/linter/test/main/object_literals_properties.ets.migrate.json b/ets2panda/linter/test/main/object_literals_properties.ets.migrate.json index 07599351fa..35c8ec6cd0 100644 --- a/ets2panda/linter/test/main/object_literals_properties.ets.migrate.json +++ b/ets2panda/linter/test/main/object_literals_properties.ets.migrate.json @@ -285,19 +285,9 @@ "severity": "ERROR" }, { - "line": 267, - "column": 3, - "endLine": 267, - "endColumn": 9, - "problem": "ObjectLiteralProperty", - "suggest": "", - "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", - "severity": "ERROR" - }, - { - "line": 274, + "line": 272, "column": 1, - "endLine": 276, + "endLine": 274, "endColumn": 2, "problem": "MissingSuperCall", "suggest": "", @@ -305,9 +295,9 @@ "severity": "ERROR" }, { - "line": 286, + "line": 284, "column": 1, - "endLine": 288, + "endLine": 286, "endColumn": 2, "problem": "MissingSuperCall", "suggest": "", @@ -335,9 +325,9 @@ "severity": "ERROR" }, { - "line": 303, + "line": 301, "column": 1, - "endLine": 305, + "endLine": 303, "endColumn": 2, "problem": "MissingSuperCall", "suggest": "", -- Gitee From a635048fc2b798df4919a9735c8cc113220b6738 Mon Sep 17 00:00:00 2001 From: xudan16 Date: Mon, 7 Jul 2025 19:22:05 +0800 Subject: [PATCH 11/13] homecheck get array item with index instead of at Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICKL7K Signed-off-by: xudan16 --- ets2panda/linter/homecheck/src/utils/common/ScopeHelper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ets2panda/linter/homecheck/src/utils/common/ScopeHelper.ts b/ets2panda/linter/homecheck/src/utils/common/ScopeHelper.ts index 4c481600dd..461709e972 100644 --- a/ets2panda/linter/homecheck/src/utils/common/ScopeHelper.ts +++ b/ets2panda/linter/homecheck/src/utils/common/ScopeHelper.ts @@ -226,7 +226,7 @@ export class ScopeHelper { const succStmts = succBlock.getStmts(); if (succStmts.length > 0 && this.gTernaryConditionLines.has(succStmts[0].getOriginPositionInfo().getLineNo())) { return true; - } else if (predBlocks.length === 1 && this.gTernaryConditionLines.has(predBlocks?.[0].getStmts()?.at(-1)?.getOriginPositionInfo().getLineNo() ?? 0)) { + } else if (predBlocks.length === 1 && this.gTernaryConditionLines.has(predBlocks[0].getTail()?.getOriginPositionInfo().getLineNo() ?? 0)) { return true; } else { return false; -- Gitee From c6ad76d3f29e96d507a1bca271f2322ee5b7a9bc Mon Sep 17 00:00:00 2001 From: ZhongNing Date: Mon, 14 Jul 2025 11:44:26 +0800 Subject: [PATCH 12/13] Fix for GenericCallNoTypeArgs Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICJQD9 Test scenarios: fix bug Signed-off-by: ZhongNing --- .../linter/src/lib/autofixes/Autofixer.ts | 98 +++++++++++++---- .../test/main/func_inferred_type_args_3.ets | 43 ++++++++ .../func_inferred_type_args_3.ets.args.json | 21 ++++ .../func_inferred_type_args_3.ets.arkts2.json | 68 ++++++++++++ ...func_inferred_type_args_3.ets.autofix.json | 101 ++++++++++++++++++ .../main/func_inferred_type_args_3.ets.json | 17 +++ .../func_inferred_type_args_3.ets.migrate.ets | 43 ++++++++ ...func_inferred_type_args_3.ets.migrate.json | 38 +++++++ .../test/main/func_inferred_type_args_ts.ts | 21 ++++ .../main/func_inferred_type_args_ts.ts.json | 17 +++ .../test/main/func_inferred_type_args_ts2.ts | 24 +++++ .../main/func_inferred_type_args_ts2.ts.json | 17 +++ 12 files changed, 490 insertions(+), 18 deletions(-) create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_3.ets create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_3.ets.args.json create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_3.ets.arkts2.json create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_3.ets.autofix.json create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_3.ets.json create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_3.ets.migrate.ets create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_3.ets.migrate.json create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_ts.ts create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_ts.ts.json create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_ts2.ts create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_ts2.ts.json diff --git a/ets2panda/linter/src/lib/autofixes/Autofixer.ts b/ets2panda/linter/src/lib/autofixes/Autofixer.ts index 36ff8421dc..836d4e2f4e 100644 --- a/ets2panda/linter/src/lib/autofixes/Autofixer.ts +++ b/ets2panda/linter/src/lib/autofixes/Autofixer.ts @@ -61,6 +61,9 @@ import { LENGTH, IS_INSTANCE_OF } from '../utils/consts/InteropAPI'; +import { ESLIB_SHAREDARRAYBUFFER } from '../utils/consts/ConcurrentAPI'; +import path from 'node:path'; +import { isStdLibrarySymbol } from '../utils/functions/IsStdLibrary'; const UNDEFINED_NAME = 'undefined'; @@ -4949,12 +4952,10 @@ export class Autofixer { } const srcFile = node.getSourceFile(); - const typeArgsText = `<${typeNode.typeArguments?. - map((arg) => { - return this.nonCommentPrinter.printNode(ts.EmitHint.Unspecified, arg, srcFile); - }). - join(', ')}>`; - // Insert the type arguments immediately after the constructor name + const typeArgsText = this.printGenericCallTypeArgs(srcFile, typeNode.typeArguments); + if (!typeArgsText) { + return undefined; + } const insertPos = node.expression.getEnd(); return [{ start: insertPos, end: insertPos, replacementText: typeArgsText }]; } @@ -4965,7 +4966,10 @@ export class Autofixer { ): Autofix[] | undefined { const elementTypeNode = arrayTypeNode.elementType; const srcFile = node.getSourceFile(); - const typeArgsText = `<${this.nonCommentPrinter.printNode(ts.EmitHint.Unspecified, elementTypeNode, srcFile)}>`; + const typeArgsText = this.printGenericCallTypeArgs(srcFile, elementTypeNode); + if (!typeArgsText) { + return undefined; + } const insertPos = node.expression.getEnd(); return [{ start: insertPos, end: insertPos, replacementText: typeArgsText }]; } @@ -4982,12 +4986,10 @@ export class Autofixer { const matchingType = matchingTypes[0]; if (matchingType.typeArguments) { const srcFile = node.getSourceFile(); - const typeArgsText = `<${matchingType.typeArguments. - map((arg) => { - return this.nonCommentPrinter.printNode(ts.EmitHint.Unspecified, arg, srcFile); - }). - join(', ')}>`; - + const typeArgsText = this.printGenericCallTypeArgs(srcFile, matchingType.typeArguments); + if (!typeArgsText) { + return undefined; + } const insertPos = node.expression.getEnd(); return [{ start: insertPos, end: insertPos, replacementText: typeArgsText }]; } @@ -4995,6 +4997,67 @@ export class Autofixer { return undefined; } + private printGenericCallTypeArgs( + sourceFile: ts.SourceFile, + typeArg: ts.TypeNode | readonly ts.Node[] | undefined + ): string | undefined { + if (Array.isArray(typeArg)) { + if ( + typeArg.some((arg) => { + return !this.isTypeArgumentAccessible(sourceFile, arg as ts.TypeNode); + }) + ) { + return undefined; + } + return `<${typeArg. + map((arg) => { + return this.nonCommentPrinter.printNode(ts.EmitHint.Unspecified, arg, sourceFile); + }). + join(', ')}>`; + } + if (!typeArg || !this.isTypeArgumentAccessible(sourceFile, typeArg as ts.TypeNode)) { + return undefined; + } + + return `<${this.nonCommentPrinter.printNode(ts.EmitHint.Unspecified, typeArg as ts.TypeNode, sourceFile)}>`; + } + + private isTypeArgumentAccessible(sourceFile: ts.SourceFile, arg: ts.TypeNode): boolean { + const type = this.typeChecker.getTypeFromTypeNode(arg); + const symbol = type.symbol || type.aliasSymbol; + const decl = TsUtils.getDeclaration(symbol); + const fileName = decl?.getSourceFile().fileName; + const isStdLib = isStdLibrarySymbol(symbol); + const isMatchPathOnSourceAndDecl = decl && path.normalize(sourceFile.fileName) === path.normalize(fileName!); + if (!decl || isMatchPathOnSourceAndDecl || isStdLib) { + return true; + } + let result = false; + ts.forEachChild(sourceFile, (node) => { + if (ts.isImportDeclaration(node)) { + if (node.importClause?.namedBindings && ts.isNamedImports(node.importClause.namedBindings)) { + node.importClause.namedBindings.elements.some((element) => { + result = this.isTypeArgImport(arg, element.name, symbol); + return result; + }); + } + if (node.importClause?.name) { + result = this.isTypeArgImport(arg, node.importClause.name, symbol); + } + } + return result; + }); + return result; + } + + private isTypeArgImport(arg: ts.Node, importName: ts.Identifier, typeArgSym: ts.Symbol): boolean { + if (arg.getText() !== importName.text) { + return false; + } + const importSym = this.utils.trueSymbolAtLocation(importName); + return importSym === typeArgSym; + } + private generateGenericTypeArgumentsAutofix( node: ts.NewExpression, typeArgs: ts.TypeReferenceNode[] @@ -5013,11 +5076,10 @@ export class Autofixer { if (hasAnyType) { return undefined; } - const typeArgsText = `<${typeArgs?. - map((arg) => { - return this.nonCommentPrinter.printNode(ts.EmitHint.Unspecified, arg, srcFile); - }). - join(', ')}>`; + const typeArgsText = this.printGenericCallTypeArgs(srcFile, typeArgs); + if (!typeArgsText) { + return undefined; + } return [{ start: identifier.getEnd(), end: identifier.getEnd(), replacementText: typeArgsText }]; } diff --git a/ets2panda/linter/test/main/func_inferred_type_args_3.ets b/ets2panda/linter/test/main/func_inferred_type_args_3.ets new file mode 100644 index 0000000000..0425eba064 --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_3.ets @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import {A} from './func_inferred_type_args_ts'; +import B from './func_inferred_type_args_ts' +import A2 from './func_inferred_type_args_ts2' +import {A3} from './func_inferred_type_args_ts2' +import { HashMap } from '@kit.ArkTS'; + +function test() { + const a = new A(); + a.map = new Map(); //error +} +function test2() { + const a = new A2(); + a.map = new Map(); //error +} +function test3() { + const a = new A3(); + a.map = new Map(); //error +} + +class A4 { + id?: string; + map?: HashMap; +} +class Demo{} + +function test4() { + const a = new A4(); + a.map = new HashMap(); //error +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/func_inferred_type_args_3.ets.args.json b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.args.json new file mode 100644 index 0000000000..30973c00a2 --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.args.json @@ -0,0 +1,21 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "mode": { + "arkts2": "", + "autofix": "--arkts-2", + "migrate": "--arkts-2" + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/func_inferred_type_args_3.ets.arkts2.json b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.arkts2.json new file mode 100644 index 0000000000..868ccdbc43 --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.arkts2.json @@ -0,0 +1,68 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 23, + "column": 11, + "endLine": 23, + "endColumn": 20, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 11, + "endLine": 27, + "endColumn": 20, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 11, + "endLine": 31, + "endColumn": 20, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 42, + "column": 15, + "endLine": 42, + "endColumn": 22, + "problem": "DynamicCtorCall", + "suggest": "", + "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", + "severity": "ERROR" + }, + { + "line": 42, + "column": 11, + "endLine": 42, + "endColumn": 24, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/func_inferred_type_args_3.ets.autofix.json b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.autofix.json new file mode 100644 index 0000000000..6c9b2975d9 --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.autofix.json @@ -0,0 +1,101 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 23, + "column": 11, + "endLine": 23, + "endColumn": 20, + "problem": "GenericCallNoTypeArgs", + "autofix": [ + { + "start": 888, + "end": 888, + "replacementText": "", + "line": 23, + "column": 11, + "endLine": 23, + "endColumn": 20 + } + ], + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 11, + "endLine": 27, + "endColumn": 20, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 11, + "endLine": 31, + "endColumn": 20, + "problem": "GenericCallNoTypeArgs", + "autofix": [ + { + "start": 1032, + "end": 1032, + "replacementText": "", + "line": 31, + "column": 11, + "endLine": 31, + "endColumn": 20 + } + ], + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 42, + "column": 15, + "endLine": 42, + "endColumn": 22, + "problem": "DynamicCtorCall", + "suggest": "", + "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", + "severity": "ERROR" + }, + { + "line": 42, + "column": 11, + "endLine": 42, + "endColumn": 24, + "problem": "GenericCallNoTypeArgs", + "autofix": [ + { + "start": 1183, + "end": 1183, + "replacementText": "", + "line": 42, + "column": 11, + "endLine": 42, + "endColumn": 24 + } + ], + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/func_inferred_type_args_3.ets.json b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.json new file mode 100644 index 0000000000..b7a8809e02 --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.json @@ -0,0 +1,17 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/func_inferred_type_args_3.ets.migrate.ets b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.migrate.ets new file mode 100644 index 0000000000..c038713ec9 --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.migrate.ets @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import {A} from './func_inferred_type_args_ts'; +import B from './func_inferred_type_args_ts' +import A2 from './func_inferred_type_args_ts2' +import {A3} from './func_inferred_type_args_ts2' +import { HashMap } from '@kit.ArkTS'; + +function test() { + const a = new A(); + a.map = new Map(); //error +} +function test2() { + const a = new A2(); + a.map = new Map(); //error +} +function test3() { + const a = new A3(); + a.map = new Map(); //error +} + +class A4 { + id?: string; + map?: HashMap; +} +class Demo{} + +function test4() { + const a = new A4(); + a.map = new HashMap(); //error +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/func_inferred_type_args_3.ets.migrate.json b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.migrate.json new file mode 100644 index 0000000000..f7a8d2c4bd --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.migrate.json @@ -0,0 +1,38 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 27, + "column": 11, + "endLine": 27, + "endColumn": 20, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 42, + "column": 15, + "endLine": 42, + "endColumn": 22, + "problem": "DynamicCtorCall", + "suggest": "", + "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/func_inferred_type_args_ts.ts b/ets2panda/linter/test/main/func_inferred_type_args_ts.ts new file mode 100644 index 0000000000..59435fad58 --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_ts.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export class A { + id?: string; + map?: Map; +} + +export default class B {} +export class C {} \ No newline at end of file diff --git a/ets2panda/linter/test/main/func_inferred_type_args_ts.ts.json b/ets2panda/linter/test/main/func_inferred_type_args_ts.ts.json new file mode 100644 index 0000000000..b7a8809e02 --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_ts.ts.json @@ -0,0 +1,17 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/func_inferred_type_args_ts2.ts b/ets2panda/linter/test/main/func_inferred_type_args_ts2.ts new file mode 100644 index 0000000000..aedcb256cb --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_ts2.ts @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import {C} from './func_inferred_type_args_ts' +import B from './func_inferred_type_args_ts' +export default class A2 { + id?: string; + map?: Map; +} +export class A3 { + id?: string; + map?: Map; +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/func_inferred_type_args_ts2.ts.json b/ets2panda/linter/test/main/func_inferred_type_args_ts2.ts.json new file mode 100644 index 0000000000..b7a8809e02 --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_ts2.ts.json @@ -0,0 +1,17 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [] +} \ No newline at end of file -- Gitee From 6f9f44a6c83f791e7996d141510c6a44df661cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=92=9F=E6=9F=A0?= Date: Mon, 14 Jul 2025 11:00:06 +0800 Subject: [PATCH 13/13] Fix bug arkts-no-ts-like-catch-type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICIW6Y Test scenarios:Fix bug arkts-no-ts-like-catch-type Signed-off-by: 钟柠 --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 296 ++++++- .../linter/src/lib/autofixes/Autofixer.ts | 1 - .../linter/test/main/ts-like-catch-type.ets | 181 +++++ .../main/ts-like-catch-type.ets.arkts2.json | 736 +++++++++++++++++- .../test/main/ts-like-catch-type.ets.json | 104 ++- .../linter/test/main/ts-like-catch-type111.ts | 48 ++ .../main/ts-like-catch-type111.ts.args.json | 17 + .../test/main/ts-like-catch-type111.ts.json | 17 + 8 files changed, 1384 insertions(+), 16 deletions(-) create mode 100644 ets2panda/linter/test/main/ts-like-catch-type111.ts create mode 100644 ets2panda/linter/test/main/ts-like-catch-type111.ts.args.json create mode 100644 ets2panda/linter/test/main/ts-like-catch-type111.ts.json diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index 7f045f08d6..666921f942 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -2719,23 +2719,309 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (this.options.arkts2 && tsCatch.variableDeclaration?.name) { const varDeclName = tsCatch.variableDeclaration?.name.getText(); tsCatch.block.statements.forEach((statement) => { - this.checkTsLikeCatchType(statement, varDeclName); + this.checkTsLikeCatchType(statement, varDeclName, undefined); }); } } - private checkTsLikeCatchType(node: ts.Node, variableDeclarationName: string): void { + private checkTsLikeCatchType( + node: ts.Node, + variableDeclarationName: string, + typeNode: ts.ClassDeclaration | ts.InterfaceDeclaration | undefined + ): void { if (!node) { return; } + const hasChecked = this.hasCheckedTsLikeCatchTypeInIfStatement(node, variableDeclarationName, typeNode); + if (hasChecked) { + return; + } + const hasCheckedInConditionalExpr = this.hasCheckedTsLikeCatchTypeInConditionalExpression( + node, + variableDeclarationName, + typeNode + ); + if (hasCheckedInConditionalExpr) { + return; + } + this.checkTsLikeCatchTypeForAsExpr(node, variableDeclarationName); + for (const child of node.getChildren()) { if (ts.isPropertyAccessExpression(child)) { - if (child.expression.getText() === variableDeclarationName && !ERROR_PROP_LIST.has(child.name.getText())) { - this.incrementCounters(child, FaultID.TsLikeCatchType); + this.checkTsLikeCatchTypeForPropAccessExpr(child, variableDeclarationName, typeNode); + + if ( + ts.isParenthesizedExpression(child.expression) && + ts.isAsExpression(child.expression.expression) && + child.expression.expression.expression.getText() === variableDeclarationName + ) { + this.checkTsLikeCatchTypePropForAsExpression(child, child.expression.expression); + } + } + this.checkTsLikeCatchType(child, variableDeclarationName, typeNode); + } + } + + private hasCheckedTsLikeCatchTypeInIfStatement( + node: ts.Node, + variableDeclarationName: string, + typeNode: ts.ClassDeclaration | ts.InterfaceDeclaration | undefined + ): boolean { + const checkSubStatement = (node: ts.IfStatement, declaration: ts.ClassDeclaration): void => { + if (!this.isErrorOrInheritError(declaration)) { + this.incrementCounters(node.expression, FaultID.TsLikeCatchType); + } else { + this.checkTsLikeCatchType(node.thenStatement, variableDeclarationName, declaration); + } + const elseStatement = node.elseStatement; + if (elseStatement) { + this.checkTsLikeCatchType(elseStatement, variableDeclarationName, typeNode); + } + }; + + if ( + ts.isIfStatement(node) && + ts.isBinaryExpression(node.expression) && + node.expression.operatorToken.kind === ts.SyntaxKind.InstanceOfKeyword && + node.expression.left.getText() === variableDeclarationName + ) { + const rightSym = this.tsTypeChecker.getSymbolAtLocation(node.expression.right); + const decl = rightSym?.declarations?.[0]; + if (decl && ts.isClassDeclaration(decl)) { + checkSubStatement(node, decl); + return true; + } + if (decl && ts.isImportSpecifier(decl)) { + const symbol = this.getSymbolByImportSpecifier(decl); + const declaration = symbol?.declarations?.[0]; + if (declaration && ts.isClassDeclaration(declaration)) { + checkSubStatement(node, declaration); + return true; + } + } + } + return false; + } + + private hasCheckedTsLikeCatchTypeInConditionalExpression( + node: ts.Node, + variableDeclarationName: string, + typeNode: ts.ClassDeclaration | ts.InterfaceDeclaration | undefined + ): boolean { + if ( + ts.isConditionalExpression(node) && + ts.isBinaryExpression(node.condition) && + node.condition.operatorToken.kind === ts.SyntaxKind.InstanceOfKeyword && + node.condition.left.getText() === variableDeclarationName + ) { + const rightSym = this.tsTypeChecker.getSymbolAtLocation(node.condition.right); + const decl = rightSym?.declarations?.[0]; + if (decl && ts.isClassDeclaration(decl)) { + this.checkTsLikeCatchTypeInConditionalExprSubStatement(node, decl, variableDeclarationName, typeNode); + return true; + } else if (decl && ts.isImportSpecifier(decl)) { + const symbol = this.getSymbolByImportSpecifier(decl); + const declaration = symbol?.declarations?.[0]; + if (declaration && ts.isClassDeclaration(declaration)) { + this.checkTsLikeCatchTypeInConditionalExprSubStatement(node, declaration, variableDeclarationName, typeNode); + return true; + } + } + } + return false; + } + + private checkTsLikeCatchTypeInConditionalExprSubStatement( + node: ts.ConditionalExpression, + declarationType: ts.ClassDeclaration, + variableDeclarationName: string, + typeNode: ts.ClassDeclaration | ts.InterfaceDeclaration | undefined + ): void { + const checkWhenFalseExpr = ( + whenFalse: ts.Node, + typeNode: ts.ClassDeclaration | ts.InterfaceDeclaration | undefined + ): void => { + if (ts.isPropertyAccessExpression(whenFalse) && whenFalse.expression.getText() === variableDeclarationName) { + if (!typeNode) { + if (!ERROR_PROP_LIST.has(whenFalse.name.getText())) { + this.incrementCounters(whenFalse, FaultID.TsLikeCatchType); + } + } else { + const isValidErrorPropAccess = this.isValidErrorPropAccess(whenFalse, typeNode); + if (!isValidErrorPropAccess) { + this.incrementCounters(whenFalse, FaultID.TsLikeCatchType); + } + } + } else { + this.checkTsLikeCatchType(whenFalse, variableDeclarationName, typeNode); + } + }; + + if (!this.isErrorOrInheritError(declarationType)) { + this.incrementCounters(node.condition, FaultID.TsLikeCatchType); + checkWhenFalseExpr(node.whenFalse, typeNode); + } else { + if ( + ts.isPropertyAccessExpression(node.whenTrue) && + node.whenTrue.expression.getText() === variableDeclarationName + ) { + const whenTrue: ts.PropertyAccessExpression = node.whenTrue; + const isValidErrorPropAccess = this.isValidErrorPropAccess(whenTrue, declarationType); + if (!isValidErrorPropAccess) { + this.incrementCounters(whenTrue, FaultID.TsLikeCatchType); } + } else { + this.checkTsLikeCatchType(node.whenTrue, variableDeclarationName, declarationType); + } + checkWhenFalseExpr(node.whenFalse, typeNode); + } + } + + private checkTsLikeCatchTypeForAsExpr(node: ts.Node, variableDeclarationName: string): void { + if (!ts.isAsExpression(node) || node.expression.getText() !== variableDeclarationName) { + return; + } + const asExprTypeNode = node.type; + if (!asExprTypeNode || !ts.isTypeReferenceNode(asExprTypeNode)) { + return; + } + const checkReport = (node: ts.AsExpression, declaration: ts.ClassDeclaration | ts.InterfaceDeclaration): void => { + if (!this.isErrorOrInheritError(declaration)) { + this.incrementCounters(node, FaultID.TsLikeCatchType); + } + }; + + const checkImportSpecifier = (decl: ts.ImportSpecifier): void => { + const symbol = this.getSymbolByImportSpecifier(decl); + const declaration = symbol?.declarations?.[0]; + if (declaration && (ts.isClassDeclaration(declaration) || ts.isInterfaceDeclaration(declaration))) { + checkReport(node, declaration); + } + }; + const typeName = asExprTypeNode.typeName; + const sym = this.tsTypeChecker.getSymbolAtLocation(typeName); + const decl = sym?.declarations?.[0]; + if (decl && (ts.isClassDeclaration(decl) || ts.isInterfaceDeclaration(decl))) { + checkReport(node, decl); + } else if (decl && ts.isImportSpecifier(decl)) { + checkImportSpecifier(decl); + } + } + + private checkTsLikeCatchTypeHasPropInType( + propAccessExpr: ts.PropertyAccessExpression, + decl: ts.ClassDeclaration | ts.InterfaceDeclaration + ): void { + if (!decl) { + return; + } + if (this.isErrorOrInheritError(decl)) { + const isValidErrorPropAccess = this.isValidErrorPropAccess(propAccessExpr, decl); + if (!isValidErrorPropAccess) { + this.incrementCounters(propAccessExpr, FaultID.TsLikeCatchType); + } + } + } + + private checkTsLikeCatchTypeForPropAccessExpr( + propAccessExpr: ts.PropertyAccessExpression, + variableDeclarationName: string, + typeNode: ts.ClassDeclaration | ts.InterfaceDeclaration | undefined + ): void { + const checkProp = (): void => { + if (!typeNode) { + if (!ERROR_PROP_LIST.has(propAccessExpr.name.getText())) { + this.incrementCounters(propAccessExpr, FaultID.TsLikeCatchType); + } + } else { + const isValidErrorPropAccess = this.isValidErrorPropAccess(propAccessExpr, typeNode); + if (!isValidErrorPropAccess) { + this.incrementCounters(propAccessExpr, FaultID.TsLikeCatchType); + } + } + }; + + if (propAccessExpr.expression.getText() === variableDeclarationName) { + checkProp(); + return; + } + + const sym = this.tsTypeChecker.getSymbolAtLocation(propAccessExpr.expression); + const decl = sym?.declarations?.[0]; + if (decl && ts.isVariableDeclaration(decl) && decl.initializer) { + if (decl.initializer.getText() === variableDeclarationName) { + checkProp(); + return; + } + if (ts.isAsExpression(decl.initializer) && decl.initializer.expression.getText() === variableDeclarationName) { + this.checkTsLikeCatchTypePropForAsExpression(propAccessExpr, decl.initializer); + } + } + } + + private checkTsLikeCatchTypePropForAsExpression( + propAccessExpr: ts.PropertyAccessExpression, + asExpr: ts.AsExpression + ): void { + const asExprTypeNode = asExpr.type; + if (asExprTypeNode && ts.isTypeReferenceNode(asExprTypeNode)) { + const typeName = asExprTypeNode.typeName; + const sym = this.tsTypeChecker.getSymbolAtLocation(typeName); + const decl = sym?.declarations?.[0]; + if (decl && (ts.isClassDeclaration(decl) || ts.isInterfaceDeclaration(decl))) { + this.checkTsLikeCatchTypeHasPropInType(propAccessExpr, decl); + } else if (decl && ts.isImportSpecifier(decl)) { + const symbol = this.getSymbolByImportSpecifier(decl); + const declaration = symbol?.declarations?.[0]; + if (declaration && (ts.isClassDeclaration(declaration) || ts.isInterfaceDeclaration(declaration))) { + this.checkTsLikeCatchTypeHasPropInType(propAccessExpr, declaration); + } + } + } + } + + private isErrorOrInheritError(declaration: ts.ClassDeclaration | ts.InterfaceDeclaration): boolean { + const type = this.tsTypeChecker.getTypeAtLocation(declaration); + return this.tsUtils.isOrDerivedFrom(type, this.tsUtils.isStdErrorType); + } + + private isValidErrorPropAccess( + propertyAccessExpr: ts.PropertyAccessExpression, + decl: ts.ClassDeclaration | ts.InterfaceDeclaration | undefined + ): boolean { + void this; + let containsMember = false; + decl?.members.forEach((member) => { + if (member.name?.getText() === propertyAccessExpr.name.getText()) { + containsMember = true; + } + }); + return containsMember || ERROR_PROP_LIST.has(propertyAccessExpr.name.getText()); + } + + private getSymbolByImportSpecifier(declaration: ts.ImportSpecifier): ts.Symbol | undefined { + if (!declaration?.parent?.parent) { + return undefined; + } + if (!ts.isImportClause(declaration.parent.parent)) { + return undefined; + } + const importClause = declaration.parent.parent; + const namedBindings = importClause.namedBindings; + let symbol: ts.Symbol | undefined; + if (namedBindings) { + if (ts.isNamedImports(namedBindings) && namedBindings.elements?.length > 0) { + for (let i = 0; i < namedBindings.elements.length; i++) { + if (namedBindings.elements[i].name.getText() === declaration.name.getText()) { + symbol = this.tsUtils.trueSymbolAtLocation(namedBindings.elements[i].name); + break; + } + } + } else if (ts.isNamespaceImport(namedBindings)) { + symbol = this.tsUtils.trueSymbolAtLocation(namedBindings.name); } - this.checkTsLikeCatchType(child, variableDeclarationName); } + return symbol; } private handleClassExtends(tsClassDecl: ts.ClassDeclaration): void { diff --git a/ets2panda/linter/src/lib/autofixes/Autofixer.ts b/ets2panda/linter/src/lib/autofixes/Autofixer.ts index 836d4e2f4e..243071ad18 100644 --- a/ets2panda/linter/src/lib/autofixes/Autofixer.ts +++ b/ets2panda/linter/src/lib/autofixes/Autofixer.ts @@ -61,7 +61,6 @@ import { LENGTH, IS_INSTANCE_OF } from '../utils/consts/InteropAPI'; -import { ESLIB_SHAREDARRAYBUFFER } from '../utils/consts/ConcurrentAPI'; import path from 'node:path'; import { isStdLibrarySymbol } from '../utils/functions/IsStdLibrary'; diff --git a/ets2panda/linter/test/main/ts-like-catch-type.ets b/ets2panda/linter/test/main/ts-like-catch-type.ets index 84b0d23a10..1f16edc96f 100644 --- a/ets2panda/linter/test/main/ts-like-catch-type.ets +++ b/ets2panda/linter/test/main/ts-like-catch-type.ets @@ -14,6 +14,7 @@ */ import { BusinessError } from '@ohos.base'; +import { AError, AError1, BError, BError1 } from "./ts-like-catch-type111"; try { throw new Error(); @@ -31,4 +32,184 @@ try { let that = 123; } catch (err: BusinessError) { console.log(err.toString()); +} + +class RpcException { + msg: string; + code: number; +} + +class RpcException1 { + msg: string; + code: number; +} + +// not extends Error +function a1() { + try { + throw new RpcException('msg', 1); + } catch (e) { + let errorCode = 1; + let errorMsg = ''; + if (e instanceof RpcException) { // error + errorMsg = e.msg; // not check + errorCode = e.code; // not check + } else if (e instanceof RpcException1) { // error + errorMsg = e.msg; // not check + errorCode = e.code; // not check + } else { + console.log('else prop: ' + e.prop); // error + console.log('else message: ' + e.message); // ok + } + // e instanceof RpcException / e.prop error + e instanceof RpcException ? e.msg : e.prop; + // e instanceof RpcException / e.prop error + e instanceof RpcException ? console.log('when true: ' + e.msg) : console.log('when false: ' + e.prop); + // e instanceof RpcException / e instanceof RpcException1 / e.prop error + e instanceof RpcException ? console.log('when true: ' + (e instanceof RpcException1 ? e.msg : e.code)) : console.log('when false: ' + (e instanceof RpcException1 ? e.msg : e.prop)); + // e instanceof RpcException / e instanceof RpcException1 + e instanceof RpcException ? console.log('when true: ' + (e instanceof RpcException1 ? e.msg : e.code)) : console.log('when false: ' + (e instanceof RpcException1 ? e.msg : e.message)); // error * 2 + console.log(errorMsg); + (e as RpcException).msg; // error + console.log('errorMsg: ' + (e as RpcException).msg); // error + const temp = e; + temp.prop; // error + console.log('errorMsg: ' + temp.prop); // error + const temp1 = e as RpcException; // error + temp1.msg; // not check + temp1.message; // not check + console.log('errorMsg: ' + temp1.message); // not check + } +} + +// import / not extends Error +function a2() { + try { + throw new BError('msg', 1); + } catch (e) { + let errorCode = 1; + let errorMsg = ''; + if (e instanceof BError) { // error + errorMsg = e.a; // not check + errorCode = e.code; // not check + } else if (e instanceof BError1) { // error + errorMsg = e.b; // not check + errorCode = e.message; // not check + } else { + console.log('else prop: ' + e.prop); // error + console.log('else message: ' + e.message); // ok + } + // e instanceof BError / e.prop error + e instanceof BError ? e.msg : e.prop; + // e instanceof BError / e.prop error + e instanceof BError ? console.log('when true: ' + e.msg) : console.log('when false: ' + e.prop); + // e instanceof BError / e instanceof BError1 / e.prop error + e instanceof BError ? console.log('when true: ' + (e instanceof BError1 ? e.msg : e.code)) : console.log('when false: ' + (e instanceof BError1 ? e.msg : e.prop)); + // e instanceof BError / e instanceof BError1 + e instanceof BError ? console.log('when true: ' + (e instanceof BError1 ? e.msg : e.code)) : console.log('when false: ' + (e instanceof BError1 ? e.msg : e.message)); + console.log(errorMsg); + (e as BError).msg; // error + console.log('errorMsg: ' + (e as BError).msg); // error + const temp = e; + temp.prop; // error + console.log('errorMsg: ' + temp.prop); // error + const temp1 = e as BError; // error + temp1.msg; // not check + temp1.message; // not check + console.log('errorMsg: ' + temp1.message); // not check + } +} + +class RpcException2 extends Error { + msg: string; + code: number; + constructor(msg: string, code: number) { + super(msg); + this.msg = msg; + this.code = code; + } +} + +class RpcException3 extends Error { + msg: string; + code: number; + constructor(msg: string, code: number) { + super(msg); + this.msg = msg; + this.code = code; + } +} + +// extends Error +function a3() { + try { + throw new RpcException2(); + } catch (e) { + let errorCode = 1; + let errorMsg = ''; + if (e instanceof RpcException2) { + errorMsg = e.msg; + errorCode = e.code; + console.log('a3: ' + e.prop); // error + } else if (e instanceof RpcException3) { + errorMsg = e.msg; + errorCode = e.code; + } else { + console.log('else prop: ' + e.prop); // error + console.log('else message: ' + e.message); // ok + } + e instanceof RpcException2 ? e.msg : e.prop; // e.prop error + e instanceof RpcException2 ? console.log('when true: ' + e.msg) : console.log('when false: ' + e.prop); // e.prop error + // e.msg1 / e.prop error + e instanceof RpcException2 ? console.log('when true: ' + (e instanceof RpcException3 ? e.msg1 : e.code)) : console.log('when false: ' + (e instanceof RpcException3 ? e.msg : e.prop)); + e instanceof RpcException2 ? console.log('when true: ' + (e instanceof RpcException3 ? e.msg : e.code)) : console.log('when false: ' + (e instanceof RpcException3 ? e.msg : e.message)); + console.log(errorMsg); + (e as RpcException2).msg; // ok + console.log('errorMsg: ' + (e as RpcException2).msg); // ok + const temp = e; + temp.prop; // error + console.log('errorMsg: ' + temp.prop); // error + const temp1 = e as RpcException2; + temp1.msg; // ok + temp1.message; // ok + console.log('errorMsg: ' + temp1.message); // ok + console.log('errorMsg: ' + temp1.prop); // error + } +} + +// import / extends Error +function a4() { + try { + throw new AError('msg'); + } catch (e) { + let errorCode = 1; + let errorMsg = ''; + if (e instanceof AError) { + errorMsg = e.customProp; + errorCode = e.code; + console.log('a4: ' + e.prop); // error + } else if (e instanceof AError1) { + errorMsg = e.customProp; + errorCode = e.code; + } else { + console.log('else prop: ' + e.prop); // error + console.log('else message: ' + e.message); // ok + } + e instanceof AError ? e.customProp : e.prop; // e.prop error + e instanceof AError ? console.log('when true: ' + e.customProp) : console.log('when false: ' + e.prop); // e.prop error + // e.customProp1 / e.prop error + e instanceof AError ? console.log('when true: ' + (e instanceof AError1 ? e.customProp1 : e.code)) : console.log('when false: ' + (e instanceof AError1 ? e.customProp : e.prop)); + e instanceof AError ? console.log('when true: ' + (e instanceof AError1 ? e.customProp : e.code)) : console.log('when false: ' + (e instanceof AError1 ? e.customProp : e.message)); + console.log(errorMsg); + (e as AError).customProp; // ok + console.log('errorMsg: ' + (e as AError).customProp); // ok + const temp = e; + temp.prop; // error + console.log('errorMsg: ' + temp.prop); // error + const temp1 = e as AError; + temp1.customProp; // ok + temp1.message; // ok + console.log('errorMsg: ' + temp1.message); // ok + console.log('errorMsg: ' + temp1.prop); // error + } } \ No newline at end of file diff --git a/ets2panda/linter/test/main/ts-like-catch-type.ets.arkts2.json b/ets2panda/linter/test/main/ts-like-catch-type.ets.arkts2.json index e77370a4f3..8decc568f8 100644 --- a/ets2panda/linter/test/main/ts-like-catch-type.ets.arkts2.json +++ b/ets2panda/linter/test/main/ts-like-catch-type.ets.arkts2.json @@ -15,9 +15,9 @@ ], "result": [ { - "line": 22, + "line": 23, "column": 3, - "endLine": 22, + "endLine": 23, "endColumn": 9, "problem": "TsLikeCatchType", "suggest": "", @@ -25,9 +25,9 @@ "severity": "ERROR" }, { - "line": 31, + "line": 32, "column": 7, - "endLine": 31, + "endLine": 32, "endColumn": 17, "problem": "NumericSemantics", "suggest": "", @@ -35,9 +35,9 @@ "severity": "ERROR" }, { - "line": 31, + "line": 32, "column": 14, - "endLine": 31, + "endLine": 32, "endColumn": 17, "problem": "NumericSemantics", "suggest": "", @@ -45,14 +45,734 @@ "severity": "ERROR" }, { - "line": 32, + "line": 33, "column": 10, - "endLine": 32, + "endLine": 33, "endColumn": 28, "problem": "CatchWithUnsupportedType", "suggest": "", "rule": "Type annotation in catch clause is not supported (arkts-no-types-in-catch)", "severity": "ERROR" + }, + { + "line": 50, + "column": 5, + "endLine": 50, + "endColumn": 38, + "problem": "ThrowStatement", + "suggest": "", + "rule": "\"throw\" statements cannot accept values of arbitrary types (arkts-limited-throw)", + "severity": "ERROR" + }, + { + "line": 50, + "column": 35, + "endLine": 50, + "endColumn": 36, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 54, + "column": 9, + "endLine": 54, + "endColumn": 34, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 57, + "column": 16, + "endLine": 57, + "endColumn": 42, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 61, + "column": 35, + "endLine": 61, + "endColumn": 41, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 65, + "column": 5, + "endLine": 65, + "endColumn": 30, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 65, + "column": 41, + "endLine": 65, + "endColumn": 47, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 67, + "column": 5, + "endLine": 67, + "endColumn": 30, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 67, + "column": 99, + "endLine": 67, + "endColumn": 105, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 69, + "column": 5, + "endLine": 69, + "endColumn": 30, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 69, + "column": 141, + "endLine": 69, + "endColumn": 167, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 69, + "column": 178, + "endLine": 69, + "endColumn": 184, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 71, + "column": 5, + "endLine": 71, + "endColumn": 30, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 71, + "column": 141, + "endLine": 71, + "endColumn": 167, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 73, + "column": 6, + "endLine": 73, + "endColumn": 23, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 74, + "column": 33, + "endLine": 74, + "endColumn": 50, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 76, + "column": 5, + "endLine": 76, + "endColumn": 14, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 77, + "column": 32, + "endLine": 77, + "endColumn": 41, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 78, + "column": 19, + "endLine": 78, + "endColumn": 36, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 52, + "column": 9, + "endLine": 52, + "endColumn": 22, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 52, + "column": 21, + "endLine": 52, + "endColumn": 22, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 75, + "column": 11, + "endLine": 75, + "endColumn": 19, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 88, + "column": 5, + "endLine": 88, + "endColumn": 32, + "problem": "ThrowStatement", + "suggest": "", + "rule": "\"throw\" statements cannot accept values of arbitrary types (arkts-limited-throw)", + "severity": "ERROR" + }, + { + "line": 88, + "column": 29, + "endLine": 88, + "endColumn": 30, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 92, + "column": 9, + "endLine": 92, + "endColumn": 28, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 95, + "column": 16, + "endLine": 95, + "endColumn": 36, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 99, + "column": 35, + "endLine": 99, + "endColumn": 41, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 103, + "column": 5, + "endLine": 103, + "endColumn": 24, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 103, + "column": 35, + "endLine": 103, + "endColumn": 41, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 105, + "column": 5, + "endLine": 105, + "endColumn": 24, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 105, + "column": 93, + "endLine": 105, + "endColumn": 99, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 107, + "column": 5, + "endLine": 107, + "endColumn": 24, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 107, + "column": 129, + "endLine": 107, + "endColumn": 149, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 107, + "column": 160, + "endLine": 107, + "endColumn": 166, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 109, + "column": 5, + "endLine": 109, + "endColumn": 24, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 109, + "column": 129, + "endLine": 109, + "endColumn": 149, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 111, + "column": 6, + "endLine": 111, + "endColumn": 17, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 112, + "column": 33, + "endLine": 112, + "endColumn": 44, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 114, + "column": 5, + "endLine": 114, + "endColumn": 14, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 115, + "column": 32, + "endLine": 115, + "endColumn": 41, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 116, + "column": 19, + "endLine": 116, + "endColumn": 30, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 90, + "column": 9, + "endLine": 90, + "endColumn": 22, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 90, + "column": 21, + "endLine": 90, + "endColumn": 22, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 113, + "column": 11, + "endLine": 113, + "endColumn": 19, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 153, + "column": 28, + "endLine": 153, + "endColumn": 34, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 158, + "column": 35, + "endLine": 158, + "endColumn": 41, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 161, + "column": 42, + "endLine": 161, + "endColumn": 48, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 162, + "column": 100, + "endLine": 162, + "endColumn": 106, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 164, + "column": 92, + "endLine": 164, + "endColumn": 98, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 164, + "column": 180, + "endLine": 164, + "endColumn": 186, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 170, + "column": 5, + "endLine": 170, + "endColumn": 14, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 171, + "column": 32, + "endLine": 171, + "endColumn": 41, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 176, + "column": 32, + "endLine": 176, + "endColumn": 42, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 148, + "column": 9, + "endLine": 148, + "endColumn": 22, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 148, + "column": 21, + "endLine": 148, + "endColumn": 22, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 169, + "column": 11, + "endLine": 169, + "endColumn": 19, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 190, + "column": 28, + "endLine": 190, + "endColumn": 34, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 195, + "column": 35, + "endLine": 195, + "endColumn": 41, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 198, + "column": 42, + "endLine": 198, + "endColumn": 48, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 199, + "column": 100, + "endLine": 199, + "endColumn": 106, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 201, + "column": 79, + "endLine": 201, + "endColumn": 92, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 201, + "column": 175, + "endLine": 201, + "endColumn": 181, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 207, + "column": 5, + "endLine": 207, + "endColumn": 14, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 208, + "column": 32, + "endLine": 208, + "endColumn": 41, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 213, + "column": 32, + "endLine": 213, + "endColumn": 42, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, + { + "line": 185, + "column": 9, + "endLine": 185, + "endColumn": 22, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 185, + "column": 21, + "endLine": 185, + "endColumn": 22, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 206, + "column": 11, + "endLine": 206, + "endColumn": 19, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 38, + "column": 3, + "endLine": 38, + "endColumn": 6, + "problem": "StrictDiagnostic", + "suggest": "Property 'msg' has no initializer and is not definitely assigned in the constructor.", + "rule": "Property 'msg' has no initializer and is not definitely assigned in the constructor.", + "severity": "ERROR" + }, + { + "line": 39, + "column": 3, + "endLine": 39, + "endColumn": 7, + "problem": "StrictDiagnostic", + "suggest": "Property 'code' has no initializer and is not definitely assigned in the constructor.", + "rule": "Property 'code' has no initializer and is not definitely assigned in the constructor.", + "severity": "ERROR" + }, + { + "line": 43, + "column": 3, + "endLine": 43, + "endColumn": 6, + "problem": "StrictDiagnostic", + "suggest": "Property 'msg' has no initializer and is not definitely assigned in the constructor.", + "rule": "Property 'msg' has no initializer and is not definitely assigned in the constructor.", + "severity": "ERROR" + }, + { + "line": 44, + "column": 3, + "endLine": 44, + "endColumn": 7, + "problem": "StrictDiagnostic", + "suggest": "Property 'code' has no initializer and is not definitely assigned in the constructor.", + "rule": "Property 'code' has no initializer and is not definitely assigned in the constructor.", + "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/main/ts-like-catch-type.ets.json b/ets2panda/linter/test/main/ts-like-catch-type.ets.json index 50c51fe194..e5a6b2de81 100644 --- a/ets2panda/linter/test/main/ts-like-catch-type.ets.json +++ b/ets2panda/linter/test/main/ts-like-catch-type.ets.json @@ -15,14 +15,114 @@ ], "result": [ { - "line": 32, + "line": 33, "column": 10, - "endLine": 32, + "endLine": 33, "endColumn": 28, "problem": "CatchWithUnsupportedType", "suggest": "", "rule": "Type annotation in catch clause is not supported (arkts-no-types-in-catch)", "severity": "ERROR" + }, + { + "line": 50, + "column": 5, + "endLine": 50, + "endColumn": 38, + "problem": "ThrowStatement", + "suggest": "", + "rule": "\"throw\" statements cannot accept values of arbitrary types (arkts-limited-throw)", + "severity": "ERROR" + }, + { + "line": 75, + "column": 11, + "endLine": 75, + "endColumn": 19, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 88, + "column": 5, + "endLine": 88, + "endColumn": 32, + "problem": "ThrowStatement", + "suggest": "", + "rule": "\"throw\" statements cannot accept values of arbitrary types (arkts-limited-throw)", + "severity": "ERROR" + }, + { + "line": 113, + "column": 11, + "endLine": 113, + "endColumn": 19, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 169, + "column": 11, + "endLine": 169, + "endColumn": 19, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 206, + "column": 11, + "endLine": 206, + "endColumn": 19, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 38, + "column": 3, + "endLine": 38, + "endColumn": 6, + "problem": "StrictDiagnostic", + "suggest": "Property 'msg' has no initializer and is not definitely assigned in the constructor.", + "rule": "Property 'msg' has no initializer and is not definitely assigned in the constructor.", + "severity": "ERROR" + }, + { + "line": 39, + "column": 3, + "endLine": 39, + "endColumn": 7, + "problem": "StrictDiagnostic", + "suggest": "Property 'code' has no initializer and is not definitely assigned in the constructor.", + "rule": "Property 'code' has no initializer and is not definitely assigned in the constructor.", + "severity": "ERROR" + }, + { + "line": 43, + "column": 3, + "endLine": 43, + "endColumn": 6, + "problem": "StrictDiagnostic", + "suggest": "Property 'msg' has no initializer and is not definitely assigned in the constructor.", + "rule": "Property 'msg' has no initializer and is not definitely assigned in the constructor.", + "severity": "ERROR" + }, + { + "line": 44, + "column": 3, + "endLine": 44, + "endColumn": 7, + "problem": "StrictDiagnostic", + "suggest": "Property 'code' has no initializer and is not definitely assigned in the constructor.", + "rule": "Property 'code' has no initializer and is not definitely assigned in the constructor.", + "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/main/ts-like-catch-type111.ts b/ets2panda/linter/test/main/ts-like-catch-type111.ts new file mode 100644 index 0000000000..4c483947ad --- /dev/null +++ b/ets2panda/linter/test/main/ts-like-catch-type111.ts @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +export class AError extends Error { + customProp: string; + constructor(message: string) { + super(message); + this.customProp = "custom"; + } +} + +export class AError1 extends Error { + customProp: string; + constructor(message: string) { + super(message); + this.customProp = "custom"; + } +} + +export class BError { + msg: string; + code: number; + constructor(msg: string, code: number) { + this.msg = msg; + this.code = code; + } +} + +export class BError1 { + msg: string; + code: number; + constructor(msg: string, code: number) { + this.msg = msg; + this.code = code; + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/ts-like-catch-type111.ts.args.json b/ets2panda/linter/test/main/ts-like-catch-type111.ts.args.json new file mode 100644 index 0000000000..b87ffd2bb3 --- /dev/null +++ b/ets2panda/linter/test/main/ts-like-catch-type111.ts.args.json @@ -0,0 +1,17 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "commonArgs": "--no-check-ts-as-source" +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/ts-like-catch-type111.ts.json b/ets2panda/linter/test/main/ts-like-catch-type111.ts.json new file mode 100644 index 0000000000..ca88f857e9 --- /dev/null +++ b/ets2panda/linter/test/main/ts-like-catch-type111.ts.json @@ -0,0 +1,17 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [] +} \ No newline at end of file -- Gitee