diff --git a/ets2panda/linter/rule-config.json b/ets2panda/linter/rule-config.json index 86ed49ff43ca9bca6868bb3e2e6e0fe94c3ac3d9..47514b0ffa8a72e5fef512b865ca19840d5fb8ea 100644 --- a/ets2panda/linter/rule-config.json +++ b/ets2panda/linter/rule-config.json @@ -114,7 +114,8 @@ "arkui-no-setandprop-function", "arkui-prop-need-call-method-for-deep-copy", "arkui-no-localbuilder-decorator", - "arkui-statestyles-block-need-arrow-func" + "arkui-statestyles-block-need-arrow-func", + "arkui-persistprop-serialization" ], "builtin": [ "arkts-builtin-thisArgs", diff --git a/ets2panda/linter/src/lib/CookBookMsg.ts b/ets2panda/linter/src/lib/CookBookMsg.ts index 31ef5659cba1e9c03963f5c8f1d749e6ebcfbfc9..ac4cf1e1f7c0697e1930e1c24738e85f23fc4c15 100644 --- a/ets2panda/linter/src/lib/CookBookMsg.ts +++ b/ets2panda/linter/src/lib/CookBookMsg.ts @@ -361,6 +361,8 @@ cookBookTag[357] = 'Worker are not supported(arkts-no-need-stdlib-worker)'; cookBookTag[358] = 'Using "Object.getOwnPropertyNames" is not allowed in this API (arkts-builtin-object-getOwnPropertyNames))'; cookBookTag[359] = '"@LocalBuilder" Decorator is not supported (arkui-no-localbuilder-decorator)'; +cookBookTag[360] = + 'The class of the second parameter of "persistProp" should be a primitive type or Date type, or implement "Parcelable" and "Stringifiable" interface to ensure it can be serialized and deserialized (arkui-persistprop-serialization)'; 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 c183485e36625039dc9841133f3648365539596e..fcffd202b35fc0bea08e8beb1d7badbea95b7bd7 100644 --- a/ets2panda/linter/src/lib/FaultAttrs.ts +++ b/ets2panda/linter/src/lib/FaultAttrs.ts @@ -256,6 +256,7 @@ faultsAttrs[FaultID.LimitedStdLibNoDoncurrentDecorator] = new FaultAttributes(35 faultsAttrs[FaultID.NoNeedStdlibWorker] = new FaultAttributes(357); faultsAttrs[FaultID.BuiltinGetOwnPropertyNames] = new FaultAttributes(358); faultsAttrs[FaultID.LocalBuilderDecoratorNotSupported] = new FaultAttributes(359); +faultsAttrs[FaultID.PropNeedCallMethodForSerialization] = new FaultAttributes(360); 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 2ae56f2bd19b33b9636c705f35b6bd8629a06975..bbe2f8dd6869f1414774bd60e53fce2ab08aa0ca 100644 --- a/ets2panda/linter/src/lib/FaultDesc.ts +++ b/ets2panda/linter/src/lib/FaultDesc.ts @@ -256,3 +256,4 @@ faultDesc[FaultID.SetAndPropFunctionNotSupported] = '"setAndProp" function is no faultDesc[FaultID.PropNeedCallMethodForDeepCopy] = 'Deep copy needs to call the specific method'; faultDesc[FaultID.StateStylesBlockNeedArrowFunc] = 'StateStyles needs arrow function block'; faultDesc[FaultID.PromiseVoidNeedResolveArg] = 'Promiseconstructor only supports using resolve (undefined)'; +faultDesc[FaultID.PropNeedCallMethodForSerialization] = 'Serialization needs to call the specific method'; diff --git a/ets2panda/linter/src/lib/Problems.ts b/ets2panda/linter/src/lib/Problems.ts index e8a9b611d3a9f494526d756a744014f060d82252..b555a0257effe75463578dff455cc9ceac4448f8 100644 --- a/ets2panda/linter/src/lib/Problems.ts +++ b/ets2panda/linter/src/lib/Problems.ts @@ -256,6 +256,7 @@ export enum FaultID { PropNeedCallMethodForDeepCopy, StateStylesBlockNeedArrowFunc, PromiseVoidNeedResolveArg, + PropNeedCallMethodForSerialization, // 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 70ab7059c246a0cac14219687a5714b5ac12ab36..9f5aaa6e41cf36dc3975417046a3b9edc2f8158b 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -102,7 +102,11 @@ import { PropDecoratorName, PropFunctionName, StorageTypeName, - customLayoutFunctionName + customLayoutFunctionName, + PERSIST_PROP_FUNC_NAME, + PERSIST_PROP_ARG_COUNT, + serializationTypeFlags, + serializationTypeName } from './utils/consts/ArkuiConstants'; import { arkuiImportList } from './utils/consts/ArkuiImportList'; import type { IdentifierAndArguments, ForbidenAPICheckResult } from './utils/consts/InteropAPI'; @@ -4530,7 +4534,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { private handleCallExpression(node: ts.Node): void { const tsCallExpr = node as ts.CallExpression; this.checkSdkAbilityLifecycleMonitor(tsCallExpr); - this.handleStateStyles(tsCallExpr); + this.handleCallExpressionForUI(tsCallExpr); this.handleBuiltinCtorCallSignature(tsCallExpr); this.handleSdkConstructorIfaceForCallExpression(tsCallExpr); if (this.options.arkts2 && tsCallExpr.typeArguments !== undefined) { @@ -4572,6 +4576,11 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { this.checkRestrictedAPICall(tsCallExpr); } + private handleCallExpressionForUI(node: ts.CallExpression): void { + this.handleStateStyles(node); + this.handleCallExpressionForSerialization(node); + } + handleNoTsLikeFunctionCall(callExpr: ts.CallExpression): void { if (!this.options.arkts2) { return; @@ -11108,4 +11117,62 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return false; } + + private handleCallExpressionForSerialization(node: ts.CallExpression): void { + if (!this.options.arkts2) { + return; + } + + const propertyAccess = node.expression; + if (!ts.isPropertyAccessExpression(propertyAccess)) { + return; + } + + const storage = propertyAccess.expression; + if ( + !ts.isIdentifier(storage) || + storage.getText() !== StorageTypeName.PersistentStorage || + this.isDeclarationInSameFile(storage) + ) { + return; + } + + const funcName = propertyAccess.name; + if (!ts.isIdentifier(funcName) || funcName.getText() !== PERSIST_PROP_FUNC_NAME) { + return; + } + + if (node.arguments.length !== PERSIST_PROP_ARG_COUNT) { + return; + } + const arg = node.arguments[1]; + if (this.checkArgumentForSerialization(arg)) { + return; + } + + this.incrementCounters(node, FaultID.PropNeedCallMethodForSerialization); + } + + private checkArgumentForSerialization(arg: ts.Node): boolean { + const type = this.tsTypeChecker.getTypeAtLocation(arg); + + if (type.isUnion()) { + if ( + type.types.some((type) => { + return !this.isSpecificTypeOfSerialization(type); + }) + ) { + return false; + } + return true; + } + + return this.isSpecificTypeOfSerialization(type); + } + + private isSpecificTypeOfSerialization(node: ts.Type): boolean { + const flag = node.flags; + const typeName = this.tsTypeChecker.typeToString(node); + return serializationTypeFlags.has(flag) || serializationTypeName.has(typeName); + } } diff --git a/ets2panda/linter/src/lib/utils/consts/ArkuiConstants.ts b/ets2panda/linter/src/lib/utils/consts/ArkuiConstants.ts index 5405ffe91fbad020ed6821eed61444cea308736f..977fc072af22292515df30f7c46eaeabe80691b1 100644 --- a/ets2panda/linter/src/lib/utils/consts/ArkuiConstants.ts +++ b/ets2panda/linter/src/lib/utils/consts/ArkuiConstants.ts @@ -26,6 +26,8 @@ export const INDENT_STEP = 2; export const MAKE_OBSERVED = 'makeObserved'; export const ARKUI_STATE_MANAGEMENT = '@ohos.arkui.StateManagement'; export const NEW_PROP_DECORATOR_SUFFIX = 'Ref'; +export const PERSIST_PROP_FUNC_NAME = 'persistProp'; +export const PERSIST_PROP_ARG_COUNT = 2; export enum CustomDecoratorName { Extend = 'Extend', @@ -40,7 +42,8 @@ export enum CustomDecoratorName { export enum StorageTypeName { LocalStorage = 'LocalStorage', - AppStorage = 'AppStorage' + AppStorage = 'AppStorage', + PersistentStorage = 'PersistentStorage' } export enum PropDecoratorName { @@ -78,6 +81,74 @@ export const skipImportDecoratorName: Set = new Set([ 'LocalStorageProp' ]); +export const serializationTypeFlags: Set = new Set([ + 4, + 8, + 16, + 128, + 256, + 512, + 32768, + 65536 +]); + +export const serializationTypeName: Set = new Set([ + 'Date', + 'number', + 'boolean', + 'string', + 'undefined', + 'null', + 'Date[]', + 'number[]', + 'boolean[]', + 'string[]', + 'undefined[]', + 'null[]', + 'Set', + 'Set', + 'Set', + 'Set', + 'Set', + 'Set', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map', + 'Map' +]); + export const customLayoutFunctionName: Set = new Set(['onMeasureSize', 'onPlaceChildren']); export const ENTRY_DECORATOR_NAME = 'Entry'; diff --git a/ets2panda/linter/test/main/persist_prop_1.ets b/ets2panda/linter/test/main/persist_prop_1.ets new file mode 100644 index 0000000000000000000000000000000000000000..7166d8ce44177c29337bfcdfab2655c6a09fb828 --- /dev/null +++ b/ets2panda/linter/test/main/persist_prop_1.ets @@ -0,0 +1,68 @@ +/* + * 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. + */ + +class MyClassA {} + +function MyGet1() { + if (1 > 0) { + return 1 + } else { + return 2 + } +} + +function MyGet2() { + if (1 > 0) { + return 0 + } else { + return new MyClassA() + } +} + +const a1 = new MyClassA(); +const a2 = new MyClassA(); +const myArr1: Array = new Array(1, 2); +const mySet1: Set = new Set([1, 2, 3]); +const myMap1: Map = new Map([["jack", 3], ["tom", 2]]); +const myMap2: Map = new Map([[1, a1], [2, a2]]); + +PersistentStorage.persistProp('PropA', 47); +PersistentStorage.persistProp('PropA', true); +PersistentStorage.persistProp('PropA', "Jack"); +PersistentStorage.persistProp('PropA', null); +PersistentStorage.persistProp('PropA', undefined); +PersistentStorage.persistProp('PropA', new Date()); +PersistentStorage.persistProp('PropA', a1); // error +PersistentStorage.persistProp('PropA', new MyClassA()); // error +PersistentStorage.persistProp('PropA', MyGet1()); +PersistentStorage.persistProp('PropA', MyGet2()); // error +PersistentStorage.persistProp('PropA', 1 < 0 ? 1 : new MyClassA()); // error + +PersistentStorage.persistProp('PropA', new Array(1, 2)); +PersistentStorage.persistProp('PropA', new Array("jack", "tom")); +PersistentStorage.persistProp('PropA', new Array(myArr1)); // error +PersistentStorage.persistProp('PropA', new Array(new MyClassA())); // error +PersistentStorage.persistProp('PropA', new Array(a1)); // error + +PersistentStorage.persistProp('PropA', new Set([1, 2])); +PersistentStorage.persistProp('PropA', new Set(["jack", "tom"])); +PersistentStorage.persistProp('PropA', mySet1); +PersistentStorage.persistProp('PropA', new Set([new MyClassA()])); // error +PersistentStorage.persistProp('PropA', new Set([a1])); // error + +PersistentStorage.persistProp('PropA', new Map([["jack", 3], ["tom", 2]])); +PersistentStorage.persistProp('PropA', new Map([[1, a1], [2, a2]])); // error +PersistentStorage.persistProp('PropA', myMap1); +PersistentStorage.persistProp('PropA', myMap2); // error \ No newline at end of file diff --git a/ets2panda/linter/test/main/persist_prop_1.ets.args.json b/ets2panda/linter/test/main/persist_prop_1.ets.args.json new file mode 100644 index 0000000000000000000000000000000000000000..ec9992d92461d66e16b80975e33f95872c06af54 --- /dev/null +++ b/ets2panda/linter/test/main/persist_prop_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/persist_prop_1.ets.arkts2.json b/ets2panda/linter/test/main/persist_prop_1.ets.arkts2.json new file mode 100644 index 0000000000000000000000000000000000000000..a0d53da1c0b6d0fce2fee8dfa16f99f770ad2ab9 --- /dev/null +++ b/ets2panda/linter/test/main/persist_prop_1.ets.arkts2.json @@ -0,0 +1,808 @@ +{ + "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": 19, + "column": 7, + "endLine": 19, + "endColumn": 8, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 19, + "column": 11, + "endLine": 19, + "endColumn": 12, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 12, + "endLine": 20, + "endColumn": 13, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 12, + "endLine": 22, + "endColumn": 13, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 7, + "endLine": 27, + "endColumn": 8, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 11, + "endLine": 27, + "endColumn": 12, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 28, + "column": 12, + "endLine": 28, + "endColumn": 13, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 36, + "column": 31, + "endLine": 36, + "endColumn": 46, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 36, + "column": 41, + "endLine": 36, + "endColumn": 42, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 36, + "column": 44, + "endLine": 36, + "endColumn": 45, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 37, + "column": 29, + "endLine": 37, + "endColumn": 47, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 37, + "column": 38, + "endLine": 37, + "endColumn": 39, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 37, + "column": 41, + "endLine": 37, + "endColumn": 42, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 37, + "column": 44, + "endLine": 37, + "endColumn": 45, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 38, + "column": 37, + "endLine": 38, + "endColumn": 71, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 38, + "column": 55, + "endLine": 38, + "endColumn": 56, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 38, + "column": 67, + "endLine": 38, + "endColumn": 68, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 39, + "column": 39, + "endLine": 39, + "endColumn": 66, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 39, + "column": 49, + "endLine": 39, + "endColumn": 50, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 39, + "column": 58, + "endLine": 39, + "endColumn": 59, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 41, + "column": 40, + "endLine": 41, + "endColumn": 42, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 47, + "column": 1, + "endLine": 47, + "endColumn": 43, + "problem": "PropNeedCallMethodForSerialization", + "suggest": "", + "rule": "The class of the second parameter of \"persistProp\" should be a primitive type or Date type, or implement \"Parcelable\" and \"Stringifiable\" interface to ensure it can be serialized and deserialized (arkui-persistprop-serialization)", + "severity": "ERROR" + }, + { + "line": 48, + "column": 1, + "endLine": 48, + "endColumn": 55, + "problem": "PropNeedCallMethodForSerialization", + "suggest": "", + "rule": "The class of the second parameter of \"persistProp\" should be a primitive type or Date type, or implement \"Parcelable\" and \"Stringifiable\" interface to ensure it can be serialized and deserialized (arkui-persistprop-serialization)", + "severity": "ERROR" + }, + { + "line": 50, + "column": 1, + "endLine": 50, + "endColumn": 49, + "problem": "PropNeedCallMethodForSerialization", + "suggest": "", + "rule": "The class of the second parameter of \"persistProp\" should be a primitive type or Date type, or implement \"Parcelable\" and \"Stringifiable\" interface to ensure it can be serialized and deserialized (arkui-persistprop-serialization)", + "severity": "ERROR" + }, + { + "line": 51, + "column": 1, + "endLine": 51, + "endColumn": 67, + "problem": "PropNeedCallMethodForSerialization", + "suggest": "", + "rule": "The class of the second parameter of \"persistProp\" should be a primitive type or Date type, or implement \"Parcelable\" and \"Stringifiable\" interface to ensure it can be serialized and deserialized (arkui-persistprop-serialization)", + "severity": "ERROR" + }, + { + "line": 51, + "column": 40, + "endLine": 51, + "endColumn": 41, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 51, + "column": 44, + "endLine": 51, + "endColumn": 45, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 51, + "column": 48, + "endLine": 51, + "endColumn": 49, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 53, + "column": 40, + "endLine": 53, + "endColumn": 55, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 53, + "column": 50, + "endLine": 53, + "endColumn": 51, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 53, + "column": 53, + "endLine": 53, + "endColumn": 54, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 54, + "column": 40, + "endLine": 54, + "endColumn": 64, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 55, + "column": 1, + "endLine": 55, + "endColumn": 58, + "problem": "PropNeedCallMethodForSerialization", + "suggest": "", + "rule": "The class of the second parameter of \"persistProp\" should be a primitive type or Date type, or implement \"Parcelable\" and \"Stringifiable\" interface to ensure it can be serialized and deserialized (arkui-persistprop-serialization)", + "severity": "ERROR" + }, + { + "line": 55, + "column": 40, + "endLine": 55, + "endColumn": 57, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 56, + "column": 1, + "endLine": 56, + "endColumn": 66, + "problem": "PropNeedCallMethodForSerialization", + "suggest": "", + "rule": "The class of the second parameter of \"persistProp\" should be a primitive type or Date type, or implement \"Parcelable\" and \"Stringifiable\" interface to ensure it can be serialized and deserialized (arkui-persistprop-serialization)", + "severity": "ERROR" + }, + { + "line": 56, + "column": 40, + "endLine": 56, + "endColumn": 65, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 57, + "column": 1, + "endLine": 57, + "endColumn": 54, + "problem": "PropNeedCallMethodForSerialization", + "suggest": "", + "rule": "The class of the second parameter of \"persistProp\" should be a primitive type or Date type, or implement \"Parcelable\" and \"Stringifiable\" interface to ensure it can be serialized and deserialized (arkui-persistprop-serialization)", + "severity": "ERROR" + }, + { + "line": 57, + "column": 40, + "endLine": 57, + "endColumn": 53, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 59, + "column": 40, + "endLine": 59, + "endColumn": 55, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 59, + "column": 49, + "endLine": 59, + "endColumn": 50, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 59, + "column": 52, + "endLine": 59, + "endColumn": 53, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 60, + "column": 40, + "endLine": 60, + "endColumn": 64, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 62, + "column": 1, + "endLine": 62, + "endColumn": 66, + "problem": "PropNeedCallMethodForSerialization", + "suggest": "", + "rule": "The class of the second parameter of \"persistProp\" should be a primitive type or Date type, or implement \"Parcelable\" and \"Stringifiable\" interface to ensure it can be serialized and deserialized (arkui-persistprop-serialization)", + "severity": "ERROR" + }, + { + "line": 62, + "column": 40, + "endLine": 62, + "endColumn": 65, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 63, + "column": 1, + "endLine": 63, + "endColumn": 54, + "problem": "PropNeedCallMethodForSerialization", + "suggest": "", + "rule": "The class of the second parameter of \"persistProp\" should be a primitive type or Date type, or implement \"Parcelable\" and \"Stringifiable\" interface to ensure it can be serialized and deserialized (arkui-persistprop-serialization)", + "severity": "ERROR" + }, + { + "line": 63, + "column": 40, + "endLine": 63, + "endColumn": 53, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 65, + "column": 40, + "endLine": 65, + "endColumn": 74, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 65, + "column": 58, + "endLine": 65, + "endColumn": 59, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 65, + "column": 70, + "endLine": 65, + "endColumn": 71, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 66, + "column": 1, + "endLine": 66, + "endColumn": 68, + "problem": "PropNeedCallMethodForSerialization", + "suggest": "", + "rule": "The class of the second parameter of \"persistProp\" should be a primitive type or Date type, or implement \"Parcelable\" and \"Stringifiable\" interface to ensure it can be serialized and deserialized (arkui-persistprop-serialization)", + "severity": "ERROR" + }, + { + "line": 66, + "column": 40, + "endLine": 66, + "endColumn": 67, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 66, + "column": 50, + "endLine": 66, + "endColumn": 51, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 66, + "column": 59, + "endLine": 66, + "endColumn": 60, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 68, + "column": 1, + "endLine": 68, + "endColumn": 47, + "problem": "PropNeedCallMethodForSerialization", + "suggest": "", + "rule": "The class of the second parameter of \"persistProp\" should be a primitive type or Date type, or implement \"Parcelable\" and \"Stringifiable\" interface to ensure it can be serialized and deserialized (arkui-persistprop-serialization)", + "severity": "ERROR" + }, + { + "line": 41, + "column": 1, + "endLine": 41, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 42, + "column": 1, + "endLine": 42, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 43, + "column": 1, + "endLine": 43, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 44, + "column": 1, + "endLine": 44, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 45, + "column": 1, + "endLine": 45, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 46, + "column": 1, + "endLine": 46, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 47, + "column": 1, + "endLine": 47, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 48, + "column": 1, + "endLine": 48, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 49, + "column": 1, + "endLine": 49, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 50, + "column": 1, + "endLine": 50, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 51, + "column": 1, + "endLine": 51, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 53, + "column": 1, + "endLine": 53, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 54, + "column": 1, + "endLine": 54, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 55, + "column": 1, + "endLine": 55, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 56, + "column": 1, + "endLine": 56, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 57, + "column": 1, + "endLine": 57, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 59, + "column": 1, + "endLine": 59, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 60, + "column": 1, + "endLine": 60, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 61, + "column": 1, + "endLine": 61, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 62, + "column": 1, + "endLine": 62, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 63, + "column": 1, + "endLine": 63, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 65, + "column": 1, + "endLine": 65, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 66, + "column": 1, + "endLine": 66, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 67, + "column": 1, + "endLine": 67, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" should be imported before it is used (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 68, + "column": 1, + "endLine": 68, + "endColumn": 18, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "The ArkUI interface \"PersistentStorage\" 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/persist_prop_1.ets.json b/ets2panda/linter/test/main/persist_prop_1.ets.json new file mode 100644 index 0000000000000000000000000000000000000000..ca88f857e960b437dcf767c0ac40be998c8f1236 --- /dev/null +++ b/ets2panda/linter/test/main/persist_prop_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