From e26f01bfdc1baed04a0c9708142134caacc67317 Mon Sep 17 00:00:00 2001 From: Evgeniy Okolnov Date: Tue, 11 Jul 2023 20:56:36 +0300 Subject: [PATCH 1/5] [ArkTS Linter] Count use of limited Standard library API. Change-Id: I621224c83d4c7b7c58de6a620a485e2e0f099574 Signed-off-by: Evgeniy Okolnov --- linter/src/Problems.ts | 5 +- linter/src/TypeScriptLinter.ts | 24 + linter/src/TypeScriptLinterConfig.ts | 1 + linter/src/Utils.ts | 54 +++ linter/test/limited_stdlib_api.ts | 102 ++++ .../test/limited_stdlib_api.ts.autofix.json | 444 ++++++++++++++++++ linter/test/limited_stdlib_api.ts.relax.json | 373 +++++++++++++++ linter/test/limited_stdlib_api.ts.strict.json | 373 +++++++++++++++ linter/test/new_target.ts.relax.json | 5 + linter/test/new_target.ts.strict.json | 5 + 10 files changed, 1384 insertions(+), 2 deletions(-) create mode 100644 linter/test/limited_stdlib_api.ts create mode 100644 linter/test/limited_stdlib_api.ts.autofix.json create mode 100644 linter/test/limited_stdlib_api.ts.relax.json create mode 100644 linter/test/limited_stdlib_api.ts.strict.json diff --git a/linter/src/Problems.ts b/linter/src/Problems.ts index 1a492e5e0..c001b4178 100644 --- a/linter/src/Problems.ts +++ b/linter/src/Problems.ts @@ -33,7 +33,7 @@ export enum FaultID { InstanceofUnsupported, ShorthandAmbientModuleDecl, WildcardsInModuleName, UMDModuleDefinition, JSExtensionInModuleIdent, NewTarget, DynamicImport, DefiniteAssignment, IifeAsNamespace, Prototype, GlobalThis, UtilityType, PropertyDeclOnFunction, FunctionApplyBindCall, ReadonlyArr, ConstAssertion, ImportAssertion, - BigIntLiteral, SpreadOperator, + BigIntLiteral, SpreadOperator, LimitedStdLibApi, LAST_ID, // this should always be last enum` } @@ -69,7 +69,7 @@ faultsAttrs[FaultID.ParameterProperties] = {migratable: true, cookBookRef: '25', faultsAttrs[FaultID.IndexedAccessType] = {cookBookRef: '28',}; faultsAttrs[FaultID.PropertyAccessByIndex] = {migratable: true, cookBookRef: '29',}; faultsAttrs[FaultID.StructuralIdentity] = {cookBookRef: '30',}; -faultsAttrs[FaultID.InterfaceOptionalProp] = {warning: true, cookBookRef: '33',}; +faultsAttrs[FaultID.InterfaceOptionalProp] = {cookBookRef: '33',}; faultsAttrs[FaultID.GenericCallNoTypeArgs] = {cookBookRef: '34',}; faultsAttrs[FaultID.RegexLiteral] = {cookBookRef: '37',}; faultsAttrs[FaultID.ObjectLiteralNoContextType] = {cookBookRef: '38',}; @@ -142,3 +142,4 @@ faultsAttrs[FaultID.FunctionApplyBindCall] = {cookBookRef: '140',}; faultsAttrs[FaultID.ReadonlyArr] = {migratable: true, cookBookRef: '141',}; faultsAttrs[FaultID.ConstAssertion] = {cookBookRef: '142',}; faultsAttrs[FaultID.ImportAssertion] = {cookBookRef: '143',}; +faultsAttrs[FaultID.LimitedStdLibApi] = {cookBookRef: '144',}; diff --git a/linter/src/TypeScriptLinter.ts b/linter/src/TypeScriptLinter.ts index 4fcf809b6..d1523da4d 100644 --- a/linter/src/TypeScriptLinter.ts +++ b/linter/src/TypeScriptLinter.ts @@ -1178,6 +1178,9 @@ export class TypeScriptLinter { tsIdentifier.text === 'globalThis' ) this.incrementCounters(node, FaultID.GlobalThis); + + if (Utils.isGlobalSymbol(tsIdentSym) && Utils.LIMITED_STD_GLOBAL_VAR.includes(tsIdentSym.getName())) + this.incrementCounters(node, FaultID.LimitedStdLibApi); } } @@ -1263,6 +1266,7 @@ export class TypeScriptLinter { this.handleFunctionApplyBindPropCall(tsCallExpr); this.handleGenericCallWithNoTypeArgs(tsCallExpr); this.handleStructIdentAndUndefinedInArgs(tsCallExpr); + this.handleStdlibAPICall(tsCallExpr); } private handleImportCall(tsCallExpr: ts.CallExpression) { @@ -1362,6 +1366,26 @@ export class TypeScriptLinter { } } + private handleStdlibAPICall(callExpr: ts.CallExpression) { + let callSignature = TypeScriptLinter.tsTypeChecker.getResolvedSignature(callExpr); + if (!callSignature) return; + + let sym = TypeScriptLinter.tsTypeChecker.getSymbolAtLocation(callExpr.expression); + if (sym) { + let name = sym.getName(); + if ( + (Utils.isGlobalSymbol(sym) && Utils.LIMITED_STD_GLOBAL_FUNC.includes(name)) || + (Utils.isStdObjectAPI(sym) && Utils.LIMITED_STD_OBJECT_API.includes(name)) || + (Utils.isStdReflectAPI(sym) && Utils.LIMITED_STD_REFLECT_API.includes(name)) || + (Utils.isStdProxyHandlerAPI(sym) && Utils.LIMITED_STD_PROXYHANDLER_API.includes(name)) || + (Utils.isStdArrayAPI(sym) && Utils.LIMITED_STD_ARRAY_API.includes(name)) || + (Utils.isStdArrayBufferAPI(sym) && Utils.LIMITED_STD_ARRAYBUFFER_API.includes(name)) + ) { + this.incrementCounters(callExpr, FaultID.LimitedStdLibApi); + } + } + } + private handleNewExpression(node: ts.Node) { let tsNewExpr = node as ts.NewExpression; this.handleGenericCallWithNoTypeArgs(tsNewExpr); diff --git a/linter/src/TypeScriptLinterConfig.ts b/linter/src/TypeScriptLinterConfig.ts index 4b74afcbc..67fd421ce 100644 --- a/linter/src/TypeScriptLinterConfig.ts +++ b/linter/src/TypeScriptLinterConfig.ts @@ -118,6 +118,7 @@ export class LinterConfig { LinterConfig.nodeDesc[FaultID.ImportAssertion] = 'Import assertion'; LinterConfig.nodeDesc[FaultID.BigIntLiteral] = 'BigInt literal'; LinterConfig.nodeDesc[FaultID.SpreadOperator] = 'Spread operation'; + LinterConfig.nodeDesc[FaultID.LimitedStdLibApi] = 'Limited standard library API'; } // currently utility types from TypeScript extensions are not supported diff --git a/linter/src/Utils.ts b/linter/src/Utils.ts index df22d164a..101754b56 100644 --- a/linter/src/Utils.ts +++ b/linter/src/Utils.ts @@ -611,4 +611,58 @@ export function isSupportedType(typeNode: ts.TypeNode): boolean { typeNode.kind !== ts.SyntaxKind.SymbolKeyword && typeNode.kind !== ts.SyntaxKind.UndefinedKeyword && typeNode.kind !== ts.SyntaxKind.ConditionalType && typeNode.kind !== ts.SyntaxKind.MappedType && typeNode.kind !== ts.SyntaxKind.InferType && typeNode.kind !== ts.SyntaxKind.IndexedAccessType; +} + +export const LIMITED_STD_GLOBAL_FUNC = [ + 'eval', 'isFinite', 'isNaN', 'parseFloat', 'parseInt', 'encodeURI', 'encodeURIComponent', 'Encode', 'decodeURI', + 'decodeURIComponent', 'Decode', 'escape', 'unescape', 'ParseHexOctet' +]; +export const LIMITED_STD_GLOBAL_VAR = ['Infinity', 'NaN']; +export const LIMITED_STD_OBJECT_API = [ + '__proto__', '__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', 'assign', 'create', + 'defineProperties', 'defineProperty', 'entries', 'freeze', 'fromEntries', 'getOwnPropertyDescriptor', + 'getOwnPropertyDescriptors', 'getOwnPropertyNames', 'getOwnPropertySymbols', 'getPrototypeOf', 'hasOwn', + 'hasOwnProperty', 'is', 'isExtensible', 'isFrozen', 'isPrototypeOf', 'isSealed', 'keys', 'preventExtensions', + 'propertyIsEnumerable', 'seal', 'setPrototypeOf', 'values' +]; +export const LIMITED_STD_REFLECT_API = [ + 'apply', 'construct', 'defineProperty', 'deleteProperty', 'get', 'getOwnPropertyDescriptor', 'getPrototypeOf', + 'has', 'isExtensible', 'ownKeys', 'preventExtensions', 'set', 'setPrototypeOf' +]; +export const LIMITED_STD_PROXYHANDLER_API = [ + 'apply', 'construct', 'defineProperty', 'deleteProperty', 'get', 'getOwnPropertyDescriptor', 'getPrototypeOf', + 'has', 'isExtensible', 'ownKeys', 'preventExtensions', 'set', 'setPrototypeOf' +]; +export const LIMITED_STD_ARRAY_API = ['isArray']; +export const LIMITED_STD_ARRAYBUFFER_API = ['isView']; + +function getParentSymbolName(symbol: ts.Symbol): string | undefined { + const name = TypeScriptLinter.tsTypeChecker.getFullyQualifiedName(symbol); + const dotPosition = name.lastIndexOf('.'); + return (dotPosition === -1) ? undefined : name.substring(0, dotPosition); +} + +export function isGlobalSymbol(symbol: ts.Symbol): boolean { + let parentName = getParentSymbolName(symbol); + return !parentName || parentName === 'global'; +} +export function isStdObjectAPI(symbol: ts.Symbol): boolean { + let parentName = getParentSymbolName(symbol); + return !!parentName && (parentName === 'Object' || parentName === 'ObjectConstructor'); +} +export function isStdReflectAPI(symbol: ts.Symbol): boolean { + let parentName = getParentSymbolName(symbol); + return !!parentName && (parentName === 'Reflect'); +} +export function isStdProxyHandlerAPI(symbol: ts.Symbol): boolean { + let parentName = getParentSymbolName(symbol); + return !!parentName && (parentName === 'ProxyHandler'); +} +export function isStdArrayAPI(symbol: ts.Symbol): boolean { + let parentName = getParentSymbolName(symbol); + return !!parentName && (parentName === 'Array'); +} +export function isStdArrayBufferAPI(symbol: ts.Symbol): boolean { + let parentName = getParentSymbolName(symbol); + return !!parentName && (parentName === 'ArrayBuffer'); } \ No newline at end of file diff --git a/linter/test/limited_stdlib_api.ts b/linter/test/limited_stdlib_api.ts new file mode 100644 index 000000000..8a9e367fd --- /dev/null +++ b/linter/test/limited_stdlib_api.ts @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2022-2023 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. + */ + +/// Global +eval('console.log("foo")'); +let inf = Infinity; +let nan = NaN; +isFinite(1); +isNaN(2); +parseFloat('3'); +parseInt('4', 10); +encodeURI(''); +encodeURIComponent(''); +decodeURI(''); +decodeURIComponent(''); +escape(''); +unescape(''); + +global.eval('console.log("foo")'); +globalThis.eval('console.log("foo")'); + +class C {} +let c = new C(); + +/// Object +//Object.__proto__(), +//Object.__defineGetter__(), +//Object.__defineSetter__(); +//Object.__lookupGetter__(); +//Object.__lookupSetter__(); +Object.assign(c, c); +Object.create(c); +Object.defineProperties(c, {}); +Object.defineProperty(c, 'p', c); +Object.entries([]); +Object.freeze(() => {}); +Object.fromEntries([]); +Object.getOwnPropertyDescriptor(c, 'p'); +Object.getOwnPropertyDescriptors(c); +Object.getOwnPropertyNames(c); +Object.getOwnPropertySymbols(c); +Object.getPrototypeOf(c); +//Object.hasOwn(); +Object.hasOwnProperty('p'); +Object.is(c, c); +Object.isExtensible(c); +Object.isFrozen(c); +Object.isPrototypeOf(c); +Object.isSealed(c); +Object.keys(c); +Object.preventExtensions(c); +Object.propertyIsEnumerable('p'); +Object.seal(c); +Object.setPrototypeOf(c, c); +Object.values([]); + +/// Reflect +Reflect.apply(() => {}, c, []); +Reflect.construct(C, []); +Reflect.defineProperty(c, 'p', {}); +Reflect.deleteProperty(c, 'p', ); +Reflect.get(c, 'p'); +Reflect.getOwnPropertyDescriptor(c, 'p'); +Reflect.getPrototypeOf(c); +Reflect.has(c, 'p'); +Reflect.isExtensible(c); +Reflect.ownKeys(c); +Reflect.preventExtensions(c); +Reflect.set(c, 'p', 1); +Reflect.setPrototypeOf(c, c); + +/// Proxy +let handler: ProxyHandler = {}; +if (handler.apply) handler.apply(c, c, []); +if (handler.construct) handler.construct(c, [], () => {}); +if (handler.defineProperty) handler.defineProperty(c, "prop", {}); +if (handler.deleteProperty) handler.deleteProperty(c, "prop"); +if (handler.get) handler.get(c, "prop", {}); +if (handler.getOwnPropertyDescriptor) handler.getOwnPropertyDescriptor(c, "prop"); +if (handler.getPrototypeOf) handler.getPrototypeOf(c); +if (handler.has) handler.has(c, "prop"); +if (handler.isExtensible) handler.isExtensible(c); +if (handler.ownKeys) handler.ownKeys(c); +if (handler.preventExtensions) handler.preventExtensions(c); +if (handler.set) handler.set(c, "prop", 1, c); +if (handler.setPrototypeOf) handler.setPrototypeOf(c, null); + +/// Array +Array.isArray([]); +ArrayBuffer.isView({}); \ No newline at end of file diff --git a/linter/test/limited_stdlib_api.ts.autofix.json b/linter/test/limited_stdlib_api.ts.autofix.json new file mode 100644 index 000000000..93aeac27a --- /dev/null +++ b/linter/test/limited_stdlib_api.ts.autofix.json @@ -0,0 +1,444 @@ +{ + "copyright": [ + "Copyright (c) 2023-2023 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." + ], + "nodes": [ + { + "line": 17, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 18, + "column": 11, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 19, + "column": 11, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 20, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 21, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 22, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 23, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 24, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 25, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 26, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 27, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 28, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 29, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 31, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 32, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 32, + "column": 1, + "problem": "GlobalThis", + "autofixable": false + }, + { + "line": 43, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 44, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 45, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 45, + "column": 31, + "problem": "ObjectLiteralNoContextType", + "autofixable": false + }, + { + "line": 46, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 47, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 48, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 49, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 50, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 51, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 52, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 53, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 54, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 56, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 57, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 58, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 59, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 60, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 61, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 62, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 63, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 64, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 65, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 66, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 67, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 70, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 71, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 72, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 72, + "column": 32, + "problem": "ObjectLiteralNoContextType", + "autofixable": false + }, + { + "line": 73, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 74, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 75, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 76, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 77, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 78, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 79, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 80, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 81, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 82, + "column": 1, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 85, + "column": 32, + "problem": "ObjectLiteralNoContextType", + "autofixable": false + }, + { + "line": 86, + "column": 20, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 87, + "column": 24, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 88, + "column": 29, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 89, + "column": 29, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 90, + "column": 18, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 90, + "column": 41, + "problem": "ObjectLiteralNoContextType", + "autofixable": false + }, + { + "line": 91, + "column": 39, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 92, + "column": 29, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 93, + "column": 18, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 94, + "column": 27, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 95, + "column": 22, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 96, + "column": 32, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 97, + "column": 18, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 98, + "column": 29, + "problem": "LimitedStdLibApi", + "autofixable": false + }, + { + "line": 102, + "column": 20, + "problem": "ObjectLiteralNoContextType", + "autofixable": false + } + ] +} \ No newline at end of file diff --git a/linter/test/limited_stdlib_api.ts.relax.json b/linter/test/limited_stdlib_api.ts.relax.json new file mode 100644 index 000000000..3c8f187ad --- /dev/null +++ b/linter/test/limited_stdlib_api.ts.relax.json @@ -0,0 +1,373 @@ +{ + "copyright": [ + "Copyright (c) 2023-2023 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." + ], + "nodes": [ + { + "line": 17, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 18, + "column": 11, + "problem": "LimitedStdLibApi" + }, + { + "line": 19, + "column": 11, + "problem": "LimitedStdLibApi" + }, + { + "line": 20, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 21, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 22, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 23, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 24, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 25, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 26, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 27, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 28, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 29, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 31, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 32, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 32, + "column": 1, + "problem": "GlobalThis" + }, + { + "line": 43, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 44, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 45, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 45, + "column": 31, + "problem": "ObjectLiteralNoContextType" + }, + { + "line": 46, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 47, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 48, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 49, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 50, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 51, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 52, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 53, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 54, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 56, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 57, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 58, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 59, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 60, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 61, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 62, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 63, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 64, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 65, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 66, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 67, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 70, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 71, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 72, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 72, + "column": 32, + "problem": "ObjectLiteralNoContextType" + }, + { + "line": 73, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 74, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 75, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 76, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 77, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 78, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 79, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 80, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 81, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 82, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 85, + "column": 32, + "problem": "ObjectLiteralNoContextType" + }, + { + "line": 86, + "column": 20, + "problem": "LimitedStdLibApi" + }, + { + "line": 87, + "column": 24, + "problem": "LimitedStdLibApi" + }, + { + "line": 88, + "column": 29, + "problem": "LimitedStdLibApi" + }, + { + "line": 89, + "column": 29, + "problem": "LimitedStdLibApi" + }, + { + "line": 90, + "column": 18, + "problem": "LimitedStdLibApi" + }, + { + "line": 90, + "column": 41, + "problem": "ObjectLiteralNoContextType" + }, + { + "line": 91, + "column": 39, + "problem": "LimitedStdLibApi" + }, + { + "line": 92, + "column": 29, + "problem": "LimitedStdLibApi" + }, + { + "line": 93, + "column": 18, + "problem": "LimitedStdLibApi" + }, + { + "line": 94, + "column": 27, + "problem": "LimitedStdLibApi" + }, + { + "line": 95, + "column": 22, + "problem": "LimitedStdLibApi" + }, + { + "line": 96, + "column": 32, + "problem": "LimitedStdLibApi" + }, + { + "line": 97, + "column": 18, + "problem": "LimitedStdLibApi" + }, + { + "line": 98, + "column": 29, + "problem": "LimitedStdLibApi" + }, + { + "line": 102, + "column": 20, + "problem": "ObjectLiteralNoContextType" + } + ] +} \ No newline at end of file diff --git a/linter/test/limited_stdlib_api.ts.strict.json b/linter/test/limited_stdlib_api.ts.strict.json new file mode 100644 index 000000000..3c8f187ad --- /dev/null +++ b/linter/test/limited_stdlib_api.ts.strict.json @@ -0,0 +1,373 @@ +{ + "copyright": [ + "Copyright (c) 2023-2023 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." + ], + "nodes": [ + { + "line": 17, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 18, + "column": 11, + "problem": "LimitedStdLibApi" + }, + { + "line": 19, + "column": 11, + "problem": "LimitedStdLibApi" + }, + { + "line": 20, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 21, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 22, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 23, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 24, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 25, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 26, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 27, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 28, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 29, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 31, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 32, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 32, + "column": 1, + "problem": "GlobalThis" + }, + { + "line": 43, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 44, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 45, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 45, + "column": 31, + "problem": "ObjectLiteralNoContextType" + }, + { + "line": 46, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 47, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 48, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 49, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 50, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 51, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 52, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 53, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 54, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 56, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 57, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 58, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 59, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 60, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 61, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 62, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 63, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 64, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 65, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 66, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 67, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 70, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 71, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 72, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 72, + "column": 32, + "problem": "ObjectLiteralNoContextType" + }, + { + "line": 73, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 74, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 75, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 76, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 77, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 78, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 79, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 80, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 81, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 82, + "column": 1, + "problem": "LimitedStdLibApi" + }, + { + "line": 85, + "column": 32, + "problem": "ObjectLiteralNoContextType" + }, + { + "line": 86, + "column": 20, + "problem": "LimitedStdLibApi" + }, + { + "line": 87, + "column": 24, + "problem": "LimitedStdLibApi" + }, + { + "line": 88, + "column": 29, + "problem": "LimitedStdLibApi" + }, + { + "line": 89, + "column": 29, + "problem": "LimitedStdLibApi" + }, + { + "line": 90, + "column": 18, + "problem": "LimitedStdLibApi" + }, + { + "line": 90, + "column": 41, + "problem": "ObjectLiteralNoContextType" + }, + { + "line": 91, + "column": 39, + "problem": "LimitedStdLibApi" + }, + { + "line": 92, + "column": 29, + "problem": "LimitedStdLibApi" + }, + { + "line": 93, + "column": 18, + "problem": "LimitedStdLibApi" + }, + { + "line": 94, + "column": 27, + "problem": "LimitedStdLibApi" + }, + { + "line": 95, + "column": 22, + "problem": "LimitedStdLibApi" + }, + { + "line": 96, + "column": 32, + "problem": "LimitedStdLibApi" + }, + { + "line": 97, + "column": 18, + "problem": "LimitedStdLibApi" + }, + { + "line": 98, + "column": 29, + "problem": "LimitedStdLibApi" + }, + { + "line": 102, + "column": 20, + "problem": "ObjectLiteralNoContextType" + } + ] +} \ No newline at end of file diff --git a/linter/test/new_target.ts.relax.json b/linter/test/new_target.ts.relax.json index 77d2841bc..5ec99daa2 100644 --- a/linter/test/new_target.ts.relax.json +++ b/linter/test/new_target.ts.relax.json @@ -14,6 +14,11 @@ "limitations under the License." ], "nodes": [ + { + "line": 19, + "column": 5, + "problem": "LimitedStdLibApi" + }, { "line": 19, "column": 44, diff --git a/linter/test/new_target.ts.strict.json b/linter/test/new_target.ts.strict.json index 77d2841bc..5ec99daa2 100644 --- a/linter/test/new_target.ts.strict.json +++ b/linter/test/new_target.ts.strict.json @@ -14,6 +14,11 @@ "limitations under the License." ], "nodes": [ + { + "line": 19, + "column": 5, + "problem": "LimitedStdLibApi" + }, { "line": 19, "column": 44, -- Gitee From 95eff75dd32117f28ef55d2e412af934a94cec50 Mon Sep 17 00:00:00 2001 From: Igor Rossinski Date: Tue, 11 Jul 2023 23:55:37 +0100 Subject: [PATCH 2/5] [TS Linter] update rule for enums Signed-off-by: Igor Rossinski --- linter/src/TypeScriptLinter.ts | 20 ++++++ linter/src/Utils.ts | 61 +++++++++++++++---- linter/test/binary_wrong_types.ts.relax.json | 10 --- linter/test/binary_wrong_types.ts.strict.json | 10 --- linter/test/enum_member_non_constant.ts | 1 + .../enum_member_non_constant.ts.relax.json | 35 ----------- .../enum_member_non_constant.ts.strict.json | 35 ----------- linter/test/for_stmts.ts.relax.json | 15 ----- linter/test/for_stmts.ts.strict.json | 15 ----- linter/test/type_declarations.ts.relax.json | 30 --------- linter/test/type_declarations.ts.strict.json | 30 --------- 11 files changed, 70 insertions(+), 192 deletions(-) diff --git a/linter/src/TypeScriptLinter.ts b/linter/src/TypeScriptLinter.ts index d1523da4d..86b492b04 100644 --- a/linter/src/TypeScriptLinter.ts +++ b/linter/src/TypeScriptLinter.ts @@ -1231,8 +1231,28 @@ export class TypeScriptLinter { private handleEnumMember(node: ts.Node) { let tsEnumMember = node as ts.EnumMember; + let tsEnumMemberType = TypeScriptLinter.tsTypeChecker.getTypeAtLocation(tsEnumMember); + let constVal = TypeScriptLinter.tsTypeChecker.getConstantValue(tsEnumMember); + if (tsEnumMember.initializer && !Utils.isValidEnumMemberInit(tsEnumMember.initializer)) this.incrementCounters(node, FaultID.EnumMemberNonConstInit); + + // check for type - all members should be of same type + let enumDecl = tsEnumMember.parent; + let firstEnumMember = enumDecl.members[0]; + let firstEnumMemberType = TypeScriptLinter.tsTypeChecker.getTypeAtLocation(firstEnumMember); + let firstElewmVal = TypeScriptLinter.tsTypeChecker.getConstantValue(firstEnumMember); + // each string enum member has its own type + // so check that value type is string + if( constVal !==undefined && typeof constVal === 'string' && + firstElewmVal !==undefined && typeof firstElewmVal === 'string' ) + return; + if( constVal !==undefined && typeof constVal === 'number' && + firstElewmVal !==undefined && typeof firstElewmVal === 'number' ) + return; + if(firstEnumMemberType !== tsEnumMemberType) { + this.incrementCounters(node, FaultID.EnumMemberNonConstInit); + } } private handleExportDeclaration(node: ts.Node) { diff --git a/linter/src/Utils.ts b/linter/src/Utils.ts index 101754b56..d6915107b 100644 --- a/linter/src/Utils.ts +++ b/linter/src/Utils.ts @@ -292,45 +292,70 @@ function isVarDeclaration(tsDecl: ts.Declaration): boolean { export function isValidEnumMemberInit(tsExpr: ts.Expression): boolean { if (isIntegerConstantValue(tsExpr.parent as ts.EnumMember)) return true; + if (isStringConstantValue(tsExpr.parent as ts.EnumMember)) + return true; + return isCompileTimeExpression(tsExpr); +} +export function isCompileTimeExpression(tsExpr: ts.Expression): boolean { if ( - ts.isParenthesizedExpression(tsExpr) || - (ts.isAsExpression(tsExpr) && tsExpr.type.kind === ts.SyntaxKind.NumberKeyword)) - return isValidEnumMemberInit(tsExpr.expression); + ts.isParenthesizedExpression(tsExpr) || + (ts.isAsExpression(tsExpr) && tsExpr.type.kind === ts.SyntaxKind.NumberKeyword)) + return isCompileTimeExpression(tsExpr.expression); switch (tsExpr.kind) { case ts.SyntaxKind.PrefixUnaryExpression: return isPrefixUnaryExprValidEnumMemberInit(tsExpr as ts.PrefixUnaryExpression); case ts.SyntaxKind.ParenthesizedExpression: - return isBinaryExprValidEnumMemberInit(tsExpr as ts.BinaryExpression); + case ts.SyntaxKind.BinaryExpression: + return isBinaryExprValidEnumMemberInit(tsExpr as ts.BinaryExpression); case ts.SyntaxKind.ConditionalExpression: return isConditionalExprValidEnumMemberInit(tsExpr as ts.ConditionalExpression); case ts.SyntaxKind.Identifier: return isIdentifierValidEnumMemberInit(tsExpr as ts.Identifier); + case ts.SyntaxKind.NumericLiteral: + return isIntegerConstantValue(tsExpr as ts.NumericLiteral); + case ts.SyntaxKind.PropertyAccessExpression: + // if enum member is in current enum declaration try to get value + // if it comes from another enum consider as constant + const propertyAccess = tsExpr as ts.PropertyAccessExpression; + if(isIntegerConstantValue(propertyAccess)) + return true; + const leftHandSymbol = TypeScriptLinter.tsTypeChecker.getSymbolAtLocation(propertyAccess.expression); + if( !leftHandSymbol ) + return false; + const decls = leftHandSymbol.getDeclarations(); + if (!decls || decls.length !== 1) + return false; + return ts.isEnumDeclaration(decls[0]); default: - return ts.isPropertyAccessExpression(tsExpr) && isIntegerConstantValue(tsExpr) + return false; } } function isPrefixUnaryExprValidEnumMemberInit(tsExpr: ts.PrefixUnaryExpression): boolean { - return (isUnaryOpAllowedForEnumMemberInit(tsExpr.operator) && isValidEnumMemberInit(tsExpr.operand)); + return (isUnaryOpAllowedForEnumMemberInit(tsExpr.operator) && isCompileTimeExpression(tsExpr.operand)); } function isBinaryExprValidEnumMemberInit(tsExpr: ts.BinaryExpression): boolean { return ( - isBinaryOpAllowedForEnumMemberInit(tsExpr.operatorToken) && isValidEnumMemberInit(tsExpr.left) && - isValidEnumMemberInit(tsExpr.right) + isBinaryOpAllowedForEnumMemberInit(tsExpr.operatorToken) && isCompileTimeExpression(tsExpr.left) && + isCompileTimeExpression(tsExpr.right) ); } function isConditionalExprValidEnumMemberInit(tsExpr: ts.ConditionalExpression): boolean { - return (isValidEnumMemberInit(tsExpr.whenTrue) && isValidEnumMemberInit(tsExpr.whenFalse)); + return (isCompileTimeExpression(tsExpr.whenTrue) && isCompileTimeExpression(tsExpr.whenFalse)); } function isIdentifierValidEnumMemberInit(tsExpr: ts.Identifier): boolean { let tsSymbol = TypeScriptLinter.tsTypeChecker.getSymbolAtLocation(tsExpr); let tsDecl = getDeclaration(tsSymbol); - return (!!tsDecl && isVarDeclaration(tsDecl) && isConst(tsDecl.parent)); + return (!!tsDecl && + ( (isVarDeclaration(tsDecl) && isConst(tsDecl.parent)) || + (tsDecl.kind === ts.SyntaxKind.EnumMember) + ) + ); } function isUnaryOpAllowedForEnumMemberInit(tsPrefixUnaryOp: ts.PrefixUnaryOperator): boolean { @@ -357,13 +382,25 @@ export function isConst(tsNode: ts.Node): boolean { } export function isIntegerConstantValue( - tsExpr: ts.EnumMember | ts.PropertyAccessExpression | ts.ElementAccessExpression + tsExpr: ts.EnumMember | ts.PropertyAccessExpression | ts.ElementAccessExpression | ts.NumericLiteral ): boolean { - const tsConstValue = TypeScriptLinter.tsTypeChecker.getConstantValue(tsExpr); + + const tsConstValue = (tsExpr.kind === ts.SyntaxKind.NumericLiteral) ? + Number(tsExpr.getText()) : + TypeScriptLinter.tsTypeChecker.getConstantValue(tsExpr); return ( tsConstValue !== undefined && typeof tsConstValue === 'number' && tsConstValue.toFixed(0) === tsConstValue.toString() ); +} + +export function isStringConstantValue( + tsExpr: ts.EnumMember | ts.PropertyAccessExpression | ts.ElementAccessExpression +): boolean { + const tsConstValue = TypeScriptLinter.tsTypeChecker.getConstantValue(tsExpr); + return ( + tsConstValue !== undefined && typeof tsConstValue === 'string' + ); } // Returns true iff typeA is a subtype of typeB diff --git a/linter/test/binary_wrong_types.ts.relax.json b/linter/test/binary_wrong_types.ts.relax.json index 2c5ac497b..c79d40409 100644 --- a/linter/test/binary_wrong_types.ts.relax.json +++ b/linter/test/binary_wrong_types.ts.relax.json @@ -44,16 +44,6 @@ "column": 3, "problem": "EnumMemberNonConstInit" }, - { - "line": 55, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 56, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, { "line": 59, "column": 12, diff --git a/linter/test/binary_wrong_types.ts.strict.json b/linter/test/binary_wrong_types.ts.strict.json index 2c5ac497b..c79d40409 100644 --- a/linter/test/binary_wrong_types.ts.strict.json +++ b/linter/test/binary_wrong_types.ts.strict.json @@ -44,16 +44,6 @@ "column": 3, "problem": "EnumMemberNonConstInit" }, - { - "line": 55, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 56, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, { "line": 59, "column": 12, diff --git a/linter/test/enum_member_non_constant.ts b/linter/test/enum_member_non_constant.ts index ae601e33c..9666d197b 100644 --- a/linter/test/enum_member_non_constant.ts +++ b/linter/test/enum_member_non_constant.ts @@ -30,6 +30,7 @@ enum Direction { Down = 'DOWN', Left = 'LEFT', Right = 'RIGHT', + Across = 'UP'+'LEFT', } enum FileAccess { diff --git a/linter/test/enum_member_non_constant.ts.relax.json b/linter/test/enum_member_non_constant.ts.relax.json index b2163d5a2..95d9bb890 100644 --- a/linter/test/enum_member_non_constant.ts.relax.json +++ b/linter/test/enum_member_non_constant.ts.relax.json @@ -19,46 +19,11 @@ "column": 3, "problem": "EnumMemberNonConstInit" }, - { - "line": 29, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 30, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 31, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 32, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 47, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, { "line": 48, "column": 3, "problem": "EnumMemberNonConstInit" }, - { - "line": 49, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 51, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, { "line": 52, "column": 3, diff --git a/linter/test/enum_member_non_constant.ts.strict.json b/linter/test/enum_member_non_constant.ts.strict.json index b2163d5a2..95d9bb890 100644 --- a/linter/test/enum_member_non_constant.ts.strict.json +++ b/linter/test/enum_member_non_constant.ts.strict.json @@ -19,46 +19,11 @@ "column": 3, "problem": "EnumMemberNonConstInit" }, - { - "line": 29, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 30, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 31, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 32, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 47, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, { "line": 48, "column": 3, "problem": "EnumMemberNonConstInit" }, - { - "line": 49, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 51, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, { "line": 52, "column": 3, diff --git a/linter/test/for_stmts.ts.relax.json b/linter/test/for_stmts.ts.relax.json index e5383e8ff..19af3c293 100644 --- a/linter/test/for_stmts.ts.relax.json +++ b/linter/test/for_stmts.ts.relax.json @@ -14,21 +14,6 @@ "limitations under the License." ], "nodes": [ - { - "line": 17, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 18, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 19, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, { "line": 22, "column": 1, diff --git a/linter/test/for_stmts.ts.strict.json b/linter/test/for_stmts.ts.strict.json index afa75ba4c..1690fd17e 100644 --- a/linter/test/for_stmts.ts.strict.json +++ b/linter/test/for_stmts.ts.strict.json @@ -14,21 +14,6 @@ "limitations under the License." ], "nodes": [ - { - "line": 17, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 18, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 19, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, { "line": 22, "column": 1, diff --git a/linter/test/type_declarations.ts.relax.json b/linter/test/type_declarations.ts.relax.json index 7f956103d..9bb0205d9 100644 --- a/linter/test/type_declarations.ts.relax.json +++ b/linter/test/type_declarations.ts.relax.json @@ -19,36 +19,6 @@ "column": 10, "problem": "AnyType" }, - { - "line": 25, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 26, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 27, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 31, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 32, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 33, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, { "line": 36, "column": 14, diff --git a/linter/test/type_declarations.ts.strict.json b/linter/test/type_declarations.ts.strict.json index 7a45ff1c6..bf5339e00 100644 --- a/linter/test/type_declarations.ts.strict.json +++ b/linter/test/type_declarations.ts.strict.json @@ -19,36 +19,6 @@ "column": 10, "problem": "AnyType" }, - { - "line": 25, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 26, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 27, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 31, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 32, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, - { - "line": 33, - "column": 3, - "problem": "EnumMemberNonConstInit" - }, { "line": 36, "column": 14, -- Gitee From 2b629040df6329572ed9e16e1ff74d4b1ae1b8f0 Mon Sep 17 00:00:00 2001 From: Igor Rossinski Date: Wed, 12 Jul 2023 03:40:47 +0300 Subject: [PATCH 3/5] [TS Linter] update recipes Signed-off-by: Igor Rossinski --- linter/cookbook_convertor/md/recipe1.md | 59 +++++++ linter/cookbook_convertor/md/recipe10.md | 31 ++++ linter/cookbook_convertor/md/recipe102.md | 105 +++++++++++++ linter/cookbook_convertor/md/recipe103.md | 47 ++++++ linter/cookbook_convertor/md/recipe104.md | 41 +++++ linter/cookbook_convertor/md/recipe105.md | 73 +++++++++ linter/cookbook_convertor/md/recipe106.md | 60 +++++++ linter/cookbook_convertor/md/recipe109.md | 69 +++++++++ linter/cookbook_convertor/md/recipe111.md | 56 +++++++ linter/cookbook_convertor/md/recipe113.md | 45 ++++++ linter/cookbook_convertor/md/recipe114.md | 38 +++++ linter/cookbook_convertor/md/recipe115.md | 22 +++ linter/cookbook_convertor/md/recipe116.md | 41 +++++ linter/cookbook_convertor/md/recipe118.md | 39 +++++ linter/cookbook_convertor/md/recipe119.md | 37 +++++ linter/cookbook_convertor/md/recipe120.md | 29 ++++ linter/cookbook_convertor/md/recipe121.md | 28 ++++ linter/cookbook_convertor/md/recipe123.md | 61 ++++++++ linter/cookbook_convertor/md/recipe124.md | 40 +++++ linter/cookbook_convertor/md/recipe125.md | 58 +++++++ linter/cookbook_convertor/md/recipe126.md | 55 +++++++ linter/cookbook_convertor/md/recipe127.md | 30 ++++ linter/cookbook_convertor/md/recipe128.md | 37 +++++ linter/cookbook_convertor/md/recipe129.md | 29 ++++ linter/cookbook_convertor/md/recipe13.md | 33 ++++ linter/cookbook_convertor/md/recipe130.md | 47 ++++++ linter/cookbook_convertor/md/recipe131.md | 34 ++++ linter/cookbook_convertor/md/recipe132.md | 33 ++++ linter/cookbook_convertor/md/recipe133.md | 36 +++++ linter/cookbook_convertor/md/recipe134.md | 44 ++++++ linter/cookbook_convertor/md/recipe135.md | 38 +++++ linter/cookbook_convertor/md/recipe136.md | 37 +++++ linter/cookbook_convertor/md/recipe137.md | 44 ++++++ linter/cookbook_convertor/md/recipe138.md | 45 ++++++ linter/cookbook_convertor/md/recipe139.md | 69 +++++++++ linter/cookbook_convertor/md/recipe14.md | 53 +++++++ linter/cookbook_convertor/md/recipe140.md | 65 ++++++++ linter/cookbook_convertor/md/recipe141.md | 34 ++++ linter/cookbook_convertor/md/recipe142.md | 50 ++++++ linter/cookbook_convertor/md/recipe143.md | 38 +++++ linter/cookbook_convertor/md/recipe144.md | 54 +++++++ linter/cookbook_convertor/md/recipe15.md | 50 ++++++ linter/cookbook_convertor/md/recipe16.md | 47 ++++++ linter/cookbook_convertor/md/recipe17.md | 43 ++++++ linter/cookbook_convertor/md/recipe19.md | 49 ++++++ linter/cookbook_convertor/md/recipe2.md | 49 ++++++ linter/cookbook_convertor/md/recipe21.md | 32 ++++ linter/cookbook_convertor/md/recipe22.md | 40 +++++ linter/cookbook_convertor/md/recipe24.md | 46 ++++++ linter/cookbook_convertor/md/recipe25.md | 57 +++++++ linter/cookbook_convertor/md/recipe27.md | 44 ++++++ linter/cookbook_convertor/md/recipe28.md | 30 ++++ linter/cookbook_convertor/md/recipe29.md | 33 ++++ linter/cookbook_convertor/md/recipe3.md | 34 ++++ linter/cookbook_convertor/md/recipe30.md | 51 ++++++ linter/cookbook_convertor/md/recipe31.md | 84 ++++++++++ linter/cookbook_convertor/md/recipe32.md | 88 +++++++++++ linter/cookbook_convertor/md/recipe33.md | 58 +++++++ linter/cookbook_convertor/md/recipe34.md | 51 ++++++ linter/cookbook_convertor/md/recipe35.md | 103 ++++++++++++ linter/cookbook_convertor/md/recipe37.md | 29 ++++ linter/cookbook_convertor/md/recipe38.md | 146 ++++++++++++++++++ linter/cookbook_convertor/md/recipe4.md | 31 ++++ linter/cookbook_convertor/md/recipe40.md | 46 ++++++ linter/cookbook_convertor/md/recipe43.md | 41 +++++ linter/cookbook_convertor/md/recipe45.md | 34 ++++ linter/cookbook_convertor/md/recipe46.md | 33 ++++ linter/cookbook_convertor/md/recipe49.md | 35 +++++ linter/cookbook_convertor/md/recipe5.md | 63 ++++++++ linter/cookbook_convertor/md/recipe50.md | 49 ++++++ linter/cookbook_convertor/md/recipe51.md | 42 +++++ linter/cookbook_convertor/md/recipe52.md | 59 +++++++ linter/cookbook_convertor/md/recipe53.md | 56 +++++++ linter/cookbook_convertor/md/recipe54.md | 10 ++ linter/cookbook_convertor/md/recipe55.md | 48 ++++++ linter/cookbook_convertor/md/recipe56.md | 54 +++++++ linter/cookbook_convertor/md/recipe59.md | 54 +++++++ linter/cookbook_convertor/md/recipe60.md | 50 ++++++ linter/cookbook_convertor/md/recipe61.md | 71 +++++++++ linter/cookbook_convertor/md/recipe63.md | 55 +++++++ linter/cookbook_convertor/md/recipe65.md | 50 ++++++ linter/cookbook_convertor/md/recipe66.md | 52 +++++++ linter/cookbook_convertor/md/recipe69.md | 46 ++++++ linter/cookbook_convertor/md/recipe71.md | 41 +++++ linter/cookbook_convertor/md/recipe74.md | 52 +++++++ linter/cookbook_convertor/md/recipe76.md | 37 +++++ linter/cookbook_convertor/md/recipe79.md | 40 +++++ linter/cookbook_convertor/md/recipe8.md | 39 +++++ linter/cookbook_convertor/md/recipe80.md | 42 +++++ linter/cookbook_convertor/md/recipe81.md | 18 +++ linter/cookbook_convertor/md/recipe82.md | 41 +++++ linter/cookbook_convertor/md/recipe83.md | 43 ++++++ linter/cookbook_convertor/md/recipe84.md | 11 ++ linter/cookbook_convertor/md/recipe85.md | 56 +++++++ linter/cookbook_convertor/md/recipe86.md | 49 ++++++ linter/cookbook_convertor/md/recipe87.md | 32 ++++ linter/cookbook_convertor/md/recipe90.md | 67 ++++++++ linter/cookbook_convertor/md/recipe91.md | 47 ++++++ linter/cookbook_convertor/md/recipe92.md | 48 ++++++ linter/cookbook_convertor/md/recipe93.md | 58 +++++++ linter/cookbook_convertor/md/recipe94.md | 48 ++++++ linter/cookbook_convertor/md/recipe96.md | 84 ++++++++++ linter/cookbook_convertor/md/recipe97.md | 63 ++++++++ linter/cookbook_convertor/md/recipe99.md | 73 +++++++++ .../src/cookbook_convertor.ts | 6 +- linter/src/CookBookMsg.ts | 17 +- 106 files changed, 5028 insertions(+), 11 deletions(-) create mode 100644 linter/cookbook_convertor/md/recipe1.md create mode 100644 linter/cookbook_convertor/md/recipe10.md create mode 100644 linter/cookbook_convertor/md/recipe102.md create mode 100644 linter/cookbook_convertor/md/recipe103.md create mode 100644 linter/cookbook_convertor/md/recipe104.md create mode 100644 linter/cookbook_convertor/md/recipe105.md create mode 100644 linter/cookbook_convertor/md/recipe106.md create mode 100644 linter/cookbook_convertor/md/recipe109.md create mode 100644 linter/cookbook_convertor/md/recipe111.md create mode 100644 linter/cookbook_convertor/md/recipe113.md create mode 100644 linter/cookbook_convertor/md/recipe114.md create mode 100644 linter/cookbook_convertor/md/recipe115.md create mode 100644 linter/cookbook_convertor/md/recipe116.md create mode 100644 linter/cookbook_convertor/md/recipe118.md create mode 100644 linter/cookbook_convertor/md/recipe119.md create mode 100644 linter/cookbook_convertor/md/recipe120.md create mode 100644 linter/cookbook_convertor/md/recipe121.md create mode 100644 linter/cookbook_convertor/md/recipe123.md create mode 100644 linter/cookbook_convertor/md/recipe124.md create mode 100644 linter/cookbook_convertor/md/recipe125.md create mode 100644 linter/cookbook_convertor/md/recipe126.md create mode 100644 linter/cookbook_convertor/md/recipe127.md create mode 100644 linter/cookbook_convertor/md/recipe128.md create mode 100644 linter/cookbook_convertor/md/recipe129.md create mode 100644 linter/cookbook_convertor/md/recipe13.md create mode 100644 linter/cookbook_convertor/md/recipe130.md create mode 100644 linter/cookbook_convertor/md/recipe131.md create mode 100644 linter/cookbook_convertor/md/recipe132.md create mode 100644 linter/cookbook_convertor/md/recipe133.md create mode 100644 linter/cookbook_convertor/md/recipe134.md create mode 100644 linter/cookbook_convertor/md/recipe135.md create mode 100644 linter/cookbook_convertor/md/recipe136.md create mode 100644 linter/cookbook_convertor/md/recipe137.md create mode 100644 linter/cookbook_convertor/md/recipe138.md create mode 100644 linter/cookbook_convertor/md/recipe139.md create mode 100644 linter/cookbook_convertor/md/recipe14.md create mode 100644 linter/cookbook_convertor/md/recipe140.md create mode 100644 linter/cookbook_convertor/md/recipe141.md create mode 100644 linter/cookbook_convertor/md/recipe142.md create mode 100644 linter/cookbook_convertor/md/recipe143.md create mode 100644 linter/cookbook_convertor/md/recipe144.md create mode 100644 linter/cookbook_convertor/md/recipe15.md create mode 100644 linter/cookbook_convertor/md/recipe16.md create mode 100644 linter/cookbook_convertor/md/recipe17.md create mode 100644 linter/cookbook_convertor/md/recipe19.md create mode 100644 linter/cookbook_convertor/md/recipe2.md create mode 100644 linter/cookbook_convertor/md/recipe21.md create mode 100644 linter/cookbook_convertor/md/recipe22.md create mode 100644 linter/cookbook_convertor/md/recipe24.md create mode 100644 linter/cookbook_convertor/md/recipe25.md create mode 100644 linter/cookbook_convertor/md/recipe27.md create mode 100644 linter/cookbook_convertor/md/recipe28.md create mode 100644 linter/cookbook_convertor/md/recipe29.md create mode 100644 linter/cookbook_convertor/md/recipe3.md create mode 100644 linter/cookbook_convertor/md/recipe30.md create mode 100644 linter/cookbook_convertor/md/recipe31.md create mode 100644 linter/cookbook_convertor/md/recipe32.md create mode 100644 linter/cookbook_convertor/md/recipe33.md create mode 100644 linter/cookbook_convertor/md/recipe34.md create mode 100644 linter/cookbook_convertor/md/recipe35.md create mode 100644 linter/cookbook_convertor/md/recipe37.md create mode 100644 linter/cookbook_convertor/md/recipe38.md create mode 100644 linter/cookbook_convertor/md/recipe4.md create mode 100644 linter/cookbook_convertor/md/recipe40.md create mode 100644 linter/cookbook_convertor/md/recipe43.md create mode 100644 linter/cookbook_convertor/md/recipe45.md create mode 100644 linter/cookbook_convertor/md/recipe46.md create mode 100644 linter/cookbook_convertor/md/recipe49.md create mode 100644 linter/cookbook_convertor/md/recipe5.md create mode 100644 linter/cookbook_convertor/md/recipe50.md create mode 100644 linter/cookbook_convertor/md/recipe51.md create mode 100644 linter/cookbook_convertor/md/recipe52.md create mode 100644 linter/cookbook_convertor/md/recipe53.md create mode 100644 linter/cookbook_convertor/md/recipe54.md create mode 100644 linter/cookbook_convertor/md/recipe55.md create mode 100644 linter/cookbook_convertor/md/recipe56.md create mode 100644 linter/cookbook_convertor/md/recipe59.md create mode 100644 linter/cookbook_convertor/md/recipe60.md create mode 100644 linter/cookbook_convertor/md/recipe61.md create mode 100644 linter/cookbook_convertor/md/recipe63.md create mode 100644 linter/cookbook_convertor/md/recipe65.md create mode 100644 linter/cookbook_convertor/md/recipe66.md create mode 100644 linter/cookbook_convertor/md/recipe69.md create mode 100644 linter/cookbook_convertor/md/recipe71.md create mode 100644 linter/cookbook_convertor/md/recipe74.md create mode 100644 linter/cookbook_convertor/md/recipe76.md create mode 100644 linter/cookbook_convertor/md/recipe79.md create mode 100644 linter/cookbook_convertor/md/recipe8.md create mode 100644 linter/cookbook_convertor/md/recipe80.md create mode 100644 linter/cookbook_convertor/md/recipe81.md create mode 100644 linter/cookbook_convertor/md/recipe82.md create mode 100644 linter/cookbook_convertor/md/recipe83.md create mode 100644 linter/cookbook_convertor/md/recipe84.md create mode 100644 linter/cookbook_convertor/md/recipe85.md create mode 100644 linter/cookbook_convertor/md/recipe86.md create mode 100644 linter/cookbook_convertor/md/recipe87.md create mode 100644 linter/cookbook_convertor/md/recipe90.md create mode 100644 linter/cookbook_convertor/md/recipe91.md create mode 100644 linter/cookbook_convertor/md/recipe92.md create mode 100644 linter/cookbook_convertor/md/recipe93.md create mode 100644 linter/cookbook_convertor/md/recipe94.md create mode 100644 linter/cookbook_convertor/md/recipe96.md create mode 100644 linter/cookbook_convertor/md/recipe97.md create mode 100644 linter/cookbook_convertor/md/recipe99.md diff --git a/linter/cookbook_convertor/md/recipe1.md b/linter/cookbook_convertor/md/recipe1.md new file mode 100644 index 000000000..1f6236663 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe1.md @@ -0,0 +1,59 @@ +# Objects with property names that are not identifiers are not supported + +Rule ``arkts-identifiers-as-prop-names`` + +**Severity: error** + +ArkTS does not support Objects with name properties that are numbers or +strings. Use classes to access data by property names. Use arrays to access +data by numeric indices. + + +## TypeScript + + +``` + + var x = {"name": 1, 2: 3} + + console.log(x["name"]) + console.log(x[2]) + +``` + +## ArkTS + + +``` + + class X { + public name: number + } + let x = {name: 1} + console.log(x.name) + + let y = [1, 2, 3] + console.log(y[2]) + + // If you still need a container to store keys of different types, + // use Map: + let z = new Map() + z.set("name", 1) + z.set(2, 2) + console.log(z.get("name")) + console.log(z.get(2)) + +``` + +## See also + +- Recipe 002: undefined +- Recipe 052: undefined +- Recipe 059: undefined +- Recipe 060: undefined +- Recipe 066: undefined +- Recipe 105: undefined +- Recipe 109: undefined +- Recipe 144: undefined + + diff --git a/linter/cookbook_convertor/md/recipe10.md b/linter/cookbook_convertor/md/recipe10.md new file mode 100644 index 000000000..cfaa4830f --- /dev/null +++ b/linter/cookbook_convertor/md/recipe10.md @@ -0,0 +1,31 @@ +# ``bigint`` is not a builtin type, suffix ``n`` for numeric literals is not supported + +Rule ``arkts-no-n-suffix`` + +**Severity: error** + +ArkTS supports ``bigint`` as a part of the standard library, not as a builtin +type. ``n`` suffix for numeric literals is not supported, ``BigInt`` factory +function can be used to produce values of ``bigint`` type. + + +## TypeScript + + +``` + + let a: bigint = 1n + +``` + +## ArkTS + + +``` + + let a = BigInt(1) + let b: bigint = BigInt(2) + +``` + + diff --git a/linter/cookbook_convertor/md/recipe102.md b/linter/cookbook_convertor/md/recipe102.md new file mode 100644 index 000000000..6776df1b8 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe102.md @@ -0,0 +1,105 @@ +# Interface declarations (extends same property) + +Rule ``arkts-no-extend-same-property`` + +**Severity: error** + +In TypeScript, an interface that extends two other interfaces with the same method, +must declare that method with a combined result type. It is not allowed in +ArkTS because |LANG| does not allow an interface to contain two methods with +signatures that are not distinguishable, e.g., two methods that have the same +parameter lists, but different return types. + + +## TypeScript + + +``` + + interface Mover { + getStatus(): { speed: number } + } + interface Shaker { + getStatus(): { frequency: number } + } + + interface MoverShaker extends Mover, Shaker { + getStatus(): { + speed: number + frequency: number + } + } + + class C implements MoverShaker { + private speed: number = 0 + private frequency: number = 0 + + getStatus() { + return { speed: this.speed, frequency: this.frequency } + } + } + +``` + +## ArkTS + + +``` + + class MoveStatus { + public speed : number + constructor() { + this.speed = 0 + } + } + interface Mover { + getMoveStatus(): MoveStatus + } + + class ShakeStatus { + public frequency : number + constructor() { + this.frequency = 0 + } + } + interface Shaker { + getShakeStatus(): ShakeStatus + } + + class MoveAndShakeStatus { + public speed : number + public frequency : number + constructor() { + this.speed = 0 + this.frequency = 0 + } + } + + class C implements Mover, Shaker { + private move_status : MoveStatus + private shake_status : ShakeStatus + + constructor() { + this.move_status = new MoveStatus() + this.shake_status = new ShakeStatus() + } + + public getMoveStatus() : MoveStatus { + return this.move_status + } + + public getShakeStatus() : ShakeStatus { + return this.shake_status + } + + public getStatus(): MoveAndShakeStatus { + return { + speed: this.move_status.speed, + frequency: this.shake_status.frequency + } + } + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe103.md b/linter/cookbook_convertor/md/recipe103.md new file mode 100644 index 000000000..b1b794454 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe103.md @@ -0,0 +1,47 @@ +# Declaration merging is not supported + +Rule ``arkts-no-decl-merging`` + +**Severity: error** + +ArkTS does not support merging declratations. All definitions of classes, +interfaces and so on must be kept compact in the code base. + + +## TypeScript + + +``` + + interface Document { + createElement(tagName: any): Element + } + + interface Document { + createElement(tagName: string): HTMLElement + } + + interface Document { + createElement(tagName: number): HTMLDivElement + createElement(tagName: boolean): HTMLSpanElement + createElement(tagName: string, value: number): HTMLCanvasElement + } + +``` + +## ArkTS + + +``` + + interface Document { + createElement(tagName: number): HTMLDivElement + createElement(tagName: boolean): HTMLSpanElement + createElement(tagName: string, value: number): HTMLCanvasElement + createElement(tagName: string): HTMLElement + createElement(tagName: Object): Element + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe104.md b/linter/cookbook_convertor/md/recipe104.md new file mode 100644 index 000000000..88007dab5 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe104.md @@ -0,0 +1,41 @@ +# Interfaces cannot extend classes + +Rule ``arkts-extends-only-class`` + +**Severity: error** + +ArkTS does not support interfaces that extend classes. Interfaces can extend +only interfaces. + + +## TypeScript + + +``` + + class Control { + state: number = 0 + } + + interface SelectableControl extends Control { + select(): void + } + +``` + +## ArkTS + + +``` + + interface Control { + state: number + } + + interface SelectableControl extends Control { + select(): void + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe105.md b/linter/cookbook_convertor/md/recipe105.md new file mode 100644 index 000000000..1c28c234c --- /dev/null +++ b/linter/cookbook_convertor/md/recipe105.md @@ -0,0 +1,73 @@ +# Property-based runtime type checks are not supported + +Rule ``arkts-no-prop-existence-check`` + +**Severity: error** + +ArkTS requires that object layout is determined in compile-time and cannot +be changed at runtime. There for no runtime property-based checks are supported. +If you need to do a type cast, use ``as`` operator and use desired properties +and methods. If some property doesn't exist then an attempt to reference it +will result in a compile-time error. + + +## TypeScript + + +``` + + class A { + foo() {} + bar() {} + } + + function getSomeObject() { + return new A() + } + + let obj: any = getSomeObject() + if (obj && obj.foo && obj.bar) { + console.log("Yes") // prints "Yes" in this example + } else { + console.log("No") + } + +``` + +## ArkTS + + +``` + + class A { + foo(): void {} + bar(): void {} + } + + function getSomeObject(): A { + return new A() + } + + function main(): void { + let tmp: Object = getSomeObject() + let obj: A = tmp as A + obj.foo() // OK + obj.bar() // OK + obj.some_foo() // Compile-time error: Method some_foo does not + // exist on this type + } + +``` + +## See also + +- Recipe 001: undefined +- Recipe 002: undefined +- Recipe 052: undefined +- Recipe 059: undefined +- Recipe 060: undefined +- Recipe 066: undefined +- Recipe 109: undefined +- Recipe 144: undefined + + diff --git a/linter/cookbook_convertor/md/recipe106.md b/linter/cookbook_convertor/md/recipe106.md new file mode 100644 index 000000000..702335964 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe106.md @@ -0,0 +1,60 @@ +# Constructor function type is not supported + +Rule ``arkts-no-ctor-signatures-funcs`` + +**Severity: error** + +ArkTS does not support the usage of the constructor function type. +Use lambdas instead, as they can be generalized to several types of objects. + + +## TypeScript + + +``` + + class Person { + constructor( + name: string, + age: number + ) {} + } + + type PersonConstructor = new (name: string, age: number) => Person + + function createPerson( + Ctor: PersonConstructor, name: string, age: number): Person + { + return new Ctor(name, age) + } + + const person = createPerson(Person, 'John', 30) + +``` + +## ArkTS + + +``` + + class Person { + constructor( + name: string, + age: number + ) {} + } + type PersonCtor = (n: string, a: number) => Person + + function createPerson(Ctor: PersonCtor, n: string, a: number): Person { + return Ctor(n, a) + } + + let Impersonizer: PersonCtor = (n: string, a: number): Person => { + return new Person(n,a) + } + + const person = createPerson(Impersonizer, "John", 30) + +``` + + diff --git a/linter/cookbook_convertor/md/recipe109.md b/linter/cookbook_convertor/md/recipe109.md new file mode 100644 index 000000000..c4aedd903 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe109.md @@ -0,0 +1,69 @@ +# Dynamic property declaration is not supported + +Rule ``arkts-no-dyn-prop-decl`` + +**Severity: error** + +ArkTS does not support dynamic property declaration. All object properties must +be declared immediately in the class. While it can be replaced with an array +of objects, it is still better to adhere to the static language paradigm and +declare fields, their names and types explicitly. + + +## TypeScript + + +``` + + class Person { + name: string = "" + age: number = 0; // semicolon is required here + [key: string]: string | number + } + + const person: Person = { + name: "John", + age: 30, + email: "john@example.com", + phone: 1234567890, + } + +``` + +## ArkTS + + +``` + + class Person { + name: string + age: number + email: string + phone: number + + constructor(name: string, age: number, email: string, phone: number) { + this.name = name + this.age = age + this.email = email + this.phone = phone + } + } + + function main(): void { + const person: Person = new Person("John", 30, "john@example.com", 1234567890) + } + +``` + +## See also + +- Recipe 001: undefined +- Recipe 002: undefined +- Recipe 052: undefined +- Recipe 059: undefined +- Recipe 060: undefined +- Recipe 066: undefined +- Recipe 105: undefined +- Recipe 144: undefined + + diff --git a/linter/cookbook_convertor/md/recipe111.md b/linter/cookbook_convertor/md/recipe111.md new file mode 100644 index 000000000..d211bb011 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe111.md @@ -0,0 +1,56 @@ +# Enumeration members can be initialized only with compile time expressions of the same type + +Rule ``arkts-no-enum-mixed-types`` + +**Severity: error** + +ArkTS does not support initializing members of enumerations with expressions +that are evaluated during program runtime. Besides, all explicitly set +initializers must be of the same time. + + +## TypeScript + + +``` + + enum E1 { + A = 0xa, + B = 0xb, + C = Math.random(), + D = 0xd, + E // 0xe inferred + } + + enum E2 { + A = 0xa, + B = "0xb", + C = 0xc, + D = "0xd" + } + +``` + +## ArkTS + + +``` + + enum E1 { + A = 0xa, + B = 0xb, + C = 0xc, + D = 0xd, + E // 0xe inferred + } + + enum E2 { + A = "0xa", + B = "0xb", + C = "0xc", + D = "0xd" + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe113.md b/linter/cookbook_convertor/md/recipe113.md new file mode 100644 index 000000000..26465b677 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe113.md @@ -0,0 +1,45 @@ +# ``enum`` declaration merging is not supported + +Rule ``arkts-no-enum-merging`` + +**Severity: error** + +ArkTS does not support merging declratations for ``enum``. +The declaration of each ``enum`` must be kept compact in the code base. + + +## TypeScript + + +``` + + enum Color { + RED, + GREEN + } + enum Color { + YELLOW = 2 + } + enum Color { + BLACK = 3, + BLUE + } + +``` + +## ArkTS + + +``` + + enum Color { + RED, + GREEN, + YELLOW, + BLACK, + BLUE + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe114.md b/linter/cookbook_convertor/md/recipe114.md new file mode 100644 index 000000000..83adbec65 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe114.md @@ -0,0 +1,38 @@ +# Namespaces cannot be used as objects + +Rule ``arkts-no-ns-as-obj`` + +**Severity: error** + +ArkTS does not support the usage of namespaces as objects. +Classes or modules can be interpreted as analogues of namespaces. + + +## TypeScript + + +``` + + namespace MyNamespace { + export let x: number + } + + let m = MyNamespace + m.x = 2 + +``` + +## ArkTS + + +``` + + namespace MyNamespace { + export let x: number + } + + MyNamespace.x = 2 + +``` + + diff --git a/linter/cookbook_convertor/md/recipe115.md b/linter/cookbook_convertor/md/recipe115.md new file mode 100644 index 000000000..2090a8275 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe115.md @@ -0,0 +1,22 @@ +# Scripts and modules + +Rule ``arkts-no-scripts`` + +**Severity: error** + +In general, scripts and modules in ArkTS are very close to TypeScript. +Differences are described in separate recipes. + + +## See also + +- Recipe 118: undefined +- Recipe 119: undefined +- Recipe 120: undefined +- Recipe 121: undefined +- Recipe 123: undefined +- Recipe 124: undefined +- Recipe 125: undefined +- Recipe 126: undefined + + diff --git a/linter/cookbook_convertor/md/recipe116.md b/linter/cookbook_convertor/md/recipe116.md new file mode 100644 index 000000000..3fe4c275b --- /dev/null +++ b/linter/cookbook_convertor/md/recipe116.md @@ -0,0 +1,41 @@ +# Non-declaration statements in namespaces are not supported + +Rule ``arkts-no-ns-statements`` + +**Severity: error** + +ArkTS does not support statements in namespaces. Use a function to exectute +statements. + + +## TypeScript + + +``` + + namespace A { + export let x: number + x = 1 + } + +``` + +## ArkTS + + +``` + + namespace A { + export let x: number + + export function init() { + x = 1 + } + } + + // Initialization function should be called to execute statements: + A.init() + +``` + + diff --git a/linter/cookbook_convertor/md/recipe118.md b/linter/cookbook_convertor/md/recipe118.md new file mode 100644 index 000000000..98511662f --- /dev/null +++ b/linter/cookbook_convertor/md/recipe118.md @@ -0,0 +1,39 @@ +# Special import type declarations are not supported + +Rule ``arkts-no-special-imports`` + +**Severity: error** + +ArkTS does not have a special notation for importing types. +Use ordinary import instead. + + +## TypeScript + + +``` + + // Re-using the same import + import { APIResponseType } from "./api" + + // Explicitly use import type + import type { APIResponseType } from "./api" + +``` + +## ArkTS + + +``` + + import { APIResponseType } from "./api" + +``` + +## See also + +- Recipe 119: undefined +- Recipe 120: undefined +- Recipe 121: undefined + + diff --git a/linter/cookbook_convertor/md/recipe119.md b/linter/cookbook_convertor/md/recipe119.md new file mode 100644 index 000000000..9c03707f8 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe119.md @@ -0,0 +1,37 @@ +# Importing a module for side-effects only is not supported + +Rule ``arkts-no-side-effects-imports`` + +**Severity: error** + +ArkTS does not support global variables like ``window`` to avoid +side-effects during module importing. All variables marked as export can be +accessed through the ``*`` syntax. + + +## TypeScript + + +``` + + // === module at "path/to/module.ts" + export const EXAMPLE_VALUE = 42 + + // Set a global variable + window.MY_GLOBAL_VAR = "Hello, world!" + + // ==== using this module: + import "path/to/module" + +``` + +## ArkTS + + +``` + + import * from "path/to/module" + +``` + + diff --git a/linter/cookbook_convertor/md/recipe120.md b/linter/cookbook_convertor/md/recipe120.md new file mode 100644 index 000000000..dd38b2bf2 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe120.md @@ -0,0 +1,29 @@ +# ``import default as ...`` is not supported + +Rule ``arkts-no-import-default-as`` + +**Severity: error** + +ArkTS does not support ``import default as ...`` syntax. +Use explicit ``import ... from ...`` instead. + + +## TypeScript + + +``` + + import { default as d } from "mod" + +``` + +## ArkTS + + +``` + + import d from "mod" + +``` + + diff --git a/linter/cookbook_convertor/md/recipe121.md b/linter/cookbook_convertor/md/recipe121.md new file mode 100644 index 000000000..918ae2aed --- /dev/null +++ b/linter/cookbook_convertor/md/recipe121.md @@ -0,0 +1,28 @@ +# ``require`` is not supported + +Rule ``arkts-no-require`` + +**Severity: error** + +ArkTS does not support importing via ``require``. Use ``import`` instead. + + +## TypeScript + + +``` + + import m = require("mod") + +``` + +## ArkTS + + +``` + + import * as m from "mod" + +``` + + diff --git a/linter/cookbook_convertor/md/recipe123.md b/linter/cookbook_convertor/md/recipe123.md new file mode 100644 index 000000000..b8553fb0e --- /dev/null +++ b/linter/cookbook_convertor/md/recipe123.md @@ -0,0 +1,61 @@ +# Renaming in export declarations is not supported + +Rule ``arkts-no-export-renaming`` + +**Severity: error** + +ArkTS does not support renaming in export declarations. Similar effect +can be achieved through setting an alias for the exported entity. + + +## TypeScript + + +``` + + // file1.ts + class MyClass { + // ... + } + + export { MyClass as RenamedClass } + + // file2.ts + import { RenamedClass } from "./file1" + + function main(): void { + const myObject = new RenamedClass() + // ... + } + +``` + +## ArkTS + + +``` + + // module1 + class MyClass { + // ... + } + + export type RenamedClass = MyClass + + // module2 + import { RenamedClass } from "./module1" + + function main(): void { + const myObject = new RenamedClass() + // ... + } + +``` + +## See also + +- Recipe 124: undefined +- Recipe 125: undefined +- Recipe 126: undefined + + diff --git a/linter/cookbook_convertor/md/recipe124.md b/linter/cookbook_convertor/md/recipe124.md new file mode 100644 index 000000000..591d7d063 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe124.md @@ -0,0 +1,40 @@ +# Export list declaration is not supported + +Rule ``arkts-no-export-list-decl`` + +**Severity: error** + +ArkTS does not support syntax of export list declarations. All exported +entities must be explicitly annotated with the ``export`` keyword. + + +## TypeScript + + +``` + + export { x } + export { x } from "mod" + export { x, y as b, z as c } + +``` + +## ArkTS + + +``` + + let x = 1 + class MyClass {} + export let y = x, z: number = 2 + export RenamedClass = MyClass + +``` + +## See also + +- Recipe 123: undefined +- Recipe 125: undefined +- Recipe 126: undefined + + diff --git a/linter/cookbook_convertor/md/recipe125.md b/linter/cookbook_convertor/md/recipe125.md new file mode 100644 index 000000000..8167c06c0 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe125.md @@ -0,0 +1,58 @@ +# Re-exporting is not supported + +Rule ``arkts-no-reexport`` + +**Severity: error** + +ArkTS does not support re-exporting. All desired entities must be +imported explicitly from the modules that export them. + + +## TypeScript + + +``` + + // module1 + export class MyClass { + // ... + } + + // module2 + export { MyClass } from "module1" + + // consumer module + import { MyClass } from "module2" + + const myInstance = new MyClass() + +``` + +## ArkTS + + +``` + + // module1 + export class MyClass { + // ... + } + + // module2 + // some stuff + + // consumer module + import { MyClass } from "module1" + import * from "module2" + + const myInstance = new MyClass() + +``` + +## See also + +- Recipe 123: undefined +- Recipe 124: undefined +- Recipe 126: undefined + + diff --git a/linter/cookbook_convertor/md/recipe126.md b/linter/cookbook_convertor/md/recipe126.md new file mode 100644 index 000000000..bb9239dec --- /dev/null +++ b/linter/cookbook_convertor/md/recipe126.md @@ -0,0 +1,55 @@ +# ``export = ...`` assignment is not supported + +Rule ``arkts-no-export-assignment`` + +**Severity: error** + +ArkTS does not support ``export = ...`` syntax. +Use regular ``export`` / ``import`` instead. + + +## TypeScript + + +``` + + // module1 + export = Point + + class Point { + constructor(x: number, y: number) {} + static origin = new Point(0, 0) + } + + // module2 + import Pt = require("module1") + + let p = Pt.origin + +``` + +## ArkTS + + +``` + + // module1 + export class Point { + constructor(x: number, y: number) {} + static origin = new Point(0, 0) + } + + // module2 + import * as Pt from "module1" + + let p = Pt.origin + +``` + +## See also + +- Recipe 123: undefined +- Recipe 124: undefined +- Recipe 125: undefined + + diff --git a/linter/cookbook_convertor/md/recipe127.md b/linter/cookbook_convertor/md/recipe127.md new file mode 100644 index 000000000..0a307add9 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe127.md @@ -0,0 +1,30 @@ +# Special export type declarations are not supported + +Rule ``arkts-no-special-exports`` + +**Severity: error** + +ArkTS does not have a special notation for exporting types. +Use ordinary export instead. + + +## TypeScript + + +``` + + class C {} + export type { C } + +``` + +## ArkTS + + +``` + + export class C {} + +``` + + diff --git a/linter/cookbook_convertor/md/recipe128.md b/linter/cookbook_convertor/md/recipe128.md new file mode 100644 index 000000000..b31a34eab --- /dev/null +++ b/linter/cookbook_convertor/md/recipe128.md @@ -0,0 +1,37 @@ +# Ambient module declaration is not supported + +Rule ``arkts-no-ambient-decls`` + +**Severity: error** + +ArkTS does not support ambient module declaration because it has its +own mechanisms for interoperating with JavaScript. + + +## TypeScript + + +``` + + declare module "someModule" { + export function normalize(s : string) : string; + } + +``` + +## ArkTS + + +``` + + // Import what you need from the original module + import { normalize } from "../someModule" + +``` + +## See also + +- Recipe 129: undefined +- Recipe 131: undefined + + diff --git a/linter/cookbook_convertor/md/recipe129.md b/linter/cookbook_convertor/md/recipe129.md new file mode 100644 index 000000000..0481128e5 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe129.md @@ -0,0 +1,29 @@ +# Wildcards in module names are not supported + +Rule ``arkts-no-module-wildcards`` + +**Severity: error** + +ArkTS does not supported wildcards in module names because in |LANG|, import +is a compile-time, not a runtime feature. Use ordinary export syntax instead. + + +## TypeScript + + +``` + + declare module "*!text" { + const content: string + export default content + } + +``` + +## See also + +- Recipe 128: undefined +- Recipe 130: undefined +- Recipe 131: undefined + + diff --git a/linter/cookbook_convertor/md/recipe13.md b/linter/cookbook_convertor/md/recipe13.md new file mode 100644 index 000000000..1fcf6c6f5 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe13.md @@ -0,0 +1,33 @@ +# Use ``Object[]`` instead of tuples + +Rule ``arkts-no-tuples`` + +**Severity: error** + +Currently, ArkTS does not support tuples. You can use arrays of ``Object`` +(``Object[]``) to emulate tuples. + + +## TypeScript + + +``` + + var t: [number, string] = [3, "three"] + var n = t[0] + var s = t[1] + +``` + +## ArkTS + + +``` + + let t: Object[] = [3, "three"] + let n = t[0] + let s = t[1] + +``` + + diff --git a/linter/cookbook_convertor/md/recipe130.md b/linter/cookbook_convertor/md/recipe130.md new file mode 100644 index 000000000..5cfcf3734 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe130.md @@ -0,0 +1,47 @@ +# Universal module definitions (UMD) are not supported + +Rule ``arkts-no-umd`` + +**Severity: error** + +ArkTS does not support universal module definitions (UMD) because in |LANG| +there is no concept of "script" (as opposed to "module"). Besides, in ArkTS +import is a compile-time, not a runtime feature. Use ordinary syntax for +``export`` and ``import`` instead. + + +## TypeScript + + +``` + + // math-lib.d.ts + export const isPrime(x: number): boolean + export as namespace mathLib + + // in script + mathLib.isPrime(2) + +``` + +## ArkTS + + +``` + + // math-lib.d.ts + namespace mathLib { + export isPrime(x: number): boolean + } + + // in program + import { mathLib } from "./math-lib" + mathLib.isPrime(2) + +``` + +## See also + +- Recipe 129: undefined + + diff --git a/linter/cookbook_convertor/md/recipe131.md b/linter/cookbook_convertor/md/recipe131.md new file mode 100644 index 000000000..8fe671509 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe131.md @@ -0,0 +1,34 @@ +# ``.js`` extension is not allowed in module identifiers + +Rule ``arkts-no-js-extension`` + +**Severity: error** + +ArkTS does not allow to use ``.js`` extension in module identifiers because it +has its own mechanisms for interoperating with JavaScript. + + +## TypeScript + + +``` + + import { something } from "./module.js" + +``` + +## ArkTS + + +``` + + import { something } from "./module" + +``` + +## See also + +- Recipe 128: undefined +- Recipe 129: undefined + + diff --git a/linter/cookbook_convertor/md/recipe132.md b/linter/cookbook_convertor/md/recipe132.md new file mode 100644 index 000000000..4790b8c5a --- /dev/null +++ b/linter/cookbook_convertor/md/recipe132.md @@ -0,0 +1,33 @@ +# ``new.target`` is not supported + +Rule ``arkts-no-new-target`` + +**Severity: error** + +ArkTS does not support ``new.target`` because there is no concept of runtime +prototype inheritance in the language. This feature is considered not applicable +to the statically typing. + + +## TypeScript + + +``` + + class CustomError extends Error { + constructor(message?: string) { + // 'Error' breaks prototype chain here: + super(message) + + // Restore prototype chain: + Object.setPrototypeOf(this, new.target.prototype) + } + } + +``` + +## See also + +- Recipe 136: undefined + + diff --git a/linter/cookbook_convertor/md/recipe133.md b/linter/cookbook_convertor/md/recipe133.md new file mode 100644 index 000000000..0df7d7ccf --- /dev/null +++ b/linter/cookbook_convertor/md/recipe133.md @@ -0,0 +1,36 @@ +# Runtime import expressions are not supported + +Rule ``arkts-no-runtime-import`` + +**Severity: error** + +ArkTS does not support such "runtime" import expressions as ``await import...`` +because in ArkTS import is a compile-time, not a runtime feature. Use regular +import syntax instead. + + +## TypeScript + + +``` + + const zipUtil = await import("./utils/create-zip-file") + +``` + +## ArkTS + + +``` + + import { zipUtil } from "./utils/create-zip-file" + +``` + +## See also + +- Recipe 129: undefined +- Recipe 130: undefined +- Recipe 143: undefined + + diff --git a/linter/cookbook_convertor/md/recipe134.md b/linter/cookbook_convertor/md/recipe134.md new file mode 100644 index 000000000..3286e1cbf --- /dev/null +++ b/linter/cookbook_convertor/md/recipe134.md @@ -0,0 +1,44 @@ +# Definite assignment assertions are not supported + +Rule ``arkts-no-definite-assignment`` + +**Severity: error** + +ArkTS does not support definite assignment assertions ``let v!: T`` because +they are considered an excessive compiler hint. Use declaration with +initialization instead. + + +## TypeScript + + +``` + + let x!: number // Hint: x will be initialized before usage + + initialize() + + function initialize() { + x = 10 + } + + console.log("x = " + x) + +``` + +## ArkTS + + +``` + + function initialize() : number { + return 10 + } + + let x: number = initialize() + + console.log("x = " + x) + +``` + + diff --git a/linter/cookbook_convertor/md/recipe135.md b/linter/cookbook_convertor/md/recipe135.md new file mode 100644 index 000000000..545a49b9b --- /dev/null +++ b/linter/cookbook_convertor/md/recipe135.md @@ -0,0 +1,38 @@ +# IIFEs as namespace declarations are not supported + +Rule ``arkts-no-iife`` + +**Severity: error** + +ArkTS does not support IIFEs as namespace declarations because in |LANG|, +anonymous functions cannot serve as namespaces. Use regular syntax for +namespaces instead. + + +## TypeScript + + +``` + + var C = (function() { + function C(n) { + this.p = n + } + return C + })() + C.staticProperty = 1 + +``` + +## ArkTS + + +``` + + namespace C { + // ... + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe136.md b/linter/cookbook_convertor/md/recipe136.md new file mode 100644 index 000000000..3fa0cc3bf --- /dev/null +++ b/linter/cookbook_convertor/md/recipe136.md @@ -0,0 +1,37 @@ +# Prototype assignment is not supported + +Rule ``arkts-no-prototype-assignment`` + +**Severity: error** + +ArkTS does not support prototype assignment because there is no concept of +runtime prototype inheritance in the language. This feature is considered not +applicable to the static typing. + + +## TypeScript + + +``` + + var C = function(p) { + this.p = p + } + + C.prototype = { + m() { + console.log(this.p) + } + } + + C.prototype.q = function(r) { + return this.p === r + } + +``` + +## See also + +- Recipe 132: undefined + + diff --git a/linter/cookbook_convertor/md/recipe137.md b/linter/cookbook_convertor/md/recipe137.md new file mode 100644 index 000000000..d734fdebb --- /dev/null +++ b/linter/cookbook_convertor/md/recipe137.md @@ -0,0 +1,44 @@ +# ``globalThis`` is not supported + +Rule ``arkts-no-globalthis`` + +**Severity: error** + +ArkTS does not support both global scope and ``globalThis`` because untyped +objects with dynamically changed layout are not supported. + + +## TypeScript + + +``` + + // in a global file: + var abc = 100 + + // Refers to 'abc' from above. + globalThis.abc = 200 + +``` + +## ArkTS + + +``` + + // file1 + export let abc : number = 0 + + // file2 + import * as M from "../file1" + + M.abc = 200 + +``` + +## See also + +- Recipe 139: undefined +- Recipe 144: undefined + + diff --git a/linter/cookbook_convertor/md/recipe138.md b/linter/cookbook_convertor/md/recipe138.md new file mode 100644 index 000000000..d0f221081 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe138.md @@ -0,0 +1,45 @@ +# Utility types are not supported + +Rule ``arkts-no-utility-types`` + +**Severity: error** + +Currently ArkTS does not support utility types from TypeScript extensions to the +standard library (``Omit``, ``Partial``, ``Readonly``, ``Record``, ``Pick``, +etc.). + + +## TypeScript + + +``` + + type Person = { + name: string + age: number + location: string + } + + type QuantumPerson = Omit + +``` + +## ArkTS + + +``` + + class Person { + name: string + age: number + location: string + } + + class QuantumPerson { + name: string + age: number + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe139.md b/linter/cookbook_convertor/md/recipe139.md new file mode 100644 index 000000000..b7cec382e --- /dev/null +++ b/linter/cookbook_convertor/md/recipe139.md @@ -0,0 +1,69 @@ +# Declaring properties on functions is not supported + +Rule ``arkts-no-func-props`` + +**Severity: error** + +ArkTS does not support declaring properties on functions because there is no +support for objects with dynamically changing layout. Function objects follow +this rule and their layout cannot be changed in runtime. + + +## TypeScript + + +``` + + class MyImage { + // ... + } + + function readImage( + path: string, callback: (err: any, image: MyImage) => void + ) + { + // ... + } + + function readFileSync(path : string) : number[] { + return [] + } + + function decodeImageSync(contrents : number[]) { + // ... + } + + readImage.sync = (path: string) => { + const contents = readFileSync(path) + return decodeImageSync(contents) + } + +``` + +## ArkTS + + +``` + + class MyImage { + // ... + } + + function readImage( + path: string, callback: (err: Error, image: MyImage) => void + ) : Promise + { + // async implementation + } + + function readImageSync(path: string) : MyImage { + // sync implementation + } + +``` + +## See also + +- Recipe 137: undefined + + diff --git a/linter/cookbook_convertor/md/recipe14.md b/linter/cookbook_convertor/md/recipe14.md new file mode 100644 index 000000000..0feafbfb9 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe14.md @@ -0,0 +1,53 @@ +# Use ``class`` instead of a type with call signature + +Rule ``arkts-no-call-signatures`` + +**Severity: error** + +ArkTS does not support call signatures in object types. Use classes instead. + + +## TypeScript + + +``` + + type DescribableFunction = { + description: string + (someArg: number): string // call signature + } + + function doSomething(fn: DescribableFunction): void { + console.log(fn.description + " returned " + fn(6)) + } + +``` + +## ArkTS + + +``` + + class DescribableFunction { + description: string + public invoke(someArg: number): string { + return someArg.toString() + } + constructor() { + this.description = "desc" + } + } + + function doSomething(fn: DescribableFunction): void { + console.log(fn.description + " returned " + fn.invoke(6)) + } + + doSomething(new DescribableFunction()) + +``` + +## See also + +- Recipe 015: undefined + + diff --git a/linter/cookbook_convertor/md/recipe140.md b/linter/cookbook_convertor/md/recipe140.md new file mode 100644 index 000000000..ba6d22177 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe140.md @@ -0,0 +1,65 @@ +# ``Function.apply``, ``Function.bind``, ``Function.call`` are not supported + +Rule ``arkts-no-func-apply-bind-call`` + +**Severity: error** + +ArkTS does not allow to use standard library functions ``Function.apply``, +``Function.bind``, ``Function.call``. These APIs are needed in the standard +library to explicitly set ``this`` parameter for the called function. +In ArkTS semantics of ``this`` is restricted to the conventional OOP style, +and usage of ``this`` in stand-alone functions is prohibited. Thus these +functions are excessive. + + +## TypeScript + + +``` + + const person = { + firstName: "aa", + + fullName: function(): string { + return this.firstName + } + } + + const person1 = { + firstName: "Mary" + } + + // This will log "Mary": + console.log(person.fullName.apply(person1)) + +``` + +## ArkTS + + +``` + + class Person { + firstName : string + + constructor(firstName : string) { + this.firstName = firstName + } + fullName() : string { + return this.firstName + } + } + + let person = new Person("") + let person1 = new Person("Mary") + + // This will log "Mary": + console.log(person1.fullName()) + +``` + +## See also + +- Recipe 093: undefined + + diff --git a/linter/cookbook_convertor/md/recipe141.md b/linter/cookbook_convertor/md/recipe141.md new file mode 100644 index 000000000..1e16d75ad --- /dev/null +++ b/linter/cookbook_convertor/md/recipe141.md @@ -0,0 +1,34 @@ +# ``readonly T[]`` syntax is not supported + +Rule ``arkts-no-readonly-params`` + +**Severity: error** + +Currently ArkTS supports ``readonly`` for properties, but not for parameters. + + +## TypeScript + + +``` + + function foo(arr: readonly string[]) { + arr.slice() // OK + arr.push("hello!") // Compile-time error + } + +``` + +## ArkTS + + +``` + + function foo(arr: string[]) { + arr.slice() // OK + arr.push("hello!") // OK + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe142.md b/linter/cookbook_convertor/md/recipe142.md new file mode 100644 index 000000000..cca78dc76 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe142.md @@ -0,0 +1,50 @@ +# ``as const`` assertions are not supported + +Rule ``arkts-no-as-const`` + +**Severity: error** + +ArkTS does not support ``as const`` assertions because in the standard TypeScript +``as const`` annotates literals with corresponding literal types, and ArkTS +does not support literal types. + + +## TypeScript + + +``` + + // Type 'hello': + let x = "hello" as const + + // Type 'readonly [10, 20]': + let y = [10, 20] as const + + // Type '{ readonly text: "hello" }': + let z = { text: "hello" } as const + +``` + +## ArkTS + + +``` + + // Type 'string': + let x : string = "hello" + + // Type 'number[]': + let y : number[] = [10, 20] + + class Label { + text : string + } + + // Type 'Label': + let z : Label = { + text: "hello" + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe143.md b/linter/cookbook_convertor/md/recipe143.md new file mode 100644 index 000000000..861dd0b16 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe143.md @@ -0,0 +1,38 @@ +# Import assertions are not supported + +Rule ``arkts-no-import-assertions`` + +**Severity: error** + +ArkTS does not support import assertions because in |LANG|, import is a +compile-time, not a runtime feature. So asserting correctness of imported APIs +in runtime does not make sense for the statically typed language. Use ordinary +``import`` syntax instead. + + +## TypeScript + + +``` + + import { obj } from "./something.json" assert { type: "json" } + +``` + +## ArkTS + + +``` + + // Correctness of importing T will be checked in compile-time: + import { something } from "./module" + +``` + +## See also + +- Recipe 129: undefined +- Recipe 130: undefined +- Recipe 133: undefined + + diff --git a/linter/cookbook_convertor/md/recipe144.md b/linter/cookbook_convertor/md/recipe144.md new file mode 100644 index 000000000..f468371eb --- /dev/null +++ b/linter/cookbook_convertor/md/recipe144.md @@ -0,0 +1,54 @@ +# Usage of standard library is restricted + +Rule ``arkts-limited-stdlib`` + +**Severity: error** + +ArkTS does not allow usage of some APIs from the TypeScript/JavaScript standard library. +The most part of the restricted APIs relates to manipulating objects in +dynamic manner, which is not compatible with the static typing. Following APIs +are prohibited from usage: + +Properties and functions of the global object: ``eval``, +``Infinity``, ``NaN``, ``isFinite``, ``isNaN``, ``parseFloat``, ``parseInt``, +``encodeURI``, ``encodeURIComponent``, ``Encode``, +``decodeURI``, ``decodeURIComponent``, ``Decode``, +``escape``, ``unescape``, ``ParseHexOctet`` + +``Object``: ``__proto__``, ``__defineGetter__``, ``__defineSetter__``, +``__lookupGetter__``, ``__lookupSetter__``, ``assign``, ``create``, +``defineProperties``, ``defineProperty``, ``entries``, ``freeze``, +``fromEntries``, ``getOwnPropertyDescriptor``, ``getOwnPropertyDescriptors``, +``getOwnPropertyNames``, ``getOwnPropertySymbols``, ``getPrototypeOf``, +``hasOwn``, ``hasOwnProperty``, ``is``, ``isExtensible``, ``isFrozen``, +``isPrototypeOf``, ``isSealed``, ``keys``, ``preventExtensions``, +``propertyIsEnumerable``, ``seal``, ``setPrototypeOf``, ``values`` + +``Reflect``: ``apply``, ``construct``, ``defineProperty``, ``deleteProperty``, +``get``, ``getOwnPropertyDescriptor``, ``getPrototypeOf``, ``has``, +``isExtensible``, ``ownKeys``, ``preventExtensions``, ``set``, +``setPrototypeOf`` + +``Proxy``: ``handler.apply()``, ``handler.construct()``, +``handler.defineProperty()``, ``handler.deleteProperty()``, ``handler.get()``, +``handler.getOwnPropertyDescriptor()``, ``handler.getPrototypeOf()``, +``handler.has()``, ``handler.isExtensible()``, ``handler.ownKeys()``, +``handler.preventExtensions()``, ``handler.set()``, ``handler.setPrototypeOf()`` + +``Array``: ``isArray`` + +``ArrayBuffer``: ``isView`` + + +## See also + +- Recipe 001: undefined +- Recipe 002: undefined +- Recipe 052: undefined +- Recipe 060: undefined +- Recipe 066: undefined +- Recipe 105: undefined +- Recipe 109: undefined +- Recipe 137: undefined + + diff --git a/linter/cookbook_convertor/md/recipe15.md b/linter/cookbook_convertor/md/recipe15.md new file mode 100644 index 000000000..129d6f7f6 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe15.md @@ -0,0 +1,50 @@ +# Use ``class`` instead of a type with constructor signature + +Rule ``arkts-no-ctor-signatures-type`` + +**Severity: error** + +ArkTS does not support constructor signatures in object types. Use classes +instead. + + +## TypeScript + + +``` + + class SomeObject {} + + type SomeConstructor = { + new (s: string): SomeObject + } + + function fn(ctor: SomeConstructor) { + return new ctor("hello") + } + +``` + +## ArkTS + + +``` + + class SomeObject { + public f: string + constructor (s: string) { + this.f = s + } + } + + function fn(s: string): SomeObject { + return new SomeObject(s) + } + +``` + +## See also + +- Recipe 014: undefined + + diff --git a/linter/cookbook_convertor/md/recipe16.md b/linter/cookbook_convertor/md/recipe16.md new file mode 100644 index 000000000..8fd0da8ee --- /dev/null +++ b/linter/cookbook_convertor/md/recipe16.md @@ -0,0 +1,47 @@ +# Only one static block is supported + +Rule ``arkts-no-multiple-static-blocks`` + +**Severity: error** + +ArkTS does not allow to have sevaral static block for class initialization, +combine static blocks statements to the one static block. + + +## TypeScript + + +``` + + class C { + static s: string + + static { + C.s = "aa" + } + static { + C.s = C.s + "bb" + } + } + +``` + +## ArkTS + + +``` + + + class C { + static s: string + + static { + C.s = "aa" + C.s = C.s + "bb" + } + } + + +``` + + diff --git a/linter/cookbook_convertor/md/recipe17.md b/linter/cookbook_convertor/md/recipe17.md new file mode 100644 index 000000000..4dd591c0e --- /dev/null +++ b/linter/cookbook_convertor/md/recipe17.md @@ -0,0 +1,43 @@ +# Indexed signatures are not supported + +Rule ``arkts-no-indexed-signatures`` + +**Severity: error** + +ArkTS does not allow indexed signatures, use arrays instead. + + +## TypeScript + + +``` + + // Interface with an indexed signature: + interface StringArray { + [index: number]: string + } + + function getStringArray() : StringArray { + return ["a", "b", "c"] + } + + const myArray: StringArray = getStringArray() + const secondItem = myArray[1] + +``` + +## ArkTS + + +``` + + class X { + public f: string[] + } + + let myArray: X = new X() + const secondItem = myArray.f[1] + +``` + + diff --git a/linter/cookbook_convertor/md/recipe19.md b/linter/cookbook_convertor/md/recipe19.md new file mode 100644 index 000000000..41baed871 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe19.md @@ -0,0 +1,49 @@ +# Use inheritance instead of intersection types + +Rule ``arkts-no-intersection-types`` + +**Severity: error** + +Currently, ArkTS does not support intersection types. You can use inheritance +as a work-around. + + +## TypeScript + + +``` + + interface Identity { + id: number + name: string + } + + interface Contact { + email: string + phone: string + } + + type Employee = Identity & Contact + +``` + +## ArkTS + + +``` + + interface Identity { + id: number + name: string + } + + interface Contact { + email: string + phone: string + } + + interface Employee extends Identity, Contact {} + +``` + + diff --git a/linter/cookbook_convertor/md/recipe2.md b/linter/cookbook_convertor/md/recipe2.md new file mode 100644 index 000000000..cc02012a1 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe2.md @@ -0,0 +1,49 @@ +# ``Symbol()`` API is not supported + +Rule ``arkts-no-symbol`` + +**Severity: error** + +TypeScript has ``Symbol()`` API, which can be used among other things to generate +unique property names at runtime. ArkTS does not support ``Symbol()`` API +because its most popular use cases make no sense in the statically typed +environment. In particular, the object layout is defined at compile time +and cannot be changed at runtime. + + +## TypeScript + + +``` + + const sym = Symbol() + let o = { + [sym]: "value" + } + +``` + +## ArkTS + + +``` + + class SomeClass { + public someProperty : string + } + let o = new SomeClass() + +``` + +## See also + +- Recipe 001: undefined +- Recipe 052: undefined +- Recipe 059: undefined +- Recipe 060: undefined +- Recipe 066: undefined +- Recipe 105: undefined +- Recipe 109: undefined +- Recipe 144: undefined + + diff --git a/linter/cookbook_convertor/md/recipe21.md b/linter/cookbook_convertor/md/recipe21.md new file mode 100644 index 000000000..75024ca7b --- /dev/null +++ b/linter/cookbook_convertor/md/recipe21.md @@ -0,0 +1,32 @@ +# Returning ``this`` type is not supported + +Rule ``arkts-no-this-as-return-type`` + +**Severity: error** + +ArkTS does not support the returning ``this`` type. Use explicit type instead. + + +## TypeScript + + +``` + + interface ListItem { + getHead(): this + } + +``` + +## ArkTS + + +``` + + interface ListItem { + getHead(): ListItem + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe22.md b/linter/cookbook_convertor/md/recipe22.md new file mode 100644 index 000000000..1ea9a18cb --- /dev/null +++ b/linter/cookbook_convertor/md/recipe22.md @@ -0,0 +1,40 @@ +# Conditional types are not supported + +Rule ``arkts-no-conditional-types`` + +**Severity: error** + +ArkTS does not support conditional type aliases. Introduce a new type with +constraints explicitly or rewrite logic with use of ``Object``. ``infer`` +keyword is not supported. + + +## TypeScript + + +``` + + type X = T extends number ? T : never + + type Y = T extends Array ? Item : never + +``` + +## ArkTS + + +``` + + // Provide explicit contraints within type alias + type X1 = T + + // Rewrite with Object. Less type control, need more type checks for safety + type X2 = Object + + // Item has to be used as a generic parameter and need to be properly + // instantiated + type YI> = Item + +``` + + diff --git a/linter/cookbook_convertor/md/recipe24.md b/linter/cookbook_convertor/md/recipe24.md new file mode 100644 index 000000000..174d84055 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe24.md @@ -0,0 +1,46 @@ +# Optional parameters are not supported for primitive types + +Rule ``arkts-no-opt-params`` + +**Severity: error** + +ArkTS does not support optional parameters of primitive types. +You can use default parameter values or reference types. For reference types, +non-specified optional parameter is set to ``null``. + + +## TypeScript + + +``` + + // x is an optional parameter: + function f(x?: number) { + console.log(x) // log undefined or number + } + + // x is a required parameter with the default value: + function g(x: number = 1) { + console.log(x) + } + +``` + +## ArkTS + + +``` + + // You can use reference type (will be set to null if missing): + function f(x?: Number) { + console.log(x) // log null or some number + } + + // You can use a required parameter with the default value: + function g(x: number = 1) { + console.log(x) + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe25.md b/linter/cookbook_convertor/md/recipe25.md new file mode 100644 index 000000000..035716d5b --- /dev/null +++ b/linter/cookbook_convertor/md/recipe25.md @@ -0,0 +1,57 @@ +# Declaring fields in ``constructor`` is not supported + +Rule ``arkts-no-ctor-prop-decls`` + +**Severity: error** + +ArkTS does not support declaring class fields in the ``constructor``. +You must declare them inside the ``class`` declaration instead. + + +## TypeScript + + +``` + + class Person { + constructor( + protected ssn: string, + private firstName: string, + private lastName: string + ) { + this.ssn = ssn + this.firstName = firstName + this.lastName = lastName + } + + getFullName(): string { + return this.firstName + " " + this.lastName + } + } + +``` + +## ArkTS + + +``` + + class Person { + protected ssn: string + private firstName: string + private lastName: string + + constructor(ssn: string, firstName: string, lastName: string) { + this.ssn = ssn + this.firstName = firstName + this.lastName = lastName + } + + getFullName(): string { + return this.firstName + " " + this.lastName + } + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe27.md b/linter/cookbook_convertor/md/recipe27.md new file mode 100644 index 000000000..e29be1c3e --- /dev/null +++ b/linter/cookbook_convertor/md/recipe27.md @@ -0,0 +1,44 @@ +# Construct signatures not supported in interfaces + +Rule ``arkts-no-ctor-signatures-iface`` + +**Severity: error** + +ArkTS does not support construct signatures. Use methods instead. + + +## TypeScript + + +``` + + interface I { + new (s: string): I + } + + function fn(i: I) { + return new i("hello") + } + +``` + +## ArkTS + + +``` + + interface I { + create(s: string): I + } + + function fn(i: I) { + return i.create("hello") + } + +``` + +## See also + +- Recipe 015: undefined + + diff --git a/linter/cookbook_convertor/md/recipe28.md b/linter/cookbook_convertor/md/recipe28.md new file mode 100644 index 000000000..18a706223 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe28.md @@ -0,0 +1,30 @@ +# Indexed access types are not supported + +Rule ``arkts-no-aliases-by-index`` + +**Severity: error** + +ArkTS does not support indexed access types. Use the type name instead. + + +## TypeScript + + +``` + + type Point = {x: number, y: number} + type N = Point["x"] // is equal to number + +``` + +## ArkTS + + +``` + + class Point {x: number = 0; y: number = 0} + type N = number + +``` + + diff --git a/linter/cookbook_convertor/md/recipe29.md b/linter/cookbook_convertor/md/recipe29.md new file mode 100644 index 000000000..9f63d1485 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe29.md @@ -0,0 +1,33 @@ +# Indexed access is not supported for fields + +Rule ``arkts-no-props-by-index`` + +**Severity: error** + +ArkTS does not support indexed access for class fields. Use dot notation +instead. + + +## TypeScript + + +``` + + class Point {x: number = 0; y: number = 0} + let p: Point = {x: 1, y: 2} + let x = p["x"] + +``` + +## ArkTS + + +``` + + class Point {x: number = 0; y: number = 0} + let p: Point = {x: 1, y: 2} + let x = p.x + +``` + + diff --git a/linter/cookbook_convertor/md/recipe3.md b/linter/cookbook_convertor/md/recipe3.md new file mode 100644 index 000000000..94348f064 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe3.md @@ -0,0 +1,34 @@ +# Private '#' identifiers are not supported + +Rule ``arkts-no-private-identifiers`` + +**Severity: error** + +ArkTS does not private identifiers started with ``#`` symbol, use ``private`` +keyword instead. + + +## TypeScript + + +``` + + class C { + foo = 1 + } + +``` + +## ArkTS + + +``` + + class C { + private foo = 1 + } + + +``` + + diff --git a/linter/cookbook_convertor/md/recipe30.md b/linter/cookbook_convertor/md/recipe30.md new file mode 100644 index 000000000..fae7e5c6c --- /dev/null +++ b/linter/cookbook_convertor/md/recipe30.md @@ -0,0 +1,51 @@ +# Structural identity is not supported + +Rule ``arkts-no-structural-identity`` + +**Severity: error** + +Currently, ArkTS does not support structural identity, i.e., the compiler +cannot compare two types' public APIs and decide whether such types are +identical. Use other mechanisms (inheritance, interfaces or type aliases) +instead. + +For the examples below, types ``X`` and ``Y`` are equivalent (interchangeble) +in TypeScript, while in ArkTS they are not. + + +## TypeScript + + +``` + + interface X { + f(): string + } + + interface Y { // Y is equal to X + f(): string + } + +``` + +## ArkTS + + +``` + + interface X { + f(): string + } + + type Y = X // Y is equal to X + +``` + +## See also + +- Recipe 031: undefined +- Recipe 032: undefined +- Recipe 035: undefined + + + diff --git a/linter/cookbook_convertor/md/recipe31.md b/linter/cookbook_convertor/md/recipe31.md new file mode 100644 index 000000000..78f624383 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe31.md @@ -0,0 +1,84 @@ +# Structural typing is not supported for subtyping / supertyping + +Rule ``arkts-no-structural-subtyping`` + +**Severity: error** + +Currently, ArkTS does not check structural equivalence for type inference, +i.e., the compiler cannot compare two types' public APIs and decide whether +such types are identical. Use other mechanisms (inheritance or interfaces) +instead. + + +## TypeScript + + +``` + + class X { + public foo: number + + constructor() { + this.foo = 0 + } + } + + class Y { + public foo: number + + constructor() { + this.foo = 0 + } + } + + let x = new X() + let y = new Y() + + console.log("Assign X to Y") + y = x + + console.log("Assign Y to X") + x = y + + +``` + +## ArkTS + + +``` + + class X { + public foo: number + + constructor() { + this.foo = 0 + } + } + + // Y is derived from X, which explicitly set subtype / supertype relations: + class Y extends X { + constructor() { + super() + } + } + + let x = new X() + let y = new Y() + + console.log("Assign Y to X") + x = y // ok, X is the super class of Y + + // Cannot assign X to Y + //y = x - compile-time error + + +``` + +## See also + +- Recipe 030: undefined +- Recipe 032: undefined +- Recipe 035: undefined + + diff --git a/linter/cookbook_convertor/md/recipe32.md b/linter/cookbook_convertor/md/recipe32.md new file mode 100644 index 000000000..fcb19efaa --- /dev/null +++ b/linter/cookbook_convertor/md/recipe32.md @@ -0,0 +1,88 @@ +# Structural typing is not supported for assignability checks + +Rule ``arkts-no-structural-assignability`` + +**Severity: error** + +Currently, ArkTS does not check structural equivalence when checking if types +are assignable to each other, i.e., the compiler cannot compare two types' +public APIs and decide whether such types are identical. Use other mechanisms +(inheritance or interfaces) instead. + + +## TypeScript + + +``` + + class X { + public foo: number + + constructor() { + this.foo = 0 + } + } + + class Y { + public foo: number + constructor() { + this.foo = 0 + } + } + + let x = new X() + let y = new Y() + + console.log("Assign X to Y") + y = x + + console.log("Assign Y to X") + x = y + +``` + +## ArkTS + + +``` + + interface Z { + foo: number + } + + // X implements interface Z, which makes relation between X and Y explicit. + class X implements Z { + public foo: number + + constructor() { + this.foo = 0 + } + } + + // Y implements interface Z, which makes relation between X and Y explicit. + class Y implements Z { + public foo: number + + constructor() { + this.foo = 0 + } + } + + let x: Z = new X() + let y: Z = new Y() + + console.log("Assign X to Y") + y = x // ok, both are of the same type + + console.log("Assign Y to X") + x = y // ok, both are of the same type + +``` + +## See also + +- Recipe 030: undefined +- Recipe 031: undefined +- Recipe 035: undefined + + diff --git a/linter/cookbook_convertor/md/recipe33.md b/linter/cookbook_convertor/md/recipe33.md new file mode 100644 index 000000000..4b8adbb07 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe33.md @@ -0,0 +1,58 @@ +# Optional properties are not supported for primitive types + +Rule ``arkts-no-opt-props`` + +**Severity: error** + +ArkTS does not support optional properties of primitive types. You can use +properties with default values or reference types. For reference types, +non-specified optional property is set to ``null``. This rule applies both to +classes and interfaces. + + +## TypeScript + + +``` + + class CompilerOptions { + strict?: boolean + sourcePath?: string + targetPath?: string + } + + let options: CompilerOptions = { + strict: true, + sourcePath: "./src" + } + + if (options.targetPath == undefined) { + // Some logic + } + +``` + +## ArkTS + + +``` + + class CompilerOptions { + strict: boolean = false + sourcePath: string = "" + targetPath?: string + } + + let options: CompilerOptions = { + strict: true, + sourcePath: "./src" + // targetPath is implicitly set to null + } + + if (options.targetPath == null) { + // Some logic + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe34.md b/linter/cookbook_convertor/md/recipe34.md new file mode 100644 index 000000000..c1536ee24 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe34.md @@ -0,0 +1,51 @@ +# Type inference in case of generic function calls is limited + +Rule ``arkts-no-inferred-generic-params`` + +**Severity: error** + +ArkTS allows to omit generic type parameters if it is possible to infer +the concrete types from the parameters passed to the function. Otherwise a +compile-time error occurs. In particular, inference of generic type parameters +based only on function return types is prohibited. + + +## TypeScript + + +``` + + function choose(x: T, y: T): T { + return Math.random() < 0.5 ? x : y + } + + let x = choose(10, 20) // OK, choose(...) is inferred + let y = choose("10", 20) // Compile-time error + + function greet(): T { + return "Hello" as T + } + let z = greet() // Type of x is inferred as "unknown" + +``` + +## ArkTS + + +``` + + function choose(x: T, y: T): T { + return Math.random() < 0.5 ? x : y + } + + let x = choose(10, 20) // OK, choose(...) is inferred + let y = choose("10", 20) // Compile-time error + + function greet(): T { + return "Hello" as T + } + let z = greet() + +``` + + diff --git a/linter/cookbook_convertor/md/recipe35.md b/linter/cookbook_convertor/md/recipe35.md new file mode 100644 index 000000000..23d4a6875 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe35.md @@ -0,0 +1,103 @@ +# Structural typing is not supported for type inference + +Rule ``arkts-no-structural-inference`` + +**Severity: error** + +Currently, ArkTS does not support structural typing, i.e., the compiler cannot +compare two types' public APIs and decide whether such types are identical. +Use inheritance and interfaces to specify the relation between the types +explicitly. + + +## TypeScript + + +``` + + class X { + public foo: number + private s: string + + constructor (f: number) { + this.foo = f + this.s = "" + } + + public say(): void { + console.log("X = ", this.foo) + } + } + + class Y { + public foo: number + + constructor (f: number) { + this.foo = f + } + public say(): void { + console.log("Y = ", this.foo) + } + } + + function bar(z: X): void { + z.say() + } + + // X and Y are equivalent because their public API is equivalent. + // Thus the second call is allowed: + bar(new X(1)) + bar(new Y(2) as X) + +``` + +## ArkTS + + +``` + + interface Z { + say(): void + } + + class X implements Z { + public foo: number + private s: string + + constructor (f: number) { + this.foo = f + this.s = "" + } + public say(): void { + console.log("X = ", this.foo) + } + } + + class Y implements Z { + public foo: number + + constructor (f: number) { + this.foo = f + } + public say(): void { + console.log("Y = ", this.foo) + } + } + + function bar(z: Z): void { + z.say() + } + + // X and Y implement the same interface Z, thus both calls are allowed: + bar(new X(1)) + bar(new Y(2)) + +``` + +## See also + +- Recipe 030: undefined +- Recipe 031: undefined +- Recipe 032: undefined + + diff --git a/linter/cookbook_convertor/md/recipe37.md b/linter/cookbook_convertor/md/recipe37.md new file mode 100644 index 000000000..f0ee0385f --- /dev/null +++ b/linter/cookbook_convertor/md/recipe37.md @@ -0,0 +1,29 @@ +# RegExp literals are not supported + +Rule ``arkts-no-regexp-literals`` + +**Severity: error** + +Currently, ArkTS does not support RegExp literals. Use library call with string +literals instead. + + +## TypeScript + + +``` + + let regex: RegExp = /bc*d/ + +``` + +## ArkTS + + +``` + + let regex: RegExp = new RegExp("/bc*d/") + +``` + + diff --git a/linter/cookbook_convertor/md/recipe38.md b/linter/cookbook_convertor/md/recipe38.md new file mode 100644 index 000000000..86c2b7705 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe38.md @@ -0,0 +1,146 @@ +# Object literal must correspond to some explicitly declared class or interface + +Rule ``arkts-no-untyped-obj-literals`` + +**Severity: error** + +ArkTS supports usage of object literals if the compiler can infer to what +classes or interfaces such literals correspond to. Otherwise, a compile-time +error occurs. Specifically, using literals to initialize classes and interfaces +is not supported in following contexts: + +* Initialization of anything that has ``any``, ``Object``, or ``object`` type +* Initialization of classes or interfaces with methods +* Initialization of classes which declare a ``constructor`` with parameters +* Initialization of classes with ``readonly`` fields + + +## TypeScript + + +``` + + let o1 = {n: 42, s: "foo"} + let o2: Object = {n: 42, s: "foo"} + let o3: object = {n: 42, s: "foo"} + + let oo: Object[] = [{n: 1, s: "1"}, {n: 2, s: "2"}] + + class C2 { + s: string + constructor(s: string) { + this.s = "s =" + s + } + } + let o4: C2 = {s: "foo"} + + class C3 { + readonly n: number = 0 + readonly s: string = "" + } + let o5: C3 = {n: 42, s: "foo"} + + abstract class A {} + let o6: A = {} + + class C4 { + n: number = 0 + s: string = "" + f() { + console.log("Hello") + } + } + let o7: C4 = {n: 42, s: "foo", f : () => {}} + + class Point { + x: number = 0 + y: number = 0 + } + + function id_x_y(o: Point): Point { + return o + } + + // Structural typing is used to deduce that p is Point: + let p = {x: 5, y: 10} + id_x_y(p) + + // A literal can be contextually (i.e., implicitly) typed as Point: + id_x_y({x: 5, y: 10}) + +``` + +## ArkTS + + +``` + + class C1 { + n: number = 0 + s: string = "" + } + + let o1: C1 = {n: 42, s: "foo"} + let o2: C1 = {n: 42, s: "foo"} + let o3: C1 = {n: 42, s: "foo"} + + let oo: C1[] = [{n: 1, s: "1"}, {n: 2, s: "2"}] + + class C2 { + s: string + constructor(s: string) { + this.s = "s =" + s + } + } + let o4 = new C2("foo") + + class C3 { + n: number = 0 + s: string = "" + } + let o5: C3 = {n: 42, s: "foo"} + + abstract class A {} + class C extends A {} + let o6: C = {} // or let o6: C = new C() + + class C4 { + n: number = 0 + s: string = "" + f() { + console.log("Hello") + } + } + let o7 = new C4() + o7.n = 42 + o7.s = "foo" + + class Point { + x: number = 0 + y: number = 0 + + // constructor() is used before literal initialization + // to create a valid object. Since there is no other Point constructors, + // constructor() is automatically added by compiler + } + + function id_x_y(o: Point): Point { + return o + } + + // Explicit type is required for literal initialization + let p: Point = {x: 5, y: 10} + id_x_y(p) + + // id_x_y expects Point explicitly + // New instance of Point is initialized with the literal + id_x_y({x: 5, y: 10}) + +``` + +## See also + +- Recipe 040: undefined +- Recipe 043: undefined + + diff --git a/linter/cookbook_convertor/md/recipe4.md b/linter/cookbook_convertor/md/recipe4.md new file mode 100644 index 000000000..92f022f7f --- /dev/null +++ b/linter/cookbook_convertor/md/recipe4.md @@ -0,0 +1,31 @@ +# Use unique names for types, namespaces, etc. + +Rule ``arkts-unique-names`` + +**Severity: error** + +Names for types, namespaces and so on must be unique and distinct from other +names, e.g., variable names. + + +## TypeScript + + +``` + + let X: string + type X = number[] // Type alias with the same name as the variable + +``` + +## ArkTS + + +``` + + let X: string + type T = number[] // X is not allowed here to avoid name collisions + +``` + + diff --git a/linter/cookbook_convertor/md/recipe40.md b/linter/cookbook_convertor/md/recipe40.md new file mode 100644 index 000000000..d034e37d5 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe40.md @@ -0,0 +1,46 @@ +# Object literals cannot be used as type declarations + +Rule ``arkts-no-obj-literals-as-types`` + +**Severity: error** + +ArkTS does not support the usage of object literals to declare +types in place. Declare classes and interfaces explicitly instead. + + +## TypeScript + + +``` + + let o: {x: number, y: number} = { + x: 2, + y: 3 + } + + type S = Set<{x: number, y: number}> + +``` + +## ArkTS + + +``` + + class O { + x: number + y: number + } + + let o: O = {x: 2, y: 3} + + type S = Set + +``` + +## See also + +- Recipe 038: undefined +- Recipe 043: undefined + + diff --git a/linter/cookbook_convertor/md/recipe43.md b/linter/cookbook_convertor/md/recipe43.md new file mode 100644 index 000000000..d0a2d5c7d --- /dev/null +++ b/linter/cookbook_convertor/md/recipe43.md @@ -0,0 +1,41 @@ +# Array literals must contain elements of only inferrable types + +Rule ``arkts-no-noninferrable-arr-literals`` + +**Severity: error** + +Basically, ArkTS infers the type of an array literal as a union type of its +contents. But if there is at least one element with a non-inferrable type +(e.g. untyped object literal), a compile-time error occurs. + + +## TypeScript + + +``` + + let a = [{n: 1, s: "1"}, {n: 2, s : "2"}] + +``` + +## ArkTS + + +``` + + class C { + n: number = 0 + s: string = "" + } + + let a1 = [{n: 1, s: "1"} as C, {n: 2, s : "2"} as C] // a1 is of type "C[]" + let a2: C[] = [{n: 1, s: "1"}, {n: 2, s : "2"}] // ditto + +``` + +## See also + +- Recipe 038: undefined +- Recipe 040: undefined + + diff --git a/linter/cookbook_convertor/md/recipe45.md b/linter/cookbook_convertor/md/recipe45.md new file mode 100644 index 000000000..20680c932 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe45.md @@ -0,0 +1,34 @@ +# Lambdas require explicit type annotation for parameters + +Rule ``arkts-explicit-param-types-in-lambdas`` + +**Severity: error** + +Currently, ArkTS requires the types of lambda parameters +to be explicitly specified. + + +## TypeScript + + +``` + + let f = (s) => { // type any is assumed + console.log(s) + } + +``` + +## ArkTS + + +``` + + // Explicit types for lambda parameters are mandatory: + let f = (s: string) => { + console.log(s) + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe46.md b/linter/cookbook_convertor/md/recipe46.md new file mode 100644 index 000000000..71fcbf8a1 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe46.md @@ -0,0 +1,33 @@ +# Use arrow functions instead of function expressions + +Rule ``arkts-no-func-expressions`` + +**Severity: error** + +ArkTS does not support function expressions, use arrow functions instead +to be explicitly specified. + + +## TypeScript + + +``` + + let f = function (s: string) { + console.log(s) + } + +``` + +## ArkTS + + +``` + + let f = (s: string) => { + console.log(s) + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe49.md b/linter/cookbook_convertor/md/recipe49.md new file mode 100644 index 000000000..eb06bc02e --- /dev/null +++ b/linter/cookbook_convertor/md/recipe49.md @@ -0,0 +1,35 @@ +# Use generic functions instead of generic arrow functions + +Rule ``arkts-no-generic-lambdas`` + +**Severity: error** + +ArkTS does not support generic arrow functions. Use normal generic functions +instead. + + +## TypeScript + + +``` + + let generic_arrow_func = (x: T) => { return x } + + generic_arrow_func("string") + +``` + +## ArkTS + + +``` + + function generic_func(x: T): T { + return x + } + + generic_func("string") + +``` + + diff --git a/linter/cookbook_convertor/md/recipe5.md b/linter/cookbook_convertor/md/recipe5.md new file mode 100644 index 000000000..4d8fbb2d5 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe5.md @@ -0,0 +1,63 @@ +# Use ``let`` instead of ``var`` + +Rule ``arkts-no-var`` + +**Severity: error** + +ArkTS does not support ``var``, always use ``let`` instead. + + +## TypeScript + + +``` + + function f(shouldInitialize: boolean) { + if (shouldInitialize) { + var x = 10 + } + return x + } + + console.log(f(true)) // 10 + console.log(f(false)) // undefined + + let upper_let = 0 + { + var scoped_var = 0 + let scoped_let = 0 + upper_let = 5 + } + scoped_var = 5 // Visible + scoped_let = 5 // Compile-time error + +``` + +## ArkTS + + +``` + + function f(shouldInitialize: boolean): Object { + let x: Object = new Object() + if (shouldInitialize) { + x = 10 + } + return x + } + + console.log(f(true)) // 10 + console.log(f(false)) // {} + + let upper_let = 0 + let scoped_var = 0 + { + let scoped_let = 0 + upper_let = 5 + } + scoped_var = 5 + scoped_let = 5 // Compile-time error + +``` + + diff --git a/linter/cookbook_convertor/md/recipe50.md b/linter/cookbook_convertor/md/recipe50.md new file mode 100644 index 000000000..1f839a5e1 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe50.md @@ -0,0 +1,49 @@ +# Class literals are not supported + +Rule ``arkts-no-class-literals`` + +**Severity: error** + +ArkTS does not support class literals. A new named class type must be +introduced explicitly. + + +## TypeScript + + +``` + + const Rectangle = class { + constructor(height: number, width: number) { + this.heigth = height + this.width = width + } + + heigth + width + } + + const rectangle = new Rectangle(0.0, 0.0) + +``` + +## ArkTS + + +``` + + class Rectangle { + constructor(height: number, width: number) { + this.heigth = height + this.width = width + } + + heigth: number + width: number + } + + const rectangle = new Rectangle(0.0, 0.0) + +``` + + diff --git a/linter/cookbook_convertor/md/recipe51.md b/linter/cookbook_convertor/md/recipe51.md new file mode 100644 index 000000000..9b6ddc1fd --- /dev/null +++ b/linter/cookbook_convertor/md/recipe51.md @@ -0,0 +1,42 @@ +# Classes cannot be specified in ``implements`` clause + +Rule ``arkts-implements-only-iface`` + +**Severity: error** + +ArkTS does not allow to specify a class in implements clause. Only interfaces +may be specified. + + +## TypeScript + + +``` + + class C { + foo() {} + } + + class C1 implements C { + foo() {} + } + +``` + +## ArkTS + + +``` + + interface C { + foo() + } + + class C1 implements C { + foo() {} + } + + +``` + + diff --git a/linter/cookbook_convertor/md/recipe52.md b/linter/cookbook_convertor/md/recipe52.md new file mode 100644 index 000000000..2b8d92e7c --- /dev/null +++ b/linter/cookbook_convertor/md/recipe52.md @@ -0,0 +1,59 @@ +# Attempt to access an undefined property is a compile-time error + +Rule ``arkts-no-undefined-prop-access`` + +**Severity: error** + +ArkTS supports accessing only those class properties that are either declared +in the class, or accessible via inheritance. Accessing any other properties is +prohibited and causes compile-time errors. Use proper types to check property +existence during compilation. + + +## TypeScript + + +``` + + let person = {name: "Bob", isEmployee: true} + + let n = person["name"] + let e = person["isEmployee"] + let s = person["office"] // undefined + +``` + +## ArkTS + + +``` + + class Person { + constructor(name: string, isEmployee: boolean) { + this.name = name + this.isEmployee = isEmployee + } + + name: string + isEmployee: boolean + } + + let person = new Person("Bob", true) + let n = person.name + let e = person.isEmployee + let s = person.office // Compile-time error + +``` + +## See also + +- Recipe 001: undefined +- Recipe 002: undefined +- Recipe 059: undefined +- Recipe 060: undefined +- Recipe 066: undefined +- Recipe 105: undefined +- Recipe 109: undefined +- Recipe 144: undefined + + diff --git a/linter/cookbook_convertor/md/recipe53.md b/linter/cookbook_convertor/md/recipe53.md new file mode 100644 index 000000000..17c22a056 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe53.md @@ -0,0 +1,56 @@ +# Only ``as T`` syntax is supported for type casts + +Rule ``arkts-as-casts`` + +**Severity: error** + +ArkTS supports ``as`` keyword as the only syntax for type casts. +Incorrect cast causes a compile-time error or runtime ``ClassCastException``. +```` syntax for type casts is not supported. + + +## TypeScript + + +``` + + class Shape {} + class Circle extends Shape {x: number = 5} + class Square extends Shape {y: string = "a"} + + function createShape(): Shape { + return new Circle() + } + + let c1 = createShape() + + let c2 = createShape() as Circle + + // No report is provided during compilation + // nor during runtime if cast is wrong: + let c3 = createShape() as Square + console.log(c3.y) // undefined + +``` + +## ArkTS + + +``` + + class Shape {} + class Circle extends Shape {x: number = 5} + class Square extends Shape {y: string = "a"} + + function createShape(): Shape { + return new Circle() + } + + let c2 = createShape() as Circle + + // ClassCastException during runtime is thrown: + let c3 = createShape() as Square + +``` + + diff --git a/linter/cookbook_convertor/md/recipe54.md b/linter/cookbook_convertor/md/recipe54.md new file mode 100644 index 000000000..f966c42dd --- /dev/null +++ b/linter/cookbook_convertor/md/recipe54.md @@ -0,0 +1,10 @@ +# JSX expressions are not supported + +Rule ``arkts-no-jsx`` + +**Severity: error** + +Do not use JSX since no alternative is provided to rewrite it. + + + diff --git a/linter/cookbook_convertor/md/recipe55.md b/linter/cookbook_convertor/md/recipe55.md new file mode 100644 index 000000000..bf0dc71c2 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe55.md @@ -0,0 +1,48 @@ +# Unary operators ``+``, ``-`` and ``~`` work only on numbers + +Rule ``arkts-no-polymorphic-unops`` + +**Severity: error** + +ArkTS allows unary operators to work on numeric types only. A compile-time +error occurs if these operators are applied to a non-numeric type. Unlike in +TypeScript, implicit casting of strings in this context is not supported and must +be done explicitly. + + +## TypeScript + + +``` + + let a = +5 // 5 as number + let b = +"5" // 5 as number + let c = -5 // -5 as number + let d = -"5" // -5 as number + let e = ~5 // -6 as number + let f = ~"5" // -6 as number + let g = +"string" // NaN as number + +``` + +## ArkTS + + +``` + + let a = +5 // 5 as int + let b = +"5" // Compile-time error + let c = -5 // -5 as int + let d = -"5" // Compile-time error + let e = ~5 // -6 as int + let f = ~"5" // Compile-time error + let g = +"string" // Compile-time error + +``` + +## See also + +- Recipe 061: undefined +- Recipe 063: undefined + + diff --git a/linter/cookbook_convertor/md/recipe56.md b/linter/cookbook_convertor/md/recipe56.md new file mode 100644 index 000000000..1b171d1ad --- /dev/null +++ b/linter/cookbook_convertor/md/recipe56.md @@ -0,0 +1,54 @@ +# Unary ``+`` cannot be used for casting to ``number`` + +Rule ``arkts-no-unary-plus-cast`` + +**Severity: error** + +ArkTS does not support casting from any type to a numeric type +by using the unary ``+`` operator, which can be applied only to +numeric types. + + +## TypeScript + + +``` + + function returnTen(): string { + return "-10" + } + + function returnString(): string { + return "string" + } + + let a = +returnTen() // -10 as number + let b = +returnString() // NaN + +``` + +## ArkTS + + +``` + + function returnTen(): string { + return "-10" + } + + function returnString(): string { + return "string" + } + + let a = +returnTen() // Compile-time error + let b = +returnString() // Compile-time error + +``` + +## See also + +- Recipe 055: undefined +- Recipe 061: undefined +- Recipe 063: undefined + + diff --git a/linter/cookbook_convertor/md/recipe59.md b/linter/cookbook_convertor/md/recipe59.md new file mode 100644 index 000000000..b94b47ce7 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe59.md @@ -0,0 +1,54 @@ +# ``delete`` operator is not supported + +Rule ``arkts-no-delete`` + +**Severity: error** + +ArkTS assumes that object layout is known at compile time and cannot be +changed at runtime. Thus the operation of deleting a property makes no sense. + + +## TypeScript + + +``` + + class Point { + x?: number = 0.0 + y?: number = 0.0 + } + + let p = new Point() + delete p.y + +``` + +## ArkTS + + +``` + + // To mimic the original semantics, you may declare a nullable type + // and assign null to mark value absence: + + class Point { + x: number | null + y: number | null + } + + let p = new Point() + p.y = null + +``` + +## See also + +- Recipe 001: undefined +- Recipe 002: undefined +- Recipe 052: undefined +- Recipe 060: undefined +- Recipe 066: undefined +- Recipe 105: undefined +- Recipe 109: undefined + + diff --git a/linter/cookbook_convertor/md/recipe60.md b/linter/cookbook_convertor/md/recipe60.md new file mode 100644 index 000000000..643e5f750 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe60.md @@ -0,0 +1,50 @@ +# ``typeof`` operator is allowed only in expression contexts + +Rule ``arkts-no-type-query`` + +**Severity: error** + +ArkTS supports ``typeof`` operator only in the expression context. Specifying +type notations using ``typeof`` is not supported. + + +## TypeScript + + +``` + + let n1 = 42 + let s1 = "foo" + console.log(typeof n1) // "number" + console.log(typeof s1) // "string" + let n2: typeof n1 + let s2: typeof s1 + +``` + +## ArkTS + + +``` + + let n1 = 42 + let s1 = "foo" + console.log(typeof n1) // "number" + console.log(typeof s1) // "string" + let n2: number + let s2: string + +``` + +## See also + +- Recipe 001: undefined +- Recipe 002: undefined +- Recipe 052: undefined +- Recipe 059: undefined +- Recipe 066: undefined +- Recipe 105: undefined +- Recipe 109: undefined +- Recipe 144: undefined + + diff --git a/linter/cookbook_convertor/md/recipe61.md b/linter/cookbook_convertor/md/recipe61.md new file mode 100644 index 000000000..26dc8777d --- /dev/null +++ b/linter/cookbook_convertor/md/recipe61.md @@ -0,0 +1,71 @@ +# Binary operators ``*``, ``/``, ``%``, ``-``, ``<<``, ``>>``, ``>>>``, ``&``, ``^`` and ``|`` work only on numeric types + +Rule ``arkts-no-polymorphic-binops`` + +**Severity: error** + +ArkTS allows applying binary operators ``*``, ``/``, ``%``, ``-``, ``<<``, +``>>``, ``>>>``, ``&``, ``^`` and ``|`` only to values of numeric types. +Implicit casts from other types to numeric types are prohibited and cause +compile-time errors. + + +## TypeScript + + +``` + + let a = (5 & 5) // 5 + let b = (5.5 & 5.5) // 5, not 5.5 + let c = (5 | 5) // 5 + let d = (5.5 | 5.5) // 5, not 5.5 + + enum Direction { + Up = -1, + Down + } + let e = Direction.Up >> 1 // -1 + let f = Direction.Up >>> 1 // 2147483647 + + let g = ("10" as any) << 1 // 20 + let h = ("str" as any) << 1 // 0 + + let i = 10 * 5 + let j = 10 / 5 + let k = 10 % 5 + let l = 10 - 5 + +``` + +## ArkTS + + +``` + + let a = (5 & 5) // 5 + let b = (5.5 & 5.5) // Compile-time error + let c = (5 | 5) // 5 + let d = (5.5 | 5.5) // Compile-time error + + enum Direction { + Up, + Down + } + + let e = Direction.Up >> 1 // 0 + let f = Direction.Up >>> 1 // 0 + + let i = 10 * 5 + let j = 10 / 5 + let k = 10 % 5 + let l = 10 - 5 + +``` + +## See also + +- Recipe 055: undefined +- Recipe 056: undefined +- Recipe 063: undefined + + diff --git a/linter/cookbook_convertor/md/recipe63.md b/linter/cookbook_convertor/md/recipe63.md new file mode 100644 index 000000000..c8da81f95 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe63.md @@ -0,0 +1,55 @@ +# Binary ``+`` operator supports implicit casts only for numbers and strings + +Rule ``arkts-no-polymorphic-plus`` + +**Severity: error** + +ArkTS supports implicit casts for ``+`` only for strings and numbers. +Elsewhere, any form of an explicit cast to string is required. + + +## TypeScript + + +``` + + enum E { E1, E2 } + + let a = 10 + 32 // 42 + let b = E.E1 + 10 // 10 + let c = 10 + "5" // "105" + + let d = "5" + E.E2 // "51" + let e = "Hello, " + "world!" // "Hello, world!" + let f = "string" + true // "stringtrue" + + let g = (new Object()) + "string" // "[object Object]string" + +``` + +## ArkTS + + +``` + + enum E { E1, E2 } + + let a = 10 + 32 // 42 + let b = E.E1 + 10 // 10 + let c = 10 + "5" // "105" + + let d = "5" + E.E2 // "51" + let e = "Hello, " + "world!" // "Hello, world!" + let f = "string" + true // "stringtrue" + + let g = (new Object()).toString() + "string" + +``` + +## See also + +- Recipe 055: undefined +- Recipe 056: undefined +- Recipe 061: undefined + + diff --git a/linter/cookbook_convertor/md/recipe65.md b/linter/cookbook_convertor/md/recipe65.md new file mode 100644 index 000000000..b72b699c3 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe65.md @@ -0,0 +1,50 @@ +# ``instanceof`` operator is partially supported + +Rule ``arkts-instanceof-ref-types`` + +**Severity: error** + +In TypeScript, the left-hand side of an ``instanceof`` expression must be of type +``any``, an object type or a type parameter, otherwise the result is ``false``. +In ArkTS, the left-hand side expression may be of any reference type, otherwise +a compile-time error occurs. In addition, the left operand in ArkTS cannot be +a type. + + +## TypeScript + + +``` + + class X {} + + let a = (new X()) instanceof Object // true + let b = (new X()) instanceof X // true + // left operand is a type: + let c = X instanceof Object // true + let d = X instanceof X // false + + // left operand is not of type any + let e = (5.0 as Number) instanceof Number // false + +``` + +## ArkTS + + +``` + + class X {} + + let a = (new X()) instanceof Object // true + let b = (new X()) instanceof X // true + // left operand is a type: + let c = X instanceof Object // Compile-time error + let d = X instanceof X // Compile-time error + + // left operand may be of any reference type, like number + let e = (5.0 as Number) instanceof Number // true + +``` + + diff --git a/linter/cookbook_convertor/md/recipe66.md b/linter/cookbook_convertor/md/recipe66.md new file mode 100644 index 000000000..e4bd36c03 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe66.md @@ -0,0 +1,52 @@ +# ``in`` operator is not supported + +Rule ``arkts-no-in`` + +**Severity: error** + +ArkTS does not support the ``in`` operator. However, this operator makes +little sense since the object layout is known at compile time and cannot +be modified at runtime. Use ``instanceof`` as a work-around if you still need +to check whether certain class members exist. + + +## TypeScript + + +``` + + class Person { + name: string = "" + } + let p = new Person() + + let b = "name" in p // true + +``` + +## ArkTS + + +``` + + class Person { + name: string = "" + } + let p = new Person() + + let b = p instanceof Person // true, and "name" is guaranteed to be present + +``` + +## See also + +- Recipe 001: undefined +- Recipe 002: undefined +- Recipe 052: undefined +- Recipe 059: undefined +- Recipe 060: undefined +- Recipe 105: undefined +- Recipe 109: undefined +- Recipe 144: undefined + + diff --git a/linter/cookbook_convertor/md/recipe69.md b/linter/cookbook_convertor/md/recipe69.md new file mode 100644 index 000000000..50d253b2f --- /dev/null +++ b/linter/cookbook_convertor/md/recipe69.md @@ -0,0 +1,46 @@ +# Destructuring assignment is not supported + +Rule ``arkts-no-destruct-assignment`` + +**Severity: error** + +ArkTS does not support destructuring assignment. Other idioms (e.g., +using a temporary variable, where applicable) can be used for replacement. + + +## TypeScript + + +``` + + let [one, two] = [1, 2]; // semicolon is required here + [one, two] = [two, one] + + let head, tail + [head, ...tail] = [1, 2, 3, 4] + +``` + +## ArkTS + + +``` + + let arr: number[] = [1, 2] + let one = arr[0] + let two = arr[1] + + let tmp = one + one = two + two = tmp + + let data: Number[] = [1,2,3,4] + let head = data[0] + let tail = new Number[data.length - 1] + for (let i = 1; i < data.length; ++i) { + tail[i - 1] = data[i] + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe71.md b/linter/cookbook_convertor/md/recipe71.md new file mode 100644 index 000000000..dacc10297 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe71.md @@ -0,0 +1,41 @@ +# The comma operator ``,`` is supported only in ``for`` loops + +Rule ``arkts-no-comma-outside-loops`` + +**Severity: error** + +ArkTS supports the comma operator ``,`` only in ``for`` loops. Otherwise, +it is useless as it makes the execution order harder to understand. + + +## TypeScript + + +``` + + for (let i = 0, j = 0; i < 10; ++i, j += 2) { + console.log(i, j) + } + + let x = 0 + x = (++x, x++) // 1 + +``` + +## ArkTS + + +``` + + for (let i = 0, j = 0; i < 10; ++i, j += 2) { + console.log(i, j) + } + + // Use explicit execution order instead of the comma operator: + let x = 0 + ++x + x = x++ + +``` + + diff --git a/linter/cookbook_convertor/md/recipe74.md b/linter/cookbook_convertor/md/recipe74.md new file mode 100644 index 000000000..c52123397 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe74.md @@ -0,0 +1,52 @@ +# Destructuring variable declarations are not supported + +Rule ``arkts-no-destruct-decls`` + +**Severity: error** + +ArkTS does not support destructuring variable declarations. This is a dynamic +feature relying on structural compatibility. In addition, names in destructuring +declarations must be equal to properties within destructured classes. + + +## TypeScript + + +``` + + class Point { + x: number = 0.0 + y: number = 0.0 + } + + function returnZeroPoint(): Point { + return new Point() + } + + let {x, y} = returnZeroPoint() + +``` + +## ArkTS + + +``` + + class Point { + x: number = 0.0 + y: number = 0.0 + } + + function returnZeroPoint(): Point { + return new Point() + } + + // Create an intermediate object and work with it field by field + // without name restrictions: + let zp = returnZeroPoint() + let x = zp.x + let y = zp.y + +``` + + diff --git a/linter/cookbook_convertor/md/recipe76.md b/linter/cookbook_convertor/md/recipe76.md new file mode 100644 index 000000000..beec4a751 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe76.md @@ -0,0 +1,37 @@ +# Inference of implied types is not supported + +Rule ``arkts-no-implied-inference`` + +**Severity: error** + +Currently, ArkTS does not support inference of implied types. Use explicit +type notation instead. Use ``Object[]`` if you need containers that hold +data of mixed types. + + +## TypeScript + + +``` + + let [a, b, c] = [1, "hello", true] + +``` + +## ArkTS + + +``` + + let a = 1 + let b = "hello" + let c = true + + let arr: Object[] = [1, "hello", true] + let a1 = arr[0] + let b1 = arr[1] + let c1 = arr[2] + +``` + + diff --git a/linter/cookbook_convertor/md/recipe79.md b/linter/cookbook_convertor/md/recipe79.md new file mode 100644 index 000000000..fdbd4d493 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe79.md @@ -0,0 +1,40 @@ +# Type annotation in catch clause is not supported + +Rule ``arkts-no-types-in-catch`` + +**Severity: error** + +In TypeScript catch clause variable type annotation must be ``any`` or ``unknown`` +if specified. As ArkTS does not support these types, a type annotation should +be omitted. + + +## TypeScript + + +``` + + try { + // some code + } + catch (a: unknown) {} + +``` + +## ArkTS + + +``` + + try { + // some code + } + catch (a) {} + +``` + +## See also + +- Recipe 087: undefined + + diff --git a/linter/cookbook_convertor/md/recipe8.md b/linter/cookbook_convertor/md/recipe8.md new file mode 100644 index 000000000..6a10d291f --- /dev/null +++ b/linter/cookbook_convertor/md/recipe8.md @@ -0,0 +1,39 @@ +# Use explicit types instead of ``any``, ``undefined``, ``unknown`` + +Rule ``arkts-no-any-undefined-unknown`` + +**Severity: error** + +ArkTS does not support ``any``, ``undefined``, and ``unknown`` types. +Specify types explicitly. + + +## TypeScript + + +``` + + var x + console.log(x) // undefined + + var y: any + console.log(y) // undefined + +``` + +## ArkTS + + +``` + + // All variables should have their types specified explicitly: + let x: Object = {} + console.log(x) // {} + +``` + +## See also + +- Recipe 013: undefined + + diff --git a/linter/cookbook_convertor/md/recipe80.md b/linter/cookbook_convertor/md/recipe80.md new file mode 100644 index 000000000..9a14699b7 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe80.md @@ -0,0 +1,42 @@ +# ``for .. in`` is not supported + +Rule ``arkts-no-for-in`` + +**Severity: error** + +ArkTS does not support the iteration over object contents by the +``for .. in`` loop. For objects, iteration over properties at runtime is +considered redundant because object layout is known at compile time and cannot +change at runtime. For arrays, you can iterate with the regular ``for`` loop. + + +## TypeScript + + +``` + + let a: number[] = [1.0, 2.0, 3.0] + for (let i in a) { + console.log(a[i]) + } + +``` + +## ArkTS + + +``` + + let a: number[] = [1.0, 2.0, 3.0] + for (let i = 0; i < a.length; ++i) { + console.log(a[i]) + } + +``` + +## See also + +- Recipe 081: undefined +- Recipe 082: undefined + + diff --git a/linter/cookbook_convertor/md/recipe81.md b/linter/cookbook_convertor/md/recipe81.md new file mode 100644 index 000000000..ecb390e49 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe81.md @@ -0,0 +1,18 @@ +# Iterable interfaces are not supported + +Rule ``arkts-noiterable`` + +**Severity: error** + +ArkTS does not support the ``Symbol`` API, ``Symbol.iterator`` and +eventually iterable interfaces. Use arrays and library-level containers to +iterate over data. + + +## See also + +- Recipe 002: undefined +- Recipe 080: undefined +- Recipe 082: undefined + + diff --git a/linter/cookbook_convertor/md/recipe82.md b/linter/cookbook_convertor/md/recipe82.md new file mode 100644 index 000000000..1a4499012 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe82.md @@ -0,0 +1,41 @@ +# ``for-of`` is supported only for arrays and strings + +Rule ``arkts-for-of-str-arr`` + +**Severity: error** + +ArkTS supports the iteration over arrays and strings by the ``for .. of`` loop, +but does not support the iteration of objects content. + + +## TypeScript + + +``` + + let a: Set = new Set([1, 2, 3]) + for (let s of a) { + console.log(s) + } + +``` + +## ArkTS + + +``` + + let a: Set = new Set([1, 2, 3]) + let numbers = a.values() + for (let n of numbers) { + console.log(n) + } + +``` + +## See also + +- Recipe 080: undefined +- Recipe 081: undefined + + diff --git a/linter/cookbook_convertor/md/recipe83.md b/linter/cookbook_convertor/md/recipe83.md new file mode 100644 index 000000000..5f324a0fd --- /dev/null +++ b/linter/cookbook_convertor/md/recipe83.md @@ -0,0 +1,43 @@ +# Mapped type expression is not supported + +Rule ``arkts-no-mapped-types`` + +**Severity: error** + +ArkTS does not support mapped types. Use other language idioms and regular +classes to achieve the same behaviour. + + +## TypeScript + + +``` + + type OptionsFlags = { + [Property in keyof Type]: boolean + } + +``` + +## ArkTS + + +``` + + class C { + n: number = 0 + s: string = "" + } + + class CFlags { + n: boolean = false + s: boolean = false + } + +``` + +## See also + +- Recipe 097: undefined + + diff --git a/linter/cookbook_convertor/md/recipe84.md b/linter/cookbook_convertor/md/recipe84.md new file mode 100644 index 000000000..b0e6a2752 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe84.md @@ -0,0 +1,11 @@ +# ``with`` statement is not supported + +Rule ``arkts-no-with`` + +**Severity: error** + +ArkTS does not support the ``with`` statement. Use other language idioms +(including fully qualified names of functions) to achieve the same behaviour. + + + diff --git a/linter/cookbook_convertor/md/recipe85.md b/linter/cookbook_convertor/md/recipe85.md new file mode 100644 index 000000000..41db7a1e5 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe85.md @@ -0,0 +1,56 @@ +# Values computed at runtime are not supported in ``case`` statements + +Rule ``arkts-no-computed-case`` + +**Severity: error** + +ArkTS supports ``case`` statements that contain only compile-time values. +Use ``if`` statements as an alternative. + + +## TypeScript + + +``` + + let x = 2 + let y = 3 + switch (x) { + case 1: + console.log(1) + break + case 2: + console.log(2) + break + case y: + console.log(y) + break + default: + console.log("other") + } + +``` + +## ArkTS + + +``` + + let x = 2 + switch (x) { + case 1: + console.log(1) + break + case 2: + console.log(2) + break + case 3: + console.log(3) + break + default: + console.log("other") + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe86.md b/linter/cookbook_convertor/md/recipe86.md new file mode 100644 index 000000000..d57436d82 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe86.md @@ -0,0 +1,49 @@ +# ``switch`` statements cannot accept values of arbitrary types + +Rule ``arkts-limited-switch`` + +**Severity: error** + +ArkTS supports the values of the types ``char``, ``byte``, ``short``, ``int``, +``long``, ``Char``, ``Byte``, ``Short``, ``Int``, ``Long``, ``String`` or +``enum`` in ``switch`` statements. Use ``if`` statements in other cases. + + +## TypeScript + + +``` + + class Point { + x: number = 0 + y: number = 0 + } + + let a = new Point() + + switch (a) { + case null: break + default: console.log("not null") + } + +``` + +## ArkTS + + +``` + + class Point { + x: number = 0 + y: number = 0 + } + + let a = new Point() + + if (a != null) { + console.log("not null") + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe87.md b/linter/cookbook_convertor/md/recipe87.md new file mode 100644 index 000000000..a934a37c4 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe87.md @@ -0,0 +1,32 @@ +# ``throw`` statements cannot accept values of arbitrary types + +Rule ``arkts-limited-throw`` + +**Severity: error** + +ArkTS supports throwing only objects of the class ``Error`` or any +derived class. Throwing an arbitrary type (i.e., a ``number`` or ``string``) +is prohibited. + + +## TypeScript + + +``` + + throw 4 + throw "" + throw new Error() + +``` + +## ArkTS + + +``` + + throw new Error() + +``` + + diff --git a/linter/cookbook_convertor/md/recipe90.md b/linter/cookbook_convertor/md/recipe90.md new file mode 100644 index 000000000..5ee2428f2 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe90.md @@ -0,0 +1,67 @@ +# Function return type inference is limited + +Rule ``arkts-no-implicit-return-types`` + +**Severity: error** + +ArkTS supports type inference for function return types, but this functionality +is currently restricted. In particular, when the expression in the ``return`` +statement is a call to a function or method whose return value type is omitted, +a compile-time error occurs. In case of any such error, specify the return type +explicitly. + + +## TypeScript + + +``` + + function f(x: number) { + if (x <= 0) { + return x + } + return g(x) + } + + function g(x: number) { + return f(x - 1) + } + + function doOperation(x: number, y: number) { + return x + y + } + + console.log(f(10)) + console.log(doOperation(2, 3)) + +``` + +## ArkTS + + +``` + + // Explicit return type is required: + function f(x: number) : number { + if (x <= 0) { + return x + } + return g(x) + } + + // Explicit return type is required: + function g(x: number) : number { + return f(x - 1) + } + + // In this case, return type will be inferred + function doOperation(x: number, y: number) { + return x + y + } + + console.log(f(10)) + console.log(doOperation(2, 3)) + +``` + + diff --git a/linter/cookbook_convertor/md/recipe91.md b/linter/cookbook_convertor/md/recipe91.md new file mode 100644 index 000000000..84c862983 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe91.md @@ -0,0 +1,47 @@ +# Destructuring parameter declarations are not supported + +Rule ``arkts-no-destruct-params`` + +**Severity: error** + +ArkTS requires that parameters must be passed directly to the function, and +local names must be assigned manually. + + +## TypeScript + + +``` + + function drawText({ text = "", location: [x, y] = [0, 0], bold = false }) { + console.log(text) + console.log(x) + console.log(y) + console.log(bold) + } + + drawText({ text: "Hello, world!", location: [100, 50], bold: true }) + +``` + +## ArkTS + + +``` + + function drawText(text: String, location: number[], bold: boolean) { + let x = location[0] + let y = location[1] + console.log(text) + console.log(x) + console.log(y) + console.log(bold) + } + + function main() { + drawText("Hello, world!", [100, 50], true) + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe92.md b/linter/cookbook_convertor/md/recipe92.md new file mode 100644 index 000000000..584a28f9f --- /dev/null +++ b/linter/cookbook_convertor/md/recipe92.md @@ -0,0 +1,48 @@ +# Nested functions are not supported + +Rule ``arkts-no-nested-funcs`` + +**Severity: error** + +ArkTS does not support nested functions. Use lambdas instead. + + +## TypeScript + + +``` + + function addNum(a: number, b: number): void { + + // nested function: + function logToConsole(message: String): void { + console.log(message) + } + + let result = a + b + + // Invoking the nested function: + logToConsole("result is " + result) + } + +``` + +## ArkTS + + +``` + + function addNum(a: number, b: number): void { + // Use lambda instead of a nested function: + let logToConsole: (message: string) => void = (message: string): void => { + console.log(message) + } + + let result = a + b + + logToConsole("result is " + result) + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe93.md b/linter/cookbook_convertor/md/recipe93.md new file mode 100644 index 000000000..830cecd69 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe93.md @@ -0,0 +1,58 @@ +# Using ``this`` inside stand-alone functions is not supported + +Rule ``arkts-no-standalone-this`` + +**Severity: error** + +ArkTS does not support the usage of ``this`` inside stand-alone functions. +``this`` can be used in methods only. + + +## TypeScript + + +``` + + function foo(i: number) { + this.count = i + } + + class A { + count: number = 1 + m = foo + } + + let a = new A() + console.log(a.count) // prints "1" + a.m(2) + console.log(a.count) // prints "2" + + +``` + +## ArkTS + + +``` + + class A { + count: number = 1 + m(i: number): void { + this.count = i + } + } + + function main(): void { + let a = new A() + console.log(a.count) // prints "1" + a.m(2) + console.log(a.count) // prints "2" + } + +``` + +## See also + +- Recipe 140: undefined + + diff --git a/linter/cookbook_convertor/md/recipe94.md b/linter/cookbook_convertor/md/recipe94.md new file mode 100644 index 000000000..8f350dc7f --- /dev/null +++ b/linter/cookbook_convertor/md/recipe94.md @@ -0,0 +1,48 @@ +# Generator functions are not supported + +Rule ``arkts-no-generators`` + +**Severity: error** + +Currently, ArkTS does not support generator functions. +Use the ``async`` / ``await`` mechanism for multitasking. + + +## TypeScript + + +``` + + function* counter(start: number, end: number) { + for (let i = start; i <= end; i++) { + yield i + } + } + + for (let num of counter(1, 5)) { + console.log(num) + } + +``` + +## ArkTS + + +``` + + async function complexNumberProcessing(n : number) : Promise { + // Some complex logic for proccessing the number here + return n + } + + async function foo() { + for (let i = 1; i <= 5; i++) { + console.log(await complexNumberProcessing(i)) + } + } + + foo() + +``` + + diff --git a/linter/cookbook_convertor/md/recipe96.md b/linter/cookbook_convertor/md/recipe96.md new file mode 100644 index 000000000..4f8885762 --- /dev/null +++ b/linter/cookbook_convertor/md/recipe96.md @@ -0,0 +1,84 @@ +# Type guarding is supported with ``instanceof`` and ``as`` + +Rule ``arkts-no-is`` + +**Severity: error** + +ArkTS does not support the ``is`` operator, which must be replaced by the +``instanceof`` operator. Note that the fields of an object must be cast to the +appropriate type with the ``as`` operator before use. + + +## TypeScript + + +``` + + class Foo { + foo: number = 0 + common: string = "" + } + + class Bar { + bar: number = 0 + common: string = "" + } + + function isFoo(arg: any): arg is Foo { + return arg.foo !== undefined + } + + function doStuff(arg: Foo | Bar) { + if (isFoo(arg)) { + console.log(arg.foo) // OK + console.log(arg.bar) // Compile-time error + } else { + console.log(arg.foo) // Compile-time error + console.log(arg.bar) // OK + } + } + + doStuff({ foo: 123, common: '123' }) + doStuff({ bar: 123, common: '123' }) + +``` + +## ArkTS + + +``` + + class Foo { + foo: number = 0 + common: string = "" + } + + class Bar { + bar: number = 0 + common: string = "" + } + + function isFoo(arg: Object): boolean { + return arg instanceof Foo + } + + function doStuff(arg: Object): void { + if (isFoo(arg)) { + let fooArg = arg as Foo + console.log(fooArg.foo) // OK + console.log(arg.bar) // Compile-time error + } else { + let barArg = arg as Bar + console.log(arg.foo) // Compile-time error + console.log(barArg.bar) // OK + } + } + + function main(): void { + doStuff(new Foo()) + doStuff(new Bar()) + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe97.md b/linter/cookbook_convertor/md/recipe97.md new file mode 100644 index 000000000..ec1b161dc --- /dev/null +++ b/linter/cookbook_convertor/md/recipe97.md @@ -0,0 +1,63 @@ +# ``keyof`` operator is not supported + +Rule ``arkts-no-keyof`` + +**Severity: error** + +ArkTS has no `keyof` operator because the object layout is defined +at compile time and cannot be changed at runtime. Object fields can only be +accessed directly. + + +## TypeScript + + +``` + + class Point { + x: number = 1 + y: number = 2 + } + + type PointKeys = keyof Point // The type of PointKeys is "x" | "y" + + function getPropertyValue(obj: Point, key: PointKeys) { + return obj[key] + } + + let obj = new Point() + console.log(getPropertyValue(obj, "x")) // prints "1" + console.log(getPropertyValue(obj, "y")) // prints "2" + +``` + +## ArkTS + + +``` + + class Point { + x: number = 1 + y: number = 2 + } + + function getPropertyValue(obj: Point, key: string): number { + if (key == "x") { + return obj.x + } + if (key == "y") { + return obj.y + } + throw new Error() // No such property + return 0 + } + + function main(): void { + let obj = new Point() + console.log(getPropertyValue(obj, "x")) // prints "1" + console.log(getPropertyValue(obj, "y")) // prints "2" + } + +``` + + diff --git a/linter/cookbook_convertor/md/recipe99.md b/linter/cookbook_convertor/md/recipe99.md new file mode 100644 index 000000000..094f6841e --- /dev/null +++ b/linter/cookbook_convertor/md/recipe99.md @@ -0,0 +1,73 @@ +# It is possible to spread only arrays into the rest parameter + +Rule ``arkts-no-spread`` + +**Severity: error** + +The only supported scenario for the spread operator is to spread an array into +the rest parameter. Otherwise manually "unpack" data from arrays and objects, +where necessary. + + +## TypeScript + + +``` + + function foo(x : number, y : number, z : number) { + console.log(x, y, z) + } + + let args : [number, number, number] = [0, 1, 2] + foo(...args) + + let list1 = [1, 2] + let list2 = [...list1, 3, 4] + + let point2d = {x: 1, y: 2} + let point3d = {...point2d, z: 3} + +``` + +## ArkTS + + +``` + + function sum_numbers(...numbers: number[]): number { + let res = 0 + for (let n of numbers) + res += n + return res + } + + function log_numbers(x : number, y : number, z : number) { + console.log(x, y, z) + } + + let numbers : number[] = [0, 1, 2] + sum_numbers(...numbers) + log_numbers(numbers[0], numbers[1], numbers[2]) + + let list1 : number[] = [1, 2] + let list2 : number[] = [list1[0], list1[1], 3, 4] + + class Point2D { + x: number = 0; y: number = 0 + } + + class Point3D { + x: number = 0; y: number = 0; z: number = 0 + constructor(p2d: Point2D, z: number) { + this.x = p2d.x + this.y = p2d.y + this.z = z + } + } + + let p3d = new Point3D({x: 1, y: 2} as Point2D, 3) + console.log(p3d.x, p3d.y, p3d.z) + +``` + + diff --git a/linter/cookbook_convertor/src/cookbook_convertor.ts b/linter/cookbook_convertor/src/cookbook_convertor.ts index a8bce63b9..b5ff197a6 100644 --- a/linter/cookbook_convertor/src/cookbook_convertor.ts +++ b/linter/cookbook_convertor/src/cookbook_convertor.ts @@ -36,7 +36,7 @@ const COPYRIGHT_HEADER = "/* \n\ const CODE_PROLOGUE = "export const cookBookMsg: string[] = [];\n\ export const cookBookTag: string[] = [];\n\ \n\ -for( let i = 0; i < 143; i++) {\n\ +for( let i = 0; i < 144; i++) {\n\ cookBookMsg[ i ] = '';\n\ }\n\ "; @@ -252,14 +252,14 @@ console.error(">>>TEG>>>: " + _line + " -> " + doc_lines[_line]); return; let line = doc_lines[ _line ].split( CB_R )[1]; - mdText.push("# " + line.split(':')[1] ); + mdText.push("# " + line); //.split(':')[1] ); mdText.push(""); line = escapeSym( translateLine(line) ); let teg = translateTeg( line ); let hdr = highlightCode(line); console.log(hdr + T_BR + CL); - tegs[ recNum ] = teg.split(':')[1]; + tegs[ recNum ] = teg; //.split(':')[1]; _line++; } diff --git a/linter/src/CookBookMsg.ts b/linter/src/CookBookMsg.ts index d90a2a644..54304c1e4 100644 --- a/linter/src/CookBookMsg.ts +++ b/linter/src/CookBookMsg.ts @@ -16,11 +16,11 @@ export const cookBookMsg: string[] = []; export const cookBookTag: string[] = []; -for( let i = 0; i < 143; i++) { +for( let i = 0; i < 144; i++) { cookBookMsg[ i ] = ''; } -cookBookTag[ 1 ] = 'Objects with property names that are not identifiers are not supported (arkts-no-computed-props)'; +cookBookTag[ 1 ] = 'Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)'; cookBookTag[ 2 ] = '"Symbol()" API is not supported (arkts-no-symbol)'; cookBookTag[ 3 ] = 'Private \'#\' identifiers are not supported (arkts-no-private-identifiers)'; cookBookTag[ 4 ] = 'Use unique names for types, namespaces, etc. (arkts-unique-names)'; @@ -53,16 +53,16 @@ cookBookTag[ 30 ] = 'Structural identity is not supported (arkts-no-structural-i cookBookTag[ 31 ] = 'Structural typing is not supported for subtyping / supertyping (arkts-no-structural-subtyping)'; cookBookTag[ 32 ] = 'Structural typing is not supported for assignability checks (arkts-no-structural-assignability)'; cookBookTag[ 33 ] = 'Optional properties are not supported for primitive types (arkts-no-opt-props)'; -cookBookTag[ 34 ] = 'Generic functions must be called with explicit type specialization (arkts-no-inferred-generic-params)'; +cookBookTag[ 34 ] = 'Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)'; cookBookTag[ 35 ] = 'Structural typing is not supported for type inference (arkts-no-structural-inference)'; cookBookTag[ 36 ] = ''; cookBookTag[ 37 ] = 'RegExp literals are not supported (arkts-no-regexp-literals)'; -cookBookTag[ 38 ] = 'Object literal must correspond to explicitly declared class or interface (arkts-no-untyped-obj-literals)'; +cookBookTag[ 38 ] = 'Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)'; cookBookTag[ 39 ] = ''; cookBookTag[ 40 ] = 'Object literals cannot be used as type declarations (arkts-no-obj-literals-as-types)'; cookBookTag[ 41 ] = ''; cookBookTag[ 42 ] = ''; -cookBookTag[ 43 ] = 'Untyped array literals are not supported (arkts-no-noninferrable-arr-literals)'; +cookBookTag[ 43 ] = 'Array literals must contain elements of only inferrable types (arkts-no-noninferrable-arr-literals)'; cookBookTag[ 44 ] = ''; cookBookTag[ 45 ] = 'Lambdas require explicit type annotation for parameters (arkts-explicit-param-types-in-lambdas)'; cookBookTag[ 46 ] = 'Use arrow functions instead of function expressions (arkts-no-func-expressions)'; @@ -79,7 +79,7 @@ cookBookTag[ 56 ] = 'Unary "+" cannot be used for casting to "number" (arkts-no- cookBookTag[ 57 ] = ''; cookBookTag[ 58 ] = ''; cookBookTag[ 59 ] = '"delete" operator is not supported (arkts-no-delete)'; -cookBookTag[ 60 ] = '"typeof" is allowed only in expression contexts (arkts-no-type-query)'; +cookBookTag[ 60 ] = '"typeof" operator is allowed only in expression contexts (arkts-no-type-query)'; cookBookTag[ 61 ] = 'Binary operators "*", "/", "%", "-", "<<", ">>", ">>>", "&", "^" and "|" work only on numeric types (arkts-no-polymorphic-binops)'; cookBookTag[ 62 ] = ''; cookBookTag[ 63 ] = 'Binary "+" operator supports implicit casts only for numbers and strings (arkts-no-polymorphic-plus)'; @@ -116,7 +116,7 @@ cookBookTag[ 93 ] = 'Using "this" inside stand-alone functions is not supported cookBookTag[ 94 ] = 'Generator functions are not supported (arkts-no-generators)'; cookBookTag[ 95 ] = ''; cookBookTag[ 96 ] = 'Type guarding is supported with "instanceof" and "as" (arkts-no-is)'; -cookBookTag[ 97 ] = '`keyof` operator is not supported (arkts-no-keyof)'; +cookBookTag[ 97 ] = '"keyof" operator is not supported (arkts-no-keyof)'; cookBookTag[ 98 ] = ''; cookBookTag[ 99 ] = 'It is possible to spread only arrays into the rest parameter (arkts-no-spread)'; cookBookTag[ 100 ] = ''; @@ -130,7 +130,7 @@ cookBookTag[ 107 ] = ''; cookBookTag[ 108 ] = ''; cookBookTag[ 109 ] = 'Dynamic property declaration is not supported (arkts-no-dyn-prop-decl)'; cookBookTag[ 110 ] = ''; -cookBookTag[ 111 ] = 'Explicit values for enumeration constants are not supported (arkts-no-explicit-enum-init)'; +cookBookTag[ 111 ] = 'Enumeration members can be initialized only with compile time expressions of the same type (arkts-no-enum-mixed-types)'; cookBookTag[ 112 ] = ''; cookBookTag[ 113 ] = '"enum" declaration merging is not supported (arkts-no-enum-merging)'; cookBookTag[ 114 ] = 'Namespaces cannot be used as objects (arkts-no-ns-as-obj)'; @@ -163,3 +163,4 @@ cookBookTag[ 140 ] = '"Function.apply", "Function.bind", "Function.call" are not cookBookTag[ 141 ] = '"readonly T[]" syntax is not supported (arkts-no-readonly-params)'; cookBookTag[ 142 ] = '"as const" assertions are not supported (arkts-no-as-const)'; cookBookTag[ 143 ] = 'Import assertions are not supported (arkts-no-import-assertions)'; +cookBookTag[ 144 ] = 'Usage of standard library is restricted (arkts-limited-stdlib)'; -- Gitee From e7a8881bd5b3ca788590ec897edc36536425e3cf Mon Sep 17 00:00:00 2001 From: Urakov Alexandr Date: Wed, 12 Jul 2023 10:20:00 +0800 Subject: [PATCH 4/5] [ArkTS][Linter] Fix codecheck warnings Change-Id: I617ae1e8333b20723072b2d0acac271757b4bece Signed-off-by: Urakov Alexandr --- linter/src/Autofixer.ts | 2 +- linter/src/TestRunner.ts | 4 +-- linter/src/TypeScriptLinter.ts | 66 +++++++++++++++++----------------- linter/src/Utils.ts | 48 ++++++++++++++----------- 4 files changed, 63 insertions(+), 57 deletions(-) diff --git a/linter/src/Autofixer.ts b/linter/src/Autofixer.ts index fe564020e..4ae69abec 100644 --- a/linter/src/Autofixer.ts +++ b/linter/src/Autofixer.ts @@ -138,7 +138,7 @@ export function fixFunctionExpression(funcExpr: ts.FunctionExpression, } export function fixReturnType(funcLikeDecl: ts.FunctionLikeDeclaration, typeNode: ts.TypeNode): Autofix { - let text = ": " + printer.printNode(ts.EmitHint.Unspecified, typeNode, funcLikeDecl.getSourceFile()); + let text = ': ' + printer.printNode(ts.EmitHint.Unspecified, typeNode, funcLikeDecl.getSourceFile()); let pos = getReturnTypePosition(funcLikeDecl); return { start: pos, end: pos, replacementText: text }; } diff --git a/linter/src/TestRunner.ts b/linter/src/TestRunner.ts index 25a346978..a11921a59 100644 --- a/linter/src/TestRunner.ts +++ b/linter/src/TestRunner.ts @@ -47,8 +47,8 @@ const RESULT_EXT: string[] = []; RESULT_EXT[Mode.STRICT] = '.strict.json'; RESULT_EXT[Mode.RELAX] = '.relax.json'; RESULT_EXT[Mode.AUTOFIX] = '.autofix.json'; -const AUTOFIX_CONFIG_EXT = ".autofix.cfg.json"; -const AUTOFIX_SKIP_EXT = ".autofix.skip"; +const AUTOFIX_CONFIG_EXT = '.autofix.cfg.json'; +const AUTOFIX_SKIP_EXT = '.autofix.skip'; function runTests(baseDir: string): number { let hasComparisonFailures = false; diff --git a/linter/src/TypeScriptLinter.ts b/linter/src/TypeScriptLinter.ts index 86b492b04..1b0060036 100644 --- a/linter/src/TypeScriptLinter.ts +++ b/linter/src/TypeScriptLinter.ts @@ -495,10 +495,10 @@ export class TypeScriptLinter { let objectLiteralType = TypeScriptLinter.tsTypeChecker.getContextualType(objectLiteralExpr); if ( - !Utils.validateObjectLiteralType(objectLiteralType) || Utils.hasMemberFunction(objectLiteralExpr) || - !Utils.validateFields(objectLiteralType, objectLiteralExpr) - ) - this.incrementCounters(node, FaultID.ObjectLiteralNoContextType); + !Utils.validateObjectLiteralType(objectLiteralType) || Utils.hasMemberFunction(objectLiteralExpr) || + !Utils.validateFields(objectLiteralType, objectLiteralExpr) + ) + this.incrementCounters(node, FaultID.ObjectLiteralNoContextType); } private handleArrayLiteralExpression(node: ts.Node) { @@ -675,7 +675,7 @@ export class TypeScriptLinter { let prop = (node as ts.PropertyAssignment | ts.PropertyDeclaration).name; if (prop && (prop.kind === ts.SyntaxKind.NumericLiteral || prop.kind === ts.SyntaxKind.StringLiteral)) { - let autofix : Autofix[] | undefined = undefined; + let autofix : Autofix[] | undefined; let autofixable = true; if (Autofixer.shouldAutofix(node, FaultID.LiteralAsPropertyName)) { autofix = Autofixer.fixLiteralAsPropertyName(node); @@ -699,7 +699,7 @@ export class TypeScriptLinter { let autofixable = !isGeneric && !isGenerator && !containsThis && newParams && !hasUnfixableReturnType; - let autofix: Autofix[] | undefined = undefined; + let autofix: Autofix[] | undefined; if (autofixable && Autofixer.shouldAutofix(node, FaultID.FunctionExpression)) { autofix = [ Autofixer.fixFunctionExpression(funcExpr, newParams, newRetTypeNode) ]; } @@ -725,7 +725,7 @@ export class TypeScriptLinter { ts.NodeArray | undefined { let hasOmittedType = false; let autofixable = true; - let autofix: Autofix[] | undefined = undefined; + let autofix: Autofix[] | undefined; let isFuncExpr = signDecl.kind === ts.SyntaxKind.FunctionExpression; let newParams: ts.ParameterDeclaration[] = []; for (const param of signDecl.parameters) { @@ -787,8 +787,8 @@ export class TypeScriptLinter { if (!funcLikeDecl.body) return [false, undefined]; let autofixable = false; - let autofix : Autofix[] | undefined = undefined; - let newRetTypeNode: ts.TypeNode | undefined = undefined; + let autofix : Autofix[] | undefined; + let newRetTypeNode: ts.TypeNode | undefined; let isFuncExpr = ts.isFunctionExpression(funcLikeDecl); // Currently, ArkTS can't infer return type of function, when expression @@ -821,29 +821,29 @@ export class TypeScriptLinter { private hasLimitedTypeInferenceFromReturnExpr(funBody: ts.ConciseBody): boolean { let hasLimitedTypeInference = false; - if (ts.isBlock(funBody)) { - function visitNode(tsNode: ts.Node): void { - if (hasLimitedTypeInference) return; - - if ( - ts.isReturnStatement(tsNode) && tsNode.expression && - Utils.isCallToFunctionWithOmittedReturnType(Utils.unwrapParenthesized(tsNode.expression)) - ) { - hasLimitedTypeInference = true; - return; - } - - // Visit children nodes. Don't traverse other nested function-like declarations. - if ( - !ts.isFunctionDeclaration(tsNode) && - !ts.isFunctionExpression(tsNode) && - !ts.isMethodDeclaration(tsNode) && - !ts.isAccessor(tsNode) && - !ts.isArrowFunction(tsNode) - ) - tsNode.forEachChild(visitNode); + function visitNode(tsNode: ts.Node): void { + if (hasLimitedTypeInference) return; + + if ( + ts.isReturnStatement(tsNode) && tsNode.expression && + Utils.isCallToFunctionWithOmittedReturnType(Utils.unwrapParenthesized(tsNode.expression)) + ) { + hasLimitedTypeInference = true; + return; } - + + // Visit children nodes. Don't traverse other nested function-like declarations. + if ( + !ts.isFunctionDeclaration(tsNode) && + !ts.isFunctionExpression(tsNode) && + !ts.isMethodDeclaration(tsNode) && + !ts.isAccessor(tsNode) && + !ts.isArrowFunction(tsNode) + ) + tsNode.forEachChild(visitNode); + } + + if (ts.isBlock(funBody)) { visitNode(funBody); } else { const tsExpr = Utils.unwrapParenthesized(funBody); @@ -1249,7 +1249,7 @@ export class TypeScriptLinter { return; if( constVal !==undefined && typeof constVal === 'number' && firstElewmVal !==undefined && typeof firstElewmVal === 'number' ) - return; + return; if(firstEnumMemberType !== tsEnumMemberType) { this.incrementCounters(node, FaultID.EnumMemberNonConstInit); } @@ -1447,7 +1447,7 @@ export class TypeScriptLinter { } private handleBigIntLiteral(node: ts.Node) { - let autofixes: Autofix[] | undefined = undefined; + let autofixes: Autofix[] | undefined; if (Autofixer.shouldAutofix(node, FaultID.BigIntLiteral)) { // If decimal value of literal exceeds 15 digits, create diff --git a/linter/src/Utils.ts b/linter/src/Utils.ts index d6915107b..3ebe7e296 100644 --- a/linter/src/Utils.ts +++ b/linter/src/Utils.ts @@ -299,8 +299,8 @@ export function isValidEnumMemberInit(tsExpr: ts.Expression): boolean { export function isCompileTimeExpression(tsExpr: ts.Expression): boolean { if ( - ts.isParenthesizedExpression(tsExpr) || - (ts.isAsExpression(tsExpr) && tsExpr.type.kind === ts.SyntaxKind.NumberKeyword)) + ts.isParenthesizedExpression(tsExpr) || + (ts.isAsExpression(tsExpr) && tsExpr.type.kind === ts.SyntaxKind.NumberKeyword)) return isCompileTimeExpression(tsExpr.expression); switch (tsExpr.kind) { @@ -315,7 +315,7 @@ export function isCompileTimeExpression(tsExpr: ts.Expression): boolean { return isIdentifierValidEnumMemberInit(tsExpr as ts.Identifier); case ts.SyntaxKind.NumericLiteral: return isIntegerConstantValue(tsExpr as ts.NumericLiteral); - case ts.SyntaxKind.PropertyAccessExpression: + case ts.SyntaxKind.PropertyAccessExpression: { // if enum member is in current enum declaration try to get value // if it comes from another enum consider as constant const propertyAccess = tsExpr as ts.PropertyAccessExpression; @@ -328,6 +328,7 @@ export function isCompileTimeExpression(tsExpr: ts.Expression): boolean { if (!decls || decls.length !== 1) return false; return ts.isEnumDeclaration(decls[0]); + } default: return false; } @@ -355,7 +356,7 @@ function isIdentifierValidEnumMemberInit(tsExpr: ts.Identifier): boolean { ( (isVarDeclaration(tsDecl) && isConst(tsDecl.parent)) || (tsDecl.kind === ts.SyntaxKind.EnumMember) ) - ); + ); } function isUnaryOpAllowedForEnumMemberInit(tsPrefixUnaryOp: ts.PrefixUnaryOperator): boolean { @@ -483,12 +484,12 @@ function hasReadonlyFields(type: ts.Type): boolean { if ( value.declarations !== undefined && value.declarations.length > 0 && ts.isPropertyDeclaration(value.declarations[0]) - ) { - let propmMods = ts.getModifiers(value.declarations[0] as ts.PropertyDeclaration); - if (hasModifier(propmMods, ts.SyntaxKind.ReadonlyKeyword)) { - result = true; - return; - } + ) { + let propmMods = ts.getModifiers(value.declarations[0] as ts.PropertyDeclaration); + if (hasModifier(propmMods, ts.SyntaxKind.ReadonlyKeyword)) { + result = true; + return; + } } }); @@ -533,7 +534,7 @@ export function validateObjectLiteralType(type: ts.Type | undefined): boolean { return ( type != undefined && type.isClassOrInterface() && hasDefaultCtor(type) && !hasReadonlyFields(type) && !isAbstractClass(type) - ); + ); } export function hasMemberFunction(objectLiteral: ts.ObjectLiteralExpression): boolean { @@ -551,9 +552,9 @@ export function hasMemberFunction(objectLiteral: ts.ObjectLiteralExpression): bo } function findDelaration(type: ts.ClassDeclaration | ts.InterfaceDeclaration, name: string) -: ts.NamedDeclaration | undefined { + : ts.NamedDeclaration | undefined { let members: ts.NodeArray | ts.NodeArray = type.members; - let declFound: ts.NamedDeclaration | undefined = undefined; + let declFound: ts.NamedDeclaration | undefined; for(let m of members) { if (m.name && m.name.getText() === name) { @@ -573,11 +574,11 @@ function findDelaration(type: ts.ClassDeclaration | ts.InterfaceDeclaration, nam if ( (symbol.flags === ts.SymbolFlags.Class || symbol.flags === ts.SymbolFlags.Interface) && symbol.declarations && symbol.declarations.length > 0 - ) { - declFound = findDelaration(symbol.declarations[0] as (ts.ClassDeclaration | ts.InterfaceDeclaration), name); - - if (declFound) break; + ) { + declFound = findDelaration(symbol.declarations[0] as (ts.ClassDeclaration | ts.InterfaceDeclaration), name); } + + if (declFound) break; }; if (declFound) break; @@ -625,6 +626,14 @@ export function validateFields(type: ts.Type | undefined, objectLiteral: ts.Obje return true; } +function isSupportedTypeNodeKind(kind: ts.SyntaxKind): boolean { + return kind !== ts.SyntaxKind.AnyKeyword && kind !== ts.SyntaxKind.UnknownKeyword && + kind !== ts.SyntaxKind.SymbolKeyword && kind !== ts.SyntaxKind.UndefinedKeyword && + kind !== ts.SyntaxKind.ConditionalType && kind !== ts.SyntaxKind.MappedType && + kind !== ts.SyntaxKind.InferType && kind !== ts.SyntaxKind.IndexedAccessType; + +} + export function isSupportedType(typeNode: ts.TypeNode): boolean { if (ts.isParenthesizedTypeNode(typeNode)) return isSupportedType(typeNode.type); @@ -644,10 +653,7 @@ export function isSupportedType(typeNode: ts.TypeNode): boolean { return !ts.isTypeLiteralNode(typeNode) && !ts.isTypeQueryNode(typeNode) && !ts.isIntersectionTypeNode(typeNode) && !ts.isTupleTypeNode(typeNode) && - typeNode.kind !== ts.SyntaxKind.AnyKeyword && typeNode.kind !== ts.SyntaxKind.UnknownKeyword && - typeNode.kind !== ts.SyntaxKind.SymbolKeyword && typeNode.kind !== ts.SyntaxKind.UndefinedKeyword && - typeNode.kind !== ts.SyntaxKind.ConditionalType && typeNode.kind !== ts.SyntaxKind.MappedType && - typeNode.kind !== ts.SyntaxKind.InferType && typeNode.kind !== ts.SyntaxKind.IndexedAccessType; + isSupportedTypeNodeKind(typeNode.kind); } export const LIMITED_STD_GLOBAL_FUNC = [ -- Gitee From 11ef1472c47a326c985fe38cdd98fecc42a6ef63 Mon Sep 17 00:00:00 2001 From: Igor Rossinski Date: Wed, 12 Jul 2023 13:10:02 +0300 Subject: [PATCH 5/5] [TS Lnter] update .md files Signed-off-by: Igor Rossinski --- linter/cookbook_convertor/md/recipe1.md | 16 ++++++++-------- linter/cookbook_convertor/md/recipe105.md | 16 ++++++++-------- linter/cookbook_convertor/md/recipe109.md | 16 ++++++++-------- linter/cookbook_convertor/md/recipe115.md | 16 ++++++++-------- linter/cookbook_convertor/md/recipe118.md | 6 +++--- linter/cookbook_convertor/md/recipe123.md | 6 +++--- linter/cookbook_convertor/md/recipe124.md | 6 +++--- linter/cookbook_convertor/md/recipe125.md | 6 +++--- linter/cookbook_convertor/md/recipe126.md | 6 +++--- linter/cookbook_convertor/md/recipe128.md | 4 ++-- linter/cookbook_convertor/md/recipe129.md | 6 +++--- linter/cookbook_convertor/md/recipe130.md | 2 +- linter/cookbook_convertor/md/recipe131.md | 4 ++-- linter/cookbook_convertor/md/recipe132.md | 2 +- linter/cookbook_convertor/md/recipe133.md | 6 +++--- linter/cookbook_convertor/md/recipe136.md | 2 +- linter/cookbook_convertor/md/recipe137.md | 4 ++-- linter/cookbook_convertor/md/recipe139.md | 2 +- linter/cookbook_convertor/md/recipe14.md | 2 +- linter/cookbook_convertor/md/recipe140.md | 2 +- linter/cookbook_convertor/md/recipe143.md | 6 +++--- linter/cookbook_convertor/md/recipe144.md | 16 ++++++++-------- linter/cookbook_convertor/md/recipe15.md | 2 +- linter/cookbook_convertor/md/recipe2.md | 16 ++++++++-------- linter/cookbook_convertor/md/recipe27.md | 2 +- linter/cookbook_convertor/md/recipe30.md | 6 +++--- linter/cookbook_convertor/md/recipe31.md | 6 +++--- linter/cookbook_convertor/md/recipe32.md | 6 +++--- linter/cookbook_convertor/md/recipe35.md | 6 +++--- linter/cookbook_convertor/md/recipe38.md | 4 ++-- linter/cookbook_convertor/md/recipe40.md | 4 ++-- linter/cookbook_convertor/md/recipe43.md | 4 ++-- linter/cookbook_convertor/md/recipe52.md | 16 ++++++++-------- linter/cookbook_convertor/md/recipe55.md | 4 ++-- linter/cookbook_convertor/md/recipe56.md | 6 +++--- linter/cookbook_convertor/md/recipe59.md | 14 +++++++------- linter/cookbook_convertor/md/recipe60.md | 16 ++++++++-------- linter/cookbook_convertor/md/recipe61.md | 6 +++--- linter/cookbook_convertor/md/recipe63.md | 6 +++--- linter/cookbook_convertor/md/recipe66.md | 16 ++++++++-------- linter/cookbook_convertor/md/recipe79.md | 2 +- linter/cookbook_convertor/md/recipe8.md | 2 +- linter/cookbook_convertor/md/recipe80.md | 4 ++-- linter/cookbook_convertor/md/recipe81.md | 6 +++--- linter/cookbook_convertor/md/recipe82.md | 4 ++-- linter/cookbook_convertor/md/recipe83.md | 2 +- linter/cookbook_convertor/md/recipe93.md | 2 +- .../src/cookbook_convertor.ts | 17 ++++++++++++----- 48 files changed, 169 insertions(+), 162 deletions(-) diff --git a/linter/cookbook_convertor/md/recipe1.md b/linter/cookbook_convertor/md/recipe1.md index 1f6236663..317d04c6b 100644 --- a/linter/cookbook_convertor/md/recipe1.md +++ b/linter/cookbook_convertor/md/recipe1.md @@ -47,13 +47,13 @@ data by numeric indices. ## See also -- Recipe 002: undefined -- Recipe 052: undefined -- Recipe 059: undefined -- Recipe 060: undefined -- Recipe 066: undefined -- Recipe 105: undefined -- Recipe 109: undefined -- Recipe 144: undefined +- Recipe 002: ``Symbol()`` API is not supported (``arkts-no-symbol``) +- Recipe 052: Attempt to access an undefined property is a compile-time error (``arkts-no-undefined-prop-access``) +- Recipe 059: ``delete`` operator is not supported (``arkts-no-delete``) +- Recipe 060: ``typeof`` operator is allowed only in expression contexts (``arkts-no-type-query``) +- Recipe 066: ``in`` operator is not supported (``arkts-no-in``) +- Recipe 105: Property-based runtime type checks are not supported (``arkts-no-prop-existence-check``) +- Recipe 109: Dynamic property declaration is not supported (``arkts-no-dyn-prop-decl``) +- Recipe 144: Usage of standard library is restricted (``arkts-limited-stdlib``) diff --git a/linter/cookbook_convertor/md/recipe105.md b/linter/cookbook_convertor/md/recipe105.md index 1c28c234c..e7e9d47bd 100644 --- a/linter/cookbook_convertor/md/recipe105.md +++ b/linter/cookbook_convertor/md/recipe105.md @@ -61,13 +61,13 @@ will result in a compile-time error. ## See also -- Recipe 001: undefined -- Recipe 002: undefined -- Recipe 052: undefined -- Recipe 059: undefined -- Recipe 060: undefined -- Recipe 066: undefined -- Recipe 109: undefined -- Recipe 144: undefined +- Recipe 001: Objects with property names that are not identifiers are not supported (``arkts-identifiers-as-prop-names``) +- Recipe 002: ``Symbol()`` API is not supported (``arkts-no-symbol``) +- Recipe 052: Attempt to access an undefined property is a compile-time error (``arkts-no-undefined-prop-access``) +- Recipe 059: ``delete`` operator is not supported (``arkts-no-delete``) +- Recipe 060: ``typeof`` operator is allowed only in expression contexts (``arkts-no-type-query``) +- Recipe 066: ``in`` operator is not supported (``arkts-no-in``) +- Recipe 109: Dynamic property declaration is not supported (``arkts-no-dyn-prop-decl``) +- Recipe 144: Usage of standard library is restricted (``arkts-limited-stdlib``) diff --git a/linter/cookbook_convertor/md/recipe109.md b/linter/cookbook_convertor/md/recipe109.md index c4aedd903..05dd754c2 100644 --- a/linter/cookbook_convertor/md/recipe109.md +++ b/linter/cookbook_convertor/md/recipe109.md @@ -57,13 +57,13 @@ declare fields, their names and types explicitly. ## See also -- Recipe 001: undefined -- Recipe 002: undefined -- Recipe 052: undefined -- Recipe 059: undefined -- Recipe 060: undefined -- Recipe 066: undefined -- Recipe 105: undefined -- Recipe 144: undefined +- Recipe 001: Objects with property names that are not identifiers are not supported (``arkts-identifiers-as-prop-names``) +- Recipe 002: ``Symbol()`` API is not supported (``arkts-no-symbol``) +- Recipe 052: Attempt to access an undefined property is a compile-time error (``arkts-no-undefined-prop-access``) +- Recipe 059: ``delete`` operator is not supported (``arkts-no-delete``) +- Recipe 060: ``typeof`` operator is allowed only in expression contexts (``arkts-no-type-query``) +- Recipe 066: ``in`` operator is not supported (``arkts-no-in``) +- Recipe 105: Property-based runtime type checks are not supported (``arkts-no-prop-existence-check``) +- Recipe 144: Usage of standard library is restricted (``arkts-limited-stdlib``) diff --git a/linter/cookbook_convertor/md/recipe115.md b/linter/cookbook_convertor/md/recipe115.md index 2090a8275..b7ed86e5f 100644 --- a/linter/cookbook_convertor/md/recipe115.md +++ b/linter/cookbook_convertor/md/recipe115.md @@ -10,13 +10,13 @@ Differences are described in separate recipes. ## See also -- Recipe 118: undefined -- Recipe 119: undefined -- Recipe 120: undefined -- Recipe 121: undefined -- Recipe 123: undefined -- Recipe 124: undefined -- Recipe 125: undefined -- Recipe 126: undefined +- Recipe 118: Special import type declarations are not supported (``arkts-no-special-imports``) +- Recipe 119: Importing a module for side-effects only is not supported (``arkts-no-side-effects-imports``) +- Recipe 120: ``import default as ...`` is not supported (``arkts-no-import-default-as``) +- Recipe 121: ``require`` is not supported (``arkts-no-require``) +- Recipe 123: Renaming in export declarations is not supported (``arkts-no-export-renaming``) +- Recipe 124: Export list declaration is not supported (``arkts-no-export-list-decl``) +- Recipe 125: Re-exporting is not supported (``arkts-no-reexport``) +- Recipe 126: ``export = ...`` assignment is not supported (``arkts-no-export-assignment``) diff --git a/linter/cookbook_convertor/md/recipe118.md b/linter/cookbook_convertor/md/recipe118.md index 98511662f..5cd2e85ed 100644 --- a/linter/cookbook_convertor/md/recipe118.md +++ b/linter/cookbook_convertor/md/recipe118.md @@ -32,8 +32,8 @@ Use ordinary import instead. ## See also -- Recipe 119: undefined -- Recipe 120: undefined -- Recipe 121: undefined +- Recipe 119: Importing a module for side-effects only is not supported (``arkts-no-side-effects-imports``) +- Recipe 120: ``import default as ...`` is not supported (``arkts-no-import-default-as``) +- Recipe 121: ``require`` is not supported (``arkts-no-require``) diff --git a/linter/cookbook_convertor/md/recipe123.md b/linter/cookbook_convertor/md/recipe123.md index b8553fb0e..936673738 100644 --- a/linter/cookbook_convertor/md/recipe123.md +++ b/linter/cookbook_convertor/md/recipe123.md @@ -54,8 +54,8 @@ can be achieved through setting an alias for the exported entity. ## See also -- Recipe 124: undefined -- Recipe 125: undefined -- Recipe 126: undefined +- Recipe 124: Export list declaration is not supported (``arkts-no-export-list-decl``) +- Recipe 125: Re-exporting is not supported (``arkts-no-reexport``) +- Recipe 126: ``export = ...`` assignment is not supported (``arkts-no-export-assignment``) diff --git a/linter/cookbook_convertor/md/recipe124.md b/linter/cookbook_convertor/md/recipe124.md index 591d7d063..d86e3f384 100644 --- a/linter/cookbook_convertor/md/recipe124.md +++ b/linter/cookbook_convertor/md/recipe124.md @@ -33,8 +33,8 @@ entities must be explicitly annotated with the ``export`` keyword. ## See also -- Recipe 123: undefined -- Recipe 125: undefined -- Recipe 126: undefined +- Recipe 123: Renaming in export declarations is not supported (``arkts-no-export-renaming``) +- Recipe 125: Re-exporting is not supported (``arkts-no-reexport``) +- Recipe 126: ``export = ...`` assignment is not supported (``arkts-no-export-assignment``) diff --git a/linter/cookbook_convertor/md/recipe125.md b/linter/cookbook_convertor/md/recipe125.md index 8167c06c0..47ee1ddd3 100644 --- a/linter/cookbook_convertor/md/recipe125.md +++ b/linter/cookbook_convertor/md/recipe125.md @@ -51,8 +51,8 @@ imported explicitly from the modules that export them. ## See also -- Recipe 123: undefined -- Recipe 124: undefined -- Recipe 126: undefined +- Recipe 123: Renaming in export declarations is not supported (``arkts-no-export-renaming``) +- Recipe 124: Export list declaration is not supported (``arkts-no-export-list-decl``) +- Recipe 126: ``export = ...`` assignment is not supported (``arkts-no-export-assignment``) diff --git a/linter/cookbook_convertor/md/recipe126.md b/linter/cookbook_convertor/md/recipe126.md index bb9239dec..94f88de58 100644 --- a/linter/cookbook_convertor/md/recipe126.md +++ b/linter/cookbook_convertor/md/recipe126.md @@ -48,8 +48,8 @@ Use regular ``export`` / ``import`` instead. ## See also -- Recipe 123: undefined -- Recipe 124: undefined -- Recipe 125: undefined +- Recipe 123: Renaming in export declarations is not supported (``arkts-no-export-renaming``) +- Recipe 124: Export list declaration is not supported (``arkts-no-export-list-decl``) +- Recipe 125: Re-exporting is not supported (``arkts-no-reexport``) diff --git a/linter/cookbook_convertor/md/recipe128.md b/linter/cookbook_convertor/md/recipe128.md index b31a34eab..9a5ccebd4 100644 --- a/linter/cookbook_convertor/md/recipe128.md +++ b/linter/cookbook_convertor/md/recipe128.md @@ -31,7 +31,7 @@ own mechanisms for interoperating with JavaScript. ## See also -- Recipe 129: undefined -- Recipe 131: undefined +- Recipe 129: Wildcards in module names are not supported (``arkts-no-module-wildcards``) +- Recipe 131: ``.js`` extension is not allowed in module identifiers (``arkts-no-js-extension``) diff --git a/linter/cookbook_convertor/md/recipe129.md b/linter/cookbook_convertor/md/recipe129.md index 0481128e5..fa5e7dc9e 100644 --- a/linter/cookbook_convertor/md/recipe129.md +++ b/linter/cookbook_convertor/md/recipe129.md @@ -22,8 +22,8 @@ is a compile-time, not a runtime feature. Use ordinary export syntax instead. ## See also -- Recipe 128: undefined -- Recipe 130: undefined -- Recipe 131: undefined +- Recipe 128: Ambient module declaration is not supported (``arkts-no-ambient-decls``) +- Recipe 130: Universal module definitions (UMD) are not supported (``arkts-no-umd``) +- Recipe 131: ``.js`` extension is not allowed in module identifiers (``arkts-no-js-extension``) diff --git a/linter/cookbook_convertor/md/recipe130.md b/linter/cookbook_convertor/md/recipe130.md index 5cfcf3734..da2aada01 100644 --- a/linter/cookbook_convertor/md/recipe130.md +++ b/linter/cookbook_convertor/md/recipe130.md @@ -42,6 +42,6 @@ import is a compile-time, not a runtime feature. Use ordinary syntax for ## See also -- Recipe 129: undefined +- Recipe 129: Wildcards in module names are not supported (``arkts-no-module-wildcards``) diff --git a/linter/cookbook_convertor/md/recipe131.md b/linter/cookbook_convertor/md/recipe131.md index 8fe671509..c9f6e9c22 100644 --- a/linter/cookbook_convertor/md/recipe131.md +++ b/linter/cookbook_convertor/md/recipe131.md @@ -28,7 +28,7 @@ has its own mechanisms for interoperating with JavaScript. ## See also -- Recipe 128: undefined -- Recipe 129: undefined +- Recipe 128: Ambient module declaration is not supported (``arkts-no-ambient-decls``) +- Recipe 129: Wildcards in module names are not supported (``arkts-no-module-wildcards``) diff --git a/linter/cookbook_convertor/md/recipe132.md b/linter/cookbook_convertor/md/recipe132.md index 4790b8c5a..c38299638 100644 --- a/linter/cookbook_convertor/md/recipe132.md +++ b/linter/cookbook_convertor/md/recipe132.md @@ -28,6 +28,6 @@ to the statically typing. ## See also -- Recipe 136: undefined +- Recipe 136: Prototype assignment is not supported (``arkts-no-prototype-assignment``) diff --git a/linter/cookbook_convertor/md/recipe133.md b/linter/cookbook_convertor/md/recipe133.md index 0df7d7ccf..222bfdee0 100644 --- a/linter/cookbook_convertor/md/recipe133.md +++ b/linter/cookbook_convertor/md/recipe133.md @@ -29,8 +29,8 @@ import syntax instead. ## See also -- Recipe 129: undefined -- Recipe 130: undefined -- Recipe 143: undefined +- Recipe 129: Wildcards in module names are not supported (``arkts-no-module-wildcards``) +- Recipe 130: Universal module definitions (UMD) are not supported (``arkts-no-umd``) +- Recipe 143: Import assertions are not supported (``arkts-no-import-assertions``) diff --git a/linter/cookbook_convertor/md/recipe136.md b/linter/cookbook_convertor/md/recipe136.md index 3fa0cc3bf..eb2ada706 100644 --- a/linter/cookbook_convertor/md/recipe136.md +++ b/linter/cookbook_convertor/md/recipe136.md @@ -32,6 +32,6 @@ applicable to the static typing. ## See also -- Recipe 132: undefined +- Recipe 132: ``new.target`` is not supported (``arkts-no-new-target``) diff --git a/linter/cookbook_convertor/md/recipe137.md b/linter/cookbook_convertor/md/recipe137.md index d734fdebb..588cc70f4 100644 --- a/linter/cookbook_convertor/md/recipe137.md +++ b/linter/cookbook_convertor/md/recipe137.md @@ -38,7 +38,7 @@ objects with dynamically changed layout are not supported. ## See also -- Recipe 139: undefined -- Recipe 144: undefined +- Recipe 139: Declaring properties on functions is not supported (``arkts-no-func-props``) +- Recipe 144: Usage of standard library is restricted (``arkts-limited-stdlib``) diff --git a/linter/cookbook_convertor/md/recipe139.md b/linter/cookbook_convertor/md/recipe139.md index b7cec382e..5b27d1ebf 100644 --- a/linter/cookbook_convertor/md/recipe139.md +++ b/linter/cookbook_convertor/md/recipe139.md @@ -64,6 +64,6 @@ this rule and their layout cannot be changed in runtime. ## See also -- Recipe 137: undefined +- Recipe 137: ``globalThis`` is not supported (``arkts-no-globalthis``) diff --git a/linter/cookbook_convertor/md/recipe14.md b/linter/cookbook_convertor/md/recipe14.md index 0feafbfb9..b5e575621 100644 --- a/linter/cookbook_convertor/md/recipe14.md +++ b/linter/cookbook_convertor/md/recipe14.md @@ -48,6 +48,6 @@ ArkTS does not support call signatures in object types. Use classes instead. ## See also -- Recipe 015: undefined +- Recipe 015: Use ``class`` instead of a type with constructor signature (``arkts-no-ctor-signatures-type``) diff --git a/linter/cookbook_convertor/md/recipe140.md b/linter/cookbook_convertor/md/recipe140.md index ba6d22177..ae347c437 100644 --- a/linter/cookbook_convertor/md/recipe140.md +++ b/linter/cookbook_convertor/md/recipe140.md @@ -60,6 +60,6 @@ functions are excessive. ## See also -- Recipe 093: undefined +- Recipe 093: Using ``this`` inside stand-alone functions is not supported (``arkts-no-standalone-this``) diff --git a/linter/cookbook_convertor/md/recipe143.md b/linter/cookbook_convertor/md/recipe143.md index 861dd0b16..946b66efa 100644 --- a/linter/cookbook_convertor/md/recipe143.md +++ b/linter/cookbook_convertor/md/recipe143.md @@ -31,8 +31,8 @@ in runtime does not make sense for the statically typed language. Use ordinary ## See also -- Recipe 129: undefined -- Recipe 130: undefined -- Recipe 133: undefined +- Recipe 129: Wildcards in module names are not supported (``arkts-no-module-wildcards``) +- Recipe 130: Universal module definitions (UMD) are not supported (``arkts-no-umd``) +- Recipe 133: Runtime import expressions are not supported (``arkts-no-runtime-import``) diff --git a/linter/cookbook_convertor/md/recipe144.md b/linter/cookbook_convertor/md/recipe144.md index f468371eb..7a2ed2363 100644 --- a/linter/cookbook_convertor/md/recipe144.md +++ b/linter/cookbook_convertor/md/recipe144.md @@ -42,13 +42,13 @@ Properties and functions of the global object: ``eval``, ## See also -- Recipe 001: undefined -- Recipe 002: undefined -- Recipe 052: undefined -- Recipe 060: undefined -- Recipe 066: undefined -- Recipe 105: undefined -- Recipe 109: undefined -- Recipe 137: undefined +- Recipe 001: Objects with property names that are not identifiers are not supported (``arkts-identifiers-as-prop-names``) +- Recipe 002: ``Symbol()`` API is not supported (``arkts-no-symbol``) +- Recipe 052: Attempt to access an undefined property is a compile-time error (``arkts-no-undefined-prop-access``) +- Recipe 060: ``typeof`` operator is allowed only in expression contexts (``arkts-no-type-query``) +- Recipe 066: ``in`` operator is not supported (``arkts-no-in``) +- Recipe 105: Property-based runtime type checks are not supported (``arkts-no-prop-existence-check``) +- Recipe 109: Dynamic property declaration is not supported (``arkts-no-dyn-prop-decl``) +- Recipe 137: ``globalThis`` is not supported (``arkts-no-globalthis``) diff --git a/linter/cookbook_convertor/md/recipe15.md b/linter/cookbook_convertor/md/recipe15.md index 129d6f7f6..b99784a3c 100644 --- a/linter/cookbook_convertor/md/recipe15.md +++ b/linter/cookbook_convertor/md/recipe15.md @@ -45,6 +45,6 @@ instead. ## See also -- Recipe 014: undefined +- Recipe 014: Use ``class`` instead of a type with call signature (``arkts-no-call-signatures``) diff --git a/linter/cookbook_convertor/md/recipe2.md b/linter/cookbook_convertor/md/recipe2.md index cc02012a1..623cbff52 100644 --- a/linter/cookbook_convertor/md/recipe2.md +++ b/linter/cookbook_convertor/md/recipe2.md @@ -37,13 +37,13 @@ and cannot be changed at runtime. ## See also -- Recipe 001: undefined -- Recipe 052: undefined -- Recipe 059: undefined -- Recipe 060: undefined -- Recipe 066: undefined -- Recipe 105: undefined -- Recipe 109: undefined -- Recipe 144: undefined +- Recipe 001: Objects with property names that are not identifiers are not supported (``arkts-identifiers-as-prop-names``) +- Recipe 052: Attempt to access an undefined property is a compile-time error (``arkts-no-undefined-prop-access``) +- Recipe 059: ``delete`` operator is not supported (``arkts-no-delete``) +- Recipe 060: ``typeof`` operator is allowed only in expression contexts (``arkts-no-type-query``) +- Recipe 066: ``in`` operator is not supported (``arkts-no-in``) +- Recipe 105: Property-based runtime type checks are not supported (``arkts-no-prop-existence-check``) +- Recipe 109: Dynamic property declaration is not supported (``arkts-no-dyn-prop-decl``) +- Recipe 144: Usage of standard library is restricted (``arkts-limited-stdlib``) diff --git a/linter/cookbook_convertor/md/recipe27.md b/linter/cookbook_convertor/md/recipe27.md index e29be1c3e..776f84abd 100644 --- a/linter/cookbook_convertor/md/recipe27.md +++ b/linter/cookbook_convertor/md/recipe27.md @@ -39,6 +39,6 @@ ArkTS does not support construct signatures. Use methods instead. ## See also -- Recipe 015: undefined +- Recipe 015: Use ``class`` instead of a type with constructor signature (``arkts-no-ctor-signatures-type``) diff --git a/linter/cookbook_convertor/md/recipe30.md b/linter/cookbook_convertor/md/recipe30.md index fae7e5c6c..78cd9278b 100644 --- a/linter/cookbook_convertor/md/recipe30.md +++ b/linter/cookbook_convertor/md/recipe30.md @@ -43,9 +43,9 @@ in TypeScript, while in ArkTS they are not. ## See also -- Recipe 031: undefined -- Recipe 032: undefined -- Recipe 035: undefined +- Recipe 031: Structural typing is not supported for subtyping / supertyping (``arkts-no-structural-subtyping``) +- Recipe 032: Structural typing is not supported for assignability checks (``arkts-no-structural-assignability``) +- Recipe 035: Structural typing is not supported for type inference (``arkts-no-structural-inference``) diff --git a/linter/cookbook_convertor/md/recipe31.md b/linter/cookbook_convertor/md/recipe31.md index 78f624383..bd8337a3c 100644 --- a/linter/cookbook_convertor/md/recipe31.md +++ b/linter/cookbook_convertor/md/recipe31.md @@ -77,8 +77,8 @@ instead. ## See also -- Recipe 030: undefined -- Recipe 032: undefined -- Recipe 035: undefined +- Recipe 030: Structural identity is not supported (``arkts-no-structural-identity``) +- Recipe 032: Structural typing is not supported for assignability checks (``arkts-no-structural-assignability``) +- Recipe 035: Structural typing is not supported for type inference (``arkts-no-structural-inference``) diff --git a/linter/cookbook_convertor/md/recipe32.md b/linter/cookbook_convertor/md/recipe32.md index fcb19efaa..6bb5251a6 100644 --- a/linter/cookbook_convertor/md/recipe32.md +++ b/linter/cookbook_convertor/md/recipe32.md @@ -81,8 +81,8 @@ public APIs and decide whether such types are identical. Use other mechanisms ## See also -- Recipe 030: undefined -- Recipe 031: undefined -- Recipe 035: undefined +- Recipe 030: Structural identity is not supported (``arkts-no-structural-identity``) +- Recipe 031: Structural typing is not supported for subtyping / supertyping (``arkts-no-structural-subtyping``) +- Recipe 035: Structural typing is not supported for type inference (``arkts-no-structural-inference``) diff --git a/linter/cookbook_convertor/md/recipe35.md b/linter/cookbook_convertor/md/recipe35.md index 23d4a6875..0aab3e3bd 100644 --- a/linter/cookbook_convertor/md/recipe35.md +++ b/linter/cookbook_convertor/md/recipe35.md @@ -96,8 +96,8 @@ explicitly. ## See also -- Recipe 030: undefined -- Recipe 031: undefined -- Recipe 032: undefined +- Recipe 030: Structural identity is not supported (``arkts-no-structural-identity``) +- Recipe 031: Structural typing is not supported for subtyping / supertyping (``arkts-no-structural-subtyping``) +- Recipe 032: Structural typing is not supported for assignability checks (``arkts-no-structural-assignability``) diff --git a/linter/cookbook_convertor/md/recipe38.md b/linter/cookbook_convertor/md/recipe38.md index 86c2b7705..62b06f7a9 100644 --- a/linter/cookbook_convertor/md/recipe38.md +++ b/linter/cookbook_convertor/md/recipe38.md @@ -140,7 +140,7 @@ is not supported in following contexts: ## See also -- Recipe 040: undefined -- Recipe 043: undefined +- Recipe 040: Object literals cannot be used as type declarations (``arkts-no-obj-literals-as-types``) +- Recipe 043: Array literals must contain elements of only inferrable types (``arkts-no-noninferrable-arr-literals``) diff --git a/linter/cookbook_convertor/md/recipe40.md b/linter/cookbook_convertor/md/recipe40.md index d034e37d5..9fd22580f 100644 --- a/linter/cookbook_convertor/md/recipe40.md +++ b/linter/cookbook_convertor/md/recipe40.md @@ -40,7 +40,7 @@ types in place. Declare classes and interfaces explicitly instead. ## See also -- Recipe 038: undefined -- Recipe 043: undefined +- Recipe 038: Object literal must correspond to some explicitly declared class or interface (``arkts-no-untyped-obj-literals``) +- Recipe 043: Array literals must contain elements of only inferrable types (``arkts-no-noninferrable-arr-literals``) diff --git a/linter/cookbook_convertor/md/recipe43.md b/linter/cookbook_convertor/md/recipe43.md index d0a2d5c7d..e7257c77b 100644 --- a/linter/cookbook_convertor/md/recipe43.md +++ b/linter/cookbook_convertor/md/recipe43.md @@ -35,7 +35,7 @@ contents. But if there is at least one element with a non-inferrable type ## See also -- Recipe 038: undefined -- Recipe 040: undefined +- Recipe 038: Object literal must correspond to some explicitly declared class or interface (``arkts-no-untyped-obj-literals``) +- Recipe 040: Object literals cannot be used as type declarations (``arkts-no-obj-literals-as-types``) diff --git a/linter/cookbook_convertor/md/recipe52.md b/linter/cookbook_convertor/md/recipe52.md index 2b8d92e7c..91042ae77 100644 --- a/linter/cookbook_convertor/md/recipe52.md +++ b/linter/cookbook_convertor/md/recipe52.md @@ -47,13 +47,13 @@ existence during compilation. ## See also -- Recipe 001: undefined -- Recipe 002: undefined -- Recipe 059: undefined -- Recipe 060: undefined -- Recipe 066: undefined -- Recipe 105: undefined -- Recipe 109: undefined -- Recipe 144: undefined +- Recipe 001: Objects with property names that are not identifiers are not supported (``arkts-identifiers-as-prop-names``) +- Recipe 002: ``Symbol()`` API is not supported (``arkts-no-symbol``) +- Recipe 059: ``delete`` operator is not supported (``arkts-no-delete``) +- Recipe 060: ``typeof`` operator is allowed only in expression contexts (``arkts-no-type-query``) +- Recipe 066: ``in`` operator is not supported (``arkts-no-in``) +- Recipe 105: Property-based runtime type checks are not supported (``arkts-no-prop-existence-check``) +- Recipe 109: Dynamic property declaration is not supported (``arkts-no-dyn-prop-decl``) +- Recipe 144: Usage of standard library is restricted (``arkts-limited-stdlib``) diff --git a/linter/cookbook_convertor/md/recipe55.md b/linter/cookbook_convertor/md/recipe55.md index bf0dc71c2..a03384222 100644 --- a/linter/cookbook_convertor/md/recipe55.md +++ b/linter/cookbook_convertor/md/recipe55.md @@ -42,7 +42,7 @@ be done explicitly. ## See also -- Recipe 061: undefined -- Recipe 063: undefined +- Recipe 061: Binary operators ``*``, ``/``, ``%``, ``-``, ``<<``, ``>>``, ``>>>``, ``&``, ``^`` and ``|`` work only on numeric types (``arkts-no-polymorphic-binops``) +- Recipe 063: Binary ``+`` operator supports implicit casts only for numbers and strings (``arkts-no-polymorphic-plus``) diff --git a/linter/cookbook_convertor/md/recipe56.md b/linter/cookbook_convertor/md/recipe56.md index 1b171d1ad..8f1cb613e 100644 --- a/linter/cookbook_convertor/md/recipe56.md +++ b/linter/cookbook_convertor/md/recipe56.md @@ -47,8 +47,8 @@ numeric types. ## See also -- Recipe 055: undefined -- Recipe 061: undefined -- Recipe 063: undefined +- Recipe 055: Unary operators ``+``, ``-`` and ``~`` work only on numbers (``arkts-no-polymorphic-unops``) +- Recipe 061: Binary operators ``*``, ``/``, ``%``, ``-``, ``<<``, ``>>``, ``>>>``, ``&``, ``^`` and ``|`` work only on numeric types (``arkts-no-polymorphic-binops``) +- Recipe 063: Binary ``+`` operator supports implicit casts only for numbers and strings (``arkts-no-polymorphic-plus``) diff --git a/linter/cookbook_convertor/md/recipe59.md b/linter/cookbook_convertor/md/recipe59.md index b94b47ce7..d64602e17 100644 --- a/linter/cookbook_convertor/md/recipe59.md +++ b/linter/cookbook_convertor/md/recipe59.md @@ -43,12 +43,12 @@ changed at runtime. Thus the operation of deleting a property makes no sense. ## See also -- Recipe 001: undefined -- Recipe 002: undefined -- Recipe 052: undefined -- Recipe 060: undefined -- Recipe 066: undefined -- Recipe 105: undefined -- Recipe 109: undefined +- Recipe 001: Objects with property names that are not identifiers are not supported (``arkts-identifiers-as-prop-names``) +- Recipe 002: ``Symbol()`` API is not supported (``arkts-no-symbol``) +- Recipe 052: Attempt to access an undefined property is a compile-time error (``arkts-no-undefined-prop-access``) +- Recipe 060: ``typeof`` operator is allowed only in expression contexts (``arkts-no-type-query``) +- Recipe 066: ``in`` operator is not supported (``arkts-no-in``) +- Recipe 105: Property-based runtime type checks are not supported (``arkts-no-prop-existence-check``) +- Recipe 109: Dynamic property declaration is not supported (``arkts-no-dyn-prop-decl``) diff --git a/linter/cookbook_convertor/md/recipe60.md b/linter/cookbook_convertor/md/recipe60.md index 643e5f750..38b6ca476 100644 --- a/linter/cookbook_convertor/md/recipe60.md +++ b/linter/cookbook_convertor/md/recipe60.md @@ -38,13 +38,13 @@ type notations using ``typeof`` is not supported. ## See also -- Recipe 001: undefined -- Recipe 002: undefined -- Recipe 052: undefined -- Recipe 059: undefined -- Recipe 066: undefined -- Recipe 105: undefined -- Recipe 109: undefined -- Recipe 144: undefined +- Recipe 001: Objects with property names that are not identifiers are not supported (``arkts-identifiers-as-prop-names``) +- Recipe 002: ``Symbol()`` API is not supported (``arkts-no-symbol``) +- Recipe 052: Attempt to access an undefined property is a compile-time error (``arkts-no-undefined-prop-access``) +- Recipe 059: ``delete`` operator is not supported (``arkts-no-delete``) +- Recipe 066: ``in`` operator is not supported (``arkts-no-in``) +- Recipe 105: Property-based runtime type checks are not supported (``arkts-no-prop-existence-check``) +- Recipe 109: Dynamic property declaration is not supported (``arkts-no-dyn-prop-decl``) +- Recipe 144: Usage of standard library is restricted (``arkts-limited-stdlib``) diff --git a/linter/cookbook_convertor/md/recipe61.md b/linter/cookbook_convertor/md/recipe61.md index 26dc8777d..e5bdfd14a 100644 --- a/linter/cookbook_convertor/md/recipe61.md +++ b/linter/cookbook_convertor/md/recipe61.md @@ -64,8 +64,8 @@ compile-time errors. ## See also -- Recipe 055: undefined -- Recipe 056: undefined -- Recipe 063: undefined +- Recipe 055: Unary operators ``+``, ``-`` and ``~`` work only on numbers (``arkts-no-polymorphic-unops``) +- Recipe 056: Unary ``+`` cannot be used for casting to ``number`` (``arkts-no-unary-plus-cast``) +- Recipe 063: Binary ``+`` operator supports implicit casts only for numbers and strings (``arkts-no-polymorphic-plus``) diff --git a/linter/cookbook_convertor/md/recipe63.md b/linter/cookbook_convertor/md/recipe63.md index c8da81f95..47b26ae72 100644 --- a/linter/cookbook_convertor/md/recipe63.md +++ b/linter/cookbook_convertor/md/recipe63.md @@ -48,8 +48,8 @@ Elsewhere, any form of an explicit cast to string is required. ## See also -- Recipe 055: undefined -- Recipe 056: undefined -- Recipe 061: undefined +- Recipe 055: Unary operators ``+``, ``-`` and ``~`` work only on numbers (``arkts-no-polymorphic-unops``) +- Recipe 056: Unary ``+`` cannot be used for casting to ``number`` (``arkts-no-unary-plus-cast``) +- Recipe 061: Binary operators ``*``, ``/``, ``%``, ``-``, ``<<``, ``>>``, ``>>>``, ``&``, ``^`` and ``|`` work only on numeric types (``arkts-no-polymorphic-binops``) diff --git a/linter/cookbook_convertor/md/recipe66.md b/linter/cookbook_convertor/md/recipe66.md index e4bd36c03..10476f234 100644 --- a/linter/cookbook_convertor/md/recipe66.md +++ b/linter/cookbook_convertor/md/recipe66.md @@ -40,13 +40,13 @@ to check whether certain class members exist. ## See also -- Recipe 001: undefined -- Recipe 002: undefined -- Recipe 052: undefined -- Recipe 059: undefined -- Recipe 060: undefined -- Recipe 105: undefined -- Recipe 109: undefined -- Recipe 144: undefined +- Recipe 001: Objects with property names that are not identifiers are not supported (``arkts-identifiers-as-prop-names``) +- Recipe 002: ``Symbol()`` API is not supported (``arkts-no-symbol``) +- Recipe 052: Attempt to access an undefined property is a compile-time error (``arkts-no-undefined-prop-access``) +- Recipe 059: ``delete`` operator is not supported (``arkts-no-delete``) +- Recipe 060: ``typeof`` operator is allowed only in expression contexts (``arkts-no-type-query``) +- Recipe 105: Property-based runtime type checks are not supported (``arkts-no-prop-existence-check``) +- Recipe 109: Dynamic property declaration is not supported (``arkts-no-dyn-prop-decl``) +- Recipe 144: Usage of standard library is restricted (``arkts-limited-stdlib``) diff --git a/linter/cookbook_convertor/md/recipe79.md b/linter/cookbook_convertor/md/recipe79.md index fdbd4d493..56ac1ea4f 100644 --- a/linter/cookbook_convertor/md/recipe79.md +++ b/linter/cookbook_convertor/md/recipe79.md @@ -35,6 +35,6 @@ be omitted. ## See also -- Recipe 087: undefined +- Recipe 087: ``throw`` statements cannot accept values of arbitrary types (``arkts-limited-throw``) diff --git a/linter/cookbook_convertor/md/recipe8.md b/linter/cookbook_convertor/md/recipe8.md index 6a10d291f..4c4e1056c 100644 --- a/linter/cookbook_convertor/md/recipe8.md +++ b/linter/cookbook_convertor/md/recipe8.md @@ -34,6 +34,6 @@ Specify types explicitly. ## See also -- Recipe 013: undefined +- Recipe 013: Use ``Object[]`` instead of tuples (``arkts-no-tuples``) diff --git a/linter/cookbook_convertor/md/recipe80.md b/linter/cookbook_convertor/md/recipe80.md index 9a14699b7..190320e61 100644 --- a/linter/cookbook_convertor/md/recipe80.md +++ b/linter/cookbook_convertor/md/recipe80.md @@ -36,7 +36,7 @@ change at runtime. For arrays, you can iterate with the regular ``for`` loop. ## See also -- Recipe 081: undefined -- Recipe 082: undefined +- Recipe 081: Iterable interfaces are not supported (``arkts-noiterable``) +- Recipe 082: ``for-of`` is supported only for arrays and strings (``arkts-for-of-str-arr``) diff --git a/linter/cookbook_convertor/md/recipe81.md b/linter/cookbook_convertor/md/recipe81.md index ecb390e49..226c41097 100644 --- a/linter/cookbook_convertor/md/recipe81.md +++ b/linter/cookbook_convertor/md/recipe81.md @@ -11,8 +11,8 @@ iterate over data. ## See also -- Recipe 002: undefined -- Recipe 080: undefined -- Recipe 082: undefined +- Recipe 002: ``Symbol()`` API is not supported (``arkts-no-symbol``) +- Recipe 080: ``for .. in`` is not supported (``arkts-no-for-in``) +- Recipe 082: ``for-of`` is supported only for arrays and strings (``arkts-for-of-str-arr``) diff --git a/linter/cookbook_convertor/md/recipe82.md b/linter/cookbook_convertor/md/recipe82.md index 1a4499012..1bd77d931 100644 --- a/linter/cookbook_convertor/md/recipe82.md +++ b/linter/cookbook_convertor/md/recipe82.md @@ -35,7 +35,7 @@ but does not support the iteration of objects content. ## See also -- Recipe 080: undefined -- Recipe 081: undefined +- Recipe 080: ``for .. in`` is not supported (``arkts-no-for-in``) +- Recipe 081: Iterable interfaces are not supported (``arkts-noiterable``) diff --git a/linter/cookbook_convertor/md/recipe83.md b/linter/cookbook_convertor/md/recipe83.md index 5f324a0fd..3eedbaee4 100644 --- a/linter/cookbook_convertor/md/recipe83.md +++ b/linter/cookbook_convertor/md/recipe83.md @@ -38,6 +38,6 @@ classes to achieve the same behaviour. ## See also -- Recipe 097: undefined +- Recipe 097: ``keyof`` operator is not supported (``arkts-no-keyof``) diff --git a/linter/cookbook_convertor/md/recipe93.md b/linter/cookbook_convertor/md/recipe93.md index 830cecd69..ceb0cacf5 100644 --- a/linter/cookbook_convertor/md/recipe93.md +++ b/linter/cookbook_convertor/md/recipe93.md @@ -53,6 +53,6 @@ ArkTS does not support the usage of ``this`` inside stand-alone functions. ## See also -- Recipe 140: undefined +- Recipe 140: ``Function.apply``, ``Function.bind``, ``Function.call`` are not supported (``arkts-no-func-apply-bind-call``) diff --git a/linter/cookbook_convertor/src/cookbook_convertor.ts b/linter/cookbook_convertor/src/cookbook_convertor.ts index b5ff197a6..201123993 100644 --- a/linter/cookbook_convertor/src/cookbook_convertor.ts +++ b/linter/cookbook_convertor/src/cookbook_convertor.ts @@ -66,6 +66,9 @@ const CB_SEE = "|CB_SEE|"; const CB_REF = ":ref:"; const CB_META = ".. meta"; +const NEW_REC_HEADER = ".. _R"; +const CODE_BLOCK = ".. code"; // should be ".. code-block" but in some places there is error in doc file + let MAKE_MD = false; // flag to generate .md files let doc_lines: string[]; @@ -78,8 +81,6 @@ let cooks: string[] = []; let mdText: string[] = []; -const NEW_REC_HEADER = ".. _R"; -const CODE_BLOCK = ".. code"; // should be ".. code-block" but in some places there is error in doc file const CL = " \\"; // continue line const STR_DLMTR = "\'"; @@ -92,12 +93,18 @@ function syncReadFile(filename: string) { // make table of rule names _line = 0; + let ruleNum = -1; while( _line < doc_lines.length ) { + if(doc_lines[ _line ].startsWith( NEW_REC_HEADER ) ) { +console.log(">>>>>>> START RULE " + doc_lines[ _line ].split( NEW_REC_HEADER )[1]) + ruleNum = Number((doc_lines[ _line ].split( NEW_REC_HEADER )[1]).split(":")[0]); +console.log(" NUMBER: " + ruleNum) + } if( doc_lines[ _line ].startsWith( CB_R ) ) { let line = doc_lines[ _line ].split( CB_R )[1]; - let tegNumStr = line.split(':')[0]; - let ruleNum = Number(tegNumStr.split('#')[1]); - ruleNames[ ruleNum ] = line.split(':')[1]; + //let tegNumStr = line.split(':')[0]; + //let ruleNum = Number(tegNumStr.split('#')[1]); + ruleNames[ ruleNum ] = line; //line.split(':')[1]; _line++; needHeader(); if( doc_lines[ _line ].startsWith( CB_RULE ) ) { -- Gitee