diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index e58892c5304b12d882aa65c1a7e5728daf368fb5..7b3b0ffe0d5e2b7f7089c2e62b4d86b2dc4a6af1 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -11554,24 +11554,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { instanceProps: new Map() }; - classDecl.members.forEach((member) => { - if (!ts.isPropertyDeclaration(member)) { - return; - } - - const propName = member.name.getText(); - const propType = this.tsTypeChecker.getTypeAtLocation(member); - const isStatic = member.modifiers?.some((m) => { - return m.kind === ts.SyntaxKind.StaticKeyword; - }); - - if (isStatic) { - result.staticProps.set(propName, propType); - } else { - result.instanceProps.set(propName, propType); - } - }); - + this.tsUtils.collectPropertiesFromClass(classDecl, result); return result; } diff --git a/ets2panda/linter/src/lib/utils/TsUtils.ts b/ets2panda/linter/src/lib/utils/TsUtils.ts index 738928269d0a778b945d0e0c0b9c49f2cf55b3c8..c7417e2425fac193338fead6af9f50d3c421d8f0 100644 --- a/ets2panda/linter/src/lib/utils/TsUtils.ts +++ b/ets2panda/linter/src/lib/utils/TsUtils.ts @@ -3816,4 +3816,55 @@ export class TsUtils { return false; } + + collectPropertiesFromClass( + classDecl: ts.ClassDeclaration, + result: { + staticProps: Map; + instanceProps: Map; + }, + isBase: boolean = false + ): void { + classDecl.members.forEach((member) => { + if (!ts.isPropertyDeclaration(member) || !member.name || !ts.isIdentifier(member.name)) { + return; + } + + const propName = member.name.text; + + const isPrivate = member.modifiers?.some((m) => { + return m.kind === ts.SyntaxKind.PrivateKeyword; + }); + if (isBase && isPrivate) { + return; + } + + const propType = this.tsTypeChecker.getTypeAtLocation(member); + const isStatic = member.modifiers?.some((m) => { + return m.kind === ts.SyntaxKind.StaticKeyword; + }); + + if (isStatic) { + result.staticProps.set(propName, propType); + } else { + result.instanceProps.set(propName, propType); + } + }); + + const heritage = classDecl.heritageClauses?.find((h) => { + return h.token === ts.SyntaxKind.ExtendsKeyword; + }); + if (heritage) { + const baseTypeNode = heritage?.types[0]; + if (baseTypeNode) { + const baseType = this.tsTypeChecker.getTypeAtLocation(baseTypeNode); + const baseSymbol = baseType.getSymbol(); + const declarations = baseSymbol?.getDeclarations(); + const baseClassDecl = declarations?.find(ts.isClassDeclaration); + if (baseClassDecl) { + this.collectPropertiesFromClass(baseClassDecl, result, true); + } + } + } + } } 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 7cdff3d524a3211820c8e0ecad1fe4f5692292f3..1c858dc1e1aac2057224f507ae790b707a338f32 100755 --- a/ets2panda/linter/test/main/no_ts_like_smart_type.ets +++ b/ets2panda/linter/test/main/no_ts_like_smart_type.ets @@ -193,4 +193,42 @@ class A { return this.b //error } } +} + +export class K { + _t:string + constructor(t:string) { + this._t = t; + } +} + +export class P extends K { + constructor(t:string){ + super(t) + } + toString(): string { + return this._t // legal + } +} + +export class H { + protected _t:string + constructor(t:string) { + this._t = t; + } +} + +export class T extends H { + constructor(t:string) { + super(t) + } +} + +export class N extends T { + constructor(t:string){ + super(t) + } + toString(): string { + return this._t // legal + } } \ No newline at end of file