diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index bc8354d803604501f91418e72860e8e406ec2f73..8aa978ca873c57180d247d795bf143fa089319b1 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -9947,21 +9947,9 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { for (const [idx, param] of ctorParams.entries()) { const argument = superCall.arguments[idx]; - if (!param.isOptional && !argument) { - matches[idx] = false; + if (!this.checkParameter(param, argument, matches, idx)) { 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 ( @@ -9977,6 +9965,51 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { this.incrementCounters(classDecl, FaultID.MissingSuperCall); } + private checkParameter( + param: ConstructorParameter, + argument: ts.Expression | undefined, + matches: boolean[], + idx: number + ): boolean { + if (!param.isOptional && !argument) { + matches[idx] = false; + return false; + } + + if (!argument && param.isOptional) { + matches[idx] = true; + return true; + } + + if (argument !== undefined) { + if (this.isEnumArgument(argument)) { + matches[idx] = true; + return true; + } + matches[idx] = this.checkIfArgumentAndParamMatches(param, argument); + return matches[idx]; + } + return true; + } + + private isEnumArgument(argument: ts.Expression): boolean { + if (!ts.isPropertyAccessExpression(argument)) { + return false; + } + + const leftSide = argument.expression; + const symbol = this.tsTypeChecker?.getSymbolAtLocation(leftSide); + + return ( + symbol?.declarations?.some((decl) => { + return ( + ts.isEnumDeclaration(decl) || + ts.isVariableDeclaration(decl) && decl.initializer && ts.isEnumDeclaration(decl.initializer) + ); + }) ?? false + ); + } + private checkIfArgumentAndParamMatches(param: ConstructorParameter, argument: ts.Expression): boolean { const typeNode = this.tsTypeChecker.getTypeAtLocation(argument); const typeString = this.tsTypeChecker.typeToString(typeNode); diff --git a/ets2panda/linter/test/main/subclass_super_call.ets b/ets2panda/linter/test/main/subclass_super_call.ets index 7e8034806431ea58a666b1a78cf468910585e6f3..2ed960ed9071cc0141abcf6db8a1abe4ff6985bb 100644 --- a/ets2panda/linter/test/main/subclass_super_call.ets +++ b/ets2panda/linter/test/main/subclass_super_call.ets @@ -83,3 +83,21 @@ class EpicBar extends Error { super("foo") } } + +export enum EEE { + E1, + E2, +} + +export class A { + protected _e:EEE + constructor(e: EEE) { + this._e = e; + } +} + +class B extends A { + constructor() { + super(EEE.E1) + } +}