diff --git a/ets2panda/linter/src/lib/FaultAttrs.ts b/ets2panda/linter/src/lib/FaultAttrs.ts index c183485e36625039dc9841133f3648365539596e..a7cf470e6d842666d376993fb0516288d30311dd 100644 --- a/ets2panda/linter/src/lib/FaultAttrs.ts +++ b/ets2panda/linter/src/lib/FaultAttrs.ts @@ -266,4 +266,4 @@ faultsAttrs[FaultID.NumericBigintCompare] = new FaultAttributes(376); faultsAttrs[FaultID.NondecimalBigint] = new FaultAttributes(377); faultsAttrs[FaultID.UnsupportOperator] = new FaultAttributes(378); faultsAttrs[FaultID.StateStylesBlockNeedArrowFunc] = new FaultAttributes(381); -faultsAttrs[FaultID.PromiseVoidNeedResolveArg] = new FaultAttributes(382); \ No newline at end of file +faultsAttrs[FaultID.PromiseVoidNeedResolveArg] = new FaultAttributes(382); diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index 176064982873e47fdee988a27d5cbc6353905d4f..2d8e5b93d48454f71312ae5766ad88245ae77000 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -157,6 +157,9 @@ 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 type { BaseClassConstructorInfo, ConstructorParameter, ExtendedIdentifierInfo } from './utils/consts/Types'; +import { ExtendedIdentifierType } from './utils/consts/Types'; +import { STRING_ERROR_LITERAL } from './utils/consts/Literals'; interface InterfaceSymbolTypeResult { propNames: string[]; @@ -8924,7 +8927,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { * @param node The HeritageClause node (extends clause) to analyze. */ private handleMissingSuperCallInExtendedClass(node: ts.HeritageClause): void { - if (!this.options.arkts2 || !this.useStatic) { + if (!this.options.arkts2) { return; } @@ -8933,78 +8936,249 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return; } - // Get the parent class declaration (what the child class extends) - const parentClass = this.getParentClassDeclaration(node); - if (!parentClass) { + if (!ts.isClassDeclaration(node.parent)) { return; } - // If parent class has a parameterless constructor (or no constructor at all), child is fine - if (TypeScriptLinter.parentHasParameterlessConstructor(parentClass)) { + /* + * Get the parent class declaration (what the child class extends) + * This could be a stdlib error type + */ + const identInfo = this.getExtendedIdentifiersInfo(node); + if (identInfo.type === ExtendedIdentifierType.UNKNOWN) { + // if it's unknown return return; } - // The child class node (the one extending) - const childClass = node.parent; - if (!ts.isClassDeclaration(childClass)) { + if (identInfo.type === ExtendedIdentifierType.ERROR) { + this.handleErrorClassExtend(node.parent); + // handled error case return return; } - // Look for child class constructor - const childConstructor = childClass.members.find(ts.isConstructorDeclaration); + if (identInfo.type === ExtendedIdentifierType.CLASS) { + // If it's class, get the constructor's parameters and match against it. + const extendedClassInfo = this.extractExtendedClassConstructorInfo(identInfo.decl); + if (!extendedClassInfo) { + return; + } - /* - * If child has no constructor → error (super() cannot be called) - * If child constructor exists but does not contain super() → error - */ - if (!childConstructor?.body || !TypeScriptLinter.childHasSuperCall(childConstructor)) { - this.incrementCounters(node, FaultID.MissingSuperCall); + this.handleExtendCustomClass(node.parent, extendedClassInfo); } } - /** - * Retrieves the parent class declaration node from an extends heritage clause. - */ - private getParentClassDeclaration(node: ts.HeritageClause): ts.ClassDeclaration | undefined { - const parentExpr = node.types[0]?.expression; - if (!parentExpr) { + private handleExtendCustomClass( + classDecl: ts.ClassDeclaration, + extendedClassInfo: Set + ): void { + const superCall = TypeScriptLinter.checkIfSuperCallExists(classDecl); + if (!superCall) { + this.incrementCounters(classDecl, FaultID.MissingSuperCall); + return; + } + + outer: for (const ctorParams of extendedClassInfo) { + const matches: boolean[] = []; + if (superCall.arguments.length > ctorParams.length) { + continue; + } + + for (const [idx, param] of ctorParams.entries()) { + const argument = superCall.arguments[idx]; + if (!param.isOptional && !argument) { + matches[idx] = false; + continue outer; + } + + if (!argument && param.isOptional) { + matches[idx] = true; + continue; + } + if (argument !== undefined) { + matches[idx] = this.checkIfArgumentAndParamMatches(param, argument); + if (!matches[idx]) { + continue outer; + } + } + } + + if ( + matches.some((val) => { + return !val; + }) + ) { + continue; + } + return; + } + + this.incrementCounters(classDecl, FaultID.MissingSuperCall); + } + + private checkIfArgumentAndParamMatches(param: ConstructorParameter, argument: ts.Expression): boolean { + const typeNode = this.tsTypeChecker.getTypeAtLocation(argument); + const typeString = this.tsTypeChecker.typeToString(typeNode); + + if (param.type.includes(STRINGLITERAL_STRING) && argument.kind === ts.SyntaxKind.StringLiteral) { + return true; + } + if (param.type.includes(NUMBER_LITERAL) && argument.kind === ts.SyntaxKind.NumericLiteral) { + return true; + } + + if ( + param.type.includes('boolean') && + (argument.kind === ts.SyntaxKind.FalseKeyword || argument.kind === ts.SyntaxKind.TrueKeyword) + ) { + return true; + } + + if (param.type === typeString) { + return true; + } + + return false; + } + + private handleErrorClassExtend(classDecl: ts.ClassDeclaration): void { + // if it's Error, the super method should be called with no arguments or a single string argument + const superCall = TypeScriptLinter.checkIfSuperCallExists(classDecl); + if (!superCall) { + this.incrementCounters(classDecl, FaultID.MissingSuperCall); + return; + } + + if (superCall.arguments.length > 1) { + + /* + * STD Error Type have two constructors + * either empty constructor which is just "Error" message + * or the message you provide, so if it's more than one argument provided, + * this should be raised as an issue + */ + this.incrementCounters(classDecl, FaultID.MissingSuperCall); + return; + } + + if (superCall.arguments.length === 1) { + const argument = superCall.arguments[0]; + const typeNode = this.tsTypeChecker.getTypeAtLocation(argument); + const typeString = this.tsTypeChecker.typeToString(typeNode); + + if (typeString === 'string' || ts.isStringLiteral(argument) || ts.isNumericLiteral(argument)) { + return; + } + this.incrementCounters(classDecl, FaultID.MissingSuperCall); + } + } + + private static checkIfSuperCallExists(classDecl: ts.ClassDeclaration): ts.CallExpression | undefined { + // check if current class has constructor + const constructor = TypeScriptLinter.getConstructorOfClass(classDecl); + if (!constructor) { return undefined; } - const parentSymbol = this.tsUtils.trueSymbolAtLocation(parentExpr); - return parentSymbol?.declarations?.find(ts.isClassDeclaration); + const superCallExpr = TypeScriptLinter.getSuperCallExpr(constructor); + if (!superCallExpr) { + return undefined; + } + + return superCallExpr; } /** - * Determines if a parent class has a parameterless constructor. - * If it has no constructor at all, that counts as parameterless. + * Extracts the type of the Identifier node from an extends heritage clause. */ - private static parentHasParameterlessConstructor(parentClass: ts.ClassDeclaration): boolean { - const constructors = parentClass.members.filter(ts.isConstructorDeclaration); - return ( - constructors.length === 0 || - constructors.some((ctor) => { - return ctor.parameters.length === 0; - }) - ); + private getExtendedIdentifiersInfo(node: ts.HeritageClause): ExtendedIdentifierInfo { + const extendedIdentifier = node.types[0]?.expression; + if (!extendedIdentifier) { + return { type: ExtendedIdentifierType.UNKNOWN }; + } + + const symbol = this.tsUtils.trueSymbolAtLocation(extendedIdentifier); + if (!symbol) { + return { type: ExtendedIdentifierType.UNKNOWN }; + } + + if (symbol.getName().includes(STRING_ERROR_LITERAL)) { + const declaration = this.tsUtils.getDeclarationNode(extendedIdentifier); + if (!declaration) { + return { type: ExtendedIdentifierType.ERROR }; + } + + if (declaration.getSourceFile().fileName !== this.sourceFile.fileName) { + return { type: ExtendedIdentifierType.ERROR }; + } + } + + const classDecl = symbol?.declarations?.find(ts.isClassDeclaration); + if (!classDecl) { + return { type: ExtendedIdentifierType.UNKNOWN }; + } + + return { type: ExtendedIdentifierType.CLASS, decl: classDecl }; } - private static childHasSuperCall(constructor: ts.ConstructorDeclaration): boolean { - let superCalled = false; + private extractExtendedClassConstructorInfo(extendedClass: ts.ClassDeclaration): BaseClassConstructorInfo { + const constructors = extendedClass.members.filter(ts.isConstructorDeclaration); + if (constructors.length === 0) { + return undefined; + } + const allConstructorInformation: BaseClassConstructorInfo = new Set(); + for (const ctor of constructors) { + const allParams: ConstructorParameter[] = []; + const parameters = ctor.parameters; + for (const param of parameters) { + const ident = param.name; + const name = ident.getText(); + const type = this.tsTypeChecker.getTypeAtLocation(ident); + const typeString = this.tsTypeChecker.typeToString(type); + const isOptional = !!param.questionToken; + const info = { name, type: typeString, isOptional }; + + allParams.push(info); + } + allConstructorInformation.add(allParams); + } + + return allConstructorInformation; + } + + private static getConstructorOfClass(classDecl: ts.ClassDeclaration): ts.ConstructorDeclaration | undefined { + if (classDecl.members.length === 0) { + return undefined; + } + + for (const member of classDecl.members) { + if (!ts.isConstructorDeclaration(member)) { + continue; + } + return member; + } + return undefined; + } + + private static getSuperCallExpr(constructor: ts.ConstructorDeclaration): ts.CallExpression | undefined { if (!constructor.body) { - return false; + return undefined; } - ts.forEachChild(constructor.body, (stmt) => { - if ( - ts.isExpressionStatement(stmt) && - ts.isCallExpression(stmt.expression) && - stmt.expression.expression.kind === ts.SyntaxKind.SuperKeyword - ) { - superCalled = true; + for (const stmt of constructor.body.statements) { + if (!ts.isExpressionStatement(stmt)) { + continue; } - }); - return superCalled; + const callExpr = stmt.expression; + if (!ts.isCallExpression(callExpr)) { + continue; + } + if (callExpr.expression.kind !== ts.SyntaxKind.SuperKeyword) { + continue; + } + + return callExpr; + } + return undefined; } private handleInterOpImportJs(importDecl: ts.ImportDeclaration): void { diff --git a/ets2panda/linter/src/lib/autofixes/Autofixer.ts b/ets2panda/linter/src/lib/autofixes/Autofixer.ts index 323536e1185788b40b59ff4687f5225a6c96bb04..1a87fe3eb9e1d9c6c5742e719139e56ccf8a666b 100644 --- a/ets2panda/linter/src/lib/autofixes/Autofixer.ts +++ b/ets2panda/linter/src/lib/autofixes/Autofixer.ts @@ -3701,18 +3701,17 @@ export class Autofixer { }); if (items.length > 1) { - const formattedList = items - .map((item) => { + const formattedList = items. + map((item) => { return ` ${item.trim()},`; - }) - .join('\n'); + }). + join('\n'); return `{\n${formattedList}\n}`; } return `{${importList}}`; }); } - fixStylesDecoratorGlobal( funcDecl: ts.FunctionDeclaration, calls: ts.Identifier[], @@ -4693,17 +4692,17 @@ export class Autofixer { const expr = callExpr.expression; const hasOptionalChain = !!callExpr.questionDotToken; - const replacementText = hasOptionalChain - ? `${expr.getText()}${callExpr.questionDotToken.getText()}unsafeCall` - : `${expr.getText()}.unsafeCall`; + const replacementText = hasOptionalChain ? + `${expr.getText()}${callExpr.questionDotToken.getText()}unsafeCall` : + `${expr.getText()}.unsafeCall`; - return [{ + return [ + { start: expr.getStart(), - end: hasOptionalChain - ? callExpr.questionDotToken.getEnd() - : expr.getEnd(), + end: hasOptionalChain ? callExpr.questionDotToken.getEnd() : expr.getEnd(), replacementText - }]; + } + ]; } private static createBuiltInTypeInitializer(type: ts.TypeReferenceNode): ts.Expression | undefined { @@ -4958,7 +4957,10 @@ export class Autofixer { return [{ start: insertPos, end: insertPos, replacementText: typeArgsText }]; } - private fixGenericCallNoTypeArgsForArrayType(node: ts.NewExpression, arrayTypeNode: ts.ArrayTypeNode): Autofix[] | undefined { + private fixGenericCallNoTypeArgsForArrayType( + node: ts.NewExpression, + arrayTypeNode: ts.ArrayTypeNode + ): Autofix[] | undefined { const elementTypeNode = arrayTypeNode.elementType; const srcFile = node.getSourceFile(); const typeArgsText = `<${this.printer.printNode(ts.EmitHint.Unspecified, elementTypeNode, srcFile)}>`; @@ -4966,7 +4968,10 @@ export class Autofixer { return [{ start: insertPos, end: insertPos, replacementText: typeArgsText }]; } - private fixGenericCallNoTypeArgsForUnionType(node: ts.NewExpression, unionType: ts.UnionTypeNode): Autofix[] | undefined { + private fixGenericCallNoTypeArgsForUnionType( + node: ts.NewExpression, + unionType: ts.UnionTypeNode + ): Autofix[] | undefined { const matchingTypes = unionType.types.filter((type) => { return ts.isTypeReferenceNode(type) && type.typeName.getText() === node.expression.getText(); }) as ts.TypeReferenceNode[]; diff --git a/ets2panda/linter/src/lib/utils/consts/ArkuiImportList.ts b/ets2panda/linter/src/lib/utils/consts/ArkuiImportList.ts index 3beae87577365b666ebf9f1722014fe7b1b260cf..f8ab0145c549c24f4e0c3526f3aa45adf7e98afc 100644 --- a/ets2panda/linter/src/lib/utils/consts/ArkuiImportList.ts +++ b/ets2panda/linter/src/lib/utils/consts/ArkuiImportList.ts @@ -1616,52 +1616,52 @@ export const arkuiImportList: Set = new Set([ ]); export const arkTsBuiltInTypeName: Set = new Set([ - 'Object', - 'Function', - 'Boolean', - 'Symbol', - 'Number', - 'BigInt', - 'Math', + 'Object', + 'Function', + 'Boolean', + 'Symbol', + 'Number', + 'BigInt', + 'Math', 'Date', - 'String', + 'String', 'RegExp', - 'Array', - 'Int8Array', - 'Uint8Array', - 'Uint8ClampedArray', - 'Int16Array', - 'Uint16Array', - 'Int32Array', + 'Array', + 'Int8Array', + 'Uint8Array', + 'Uint8ClampedArray', + 'Int16Array', + 'Uint16Array', + 'Int32Array', 'Uint32Array', 'Float32Array', 'Float64Array', - 'BigInt64Array', + 'BigInt64Array', 'BigUint64Array', - 'Map', - 'Set', + 'Map', + 'Set', 'WeakMap', 'WeakSet', - 'ArrayBuffer', - 'SharedArrayBuffer', - 'DataView', - 'JSON', - 'Promise', - 'Generator', - 'GeneratorFunction', + 'ArrayBuffer', + 'SharedArrayBuffer', + 'DataView', + 'JSON', + 'Promise', + 'Generator', + 'GeneratorFunction', 'AsyncFunction', - 'AsyncGenerator', - 'AsyncGeneratorFunction', - 'Reflect', - 'Proxy', + 'AsyncGenerator', + 'AsyncGeneratorFunction', + 'Reflect', + 'Proxy', 'Error', 'EvalError', - 'RangeError', - 'ReferenceError', - 'SyntaxError', - 'TypeError', - 'URIError', + 'RangeError', + 'ReferenceError', + 'SyntaxError', + 'TypeError', + 'URIError', 'AggregateError', 'Intl', 'WebAssembly' -]); \ No newline at end of file +]); diff --git a/ets2panda/linter/src/lib/utils/consts/ErrorProp.ts b/ets2panda/linter/src/lib/utils/consts/ErrorProp.ts index 212bb02ae4cc814bb5fb980a87d7876f15238c70..9bdc9da573b5a83dc98693ce7ff6138c52a7f8a4 100644 --- a/ets2panda/linter/src/lib/utils/consts/ErrorProp.ts +++ b/ets2panda/linter/src/lib/utils/consts/ErrorProp.ts @@ -1,4 +1,3 @@ - /* * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/ets2panda/linter/src/lib/utils/consts/Types.ts b/ets2panda/linter/src/lib/utils/consts/Types.ts new file mode 100644 index 0000000000000000000000000000000000000000..86abf3d58c423b9fc86627e59255ae2f830f5e3e --- /dev/null +++ b/ets2panda/linter/src/lib/utils/consts/Types.ts @@ -0,0 +1,37 @@ +/* + * 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 type { ClassDeclaration } from 'typescript'; + +export enum ExtendedIdentifierType { + UNKNOWN, + CLASS, + ERROR +} + +export type ExtendedIdentifierInfo = + | { + type: ExtendedIdentifierType.UNKNOWN | ExtendedIdentifierType.ERROR; + } + | { type: ExtendedIdentifierType.CLASS; decl: ClassDeclaration }; + +export type ConstructorParameter = { + name: string; + isOptional: boolean; + type: string; +}; + +export type ParameterName = string; + +export type BaseClassConstructorInfo = Set | undefined; diff --git a/ets2panda/linter/src/lib/utils/consts/WorkloadRelatedConst.ts b/ets2panda/linter/src/lib/utils/consts/WorkloadRelatedConst.ts index c0c5efc0cc019faef4845c53ba7dde729c9e4f7b..676b1fb1e73e634c72dae268c284e2e1569806e0 100644 --- a/ets2panda/linter/src/lib/utils/consts/WorkloadRelatedConst.ts +++ b/ets2panda/linter/src/lib/utils/consts/WorkloadRelatedConst.ts @@ -17,4 +17,4 @@ export const AVERAGE_LINE_FOR_REPAIRE_RULE_COEFFICIENT = 3; export const TEST_DEBUG_WORKLOAD_COEFFICIENT = 1.2; -export const NPAI_REPAIRE_WORKLOADA_COEFFICIEN = 0.2; \ No newline at end of file +export const NPAI_REPAIRE_WORKLOADA_COEFFICIEN = 0.2; diff --git a/ets2panda/linter/test/main/explicit_function_type.ets b/ets2panda/linter/test/main/explicit_function_type.ets index c42f90e3fbebdbd28ff66b836d2e4dad6853d178..45278cb9e486674598a43560341ba62dba19696b 100755 --- a/ets2panda/linter/test/main/explicit_function_type.ets +++ b/ets2panda/linter/test/main/explicit_function_type.ets @@ -75,8 +75,8 @@ class I24 { constructor(par: Function, par1?: string) {} } class I24_1 extends I24 { - constructor() { - super(Function) + constructor(par: Function) { + super(par) } } @@ -177,4 +177,4 @@ fn29[1](); SysApiWrapper.setTimeout = (handler: Function | string, delay?: number): number => { (handler as Function)?.(); return Math.random(); -} \ No newline at end of file +} diff --git a/ets2panda/linter/test/main/explicit_function_type.ets.arkts2.json b/ets2panda/linter/test/main/explicit_function_type.ets.arkts2.json old mode 100755 new mode 100644 index 34273528033e6cc174e71dd6df5e600dc2e94486..c771599a288f8688f72c86937b8e2daeca646243 --- a/ets2panda/linter/test/main/explicit_function_type.ets.arkts2.json +++ b/ets2panda/linter/test/main/explicit_function_type.ets.arkts2.json @@ -74,16 +74,6 @@ "rule": "Classes cannot be used as objects (arkts-no-classes-as-obj)", "severity": "ERROR" }, - { - "line": 79, - "column": 11, - "endLine": 79, - "endColumn": 19, - "problem": "ClassAsObjectError", - "suggest": "", - "rule": "Classes cannot be used as objects (arkts-no-classes-as-obj)", - "severity": "ERROR" - }, { "line": 93, "column": 11, @@ -355,4 +345,4 @@ "severity": "ERROR" } ] -} \ No newline at end of file +} diff --git a/ets2panda/linter/test/main/explicit_function_type.ets.autofix.json b/ets2panda/linter/test/main/explicit_function_type.ets.autofix.json index 9512b29aac946435a720b46d28464e7f675028ab..968aec7d48dbc2f34435f9d99353c7421f6021ed 100644 --- a/ets2panda/linter/test/main/explicit_function_type.ets.autofix.json +++ b/ets2panda/linter/test/main/explicit_function_type.ets.autofix.json @@ -1,6 +1,6 @@ { "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Copyright (c) 2024-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", @@ -129,16 +129,6 @@ "rule": "Classes cannot be used as objects (arkts-no-classes-as-obj)", "severity": "ERROR" }, - { - "line": 79, - "column": 11, - "endLine": 79, - "endColumn": 19, - "problem": "ClassAsObjectError", - "suggest": "", - "rule": "Classes cannot be used as objects (arkts-no-classes-as-obj)", - "severity": "ERROR" - }, { "line": 93, "column": 11, @@ -147,8 +137,8 @@ "problem": "NumericSemantics", "autofix": [ { - "start": 2073, - "end": 2074, + "start": 2081, + "end": 2082, "replacementText": "2.0", "line": 93, "column": 11, @@ -178,8 +168,8 @@ "problem": "NumericSemantics", "autofix": [ { - "start": 2550, - "end": 2551, + "start": 2558, + "end": 2559, "replacementText": "1.0", "line": 118, "column": 26, @@ -199,8 +189,8 @@ "problem": "NumericSemantics", "autofix": [ { - "start": 2553, - "end": 2554, + "start": 2561, + "end": 2562, "replacementText": "2.0", "line": 118, "column": 29, @@ -220,8 +210,8 @@ "problem": "NumericSemantics", "autofix": [ { - "start": 2556, - "end": 2557, + "start": 2564, + "end": 2565, "replacementText": "3.0", "line": 118, "column": 32, @@ -281,8 +271,8 @@ "problem": "NumericSemantics", "autofix": [ { - "start": 2719, - "end": 2720, + "start": 2727, + "end": 2728, "replacementText": "1.0", "line": 128, "column": 31, @@ -322,8 +312,8 @@ "problem": "NumericSemantics", "autofix": [ { - "start": 2768, - "end": 2769, + "start": 2776, + "end": 2777, "replacementText": "1.0", "line": 128, "column": 80, @@ -353,8 +343,8 @@ "problem": "NumericSemantics", "autofix": [ { - "start": 2849, - "end": 2850, + "start": 2857, + "end": 2858, "replacementText": "1.0", "line": 133, "column": 10, @@ -374,8 +364,8 @@ "problem": "ExplicitFunctionType", "autofix": [ { - "start": 2921, - "end": 2929, + "start": 2929, + "end": 2937, "replacementText": "callback.unsafeCall", "line": 139, "column": 3, @@ -395,8 +385,8 @@ "problem": "NumericSemantics", "autofix": [ { - "start": 2995, - "end": 2996, + "start": 3003, + "end": 3004, "replacementText": "1.0", "line": 142, "column": 41, @@ -446,8 +436,8 @@ "problem": "ExplicitFunctionType", "autofix": [ { - "start": 3458, - "end": 3462, + "start": 3466, + "end": 3470, "replacementText": "curr.unsafeCall", "line": 160, "column": 62, @@ -467,8 +457,8 @@ "problem": "ExplicitFunctionType", "autofix": [ { - "start": 3463, - "end": 3467, + "start": 3471, + "end": 3475, "replacementText": "prev.unsafeCall", "line": 160, "column": 67, @@ -488,8 +478,8 @@ "problem": "ExplicitFunctionType", "autofix": [ { - "start": 3586, - "end": 3588, + "start": 3594, + "end": 3596, "replacementText": "f1.unsafeCall", "line": 166, "column": 1, @@ -509,8 +499,8 @@ "problem": "ExplicitFunctionType", "autofix": [ { - "start": 3656, - "end": 3663, + "start": 3664, + "end": 3671, "replacementText": "ab3.fn3.unsafeCall", "line": 172, "column": 1, @@ -530,8 +520,8 @@ "problem": "ExplicitFunctionType", "autofix": [ { - "start": 3697, - "end": 3704, + "start": 3705, + "end": 3712, "replacementText": "fn29[1].unsafeCall", "line": 175, "column": 1, @@ -561,8 +551,8 @@ "problem": "ExplicitFunctionType", "autofix": [ { - "start": 3796, - "end": 3819, + "start": 3804, + "end": 3827, "replacementText": "(handler as Function)?.unsafeCall", "line": 178, "column": 3, @@ -575,4 +565,4 @@ "severity": "ERROR" } ] -} \ No newline at end of file +} diff --git a/ets2panda/linter/test/main/explicit_function_type.ets.json b/ets2panda/linter/test/main/explicit_function_type.ets.json old mode 100755 new mode 100644 index d1381869898d689771df539f100eaacd386998a0..a3424dbdf251cdce4f4e0e516879ffb8aed62018 --- a/ets2panda/linter/test/main/explicit_function_type.ets.json +++ b/ets2panda/linter/test/main/explicit_function_type.ets.json @@ -1,19 +1,19 @@ { - "copyright": [ - "Copyright (c) 2024-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": [ + "copyright": [ + "Copyright (c) 2024-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": 16, "column": 20, @@ -44,16 +44,6 @@ "rule": "Classes cannot be used as objects (arkts-no-classes-as-obj)", "severity": "WARNING" }, - { - "line": 79, - "column": 11, - "endLine": 79, - "endColumn": 19, - "problem": "ClassAsObject", - "suggest": "", - "rule": "Classes cannot be used as objects (arkts-no-classes-as-obj)", - "severity": "WARNING" - }, { "line": 118, "column": 16, @@ -75,4 +65,4 @@ "severity": "ERROR" } ] -} \ No newline at end of file +} diff --git a/ets2panda/linter/test/main/explicit_function_type.ets.migrate.ets b/ets2panda/linter/test/main/explicit_function_type.ets.migrate.ets index c5ecffb429d302f3dbed81aa57b822a0e37cfc5c..94cd68114ea4beab2b014c9c677be27fbdeb2aaf 100644 --- a/ets2panda/linter/test/main/explicit_function_type.ets.migrate.ets +++ b/ets2panda/linter/test/main/explicit_function_type.ets.migrate.ets @@ -75,8 +75,8 @@ class I24 { constructor(par: Function, par1?: string) {} } class I24_1 extends I24 { - constructor() { - super(Function) + constructor(par: Function) { + super(par) } } @@ -177,4 +177,4 @@ fn29[1].unsafeCall(); SysApiWrapper.setTimeout = (handler: Function | string, delay?: number): number => { (handler as Function)?.unsafeCall(); return Math.random(); -} \ No newline at end of file +} diff --git a/ets2panda/linter/test/main/explicit_function_type.ets.migrate.json b/ets2panda/linter/test/main/explicit_function_type.ets.migrate.json index b4e8db486eeaedea242edff205286dd79e155a9f..43ff503ff452b5785fb4a5a30526b3c68c8353e0 100644 --- a/ets2panda/linter/test/main/explicit_function_type.ets.migrate.json +++ b/ets2panda/linter/test/main/explicit_function_type.ets.migrate.json @@ -24,16 +24,6 @@ "rule": "Classes cannot be used as objects (arkts-no-classes-as-obj)", "severity": "ERROR" }, - { - "line": 79, - "column": 11, - "endLine": 79, - "endColumn": 19, - "problem": "ClassAsObjectError", - "suggest": "", - "rule": "Classes cannot be used as objects (arkts-no-classes-as-obj)", - "severity": "ERROR" - }, { "line": 118, "column": 16, @@ -155,4 +145,4 @@ "severity": "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 b72ff900ba7ccd4a3199f642e70b74ee16525763..8ed64f688b1637ca397321e8a120fb5b1d0c1bba 100644 --- a/ets2panda/linter/test/main/object_literals_properties.ets.arkts2.json +++ b/ets2panda/linter/test/main/object_literals_properties.ets.arkts2.json @@ -1164,6 +1164,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 216, + "column": 1, + "endLine": 218, + "endColumn": 2, + "problem": "MissingSuperCall", + "suggest": "", + "rule": "The subclass constructor must call the parent class's parametered constructor (arkts-subclass-must-call-super-constructor-with-args)", + "severity": "ERROR" + }, { "line": 219, "column": 18, @@ -1196,9 +1206,9 @@ }, { "line": 226, - "column": 16, - "endLine": 226, - "endColumn": 29, + "column": 1, + "endLine": 228, + "endColumn": 2, "problem": "MissingSuperCall", "suggest": "", "rule": "The subclass constructor must call the parent class's parametered constructor (arkts-subclass-must-call-super-constructor-with-args)", 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 ccf6076bdc6c00243b5abe01469d556165d4bf23..bbb319af18b8c79801bc869be8d35b1cd69507fd 100644 --- a/ets2panda/linter/test/main/object_literals_properties.ets.autofix.json +++ b/ets2panda/linter/test/main/object_literals_properties.ets.autofix.json @@ -2072,6 +2072,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 216, + "column": 1, + "endLine": 218, + "endColumn": 2, + "problem": "MissingSuperCall", + "suggest": "", + "rule": "The subclass constructor must call the parent class's parametered constructor (arkts-subclass-must-call-super-constructor-with-args)", + "severity": "ERROR" + }, { "line": 219, "column": 18, @@ -2135,9 +2145,9 @@ }, { "line": 226, - "column": 16, - "endLine": 226, - "endColumn": 29, + "column": 1, + "endLine": 228, + "endColumn": 2, "problem": "MissingSuperCall", "suggest": "", "rule": "The subclass constructor must call the parent class's parametered constructor (arkts-subclass-must-call-super-constructor-with-args)", 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 cb4957616222487070cf53339fedcabe2157fecb..675cc2476a8a98d88b903bea26dcf8ab85279545 100644 --- a/ets2panda/linter/test/main/object_literals_properties.ets.migrate.json +++ b/ets2panda/linter/test/main/object_literals_properties.ets.migrate.json @@ -284,11 +284,21 @@ "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", "severity": "ERROR" }, + { + "line": 274, + "column": 1, + "endLine": 276, + "endColumn": 2, + "problem": "MissingSuperCall", + "suggest": "", + "rule": "The subclass constructor must call the parent class's parametered constructor (arkts-subclass-must-call-super-constructor-with-args)", + "severity": "ERROR" + }, { "line": 286, - "column": 16, - "endLine": 286, - "endColumn": 29, + "column": 1, + "endLine": 288, + "endColumn": 2, "problem": "MissingSuperCall", "suggest": "", "rule": "The subclass constructor must call the parent class's parametered constructor (arkts-subclass-must-call-super-constructor-with-args)", @@ -314,6 +324,16 @@ "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", "severity": "ERROR" }, + { + "line": 303, + "column": 1, + "endLine": 305, + "endColumn": 2, + "problem": "MissingSuperCall", + "suggest": "", + "rule": "The subclass constructor must call the parent class's parametered constructor (arkts-subclass-must-call-super-constructor-with-args)", + "severity": "ERROR" + }, { "line": 342, "column": 5, diff --git a/ets2panda/linter/test/main/subclass_super_call.ets b/ets2panda/linter/test/main/subclass_super_call.ets index d275725c9ced20f3df8eb301562897c1f14e3845..7e8034806431ea58a666b1a78cf468910585e6f3 100644 --- a/ets2panda/linter/test/main/subclass_super_call.ets +++ b/ets2panda/linter/test/main/subclass_super_call.ets @@ -36,4 +36,50 @@ class E extends A { // NO ERROR constructor is called } } -class F extends B {} // NO ERROR +class Base { + constructor(a?: string) {} + constructor(a: string, b:string, c?:string) {} +} + +class Foo extends Base { + constructor() { + super() + } +} + +class Bar extends Base { + constructor() { + super("foo") + } +} + +class FooTheSecond extends Base { + constructor() { + super("Foo", "Bar", "Baz") + } +} + +class FaultyBar extends Base { + constructor() { + super(12) // should error + } +} + + +class FaultyFooTheSecond extends Base { + constructor() { + super("foo", "bar", false) // should error + } +} + +class EpicFoo extends Error { + constructor() { + super() + } +} + +class EpicBar extends Error { + constructor() { + super("foo") + } +} diff --git a/ets2panda/linter/test/main/subclass_super_call.ets.args.json b/ets2panda/linter/test/main/subclass_super_call.ets.args.json index 948b846fe04969bf5ccbe8bd9dc4a18559ce0c2c..bc4d2071daf6e9354e711c3b74b6be2b56659066 100644 --- a/ets2panda/linter/test/main/subclass_super_call.ets.args.json +++ b/ets2panda/linter/test/main/subclass_super_call.ets.args.json @@ -14,6 +14,6 @@ "limitations under the License." ], "mode": { - "arkts2": "" + "arkts2": "" } } diff --git a/ets2panda/linter/test/main/subclass_super_call.ets.arkts2.json b/ets2panda/linter/test/main/subclass_super_call.ets.arkts2.json index 289a83337b8aabfabe08c43a0ade753e39dfbf7b..83dc3263ef767e446928b46dd6881543375a5bd2 100644 --- a/ets2panda/linter/test/main/subclass_super_call.ets.arkts2.json +++ b/ets2panda/linter/test/main/subclass_super_call.ets.arkts2.json @@ -1,38 +1,108 @@ { - "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": 9, - "endLine": 27, - "endColumn": 18, - "problem": "MissingSuperCall", - "suggest": "", - "rule": "The subclass constructor must call the parent class's parametered constructor (arkts-subclass-must-call-super-constructor-with-args)", - "severity": "ERROR" - }, - { - "line": 29, - "column": 9, - "endLine": 29, - "endColumn": 18, - "problem": "MissingSuperCall", - "suggest": "", - "rule": "The subclass constructor must call the parent class's parametered constructor (arkts-subclass-must-call-super-constructor-with-args)", - "severity": "ERROR" - } - ] + "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": 1, + "endLine": 27, + "endColumn": 21, + "problem": "MissingSuperCall", + "suggest": "", + "rule": "The subclass constructor must call the parent class's parametered constructor (arkts-subclass-must-call-super-constructor-with-args)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 1, + "endLine": 31, + "endColumn": 2, + "problem": "MissingSuperCall", + "suggest": "", + "rule": "The subclass constructor must call the parent class's parametered constructor (arkts-subclass-must-call-super-constructor-with-args)", + "severity": "ERROR" + }, + { + "line": 40, + "column": 5, + "endLine": 40, + "endColumn": 31, + "problem": "TsOverload", + "suggest": "", + "rule": "Class TS overloading is not supported(arkts-no-ts-overload)", + "severity": "ERROR" + }, + { + "line": 41, + "column": 5, + "endLine": 41, + "endColumn": 51, + "problem": "TsOverload", + "suggest": "", + "rule": "Class TS overloading is not supported(arkts-no-ts-overload)", + "severity": "ERROR" + }, + { + "line": 62, + "column": 1, + "endLine": 66, + "endColumn": 2, + "problem": "MissingSuperCall", + "suggest": "", + "rule": "The subclass constructor must call the parent class's parametered constructor (arkts-subclass-must-call-super-constructor-with-args)", + "severity": "ERROR" + }, + { + "line": 64, + "column": 15, + "endLine": 64, + "endColumn": 17, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 69, + "column": 1, + "endLine": 73, + "endColumn": 2, + "problem": "MissingSuperCall", + "suggest": "", + "rule": "The subclass constructor must call the parent class's parametered constructor (arkts-subclass-must-call-super-constructor-with-args)", + "severity": "ERROR" + }, + { + "line": 77, + "column": 9, + "endLine": 77, + "endColumn": 14, + "problem": "BuiltinNoCtorFunc", + "suggest": "", + "rule": "API is not support ctor signature and func (arkts-builtin-cotr)", + "severity": "ERROR" + }, + { + "line": 83, + "column": 9, + "endLine": 83, + "endColumn": 14, + "problem": "BuiltinNoCtorFunc", + "suggest": "", + "rule": "API is not support ctor signature and func (arkts-builtin-cotr)", + "severity": "ERROR" + } + ] }