diff --git a/ets2panda/linter/rule-config.json b/ets2panda/linter/rule-config.json index 611a033828ee351a8d883852ab8fb3785bf19ed0..1d38b935e97c5ca7e3cbe69db2d95516324149c8 100644 --- a/ets2panda/linter/rule-config.json +++ b/ets2panda/linter/rule-config.json @@ -70,7 +70,8 @@ "arkts-no-duplicate-function-name", "arkts-require-func-arg-type", "arkts-subclass-must-call-super-constructor-with-args", - "arkts-no-esobject-support" + "arkts-no-esobject-support", + "arkts-not-support-tuple-generic-validation" ], "interop": [ "arkts-interop-js2s-inherit-js-class", diff --git a/ets2panda/linter/src/lib/CookBookMsg.ts b/ets2panda/linter/src/lib/CookBookMsg.ts index f0b8e41253982f18ac37463e1e3174e0224759f0..d208fecb493abafc8471db76671ba6e4d9991fb1 100644 --- a/ets2panda/linter/src/lib/CookBookMsg.ts +++ b/ets2panda/linter/src/lib/CookBookMsg.ts @@ -310,6 +310,8 @@ cookBookTag[284] = '"prop" function is not supported (arkui-no-prop-function)'; cookBookTag[285] = '"setAndProp" function is not supported (arkui-no-setandprop-function)'; cookBookTag[286] = 'Parameters decorated with "@Prop" need to call the specific method when receiving data to ensure deep copy of the data (arkui-prop-need-call-method-for-deep-copy)'; +cookBookTag[290] = + 'Tuple type cannot be used in generic type parameters of Promise static methods (arkts-not-support-tuple-generic-validation)'; cookBookTag[300] = 'The function type should be explicit (arkts-no-ts-like-function-call)'; cookBookTag[301] = 'Importing from "oh module" requires specifying full path (arkts-require-fullpath-name)'; cookBookTag[302] = diff --git a/ets2panda/linter/src/lib/FaultAttrs.ts b/ets2panda/linter/src/lib/FaultAttrs.ts index 8ace468f161fd5f32f2aac72700714920a6452b3..bbb1c1fb6d4d5da3544fa6a082521795dd7159e6 100644 --- a/ets2panda/linter/src/lib/FaultAttrs.ts +++ b/ets2panda/linter/src/lib/FaultAttrs.ts @@ -212,6 +212,7 @@ faultsAttrs[FaultID.LocalStoragePropDecoratorNotSupported] = new FaultAttributes faultsAttrs[FaultID.PropFunctionNotSupported] = new FaultAttributes(284); faultsAttrs[FaultID.SetAndPropFunctionNotSupported] = new FaultAttributes(285); faultsAttrs[FaultID.PropNeedCallMethodForDeepCopy] = new FaultAttributes(286); +faultsAttrs[FaultID.NotSupportTupleGenericValidation] = new FaultAttributes(290); faultsAttrs[FaultID.ExplicitFunctionType] = new FaultAttributes(300); faultsAttrs[FaultID.OhmUrlFullPath] = new FaultAttributes(301); faultsAttrs[FaultID.InteropCallObjectParam] = new FaultAttributes(302); diff --git a/ets2panda/linter/src/lib/FaultDesc.ts b/ets2panda/linter/src/lib/FaultDesc.ts index d812eab32339364d3f430dad380008fcffea5ec2..073c8543908ac61d50e92c476dfea041c1834508 100644 --- a/ets2panda/linter/src/lib/FaultDesc.ts +++ b/ets2panda/linter/src/lib/FaultDesc.ts @@ -170,6 +170,8 @@ faultDesc[FaultID.InteropJsObjectConditionJudgment] = 'Interop JS Object usage i faultDesc[FaultID.InteropJsObjectExpandStaticInstance] = 'Interop JS function usage'; faultDesc[FaultID.InteropJSFunctionInvoke] = 'Interop JS function invoke'; faultDesc[FaultID.VariableMissingInitializer] = 'Value must be assigned to variable'; +faultDesc[FaultID.NotSupportTupleGenericValidation] = + 'Tuple type cannot be used in generic type parameters of Promise static methods'; faultDesc[FaultID.ExplicitFunctionType] = 'Not explicit function type'; faultDesc[FaultID.ClassstaticInitialization] = 'The static properties of a class need to have initial values'; faultDesc[FaultID.AvoidUnionTypes] = 'Union types'; diff --git a/ets2panda/linter/src/lib/Problems.ts b/ets2panda/linter/src/lib/Problems.ts index dd700b4ed503bf045a326a84be4b9149e4628771..3c46edaec6defb39e91c1d3c926170d8390e05c5 100644 --- a/ets2panda/linter/src/lib/Problems.ts +++ b/ets2panda/linter/src/lib/Problems.ts @@ -168,6 +168,7 @@ export enum FaultID { MethodOverridingField, InteropJsObjectConditionJudgment, InteropJsObjectExpandStaticInstance, + NotSupportTupleGenericValidation, ExplicitFunctionType, ClassstaticInitialization, TaggedTemplates, diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index 1e0dd75815109e868dd9b34384f35e41c0523c98..c135393b92e9e7bfdfe5bb818c0f92910c28c5a3 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -19,7 +19,7 @@ import { FaultID } from './Problems'; import { TypeScriptLinterConfig } from './TypeScriptLinterConfig'; import type { Autofix } from './autofixes/Autofixer'; import { Autofixer } from './autofixes/Autofixer'; -import { PROMISE_METHODS, SYMBOL, SYMBOL_CONSTRUCTOR, TsUtils } from './utils/TsUtils'; +import { PROMISE_METHODS, PROMISE_METHODS_WITH_NO_TUPLE_SUPPORT, SYMBOL, SYMBOL_CONSTRUCTOR, TsUtils } from './utils/TsUtils'; import { FUNCTION_HAS_NO_RETURN_ERROR_CODE } from './utils/consts/FunctionHasNoReturnErrorCode'; import { LIMITED_STANDARD_UTILITY_TYPES, @@ -5323,6 +5323,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { this.checkRestrictedAPICall(tsCallExpr); this.handleNoDeprecatedApi(tsCallExpr); this.handleFunctionReturnThisCall(tsCallExpr); + this.handlePromiseTupleGeneric(tsCallExpr); } private handleCallExpressionForUI(node: ts.CallExpression): void { @@ -13680,4 +13681,32 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } return false; } + + private handlePromiseTupleGeneric(node: ts.CallExpression): void { + if (!this.options.arkts2) { + return; + } + + if ( + ts.isPropertyAccessExpression(node.expression) && + ts.isIdentifier(node.expression.expression) && + node.expression.expression.text === PROMISE + ) { + const methodName = node.expression.name.text; + + if (!PROMISE_METHODS_WITH_NO_TUPLE_SUPPORT.has(methodName)) { + return; + } + + const typeArguments = node.typeArguments; + if (!typeArguments || typeArguments.length === 0) { + return; + } + + const firstArg = typeArguments[0]; + if (ts.isTupleTypeNode(firstArg)) { + this.incrementCounters(firstArg, FaultID.NotSupportTupleGenericValidation); + } + } + } } diff --git a/ets2panda/linter/src/lib/utils/TsUtils.ts b/ets2panda/linter/src/lib/utils/TsUtils.ts index 39de11646f745e3c6484a38036e6be15aedccd19..6f807ca428f09d525e63e28c7d03a921f2603ec9 100644 --- a/ets2panda/linter/src/lib/utils/TsUtils.ts +++ b/ets2panda/linter/src/lib/utils/TsUtils.ts @@ -49,6 +49,7 @@ import { EXTNAME_ETS, EXTNAME_JS, EXTNAME_D_ETS } from './consts/ExtensionName'; import { CONCAT_ARRAY, STRING_ERROR_LITERAL } from './consts/Literals'; export const PROMISE_METHODS = new Set(['all', 'race', 'any', 'resolve', 'allSettled']); +export const PROMISE_METHODS_WITH_NO_TUPLE_SUPPORT = new Set(['all', 'race', 'any', 'allSettled']); export const SYMBOL = 'Symbol'; export const SYMBOL_CONSTRUCTOR = 'SymbolConstructor'; const ITERATOR = 'iterator'; diff --git a/ets2panda/linter/test/main/arkts-not-support-tuple-generic-validation.ets b/ets2panda/linter/test/main/arkts-not-support-tuple-generic-validation.ets new file mode 100644 index 0000000000000000000000000000000000000000..5f1044a71a7f3e66af4523a8d1b639375bc69e30 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-not-support-tuple-generic-validation.ets @@ -0,0 +1,25 @@ +/* + * 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. + */ + +let p1: Promise = new Promise((resolve) => resolve("ok")); +let p2: Promise = new Promise((resolve) => resolve(1)); + +Promise.all<[Promise, Promise]>([p1, p2]); // error +Promise.any<[Promise, Promise]>([p1, p2]); // error +Promise.race<[Promise, Promise]>([p1, p2]); // error +Promise.allSettled<[Promise, Promise]>([p1, p2]); // error + +Promise.all([p1, p2]); // valid +Promise.any([p1, p2]); // valid diff --git a/ets2panda/linter/test/main/arkts-not-support-tuple-generic-validation.ets.args.json b/ets2panda/linter/test/main/arkts-not-support-tuple-generic-validation.ets.args.json new file mode 100644 index 0000000000000000000000000000000000000000..d8d3390ad9befeca9b595017d9eea0f5ada3d049 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-not-support-tuple-generic-validation.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/arkts-not-support-tuple-generic-validation.ets.arkts2.json b/ets2panda/linter/test/main/arkts-not-support-tuple-generic-validation.ets.arkts2.json new file mode 100644 index 0000000000000000000000000000000000000000..25c25de79ca9b45ddafddbd3a85eb2e3ca1de5fe --- /dev/null +++ b/ets2panda/linter/test/main/arkts-not-support-tuple-generic-validation.ets.arkts2.json @@ -0,0 +1,88 @@ +{ + "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": 16, + "column": 27, + "endLine": 16, + "endColumn": 66, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 17, + "column": 27, + "endLine": 17, + "endColumn": 63, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 17, + "column": 60, + "endLine": 17, + "endColumn": 61, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 19, + "column": 13, + "endLine": 19, + "endColumn": 47, + "problem": "NotSupportTupleGenericValidation", + "suggest": "", + "rule": "Tuple type cannot be used in generic type parameters of Promise static methods (arkts-not-support-tuple-generic-validation)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 13, + "endLine": 20, + "endColumn": 47, + "problem": "NotSupportTupleGenericValidation", + "suggest": "", + "rule": "Tuple type cannot be used in generic type parameters of Promise static methods (arkts-not-support-tuple-generic-validation)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 14, + "endLine": 21, + "endColumn": 48, + "problem": "NotSupportTupleGenericValidation", + "suggest": "", + "rule": "Tuple type cannot be used in generic type parameters of Promise static methods (arkts-not-support-tuple-generic-validation)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 20, + "endLine": 22, + "endColumn": 54, + "problem": "NotSupportTupleGenericValidation", + "suggest": "", + "rule": "Tuple type cannot be used in generic type parameters of Promise static methods (arkts-not-support-tuple-generic-validation)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/arkts-not-support-tuple-generic-validation.ets.json b/ets2panda/linter/test/main/arkts-not-support-tuple-generic-validation.ets.json new file mode 100644 index 0000000000000000000000000000000000000000..895325b061c0fe9fa6b75bab6ed4259b5343c199 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-not-support-tuple-generic-validation.ets.json @@ -0,0 +1,18 @@ +{ + "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