From e81240bb3865b8192e0c53c19ea53c43deab3c8d Mon Sep 17 00:00:00 2001 From: liuqian Date: Thu, 21 Aug 2025 21:08:51 +0800 Subject: [PATCH] class-implement-interface-prop-getter-setter Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICTZ17 Signed-off-by: liuqian --- ets2panda/linter/rule-config.json | 3 +- ets2panda/linter/src/lib/CookBookMsg.ts | 3 +- ets2panda/linter/src/lib/FaultAttrs.ts | 1 + ets2panda/linter/src/lib/Problems.ts | 1 + ets2panda/linter/src/lib/TypeScriptLinter.ts | 75 ++++++++ .../builtin/builtin_class.ets.arkts2.json | 70 ++++++++ .../builtin_object_negative.ets.arkts2.json | 10 ++ .../builtin_object_positive.ets.arkts2.json | 10 ++ .../chip_group_api.ets.arkts2.json | 10 ++ .../deprecatedapi/swiper_api.ets.arkts2.json | 10 ++ ...-interface-prop-getter-setter_negative.ets | 86 ++++++++++ ...-prop-getter-setter_negative.ets.args.json | 19 +++ ...rop-getter-setter_negative.ets.arkts2.json | 68 ++++++++ ...rface-prop-getter-setter_negative.ets.json | 17 ++ ...-interface-prop-getter-setter_positive.ets | 88 ++++++++++ ...-prop-getter-setter_positive.ets.args.json | 19 +++ ...rop-getter-setter_positive.ets.arkts2.json | 19 +++ ...rface-prop-getter-setter_positive.ets.json | 17 ++ ..._class_field_type_matching.ets.arkts2.json | 20 +++ .../explicit_function_type.ets.arkts2.json | 10 ++ .../explicit_function_type.ets.autofix.json | 10 ++ .../explicit_function_type.ets.migrate.json | 10 ++ .../main/method_inheritance.ets.arkts2.json | 10 ++ .../main/method_overriding.ets.arkts2.json | 160 ++++++++++-------- ...ss_omit_interface_optional.ets.arkts2.json | 90 ++++++++++ .../limit_void_type_sdk2.ets.arkts2.json | 10 ++ 26 files changed, 774 insertions(+), 72 deletions(-) create mode 100644 ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_negative.ets create mode 100644 ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_negative.ets.args.json create mode 100644 ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_negative.ets.arkts2.json create mode 100644 ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_negative.ets.json create mode 100644 ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_positive.ets create mode 100644 ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_positive.ets.args.json create mode 100644 ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_positive.ets.arkts2.json create mode 100644 ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_positive.ets.json diff --git a/ets2panda/linter/rule-config.json b/ets2panda/linter/rule-config.json index 0c613f3a2f..a8aeb492a4 100644 --- a/ets2panda/linter/rule-config.json +++ b/ets2panda/linter/rule-config.json @@ -82,7 +82,8 @@ "arkts-no-large-numeric-literal", "arkts-no-instanceof-func", "arkts-no-unfixed-len-tuple", - "arkts-no-super-call-in-static-context" + "arkts-no-super-call-in-static-context", + "arkts-class-implement-interface-prop-getter-setter" ], "interop": [ "arkts-interop-js2s-inherit-js-class", diff --git a/ets2panda/linter/src/lib/CookBookMsg.ts b/ets2panda/linter/src/lib/CookBookMsg.ts index 7a3f6d4552..173aad1d1c 100644 --- a/ets2panda/linter/src/lib/CookBookMsg.ts +++ b/ets2panda/linter/src/lib/CookBookMsg.ts @@ -439,8 +439,9 @@ cookBookTag[409] = 'No optional tuple type (arkts-no-optional-tuple-type)'; cookBookTag[410] = 'Numeric literal exceeds allowed range (arkts-no-large-numeric-literal)'; cookBookTag[411] = '"instanceof" operator can\'t be applied to function (arkts-no-instanceof-func)'; cookBookTag[412] = 'No unfixed length tuple support (arkts-no-unfixed-len-tuple)'; - cookBookTag[413] = 'Subclass can\'t call members of super class in static context (arkts-no-super-call-in-static-context)'; +cookBookTag[414] = 'Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)'; + for (let i = 0; i <= cookBookTag.length; i++) { cookBookMsg[i] = ''; } diff --git a/ets2panda/linter/src/lib/FaultAttrs.ts b/ets2panda/linter/src/lib/FaultAttrs.ts index 7de7999b99..fcead177d6 100644 --- a/ets2panda/linter/src/lib/FaultAttrs.ts +++ b/ets2panda/linter/src/lib/FaultAttrs.ts @@ -311,3 +311,4 @@ faultsAttrs[FaultID.LargeNumericLiteral] = new FaultAttributes(410); faultsAttrs[FaultID.InstanceOfFunction] = new FaultAttributes(411); faultsAttrs[FaultID.unfixedTuple] = new FaultAttributes(412); faultsAttrs[FaultID.SuperInStaticContext] = new FaultAttributes(413); +faultsAttrs[FaultID.ClassImplementInterfacePropGetterSetter] = new FaultAttributes(414); diff --git a/ets2panda/linter/src/lib/Problems.ts b/ets2panda/linter/src/lib/Problems.ts index fd32b020c0..59a3444946 100644 --- a/ets2panda/linter/src/lib/Problems.ts +++ b/ets2panda/linter/src/lib/Problems.ts @@ -300,6 +300,7 @@ export enum FaultID { InstanceOfFunction, unfixedTuple, SuperInStaticContext, + ClassImplementInterfacePropGetterSetter, // this should always be last enum LAST_ID } diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index 317c4a8bf6..c10fd746ff 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -8717,6 +8717,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } }); this.handleInterfaceFieldImplementation(node); + this.handleClassImplementInterfacePropGetterSetter(node); this.handleMissingSuperCallInExtendedClass(node); this.handleFieldTypesMatchingBetweenDerivedAndBaseClass(node); this.checkReadonlyOverridesFromBase(node); @@ -8879,6 +8880,80 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return true; } + /** + * Checks if a class implements interface properties with both getter and setter methods. + * If a property is read - only, implementing only the getter method is acceptable. + * Otherwise, both getter and setter methods must be implemented. + */ + private handleClassImplementInterfacePropGetterSetter(clause: ts.HeritageClause): void { + if (clause.token !== ts.SyntaxKind.ImplementsKeyword) { + return; + } + const classDecl = clause.parent as ts.ClassDeclaration; + if (!ts.isClassDeclaration(classDecl) || !classDecl.name) { + return; + } + + for (const interfaceType of clause.types) { + const expr = interfaceType.expression; + if (!ts.isIdentifier(expr)) { + continue; + } + const sym = this.tsUtils.trueSymbolAtLocation(expr); + const interfaceDecl = sym?.declarations?.find(ts.isInterfaceDeclaration); + if (!interfaceDecl) { + continue; + } + // Gather all inherited interfaces + const allInterfaces = this.getAllInheritedInterfaces(interfaceDecl); + // If the class fails to implement any Getter or Setter, report once and exit + if (!this.classImplementsAllGetterSetter(classDecl, allInterfaces)) { + this.incrementCounters(classDecl.name, FaultID.ClassImplementInterfacePropGetterSetter); + return; + } + } + } + + private classImplementsAllGetterSetter(classDecl: ts.ClassDeclaration, interfaces: ts.InterfaceDeclaration[]): boolean { + void this; + + for (const intf of interfaces) { + for (const member of intf.members) { + if (ts.isPropertySignature(member) && ts.isIdentifier(member.name)) { + const name = member.name.text; + const isReadonly = TsUtils.hasModifier(member.modifiers, ts.SyntaxKind.ReadonlyKeyword); + + // Check if the Get method is implemented + const hasGetter = classDecl.members.some((m) => { + return ( + ts.isGetAccessorDeclaration(m) && + ts.isIdentifier(m.name) && + m.name.text === name + ); + }); + if (!hasGetter) { + return false; + } + + // If the property is not read-only, check if the Set method is implemented + if (!isReadonly) { + const hasSetter = classDecl.members.some((m) => { + return ( + ts.isSetAccessorDeclaration(m) && + ts.isIdentifier(m.name) && + m.name.text === name + ); + }); + if (!hasSetter) { + return false; + } + } + } + } + } + return true; + } + private isVariableReference(identifier: ts.Identifier): boolean { const symbol = this.tsTypeChecker.getSymbolAtLocation(identifier); return !!symbol && (symbol.flags & ts.SymbolFlags.Variable) !== 0; diff --git a/ets2panda/linter/test/builtin/builtin_class.ets.arkts2.json b/ets2panda/linter/test/builtin/builtin_class.ets.arkts2.json index d4f92e186a..d54b7c3b87 100755 --- a/ets2panda/linter/test/builtin/builtin_class.ets.arkts2.json +++ b/ets2panda/linter/test/builtin/builtin_class.ets.arkts2.json @@ -24,6 +24,16 @@ "rule": "API is not support use class in this API (arkts-builtin-final-class)", "severity": "ERROR" }, + { + "line": 16, + "column": 7, + "endLine": 16, + "endColumn": 17, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 16, "column": 47, @@ -84,6 +94,16 @@ "rule": "API is not support use class in this API (arkts-builtin-final-class)", "severity": "ERROR" }, + { + "line": 28, + "column": 7, + "endLine": 28, + "endColumn": 18, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 28, "column": 48, @@ -114,6 +134,16 @@ "rule": "API is not support use class in this API (arkts-builtin-final-class)", "severity": "ERROR" }, + { + "line": 31, + "column": 7, + "endLine": 31, + "endColumn": 20, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 31, "column": 51, @@ -164,6 +194,16 @@ "rule": "API is not support use class in this API (arkts-builtin-final-class)", "severity": "ERROR" }, + { + "line": 40, + "column": 7, + "endLine": 40, + "endColumn": 20, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 40, "column": 32, @@ -194,6 +234,16 @@ "rule": "API is not support use class in this API (arkts-builtin-final-class)", "severity": "ERROR" }, + { + "line": 43, + "column": 7, + "endLine": 43, + "endColumn": 23, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 43, "column": 57, @@ -284,6 +334,16 @@ "rule": "API is not support use class in this API (arkts-builtin-final-class)", "severity": "ERROR" }, + { + "line": 56, + "column": 7, + "endLine": 56, + "endColumn": 20, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 56, "column": 53, @@ -394,6 +454,16 @@ "rule": "API is not support use class in this API (arkts-builtin-final-class)", "severity": "ERROR" }, + { + "line": 65, + "column": 7, + "endLine": 65, + "endColumn": 15, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 65, "column": 43, diff --git a/ets2panda/linter/test/builtin/builtin_object_negative.ets.arkts2.json b/ets2panda/linter/test/builtin/builtin_object_negative.ets.arkts2.json index 29902703e0..8697457437 100755 --- a/ets2panda/linter/test/builtin/builtin_object_negative.ets.arkts2.json +++ b/ets2panda/linter/test/builtin/builtin_object_negative.ets.arkts2.json @@ -194,6 +194,16 @@ "rule": "API is not support ctor signature and func (arkts-builtin-cotr)", "severity": "ERROR" }, + { + "line": 48, + "column": 7, + "endLine": 48, + "endColumn": 11, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 48, "column": 23, diff --git a/ets2panda/linter/test/builtin/builtin_object_positive.ets.arkts2.json b/ets2panda/linter/test/builtin/builtin_object_positive.ets.arkts2.json index 7e7f373314..6717eddf6c 100755 --- a/ets2panda/linter/test/builtin/builtin_object_positive.ets.arkts2.json +++ b/ets2panda/linter/test/builtin/builtin_object_positive.ets.arkts2.json @@ -14,6 +14,16 @@ "limitations under the License." ], "result": [ + { + "line": 18, + "column": 7, + "endLine": 18, + "endColumn": 11, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 18, "column": 23, diff --git a/ets2panda/linter/test/deprecatedapi/chip_group_api.ets.arkts2.json b/ets2panda/linter/test/deprecatedapi/chip_group_api.ets.arkts2.json index 57125855d0..ee25874fe0 100644 --- a/ets2panda/linter/test/deprecatedapi/chip_group_api.ets.arkts2.json +++ b/ets2panda/linter/test/deprecatedapi/chip_group_api.ets.arkts2.json @@ -14,6 +14,16 @@ "limitations under the License." ], "result": [ + { + "line": 34, + "column": 7, + "endLine": 34, + "endColumn": 11, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 35, "column": 3, diff --git a/ets2panda/linter/test/deprecatedapi/swiper_api.ets.arkts2.json b/ets2panda/linter/test/deprecatedapi/swiper_api.ets.arkts2.json index 0d7d48b7bd..4f9d81a6b2 100755 --- a/ets2panda/linter/test/deprecatedapi/swiper_api.ets.arkts2.json +++ b/ets2panda/linter/test/deprecatedapi/swiper_api.ets.arkts2.json @@ -24,6 +24,16 @@ "rule": "ArkTS 1.2 should implement all optional fields from the interface in the class (arkts-no-class-omit-interface-optional-prop)", "severity": "ERROR" }, + { + "line": 17, + "column": 7, + "endLine": 17, + "endColumn": 11, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 17, "column": 37, diff --git a/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_negative.ets b/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_negative.ets new file mode 100644 index 0000000000..1e166721f2 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_negative.ets @@ -0,0 +1,86 @@ +/* + * 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. + */ + +interface I2 { + x: boolean; + y: number; +} +class C2 implements I2 { // 1. Error: missing getter and setter for `y` + private _x: boolean = true; + private _y: number = 0.0; + get x(): boolean { + return this._x; + } + set x(xx: boolean) { + this._x = xx; + } +} +class C21 implements I2 { // 2. Error: missing setter for `x` + private _x: boolean = true; + private _y: number = 5.0; + get x(): boolean { + return this._x; + } + get y(): number { + return this._y; + } + set y(yy: number) { + this._y = yy; + } +} + +// An interface extends another, check getters and setters for all fields +interface A5 { + p: string; +} +interface B5 extends A5 { + q: string; +} + +class C6 implements B5 { // 3. Error: missing getter and setter for `q` + private _p: string = 'hello'; + private _q: string = 'world'; + get p(): string { + return this._p; + } + set p(pp: string) { + this._p = pp; + } +} +class C61 implements B5 { // 4. Error: missing getter and setter for `p` + private _q: string = 'hello'; + private _p: string = 'world'; + get q(): string { + return this._q; + } + set q(qq: string) { + this._q = qq; + } +} + +// Implement multiple interfaces at once, check getters and setters for all fields +interface I6a { u: number } +interface I6b { v: boolean } + +class C8 implements I6a, I6b { // 5. Error: missing getter and setter for `v` + private _u: number = 42.0; + private _v: boolean = false; + get u(): number { + return this._u; + } + set u(uu: number) { + this._u = uu; + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_negative.ets.args.json b/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_negative.ets.args.json new file mode 100644 index 0000000000..66fb88f859 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_negative.ets.args.json @@ -0,0 +1,19 @@ +{ + "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": "" + } +} diff --git a/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_negative.ets.arkts2.json b/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_negative.ets.arkts2.json new file mode 100644 index 0000000000..2c92361489 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_negative.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": 20, + "column": 7, + "endLine": 20, + "endColumn": 9, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, + { + "line": 30, + "column": 7, + "endLine": 30, + "endColumn": 10, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, + { + "line": 52, + "column": 7, + "endLine": 52, + "endColumn": 9, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, + { + "line": 62, + "column": 7, + "endLine": 62, + "endColumn": 10, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, + { + "line": 77, + "column": 7, + "endLine": 77, + "endColumn": 9, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + } + ] +} diff --git a/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_negative.ets.json b/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_negative.ets.json new file mode 100644 index 0000000000..9f305c86d7 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_negative.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": [] +} diff --git a/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_positive.ets b/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_positive.ets new file mode 100644 index 0000000000..e951a5c074 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_positive.ets @@ -0,0 +1,88 @@ +/* + * 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. + */ + +interface I1 { + a: number; + b: string; +} +class C1 implements I1 { // 1. All fields have their getters and setters implemented — no error + private _a: number = 0.0; + private _b: string = ''; + get a(): number { + return this._a; + } + set a(aa: number) { + this._a = aa; + } + get b(): string { + return this._b; + } + set b(bb: string) { + this._b = bb; + } +} + +interface A5 { + p: string; +} +interface B5 extends A5 { + q: string; +} +class C5 implements B5 { // 2. An interface extends another, have getters and setters for all fields + private _p: string = 'hello'; + private _q: string = 'world'; + get p(): string { + return this._p; + } + set p(pp: string) { + this._p = pp; + } + get q(): string { + return this._q; + } + set q(qq: string) { + this._q = qq; + } +} + +interface I6a { u: number } +interface I6b { v: boolean } + +class C7 implements I6a, I6b { // 3. Implement multiple interfaces at once, have getters and setters for all fields + private _u: number = 42.0; + private _v: boolean = false; + get u(): number { + return this._u; + } + set u(uu: number) { + this._u = uu; + } + get v(): boolean { + return this._v; + } + set v(vv: boolean) { + this._v = vv; + } +} + +interface II8 { + readonly u: number = 8; +} + +class CC1 implements II8 { // 4. readonly field can only have getter + get u(): number { + return 1; + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_positive.ets.args.json b/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_positive.ets.args.json new file mode 100644 index 0000000000..66fb88f859 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_positive.ets.args.json @@ -0,0 +1,19 @@ +{ + "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": "" + } +} diff --git a/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_positive.ets.arkts2.json b/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_positive.ets.arkts2.json new file mode 100644 index 0000000000..191b1533f6 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_positive.ets.arkts2.json @@ -0,0 +1,19 @@ +{ + "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": [ + + ] +} diff --git a/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_positive.ets.json b/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_positive.ets.json new file mode 100644 index 0000000000..9f305c86d7 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-class-implement-interface-prop-getter-setter_positive.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": [] +} diff --git a/ets2panda/linter/test/main/derived_class_field_type_matching.ets.arkts2.json b/ets2panda/linter/test/main/derived_class_field_type_matching.ets.arkts2.json index 06df6cd967..4cc8ba668a 100644 --- a/ets2panda/linter/test/main/derived_class_field_type_matching.ets.arkts2.json +++ b/ets2panda/linter/test/main/derived_class_field_type_matching.ets.arkts2.json @@ -84,6 +84,16 @@ "rule": "The field types of the subclass and parent class must be the same (arkts-class-same-type-prop-with-super)", "severity": "ERROR" }, + { + "line": 73, + "column": 7, + "endLine": 73, + "endColumn": 10, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 74, "column": 3, @@ -104,6 +114,16 @@ "rule": "The field types of the subclass and parent class must be the same (arkts-class-same-type-prop-with-super)", "severity": "ERROR" }, + { + "line": 78, + "column": 7, + "endLine": 78, + "endColumn": 10, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 79, "column": 3, diff --git a/ets2panda/linter/test/main/explicit_function_type.ets.arkts2.json b/ets2panda/linter/test/main/explicit_function_type.ets.arkts2.json index 83cdd8667b..2979de8a84 100644 --- a/ets2panda/linter/test/main/explicit_function_type.ets.arkts2.json +++ b/ets2panda/linter/test/main/explicit_function_type.ets.arkts2.json @@ -34,6 +34,16 @@ "rule": "Use arrow functions instead of function expressions (arkts-no-func-expressions)", "severity": "ERROR" }, + { + "line": 52, + "column": 7, + "endLine": 52, + "endColumn": 9, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 57, "column": 3, 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 1a445e96ba..4834d3c8af 100644 --- a/ets2panda/linter/test/main/explicit_function_type.ets.autofix.json +++ b/ets2panda/linter/test/main/explicit_function_type.ets.autofix.json @@ -56,6 +56,16 @@ "rule": "Use arrow functions instead of function expressions (arkts-no-func-expressions)", "severity": "ERROR" }, + { + "line": 52, + "column": 7, + "endLine": 52, + "endColumn": 9, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 57, "column": 3, 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 d0ebc18694..84a835a32f 100644 --- a/ets2panda/linter/test/main/explicit_function_type.ets.migrate.json +++ b/ets2panda/linter/test/main/explicit_function_type.ets.migrate.json @@ -14,6 +14,16 @@ "limitations under the License." ], "result": [ + { + "line": 52, + "column": 7, + "endLine": 52, + "endColumn": 9, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 70, "column": 12, diff --git a/ets2panda/linter/test/main/method_inheritance.ets.arkts2.json b/ets2panda/linter/test/main/method_inheritance.ets.arkts2.json index bac26d04ac..7c1c9dd033 100644 --- a/ets2panda/linter/test/main/method_inheritance.ets.arkts2.json +++ b/ets2panda/linter/test/main/method_inheritance.ets.arkts2.json @@ -244,6 +244,16 @@ "rule": "The signature of a method in a class/interface cannot be different from the public interface in an object. (arkts-class-no-signature-distinct-with-object-public-api)", "severity": "ERROR" }, + { + "line": 237, + "column": 7, + "endLine": 237, + "endColumn": 9, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 266, "column": 9, diff --git a/ets2panda/linter/test/main/method_overriding.ets.arkts2.json b/ets2panda/linter/test/main/method_overriding.ets.arkts2.json index 4d9808c7f7..366d21cda0 100755 --- a/ets2panda/linter/test/main/method_overriding.ets.arkts2.json +++ b/ets2panda/linter/test/main/method_overriding.ets.arkts2.json @@ -14,75 +14,95 @@ "limitations under the License." ], "result": [ - { - "line": 21, - "column": 3, - "endLine": 21, - "endColumn": 10, - "problem": "MethodOverridingField", - "suggest": "", - "rule": "Method can't override filed in interface implemented (arkts-no-method-overriding-field)", - "severity": "ERROR" - }, - { - "line": 30, - "column": 5, - "endLine": 30, - "endColumn": 12, - "problem": "MethodOverridingField", - "suggest": "", - "rule": "Method can't override filed in interface implemented (arkts-no-method-overriding-field)", - "severity": "ERROR" - }, - { - "line": 31, - "column": 5, - "endLine": 31, - "endColumn": 31, - "problem": "MethodOverridingField", - "suggest": "", - "rule": "Method can't override filed in interface implemented (arkts-no-method-overriding-field)", - "severity": "ERROR" - }, - { - "line": 39, - "column": 5, - "endLine": 39, - "endColumn": 30, - "problem": "MethodOverridingField", - "suggest": "", - "rule": "Method can't override filed in interface implemented (arkts-no-method-overriding-field)", - "severity": "ERROR" - }, - { - "line": 47, - "column": 3, - "endLine": 47, - "endColumn": 13, - "problem": "MethodOverridingField", - "suggest": "", - "rule": "Method can't override filed in interface implemented (arkts-no-method-overriding-field)", - "severity": "ERROR" - }, - { - "line": 55, - "column": 3, - "endLine": 55, - "endColumn": 18, - "problem": "MethodOverridingField", - "suggest": "", - "rule": "Method can't override filed in interface implemented (arkts-no-method-overriding-field)", - "severity": "ERROR" - }, - { - "line": 63, - "column": 3, - "endLine": 63, - "endColumn": 13, - "problem": "MethodOverridingField", - "suggest": "", - "rule": "Method can't override filed in interface implemented (arkts-no-method-overriding-field)", - "severity": "ERROR" - } + { + "line": 21, + "column": 3, + "endLine": 21, + "endColumn": 10, + "problem": "MethodOverridingField", + "suggest": "", + "rule": "Method can't override filed in interface implemented (arkts-no-method-overriding-field)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 7, + "endLine": 20, + "endColumn": 14, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, + { + "line": 30, + "column": 5, + "endLine": 30, + "endColumn": 12, + "problem": "MethodOverridingField", + "suggest": "", + "rule": "Method can't override filed in interface implemented (arkts-no-method-overriding-field)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 5, + "endLine": 31, + "endColumn": 31, + "problem": "MethodOverridingField", + "suggest": "", + "rule": "Method can't override filed in interface implemented (arkts-no-method-overriding-field)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 7, + "endLine": 29, + "endColumn": 8, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, + { + "line": 39, + "column": 5, + "endLine": 39, + "endColumn": 30, + "problem": "MethodOverridingField", + "suggest": "", + "rule": "Method can't override filed in interface implemented (arkts-no-method-overriding-field)", + "severity": "ERROR" + }, + { + "line": 47, + "column": 3, + "endLine": 47, + "endColumn": 13, + "problem": "MethodOverridingField", + "suggest": "", + "rule": "Method can't override filed in interface implemented (arkts-no-method-overriding-field)", + "severity": "ERROR" + }, + { + "line": 55, + "column": 3, + "endLine": 55, + "endColumn": 18, + "problem": "MethodOverridingField", + "suggest": "", + "rule": "Method can't override filed in interface implemented (arkts-no-method-overriding-field)", + "severity": "ERROR" + }, + { + "line": 63, + "column": 3, + "endLine": 63, + "endColumn": 13, + "problem": "MethodOverridingField", + "suggest": "", + "rule": "Method can't override filed in interface implemented (arkts-no-method-overriding-field)", + "severity": "ERROR" + } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/main/no_class_omit_interface_optional.ets.arkts2.json b/ets2panda/linter/test/main/no_class_omit_interface_optional.ets.arkts2.json index 5b06edf9f5..78eb1ffefb 100644 --- a/ets2panda/linter/test/main/no_class_omit_interface_optional.ets.arkts2.json +++ b/ets2panda/linter/test/main/no_class_omit_interface_optional.ets.arkts2.json @@ -14,6 +14,26 @@ "limitations under the License." ], "result": [ + { + "line": 21, + "column": 7, + "endLine": 21, + "endColumn": 9, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 7, + "endLine": 26, + "endColumn": 9, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 35, "column": 7, @@ -24,6 +44,36 @@ "rule": "ArkTS 1.2 should implement all optional fields from the interface in the class (arkts-no-class-omit-interface-optional-prop)", "severity": "ERROR" }, + { + "line": 35, + "column": 7, + "endLine": 35, + "endColumn": 9, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, + { + "line": 38, + "column": 7, + "endLine": 38, + "endColumn": 9, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, + { + "line": 50, + "column": 7, + "endLine": 50, + "endColumn": 9, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 54, "column": 7, @@ -34,6 +84,16 @@ "rule": "ArkTS 1.2 should implement all optional fields from the interface in the class (arkts-no-class-omit-interface-optional-prop)", "severity": "ERROR" }, + { + "line": 54, + "column": 7, + "endLine": 54, + "endColumn": 9, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 57, "column": 7, @@ -44,6 +104,26 @@ "rule": "ArkTS 1.2 should implement all optional fields from the interface in the class (arkts-no-class-omit-interface-optional-prop)", "severity": "ERROR" }, + { + "line": 57, + "column": 7, + "endLine": 57, + "endColumn": 10, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, + { + "line": 64, + "column": 7, + "endLine": 64, + "endColumn": 9, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 68, "column": 7, @@ -53,6 +133,16 @@ "suggest": "", "rule": "ArkTS 1.2 should implement all optional fields from the interface in the class (arkts-no-class-omit-interface-optional-prop)", "severity": "ERROR" + }, + { + "line": 68, + "column": 7, + "endLine": 68, + "endColumn": 9, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/sdkwhite/limit_void_type_sdk2.ets.arkts2.json b/ets2panda/linter/test/sdkwhite/limit_void_type_sdk2.ets.arkts2.json index 9f578dbed8..a55bcb61d7 100644 --- a/ets2panda/linter/test/sdkwhite/limit_void_type_sdk2.ets.arkts2.json +++ b/ets2panda/linter/test/sdkwhite/limit_void_type_sdk2.ets.arkts2.json @@ -184,6 +184,16 @@ "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", "severity": "ERROR" }, + { + "line": 67, + "column": 7, + "endLine": 67, + "endColumn": 8, + "problem": "ClassImplementInterfacePropGetterSetter", + "suggest": "", + "rule": "Class implements interface property must have getter/setter (arkts-class-implement-interface-prop-getter-setter)", + "severity": "ERROR" + }, { "line": 68, "column": 19, -- Gitee