diff --git a/ets2panda/linter/rule-config.json b/ets2panda/linter/rule-config.json index 52426d571d9f7901042e4bf516026a5951cae8c9..349cef2c459fc39086f0bc974d1128ba3edbfeb5 100644 --- a/ets2panda/linter/rule-config.json +++ b/ets2panda/linter/rule-config.json @@ -115,7 +115,8 @@ "arkui-prop-need-call-method-for-deep-copy", "arkui-no-localbuilder-decorator", "arkui-statestyles-block-need-arrow-func", - "arkui-repeat-disable-default-virtualscroll" + "arkui-repeat-disable-default-virtualscroll", + "arkui-wrapbuilder-require-arrow-func-generic" ], "builtin": [ "arkts-builtin-thisArgs", diff --git a/ets2panda/linter/src/lib/CookBookMsg.ts b/ets2panda/linter/src/lib/CookBookMsg.ts index d94ca192177f4f481714eef8d4acf822e3510c6d..dd038abe97595888a88ea3955840f09b64e893c4 100644 --- a/ets2panda/linter/src/lib/CookBookMsg.ts +++ b/ets2panda/linter/src/lib/CookBookMsg.ts @@ -373,6 +373,8 @@ cookBookTag[358] = cookBookTag[359] = '"@LocalBuilder" Decorator is not supported (arkui-no-localbuilder-decorator)'; cookBookTag[360] = '"Repeat" natively supports virtual scrolling capability in ArkTS1.2, so the default virtual scrolling should be disabled (arkui-repeat-disable-default-virtualscroll)'; +cookBookTag[361] = + 'When using "WrappedBuilder" and "wrapBuilder", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)'; cookBookTag[370] = 'Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)'; cookBookTag[371] = 'Enum elements cannot be types in ArkTS1.2 (arkts-no-enum-prop-as-type)'; cookBookTag[372] = 'Smart type differences (arkts-no-ts-like-smart-type)'; diff --git a/ets2panda/linter/src/lib/FaultAttrs.ts b/ets2panda/linter/src/lib/FaultAttrs.ts index f67ac33cb405aca2cdade5ada614980da4b1c1d9..5c828160f33ab55caf85f9ed09f46a0119f99e99 100644 --- a/ets2panda/linter/src/lib/FaultAttrs.ts +++ b/ets2panda/linter/src/lib/FaultAttrs.ts @@ -257,6 +257,7 @@ faultsAttrs[FaultID.NoNeedStdlibWorker] = new FaultAttributes(357); faultsAttrs[FaultID.BuiltinGetOwnPropertyNames] = new FaultAttributes(358); faultsAttrs[FaultID.LocalBuilderDecoratorNotSupported] = new FaultAttributes(359); faultsAttrs[FaultID.RepeatDisableVirtualScroll] = new FaultAttributes(360); +faultsAttrs[FaultID.WrappedBuilderGenericNeedArrowFunc] = new FaultAttributes(361); faultsAttrs[FaultID.NosparseArray] = new FaultAttributes(370); faultsAttrs[FaultID.NoEnumPropAsType] = new FaultAttributes(371); faultsAttrs[FaultID.NoTsLikeSmartType] = new FaultAttributes(372); diff --git a/ets2panda/linter/src/lib/FaultDesc.ts b/ets2panda/linter/src/lib/FaultDesc.ts index 33cb74aca333d02802159e6e128a1f2ca4e21833..ab3cde471951da4804535c130bab4a7a6395fe0d 100644 --- a/ets2panda/linter/src/lib/FaultDesc.ts +++ b/ets2panda/linter/src/lib/FaultDesc.ts @@ -257,3 +257,4 @@ faultDesc[FaultID.PropNeedCallMethodForDeepCopy] = 'Deep copy needs to call the faultDesc[FaultID.StateStylesBlockNeedArrowFunc] = 'StateStyles needs arrow function block'; faultDesc[FaultID.PromiseVoidNeedResolveArg] = 'Promiseconstructor only supports using resolve (undefined)'; faultDesc[FaultID.RepeatDisableVirtualScroll] = '"Repeat" disable default "virtualScroll"'; +faultDesc[FaultID.WrappedBuilderGenericNeedArrowFunc] = 'Generic of "WrappedBuilder" does not support parameter list'; diff --git a/ets2panda/linter/src/lib/Problems.ts b/ets2panda/linter/src/lib/Problems.ts index 9225ec1dce5d60894eac5a3e69d95b4742c289f0..fbe1bb14130268cebc816c2cd5dc771dd69c9628 100644 --- a/ets2panda/linter/src/lib/Problems.ts +++ b/ets2panda/linter/src/lib/Problems.ts @@ -257,6 +257,7 @@ export enum FaultID { StateStylesBlockNeedArrowFunc, PromiseVoidNeedResolveArg, RepeatDisableVirtualScroll, + WrappedBuilderGenericNeedArrowFunc, // 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 dcb878796da2ccf96777761fc6bffc612e965492..884f8c80581da3b958b458ce627e435b6e419398 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -4618,6 +4618,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { private handleCallExpressionForUI(node: ts.CallExpression): void { this.handleStateStyles(node); this.handleCallExpressionForRepeat(node); + this.handleNodeForWrappedBuilder(node); } handleNoTsLikeFunctionCall(callExpr: ts.CallExpression): void { @@ -5278,7 +5279,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { private handleNewExpression(node: ts.Node): void { const tsNewExpr = node as ts.NewExpression; - + this.handleNodeForWrappedBuilder(tsNewExpr); this.checkForInterfaceInitialization(tsNewExpr); this.handleSharedArrayBuffer(tsNewExpr); this.handleSdkGlobalApi(tsNewExpr); @@ -5656,12 +5657,11 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { private handleTypeReference(node: ts.Node): void { const typeRef = node as ts.TypeReferenceNode; - this.handleBuiltinCtorCallSignature(typeRef); this.handleSharedArrayBuffer(typeRef); this.handleSdkGlobalApi(typeRef); - this.handleSdkConstructorIface(typeRef); + this.handleNodeForWrappedBuilder(typeRef); const isESValue = TsUtils.isEsValueType(typeRef); const isPossiblyValidContext = TsUtils.isEsValuePossiblyAllowed(typeRef); @@ -7071,7 +7071,12 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return; } - const autofix = this.autofixer?.fixCustomBidirectionalBinding(originalExpr, currentParam, customParam); + const decl = this.tsUtils.getDeclarationNode(currentParam); + if (!decl || !ts.isPropertyDeclaration(decl)) { + return; + } + + const autofix = this.autofixer?.fixCustomBidirectionalBinding(originalExpr, decl.type, currentParam, customParam); this.incrementCounters(firstExpr, FaultID.DoubleExclaBindingNotSupported, autofix); } @@ -11570,6 +11575,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { }); return hasOutOfBound; } + private handleCallExpressionForRepeat(node: ts.CallExpression): void { if (!this.options.arkts2) { return; @@ -11591,4 +11597,22 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { const autofix = this.autofixer?.fixRepeat(stmt); this.incrementCounters(node, FaultID.RepeatDisableVirtualScroll, autofix); } + + private handleNodeForWrappedBuilder(node: ts.Node): void { + if (!this.options.arkts2) { + return; + } + + if ( + ts.isTypeReferenceNode(node) && this.isTargetInterface(node.typeName, CustomInterfaceName.WrappedBuilder) || + ts.isNewExpression(node) && this.isTargetInterface(node.expression, CustomInterfaceName.WrappedBuilder) || + ts.isCallExpression(node) && this.isTargetInterface(node.expression, CustomInterfaceName.wrapBuilder) + ) { + this.incrementCounters(node, FaultID.WrappedBuilderGenericNeedArrowFunc); + } + } + + private isTargetInterface(node: ts.Node, targetName: string): boolean { + return ts.isIdentifier(node) && node.getText() === targetName && !this.isDeclarationInSameFile(node); + } } diff --git a/ets2panda/linter/src/lib/autofixes/Autofixer.ts b/ets2panda/linter/src/lib/autofixes/Autofixer.ts index bca8d8304e2313dc8a46587c66d274ce8cc7f519..2e40588042243bf531fa76b28888780f508fd337 100644 --- a/ets2panda/linter/src/lib/autofixes/Autofixer.ts +++ b/ets2panda/linter/src/lib/autofixes/Autofixer.ts @@ -2789,6 +2789,7 @@ export class Autofixer { fixCustomBidirectionalBinding( originalExpr: ts.ObjectLiteralExpression, + type: ts.TypeNode | undefined, currentParam: ts.Identifier, customParam: ts.Identifier ): Autofix[] | undefined { @@ -2809,14 +2810,7 @@ export class Autofixer { ], true ); - const parameter = ts.factory.createParameterDeclaration( - undefined, - undefined, - value, - undefined, - undefined, - undefined - ); + const parameter = ts.factory.createParameterDeclaration(undefined, undefined, value, undefined, type, undefined); const arrowFunc = ts.factory.createArrowFunction( undefined, undefined, diff --git a/ets2panda/linter/src/lib/utils/consts/ArkuiConstants.ts b/ets2panda/linter/src/lib/utils/consts/ArkuiConstants.ts index 22e7943117e3c7488d2ca2a88ba0ec0b833004e9..bcf0d2c1d04a17f370a318fe0af6c924796cbd60 100644 --- a/ets2panda/linter/src/lib/utils/consts/ArkuiConstants.ts +++ b/ets2panda/linter/src/lib/utils/consts/ArkuiConstants.ts @@ -36,7 +36,9 @@ export enum CustomInterfaceName { Observed = 'Observed', CustomLayout = 'CustomLayout', CustomStyles = 'CustomStyles', - Repeat = 'Repeat' + Repeat = 'Repeat', + WrappedBuilder = 'WrappedBuilder', + wrapBuilder = 'wrapBuilder' } export enum StorageTypeName { diff --git a/ets2panda/linter/src/lib/utils/consts/ArkuiImportList.ts b/ets2panda/linter/src/lib/utils/consts/ArkuiImportList.ts index f8ab0145c549c24f4e0c3526f3aa45adf7e98afc..f00234df62db7c86386840c10b0289166a81e4e2 100644 --- a/ets2panda/linter/src/lib/utils/consts/ArkuiImportList.ts +++ b/ets2panda/linter/src/lib/utils/consts/ArkuiImportList.ts @@ -1256,6 +1256,9 @@ export const arkuiImportList: Set = new Set([ 'SelectionMenuOptionsExt', 'SelectionOptions', 'Sendable', + 'sendKeyEvent', + 'sendMouseEvent', + 'sendTouchEvent', 'Serializer', 'ShadowOptions', 'ShadowStyle', diff --git a/ets2panda/linter/test/main/double_excla_binding_1.ets.autofix.json b/ets2panda/linter/test/main/double_excla_binding_1.ets.autofix.json index f70c84d16450b2b2796d25983c1283e4ec747e6b..c50bf91050e0382ae355068411b23712d4b41b2e 100644 --- a/ets2panda/linter/test/main/double_excla_binding_1.ets.autofix.json +++ b/ets2panda/linter/test/main/double_excla_binding_1.ets.autofix.json @@ -171,7 +171,7 @@ { "start": 1662, "end": 1685, - "replacementText": "{\n value: this.value,\n $value: value => {\n this.value = value;\n }\n }", + "replacementText": "{\n value: this.value,\n $value: (value: number) => {\n this.value = value;\n }\n }", "line": 92, "column": 21, "endLine": 92, @@ -192,7 +192,7 @@ { "start": 1700, "end": 1719, - "replacementText": "{\n str: this.str,\n $str: value => {\n this.str = value;\n }\n }", + "replacementText": "{\n str: this.str,\n $str: (value: string) => {\n this.str = value;\n }\n }", "line": 93, "column": 21, "endLine": 93, diff --git a/ets2panda/linter/test/main/double_excla_binding_1.ets.migrate.ets b/ets2panda/linter/test/main/double_excla_binding_1.ets.migrate.ets index e95837b57fdc91faee2a52c20e37f1b77d9e5215..c9fb83935c837c552a978de9287cfdb94c4125c8 100644 --- a/ets2panda/linter/test/main/double_excla_binding_1.ets.migrate.ets +++ b/ets2panda/linter/test/main/double_excla_binding_1.ets.migrate.ets @@ -109,13 +109,13 @@ struct Index { }) Star({ value: this.value, - $value: value => { + $value: (value: number) => { this.value = value; } }) MyCard({ str: this.str, - $str: value => { + $str: (value: string) => { this.str = value; } }) diff --git a/ets2panda/linter/test/main/double_excla_binding_1.ets.migrate.json b/ets2panda/linter/test/main/double_excla_binding_1.ets.migrate.json index 83e5c37e26b39e420ea24ba454e6e000c204250d..ca88f857e960b437dcf767c0ac40be998c8f1236 100644 --- a/ets2panda/linter/test/main/double_excla_binding_1.ets.migrate.json +++ b/ets2panda/linter/test/main/double_excla_binding_1.ets.migrate.json @@ -13,16 +13,5 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [ - { - "line": 118, - "column": 15, - "endLine": 118, - "endColumn": 20, - "problem": "AnyType", - "suggest": "", - "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", - "severity": "ERROR" - } - ] + "result": [] } \ No newline at end of file diff --git a/ets2panda/linter/test/main/wrapped_builder_generic_1.ets b/ets2panda/linter/test/main/wrapped_builder_generic_1.ets new file mode 100644 index 0000000000000000000000000000000000000000..c2d7d44538b3d84143b3ed15dbbf65e447675560 --- /dev/null +++ b/ets2panda/linter/test/main/wrapped_builder_generic_1.ets @@ -0,0 +1,44 @@ +/* + * 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. + */ + +@Builder +function MyBuilder(value: string, size: number) { + Text(value) + .fontSize(size) +} + +const wrappedBuilder1: WrappedBuilder<[string, number]> = wrapBuilder(MyBuilder); +const wrappedBuilder2: WrappedBuilder<[string, number]> = wrapBuilder<[string, number]>(MyBuilder); +const wrappedBuilder3: WrappedBuilder<[string, number]> = new WrappedBuilder(MyBuilder); +const wrappedBuilder4: WrappedBuilder<[string, number]> = new WrappedBuilder<[string, number]>(MyBuilder); + +@Entry +@Component +struct TestWrappedBuilder1 { + @State message: string = 'Hello World'; + + build() { + Row() { + Column() { + wrappedBuilder1.builder(this.message, 50) + wrappedBuilder2.builder(this.message, 50) + wrappedBuilder3.builder(this.message, 50) + wrappedBuilder4.builder(this.message, 50) + } + } + .height('100%') + .width('100%') + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/wrapped_builder_generic_1.ets.args.json b/ets2panda/linter/test/main/wrapped_builder_generic_1.ets.args.json new file mode 100644 index 0000000000000000000000000000000000000000..d8d3390ad9befeca9b595017d9eea0f5ada3d049 --- /dev/null +++ b/ets2panda/linter/test/main/wrapped_builder_generic_1.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": "" + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/wrapped_builder_generic_1.ets.arkts2.json b/ets2panda/linter/test/main/wrapped_builder_generic_1.ets.arkts2.json new file mode 100644 index 0000000000000000000000000000000000000000..301eb21df38fa5d991e9e5f3de784693eeaacc11 --- /dev/null +++ b/ets2panda/linter/test/main/wrapped_builder_generic_1.ets.arkts2.json @@ -0,0 +1,288 @@ +{ + "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": 22, + "column": 24, + "endLine": 22, + "endColumn": 56, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 59, + "endLine": 22, + "endColumn": 81, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 24, + "endLine": 23, + "endColumn": 56, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 59, + "endLine": 23, + "endColumn": 99, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 24, + "endLine": 24, + "endColumn": 56, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 59, + "endLine": 24, + "endColumn": 88, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 63, + "endLine": 24, + "endColumn": 77, + "problem": "DynamicCtorCall", + "suggest": "", + "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 24, + "endLine": 25, + "endColumn": 56, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 59, + "endLine": 25, + "endColumn": 106, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 63, + "endLine": 25, + "endColumn": 77, + "problem": "DynamicCtorCall", + "suggest": "", + "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", + "severity": "ERROR" + }, + { + "line": 35, + "column": 47, + "endLine": 35, + "endColumn": 49, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 36, + "column": 47, + "endLine": 36, + "endColumn": 49, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 37, + "column": 47, + "endLine": 37, + "endColumn": 49, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 38, + "column": 47, + "endLine": 38, + "endColumn": 49, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 16, + "column": 2, + "endLine": 16, + "endColumn": 9, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"Builder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 18, + "column": 3, + "endLine": 18, + "endColumn": 7, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"Text\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 24, + "endLine": 22, + "endColumn": 38, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"WrappedBuilder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 24, + "endLine": 23, + "endColumn": 38, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"WrappedBuilder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 24, + "endLine": 24, + "endColumn": 38, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"WrappedBuilder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 63, + "endLine": 24, + "endColumn": 77, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"WrappedBuilder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 24, + "endLine": 25, + "endColumn": 38, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"WrappedBuilder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 63, + "endLine": 25, + "endColumn": 77, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"WrappedBuilder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 2, + "endLine": 27, + "endColumn": 7, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"Entry\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 28, + "column": 2, + "endLine": 28, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"Component\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 30, + "column": 4, + "endLine": 30, + "endColumn": 9, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"State\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 33, + "column": 5, + "endLine": 33, + "endColumn": 8, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"Row\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 34, + "column": 7, + "endLine": 34, + "endColumn": 13, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"Column\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/wrapped_builder_generic_1.ets.json b/ets2panda/linter/test/main/wrapped_builder_generic_1.ets.json new file mode 100644 index 0000000000000000000000000000000000000000..ca88f857e960b437dcf767c0ac40be998c8f1236 --- /dev/null +++ b/ets2panda/linter/test/main/wrapped_builder_generic_1.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/wrapped_builder_generic_2.ets b/ets2panda/linter/test/main/wrapped_builder_generic_2.ets new file mode 100644 index 0000000000000000000000000000000000000000..2a55bd24a7f326595c0ffef8f3e4520df68bd78a --- /dev/null +++ b/ets2panda/linter/test/main/wrapped_builder_generic_2.ets @@ -0,0 +1,62 @@ +/* + * 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. + */ + +@Builder +function MyBuilder(value: string, size: number) { + Text(value) + .fontSize(size) +} + +@Builder +function YourBuilder(value: string, size: number) { + Text(value) + .fontSize(size) + .fontColor(Color.Pink) +} + +const builderArr1: WrappedBuilder<[string, number]>[] = [wrapBuilder(MyBuilder), wrapBuilder(YourBuilder)]; +const builderArr2: WrappedBuilder<[string, number]>[] = [wrapBuilder<[string, number]>(MyBuilder), wrapBuilder<[string, number]>(YourBuilder)]; +const builderArr3: WrappedBuilder<[string, number]>[] = [new WrappedBuilder(MyBuilder), new WrappedBuilder(YourBuilder)]; +const builderArr4: WrappedBuilder<[string, number]>[] = [new WrappedBuilder<[string, number]>(MyBuilder), new WrappedBuilder<[string, number]>(YourBuilder)]; + +@Entry +@Component +struct Index { + @Builder + testBuilder() { + ForEach(builderArr1, (item: WrappedBuilder<[string, number]>) => { + item.builder('Hello World', 30) + }) + ForEach(builderArr2, (item: WrappedBuilder<[string, number]>) => { + item.builder('Hello World', 30) + }) + ForEach(builderArr3, (item: WrappedBuilder<[string, number]>) => { + item.builder('Hello World', 30) + }) + ForEach(builderArr4, (item: WrappedBuilder<[string, number]>) => { + item.builder('Hello World', 30) + }) + } + + build() { + Row() { + Column() { + this.testBuilder() + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/wrapped_builder_generic_2.ets.args.json b/ets2panda/linter/test/main/wrapped_builder_generic_2.ets.args.json new file mode 100644 index 0000000000000000000000000000000000000000..d8d3390ad9befeca9b595017d9eea0f5ada3d049 --- /dev/null +++ b/ets2panda/linter/test/main/wrapped_builder_generic_2.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": "" + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/wrapped_builder_generic_2.ets.arkts2.json b/ets2panda/linter/test/main/wrapped_builder_generic_2.ets.arkts2.json new file mode 100644 index 0000000000000000000000000000000000000000..a66118bc68d92ad987c1ba64e5acf3aa29f87ac3 --- /dev/null +++ b/ets2panda/linter/test/main/wrapped_builder_generic_2.ets.arkts2.json @@ -0,0 +1,518 @@ +{ + "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": 29, + "column": 20, + "endLine": 29, + "endColumn": 52, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 58, + "endLine": 29, + "endColumn": 80, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 82, + "endLine": 29, + "endColumn": 106, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 30, + "column": 20, + "endLine": 30, + "endColumn": 52, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 30, + "column": 58, + "endLine": 30, + "endColumn": 98, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 30, + "column": 100, + "endLine": 30, + "endColumn": 142, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 20, + "endLine": 31, + "endColumn": 52, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 58, + "endLine": 31, + "endColumn": 87, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 62, + "endLine": 31, + "endColumn": 76, + "problem": "DynamicCtorCall", + "suggest": "", + "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 89, + "endLine": 31, + "endColumn": 120, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 93, + "endLine": 31, + "endColumn": 107, + "problem": "DynamicCtorCall", + "suggest": "", + "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", + "severity": "ERROR" + }, + { + "line": 32, + "column": 20, + "endLine": 32, + "endColumn": 52, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 32, + "column": 58, + "endLine": 32, + "endColumn": 105, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 32, + "column": 62, + "endLine": 32, + "endColumn": 76, + "problem": "DynamicCtorCall", + "suggest": "", + "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", + "severity": "ERROR" + }, + { + "line": 32, + "column": 107, + "endLine": 32, + "endColumn": 156, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 32, + "column": 111, + "endLine": 32, + "endColumn": 125, + "problem": "DynamicCtorCall", + "suggest": "", + "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", + "severity": "ERROR" + }, + { + "line": 39, + "column": 33, + "endLine": 39, + "endColumn": 65, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 40, + "column": 35, + "endLine": 40, + "endColumn": 37, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 42, + "column": 33, + "endLine": 42, + "endColumn": 65, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 43, + "column": 35, + "endLine": 43, + "endColumn": 37, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 45, + "column": 33, + "endLine": 45, + "endColumn": 65, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 46, + "column": 35, + "endLine": 46, + "endColumn": 37, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 48, + "column": 33, + "endLine": 48, + "endColumn": 65, + "problem": "WrappedBuilderGenericNeedArrowFunc", + "suggest": "", + "rule": "When using \"WrappedBuilder\" and \"wrapBuilder\", generics are required and must be declared as arrow function (arkui-wrapbuilder-require-arrow-func-generic)", + "severity": "ERROR" + }, + { + "line": 49, + "column": 35, + "endLine": 49, + "endColumn": 37, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 16, + "column": 2, + "endLine": 16, + "endColumn": 9, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"Builder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 18, + "column": 3, + "endLine": 18, + "endColumn": 7, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"Text\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 2, + "endLine": 22, + "endColumn": 9, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"Builder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 3, + "endLine": 24, + "endColumn": 7, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"Text\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 16, + "endLine": 26, + "endColumn": 21, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"Color\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 20, + "endLine": 29, + "endColumn": 34, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"WrappedBuilder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 30, + "column": 20, + "endLine": 30, + "endColumn": 34, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"WrappedBuilder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 20, + "endLine": 31, + "endColumn": 34, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"WrappedBuilder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 62, + "endLine": 31, + "endColumn": 76, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"WrappedBuilder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 93, + "endLine": 31, + "endColumn": 107, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"WrappedBuilder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 32, + "column": 20, + "endLine": 32, + "endColumn": 34, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"WrappedBuilder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 32, + "column": 62, + "endLine": 32, + "endColumn": 76, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"WrappedBuilder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 32, + "column": 111, + "endLine": 32, + "endColumn": 125, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"WrappedBuilder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 34, + "column": 2, + "endLine": 34, + "endColumn": 7, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"Entry\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 35, + "column": 2, + "endLine": 35, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"Component\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 37, + "column": 4, + "endLine": 37, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"Builder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 39, + "column": 5, + "endLine": 39, + "endColumn": 12, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"ForEach\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 39, + "column": 33, + "endLine": 39, + "endColumn": 47, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"WrappedBuilder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 42, + "column": 5, + "endLine": 42, + "endColumn": 12, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"ForEach\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 42, + "column": 33, + "endLine": 42, + "endColumn": 47, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"WrappedBuilder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 45, + "column": 5, + "endLine": 45, + "endColumn": 12, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"ForEach\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 45, + "column": 33, + "endLine": 45, + "endColumn": 47, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"WrappedBuilder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 48, + "column": 5, + "endLine": 48, + "endColumn": 12, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"ForEach\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 48, + "column": 33, + "endLine": 48, + "endColumn": 47, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"WrappedBuilder\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 54, + "column": 5, + "endLine": 54, + "endColumn": 8, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"Row\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 55, + "column": 7, + "endLine": 55, + "endColumn": 13, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"Column\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/wrapped_builder_generic_2.ets.json b/ets2panda/linter/test/main/wrapped_builder_generic_2.ets.json new file mode 100644 index 0000000000000000000000000000000000000000..ca88f857e960b437dcf767c0ac40be998c8f1236 --- /dev/null +++ b/ets2panda/linter/test/main/wrapped_builder_generic_2.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