diff --git a/ets2panda/linter/docs/rules-cn/recipe1.md b/ets2panda/linter/docs/rules-cn/recipe1.md new file mode 100644 index 0000000000000000000000000000000000000000..99588f7145f21fa19d30476bbcde24d3b8e9096a --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe1.md @@ -0,0 +1,23 @@ +## enum的key不能是字符串 + +**规则:**`arkts-identifiers-as-prop-names` + +**级别:error** + +ArkTS1.2不支持将字符串作为class、interface、enum等属性或元素的名称,需要使用标识符来表示。 + +**ArkTS1.1** + +```typescript +enum A{ + 'red' = '1' +} +``` + +**ArkTS1.2** + +```typescript +enum A{ + red = '1' +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe111.md b/ets2panda/linter/docs/rules-cn/recipe111.md new file mode 100644 index 0000000000000000000000000000000000000000..87225ec0561116f7da7019d005920c245ed1e859 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe111.md @@ -0,0 +1,27 @@ +## enum中不支持成员为不同类型数据 + +**规则:**`arkts-no-enum-mixed-types` + +**级别:error** + +enum用来表示一组离散的数据,使用浮点数据不符合enum的设计理念。使用浮点数据可能造成精度损失的问题。因此,ArkTS1.2中enum的值必须为整型数据。 + +**ArkTS1.1** + +```typescript +enum Size { + UP = 1.5, + MIDDLE = 1, + DOWN = 0.75 +} +``` + +**ArkTS1.2** + +```typescript +enum Size{ + UP = 1, + MIDDLE = 2, + DOWN = 3 +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe134.md b/ets2panda/linter/docs/rules-cn/recipe134.md new file mode 100644 index 0000000000000000000000000000000000000000..2a35eec54b33cb3720c52a031af40cbbca6258ee --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe134.md @@ -0,0 +1,33 @@ +## 不支持确定赋值断言 + +**规则:**`arkts-no-definite-assignment` + +**级别:error** + +ArkTS1.2不支持确定赋值断言。改为在声明变量的同时为变量赋值。 + +**ArkTS1.1** + +```typescript +let x!: number // 提示:在使用前将x初始化 + +initialize(); + +function initialize() { + x = 10; +} + +console.log('x = ' + x); +``` + +**ArkTS1.2** + +```typescript +function initialize(): number { + return 10; +} + +let x: number = initialize(); + +console.log('x = ' + x); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe137.md b/ets2panda/linter/docs/rules-cn/recipe137.md new file mode 100644 index 0000000000000000000000000000000000000000..04cf67cf4283a014cab6baf212d9e224df91e0b1 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe137.md @@ -0,0 +1,29 @@ +## 不支持globalThis + +**规则:**`arkts-no-globalthis` + +**级别:error** + +由于ArkTS1.2不支持动态更改对象的布局,因此不支持全局作用域和globalThis。 + +**ArkTS1.1** + +```typescript +// 全局文件中 +var abc = 100; + +// 从上面引用'abc' +let x = globalThis.abc; +``` + +**ArkTS1.2** + +```typescript +// file1 +export let abc: number = 100; + +// file2 +import * as M from 'file1' + +let x = M.abc; +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe139.md b/ets2panda/linter/docs/rules-cn/recipe139.md new file mode 100644 index 0000000000000000000000000000000000000000..a4fd6a5cef173eb58db292b41ae5406a95cdb7fc --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe139.md @@ -0,0 +1,81 @@ +## 不支持为函数增加属性 + +**规则:**`arkts-no-func-props` + +**级别:error** + +ArkTS1.2上不支持在函数上动态添加属性。 + +**ArkTS1.1** + +```typescript +function foo(path: string): void { + console.log(path) +} +foo.baz = 1 + +const obj = { + foo(path: string): void { + console.log(path); + } +}; +obj.foo.baz = 2; // 违反规则 + +function createLogger() { + function log(message: string) { + console.log(message); + } + log.level = "debug"; // 违反规则 + return log; +} + +const logger = createLogger(); +console.log(logger.level); + +function counter() { + counter.count = (counter.count || 0) + 1; // 违反规则 + return counter.count; +} +console.log(counter()); +``` + +**ArkTS1.2** + +```typescript +class T { + static foo(path: string): void { + console.log(path) + } + static bar: number = 1 +} + +class T { + static foo(path: string): void { + console.log(path); + } + + static baz: number = 2; +} +T.foo("example"); +console.log(T.baz); + +class Logger { + static level = "debug"; + + static log(message: string) { + console.log(message); + } +} +Logger.log("test"); +console.log(Logger.level); + +class Counter { + static count = 0; + + static increment() { + this.count += 1; + return this.count; + } +} +console.log(Counter.increment()); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe140.md b/ets2panda/linter/docs/rules-cn/recipe140.md new file mode 100644 index 0000000000000000000000000000000000000000..78fb062c4cbfcf5c2f20aab8cb505b863763b5d2 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe140.md @@ -0,0 +1,39 @@ +## 不支持Funcion.bind方法 + +**规则:**`arkts-no-func-bind` + +**级别:error** + +ArkTS不允许使用标准库函数Function.bind。标准库使用这些函数来显式设置被调用函数的this参数。 + +**ArkTS1.1** + +```typescript +class MyClass { + constructor(public name: string) {} + + greet() { + console.log(`Hello, my name is ${this.name}`); + } +} + +const instance = new MyClass("Alice"); +const boundGreet = instance.greet.bind(instance); // 违反规则,不允许使用 Function.bind +boundGreet(); +``` + +**ArkTS1.2** + +```typescript +class MyClass { + constructor(public name: string) {} + + greet() { + console.log(`Hello, my name is ${this.name}`); + } +} + +const instance = new MyClass("Alice"); +const boundGreet = () => instance.greet(); // 使用箭头函数 +boundGreet(); // Hello, my name is Alice +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe144.md b/ets2panda/linter/docs/rules-cn/recipe144.md new file mode 100644 index 0000000000000000000000000000000000000000..ae7a8b470b828f703eaf3084096e81cf65c89aa5 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe144.md @@ -0,0 +1,18 @@ +## 共享对象不添加装饰器@Sendable + +**规则:** arkts-limited-stdlib-no-sendable-decorator + +**级别:** error + +新增对象天然共享特性,不再依赖Sendable特性,无需添加@Sendable装饰器。 + +**ArkTS1.1** +```typescript +@Sendable +class A {} +``` + +**ArkTS1.2** +```typescript +class A {} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe149.md b/ets2panda/linter/docs/rules-cn/recipe149.md new file mode 100644 index 0000000000000000000000000000000000000000..ff1733a50330fed88de373cc6a9b022d51064f80 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe149.md @@ -0,0 +1,30 @@ +## 不支持将类作为对象 + +**规则:**`arkts-no-classes-as-obj` + +**级别:error** + +在ArkTS中,class声明的是一个新的类型,不是一个值。因此,不支持将class用作对象(例如将class赋值给一个变量)。 + +**ArkTS1.1** + +```typescript +class MyClass { + constructor(public name: string) {} +} + +let obj = MyClass; // 违反规则 +``` + +**ArkTS1.2** + +```typescript +class MyClass { + constructor(name: string) {} +} + +// 需要通过反射来实现 +let className = "path.to.MyClass"; +let linker = Class.ofCaller()!.getLinker(); +let classType: ClassType | undefined = linker.getType(className) as ClassType; +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe183.md b/ets2panda/linter/docs/rules-cn/recipe183.md new file mode 100644 index 0000000000000000000000000000000000000000..d9f84dcff099c784046eeb51266cbcad0d2532c8 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe183.md @@ -0,0 +1,71 @@ +## 对象字面量只包含属性不包含方法 + +**规则:**`arkts-obj-literal-props` + +**级别:error** + +ArkTS1.2中不支持在对象字面量中定义方法。因为静态语言中类的方法被所有实例所共享,无法通过对象字面量重新定义方法。 + +**ArkTS1.1** + +```typescript +class A { + foo: () => void = () => {} +} + +let a: A = { + foo() { // 违反规则 + console.log('hello') + } +} + +interface Person { + sayHello: () => void; +} + +let p: Person = { + sayHello() { // 违反规则,方法定义方式错误 + console.log('Hi'); + } +}; + +type Handler = { + foo(): void; +}; + +let handler: Handler = { + foo() { // 违反规则 + console.log("Executing handler"); + } +}; +``` + +**ArkTS1.2** + +```typescript +class A { + foo : () => void = () => {} +} + +let a: A = { + foo: () => { + console.log('hello') + } +} + +let p: Person = { + sayHello: () => { // 使用属性赋值方式 + console.log('Hi'); + } +}; + +type Handler = { + foo: () => void; +}; + +let handler: Handler = { + foo: () => { // 修正方法定义方式 + console.log("Executing handler"); + } +}; +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe184.md b/ets2panda/linter/docs/rules-cn/recipe184.md new file mode 100644 index 0000000000000000000000000000000000000000..445b8e0a8b7788e1dc3b8c14fb5c386a12434a7c --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe184.md @@ -0,0 +1,29 @@ +## 不支持可选方法 + +**规则:**`arkts-optional-methods` + +**级别:error** + +ArkTS1.2中类的方法被所有类的实例所共享,增加可选方法的支持会增加开发者判断空值的成本,影响性能。 + +**ArkTS1.1** + +```typescript +interface InterfaceA { + aboutToDisappear?(): void +} +class ClassA { + aboutToDisappear?(): void {} +} +``` + +**ArkTS1.2** + +```typescript +interface InterfaceA { + aboutToDisappear?: () => void +} +class ClassA { + aboutToDisappear?: () => void = () => {} +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe189.md b/ets2panda/linter/docs/rules-cn/recipe189.md new file mode 100644 index 0000000000000000000000000000000000000000..4fcbbaa50387c4624eadfc921c98eb6e9f7c43be --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe189.md @@ -0,0 +1,58 @@ +## 数值类型语义变化 + +**规则:** `arkts-numeric-semantic` + +**级别:** error + +在ArkTS1.2中,为了获得更好的执行效率,整型数字字面量默认是int类型。 + +**ArkTS1.1** +```typescript +let n = 1; +console.log(n / 2) // output: 0.5 + +let arr = [1, 2, 3]; + +function multiply(x = 2, y = 3) { // 需要明确类型 + return x * y; +} + +function divide(x: number, y: number) { + return x / y; +} // 函数返回值 + +let num = Math.floor(4.8); // num 可能是 int +let value = parseInt("42"); // value 可能是 int + +function identity(value: T): T { + return value; +} +identity(42); // 42 可能推导为 int +``` + +**ArkTS1.2** +```typescript +let n: number = 1; +console.log(n / 2) // output: 0.5 + +let m = 1; +console.log(m / 2) // output: 0 + +let arr: number[] = [1, 2, 3]; + +function multiply(x: number = 2, y: number = 3): number { + return x * y; +} + +function divide(x: number, y: number): number { + return x / y; +} + +let num: number = Math.floor(4.8); +let value: number = parseInt("42"); + +function identity(value: T): T { + return value; +} +identity(42 as number); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe190.md b/ets2panda/linter/docs/rules-cn/recipe190.md new file mode 100644 index 0000000000000000000000000000000000000000..ff7b37e4608da281ade3f626870c7eaa5055ccf0 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe190.md @@ -0,0 +1,47 @@ +## 函数类型 + +**规则:**`arkts-incompatible-function-types` + +**级别:error** + +TypeScript允许对函数类型的变量进行更宽松的赋值,而在ArkTS1.2中,将对函数类型的赋值进行更严格的检查。函数类型转换时,参数遵循逆变(Contravariance)规则,返回类型遵循协变(Covariance)规则。 + +**ArkTS1.1** + +```typescript +type FuncType = (p: string) => void; +let f1: FuncType = + (p: string): number => { + return 0 + } +let f2: FuncType = (p: any): void => {}; + +class Animal {} +class Dog extends Animal {} +type FuncType = () => Animal; +let f: FuncType = (): Dog => new Dog(); // 在 TypeScript 允许,但在 ArkTS 可能不允许 + +type FuncType2 = (dog: Dog) => void; +let f: FuncType2 = (animal: Animal) => {}; // 违反规则 +``` + +**ArkTS1.2** + +```typescript +type FuncType = (p: string) => void +let f1: FuncType = + (p: string) => { + ((p: string): number => { + return 0 + })(p) + } +let f2: FuncType = (p: string): void => {}; + +class Animal {} +class Dog extends Animal {} +type FuncType = () => Animal; +let f: FuncType = (): Animal => new Animal();// 返回 `Animal` + +type FuncType2 = (dog: Dog) => void; +let f: FuncType = (dog: Dog) => {}; // 参数类型严格匹配 +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe191.md b/ets2panda/linter/docs/rules-cn/recipe191.md new file mode 100644 index 0000000000000000000000000000000000000000..18ee7f34d3555c2cd5a948cb54dad86b22d64ec9 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe191.md @@ -0,0 +1,23 @@ +## 内存默认共享,不提供ASON + +**规则:** arkts-no-need-stdlib-ason + +**级别:** error + +新增对象天然共享特性,不再依赖Sendable特性,ASON.stringify()方法调用可直接更改为JSON.stringify(),且删除ArkTSUtils.前缀。 + +**ArkTS1.1** +```typescript +import { collections } from '@kit.ArkTS'; +import { ArkTSUtils } from '@kit.ArkTS'; +let arr = new collections.Array(1, 2, 3); +let str = ArkTSUtils.ASON.stringify(arr); +console.info(str); +``` + +**ArkTS1.2** +```typescript +let arr = new Array(1, 2, 3); +let str = JSON.stringify(arr); +console.info(str); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe192.md b/ets2panda/linter/docs/rules-cn/recipe192.md new file mode 100644 index 0000000000000000000000000000000000000000..64225cc939d8a5340ba4b0f2bf22f6aae0135ba4 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe192.md @@ -0,0 +1,41 @@ +## void类型只能用在返回类型的场景 + +**规则:** `arkts-limited-void-type` + +**级别:** error + +在ArkTS1.2中,void仅作为类型使用。void类型没有实体。 + +**ArkTS1.1** +```typescript +let s: void = foo(); +let t: void | number = foo(); + +function process(input: T): T { + return input; +} +let result = process(foo()); + +type VoidAlias = void; + +let { x }: { x: void } = { x: foo() }; + +function execute(callback: void) { + callback(); +} + +let x = fun() as void; +``` + +**ArkTS1.2** +```typescript +function foo(): void {} +foo(); + +function bar(): void {} + +function execute(callback: () => void) { + callback(); +} +fun(); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe193.md b/ets2panda/linter/docs/rules-cn/recipe193.md new file mode 100644 index 0000000000000000000000000000000000000000..7b93aea7f578c8edc25625b2c26e706c18b8bfec --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe193.md @@ -0,0 +1,44 @@ +## 不支持void操作符 + +**规则:** `arkts-no-void-operator` + +**级别:** error + +在ArkTS1.2中,undefined作为关键字不能作为变量名称,因此不需要通过void操作符获取undefined。 + +**ArkTS1.1** +```typescript +let s = void 'hello'; +console.log(s); // output: undefined + +let a = 5; +let b = void (a + 1); + +function logValue(value: any) { + console.log(value); +} +logValue(void 'data'); + +let fn = () => void 0; +``` + +**ArkTS1.2** +```typescript +(() => { + 'hello' + return undefined; +})() + +let a = 5; +let b = (() => { + a + 1; + return undefined; +})(); // 替换为 IIFE + +logValue((() => { + 'data'; + return undefined; +})()); // 替换为 IIFE + +let fn = () => undefined; // 直接返回 `undefined` +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe198.md b/ets2panda/linter/docs/rules-cn/recipe198.md new file mode 100644 index 0000000000000000000000000000000000000000..792bff4731ad7946dd933dff1c676d27340ffba6 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe198.md @@ -0,0 +1,53 @@ +## 不支持类TS重载 + +**规则:**`arkts-no-ts-overload` + +**级别:error** + +ArkTS1.2不支持TS-like的重载,使用不同的函数体可以提高执行效率。 + +**ArkTS1.1** + +```typescript +function foo(): void +function foo(x: string): void +function foo(x?: string): void { // 违反规则 + /*body*/ +} + +function sum(x: number, y: number): number; +function sum(x: number, y: number, z: number): number; +function sum(x: number, y: number, z?: number): number { // 违反规则 + return z ? x + y + z : x + y; +} + +function foo(): string; +function foo(x: number): number; +function foo(x?: number): string | number { // 违反规则 + return x !== undefined ? x * 2 : "default"; +} +``` + +**ArkTS1.2** + +```typescript +function foo(x?: string): void { + /*body*/ +} + +function sumTwo(x: number, y: number): number { // 独立实现 + return x + y; +} + +function sumThree(x: number, y: number, z: number): number { // 独立实现 + return x + y + z; +} + +function fooString(): string { // 独立实现 + return "default"; +} + +function fooNumber(x: number): number { // 独立实现 + return x * 2; +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe199.md b/ets2panda/linter/docs/rules-cn/recipe199.md new file mode 100644 index 0000000000000000000000000000000000000000..597435946366b65f4492e4aeec1900056431f8c7 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe199.md @@ -0,0 +1,19 @@ +## 原生容器默认共享,不需要Sendable容器 + +**规则:** arkts-no-need-stdlib-sendable-containers + +**级别:** error + +新增对象天然共享特性,不再依赖Sendable特性。可直接使用ArkTS1.2原生容器,删除collections.前缀。 + +**ArkTS1.1** +```typescript +import { collections } from '@kit.ArkTS'; + +let array = new collections.Array(); +``` + +**ArkTS1.2** +```typescript +let array = new Array(); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe202.md b/ets2panda/linter/docs/rules-cn/recipe202.md new file mode 100644 index 0000000000000000000000000000000000000000..c7a7058673af3dc5a7b5bffd963f5d3ca07e99b8 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe202.md @@ -0,0 +1,61 @@ +## 限定使用字面量类型 + +**规则:** `arkts-limited-literal-types` + +**级别:** error + +ArkTS1.2不支持数字字面量类型,布尔字面量类型。 + +ArkTS1.2提供了更多细化的数值类型供开发者选择,更关注数值的范围而非某个特定的数字值,同时,为了更好的代码简洁性和避免引入歧义,不引入复杂的数值字面量类型语法。 + +**ArkTS1.1** +```typescript +let n1: 1 = 1; +let n2: 0.1 = 0.1; +let f: true = true; + +function getOne(): 1 { + return 1; +} +function isAvailable(): true { + return true; +} + +function setFlag(flag: true) { + console.log(flag); +} +function setPrecision(precision: 0.1) { + console.log(precision); +} + +interface Config { + readonly enable: true; + readonly threshold: 100; +} +``` + +**ArkTS1.2** +```typescript +let n1: int = 1; +let n2: number = 0.1; +let f: boolean = true; + +function getOne(): int { + return 1; +} +function isAvailable(): boolean { + return true; +} + +function setFlag(flag: boolean) { + console.log(flag); +} +function setPrecision(precision: number) { + console.log(precision); +} + +interface Config { + readonly enable: boolean; + readonly threshold: int; +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe203.md b/ets2panda/linter/docs/rules-cn/recipe203.md new file mode 100644 index 0000000000000000000000000000000000000000..0c05d2115e305dcef92833a88b16f5a371358920 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe203.md @@ -0,0 +1,43 @@ +## 不支持指数操作符 + +**规则:**`arkts-no-exponent-op` + +**级别:error** + +ArkTS1.2不支持指数运算符(`**`和`**=`),采用语言基础库。 + +**ArkTS1.1** + +```typescript +let x = 2 ** 5; + +let y = 3; +y **= 4; // 违反规则 + +let result = (1 + 2) ** (3 * 2); // 违反规则 + +function power(base: number, exponent: number) { + return base ** exponent; // 违反规则 +} + +let values = [1, 2, 3]; +let squared = values.map(v => v ** 2); // 违反规则 +``` + +**ArkTS1.2** + +```typescript +let x = Math.pow(2, 5); + +let y = 3; +y = Math.pow(y, 4); // 直接使用 `Math.pow()` + +let result = Math.pow(1 + 2, 3 * 2); // 直接使用 `Math.pow()` + +function power(base: number, exponent: number) { + return Math.pow(base, exponent); // 使用 `Math.pow()` +} + +let values = [1, 2, 3]; +let squared = values.map(v => Math.pow(v, 2)); // 使用 `Math.pow()` +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe206.md b/ets2panda/linter/docs/rules-cn/recipe206.md new file mode 100644 index 0000000000000000000000000000000000000000..d9fc158b9410828d39572a61225d47941f51d642 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe206.md @@ -0,0 +1,27 @@ +## 不支持debugger + +**规则:**`arkts-no-debugger` + +**级别:error** + +1. 静态类型语言具备编译时检查和强类型约束,调试通常由IDE完成,已具备较强大的调试机制。 + +2. debugger会侵入式修改源码。 + +3. debugger语句会被优化,造成行为不一致。 + +**ArkTS1.1** + +```typescript +// ArkTS1.1 +// ... +debugger; +// ... +``` + +**ArkTS1.2** + +```typescript +// ArkTS1.2 移除debugger语句 +// ... +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe207.md b/ets2panda/linter/docs/rules-cn/recipe207.md new file mode 100644 index 0000000000000000000000000000000000000000..e0a78ca50c943f6a7f366f67fad0e9f448d365c9 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe207.md @@ -0,0 +1,54 @@ +## 不支持arguments对象 + +**规则:** `arkts-no-arguments-obj` + +**级别:** error + +ArkTS1.2对函数调用进行严格的参数检查,参数个数不符时编译报错,因此不需要在函数体内通过arguments机制获取参数。 + +**ArkTS1.1** +```typescript +function foo(u: string) { + console.log(arguments[0]); +} + +function bar(a: number, b?: number) { + if (arguments.length === 1) { + console.log("Only one argument passed"); + } +} + +function sum() { + let total = 0; + for (let i = 0; i < arguments.length; i++) { + total += arguments[i]; + } + return total; +} + +function test() { + console.log(arguments.callee); +} +``` + +**ArkTS1.2** +```typescript +function foo(u: string) { + console.log(u); +} + +function bar(a: number, b?: number) { + if (b === undefined) { + console.log("Only one argument passed"); + } +} + +function sum(...args: number[]) { + // 使用 `...rest` 替代 `arguments` + return args.reduce((acc, num) => acc + num, 0); +} + +function test() { + console.log(test); // 直接使用函数名 +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe208.md b/ets2panda/linter/docs/rules-cn/recipe208.md new file mode 100644 index 0000000000000000000000000000000000000000..1d70fd916912ad5a940d20cd8e0aae68188acf19 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe208.md @@ -0,0 +1,52 @@ +## 不支持tagged templates + +**规则:**`arkts-no-tagged-templates` + +**级别:error** + +ArkTS1.2规范函数调用方式,支持字符串相加的用法,不支持Tagged templates(标签模板字符串)。 + +**ArkTS1.1** + +```typescript +function myTag(strings: TemplateStringsArray, value: string): string { + return strings[0] + value.toUpperCase() + strings[1]; +} + +const name = 'john'; +const result = myTag`Hello, ${name}!`; +console.log(result); + +function formatTag(strings: TemplateStringsArray, first: string, last: string): string { + return `${strings[0]}${first.toUpperCase()} ${last.toUpperCase()}${strings[1]}`; +} + +const firstName = 'john'; +const lastName = 'doe'; +const result = formatTag`Hello, ${firstName} ${lastName}!`; // 违反规则 +console.log(result); +``` + +**ArkTS1.2** + +```typescript +function myTagWithoutTemplate(strings: string, value: string): string { + return strings + value.toUpperCase(); +} + +const name = 'john'; + +const part1 = 'Hello, '; +const part2 = '!'; +const result = myTagWithoutTemplate(part1, name) + part2; +console.log(result); + +function formatWithoutTemplate(greeting: string, first: string, last: string, end: string): string { + return greeting + first.toUpperCase() + ' ' + last.toUpperCase() + end; +} + +const firstName = 'john'; +const lastName = 'doe'; +const result = formatWithoutTemplate('Hello, ', firstName, lastName, '!'); // 直接使用函数参数 +console.log(result); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe209.md b/ets2panda/linter/docs/rules-cn/recipe209.md new file mode 100644 index 0000000000000000000000000000000000000000..37e2107599fbeaab1a205a79ca175088b418adde --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe209.md @@ -0,0 +1,43 @@ +## 数组索引必须是整型数据 + +**规则:**`arkts-array-index-expr-type` + +**级别:error** + +ArkTS1.2支持数值类型的细化,为了实现数组更快的访问,数组索引表达式必须是整数类型。 + +**ArkTS1.1** + +```typescript +function foo (index: number) { + let array = [1, 2, 3] + let element = array[index] +} + +function getIndex(): number { + return Math.random() * 10; // 可能返回小数 +} + +let array = [1, 2, 3]; +for (let i: number = 0; i < array.length; i++) { // 违反规则 + console.log(array[i]); +} +``` + +**ArkTS1.2** + +```typescript +function foo (index: int) { + let array = [1, 2, 3] + let element = array[index] +} + +function getIndex(): int { + return Math.floor(Math.random() * 10); // 转换为 `int` +} + +let array = [1, 2, 3]; +for (let i: int = 0; i < array.length; i++) { // 改为 `int` + console.log(array[i]); +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe210.md b/ets2panda/linter/docs/rules-cn/recipe210.md new file mode 100644 index 0000000000000000000000000000000000000000..6d3b16fb3ad4f1b570f26860447240660c485b47 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe210.md @@ -0,0 +1,55 @@ +## 限定switch语句中case语句类型 + +**规则:**`arkts-switch-expr` + +**级别:error** + +ArkTS1.2的switch表达式类型只能为number,string,enum。 + +**ArkTS1.1** + +```typescript +const isTrue = true; +switch (isTrue) { + case true: // 违反规则 + console.log('It\'s true'); break; + case false: // 违反规则 + console.log('It\'s false'); break; +} + +const obj = { value: 1 }; +switch (obj) { // 违反规则 + case { value: 1 }: + console.log('Matched'); break; +} + +const arr = [1, 2, 3]; +switch (arr) { // 违反规则 + case [1, 2, 3]: + console.log('Matched'); break; +} +``` + +**ArkTS1.2** + +```typescript +const isTrue = 'true'; +switch (isTrue) { + case 'true': + console.log('It\'s true'); break; + case 'false': + console.log('It\'s false'); break; +} + +const objValue = 1; // 仅存储值 +switch (objValue) { + case 1: + console.log('Matched'); break; +} + +const arrValue = '1,2,3'; // 变成字符串 +switch (arrValue) { + case '1,2,3': + console.log('Matched'); break; +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe211.md b/ets2panda/linter/docs/rules-cn/recipe211.md new file mode 100644 index 0000000000000000000000000000000000000000..a4dd6a5dd1562c24fcc405f0fbaba3eced183e90 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe211.md @@ -0,0 +1,58 @@ +## 不支持重复case语句 + +**规则:**`arkts-case-expr` + +**级别:error** + +ArkTS1.2不支持Switch语句的中case重复,便于提高代码可读性。 + +**ArkTS1.1** + +```typescript +const num = 1; +switch (num) { + case 1: + console.log('First match'); + case 1: + console.log('Second match'); + break; + default: + console.log('No match'); +} + +enum Status { + Active, + Inactive +} + +const state = Status.Active; +switch (state) { + case Status.Active: + console.log('User is active'); + break; + case Status.Active: // 违反规则 + console.log('Already active'); + break; +} +``` + +**ArkTS1.2** + +```typescript +const num = 1; +switch (num) { + case 1: + console.log('First match'); + console.log('Second match'); + break; + default: + console.log('No match'); +} + +switch (state) { + case Status.Active: + console.log('User is active'); + console.log('Already active'); // 代码合并 + break; +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe212.md b/ets2panda/linter/docs/rules-cn/recipe212.md new file mode 100644 index 0000000000000000000000000000000000000000..d26122a052c8b95368bcbc1024849773cb2b7806 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe212.md @@ -0,0 +1,38 @@ +## 不支持通过负数访问数组 + +**规则:**`arkts-array-index-negative` + +**级别:error** + +ArkTS1.2不支持使用负整数访问数组元素。 + +**ArkTS1.1** + +```typescript +let an_array = [1, 2, 3]; +let element = an_array [-1]; +console.log(getElement(an_array, -1)); // 违反规则 +for (let i: int = -1; i < an_array.length; i++) { // 违反规则 + console.log(an_array[i]); +} + +function getElement(arr: number[], index: int) { + return arr[index]; // 可能接收负数索引 +} +``` + +**ArkTS1.2** + +```typescript +let an_array = [1, 2, 3]; +let element = an_array [1]; +console.log(getElement(an_array, 1)); // 传递非负索引 +for (let i: int = 0; i < an_array.length; i++) { // 仅允许非负索引 + console.log(an_array[i]); +} + +function getElement(arr: number[], index: int) { + if (index < 0) throw new Error("Index must be a non-negative integer"); + return arr[index]; // 仅允许非负整数 +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe213.md b/ets2panda/linter/docs/rules-cn/recipe213.md new file mode 100644 index 0000000000000000000000000000000000000000..1dadbf87dd589c01c495b016c1f2ff7129244a93 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe213.md @@ -0,0 +1,27 @@ +## class的懒加载 + +**规则:**`arkts-class-lazy-import` + +**级别:error** + +ArkTS1.2的类在使用时进行加载或初始化,以提升启动性能,减少内存占用。 + +**ArkTS1.1** + +```typescript +class C { + static { + console.info('init'); // ArkTS1.2上不会立即执行 + } +} +``` + +**ArkTS1.2** + +```typescript +// ArkTS1.2 如果依赖没有被使用的class执行逻辑,那么将该段逻辑移出class +class C { + static {} +} +console.info('init'); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe214.md b/ets2panda/linter/docs/rules-cn/recipe214.md new file mode 100644 index 0000000000000000000000000000000000000000..7bac07e4ebcd1f0155f07e29a2f96c50177aa867 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe214.md @@ -0,0 +1,22 @@ +## 对象没有constructor + +**规则:**`arkts-obj-no-constructor` + +**级别:error** + +ArkTS1.2支持天然共享的能力,运行时需要确定类型信息。实现上不再基于原型的语言,而是基于class的语言。 + +**ArkTS1.1** + +```typescript +class A {} +let a = new A().constructor; // ArkTS1.2上编译错误 +``` + +**ArkTS1.2** + +```typescript +class A {} +let a = new A(); +let cls = Type.of(a); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe215.md b/ets2panda/linter/docs/rules-cn/recipe215.md new file mode 100644 index 0000000000000000000000000000000000000000..1a51e48fad0a477a526a5907e9f18eb011b079d1 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe215.md @@ -0,0 +1,23 @@ +## 增加数组越界运行时检查 + +**规则:**`arkts-runtime-array-check` + +**级别:error** + +为了保证类型安全,在访问数组元素时,ArkTS1.2会对索引的合法性进行校验。 + +**ArkTS1.1** + +```typescript +let a: number[] = [] +a[100] = 5; // 可能越界 +``` + +**ArkTS1.2** + +```typescript +let a: number[] = [] +if (100 < a.length) { + a[100] = 5 // a[100]的值为5 +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe222.md b/ets2panda/linter/docs/rules-cn/recipe222.md new file mode 100644 index 0000000000000000000000000000000000000000..cf3695b207f7db017a664c00a369b9997c4af619 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe222.md @@ -0,0 +1,26 @@ +## 不支持副作用导入 + +**规则:**`arkts-no-side-effect-import` + +**级别:error** + +ArkTS1.2中模块加载默认支持懒加载,无法实现导入副作用的功能。 + +**ArkTS1.1** + +```typescript +// logger.ets +console.log("Logger initialized!"); + +// main.ets +import "./logger"; +console.log("Main program running..."); +``` + +**ArkTS1.2** + +```typescript +// main.ets +console.log("Logger initialized!"); +console.log("Main program running..."); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe232.md b/ets2panda/linter/docs/rules-cn/recipe232.md new file mode 100644 index 0000000000000000000000000000000000000000..7f5cec4a61c9d05f65f3dd087ba3dec7428dd193 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe232.md @@ -0,0 +1,23 @@ +## 不支持lazy关键字 + +**规则:**`arkts-no-lazy-import` + +**级别:error** + +ArkTS1.2支持默认懒加载,无需lazy关键字。 + +**ArkTS1.1** + +```typescript +import lazy { m } from 'module' +import lazy { a, b } from 'module1'; // 违反规则 +import { c } from 'module2'; +``` + +**ArkTS1.2** + +```typescript +import { m } from 'module' +import { a, b } from 'module1'; // 移除 lazy +import { c } from 'module2'; +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe233.md b/ets2panda/linter/docs/rules-cn/recipe233.md new file mode 100644 index 0000000000000000000000000000000000000000..fe2047a3071a0a1ae48c76ae96e863ad81cd8b08 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe233.md @@ -0,0 +1,47 @@ +## 不支持动态import + +**规则:**`arkts-no-dynamic-import` + +**级别:error** + +ArkTS1.2中模块加载默认支持懒加载。 + +**ArkTS1.1** + +```typescript +function main(): void { + import('./file').then((m) => { + console.log(m.Data.name) + }) +} + +document.getElementById("btn")?.addEventListener("click", async () => { + const module = await import('./utils'); // 错误: 在ArkTS中动态`import()`是不支持的. + module.doSomething(); +}); + +function getModule() { + return import('./heavyModule') // 错误: 在ArkTS中动态`import()`是不支持的. + .then((m) => m.default); +} +``` + +**ArkTS1.2** + +```typescript +import { Data } from './file' +import { doSomething } from './utils'; // 静态import是可以的. +import heavyModule from './heavyModule'; // 静态import是可以的. + +function main(): void { + console.log(Data.name) +} + +document.getElementById("btn")?.addEventListener("click", () => { + doSomething(); +}); + +function getModule() { + return heavyModule; +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe234.md b/ets2panda/linter/docs/rules-cn/recipe234.md new file mode 100644 index 0000000000000000000000000000000000000000..3547c5dfe63bb8ddfcbf6d88e53832c9d2976ce3 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe234.md @@ -0,0 +1,35 @@ +## 不支持TS装饰器 + +**规则:**`arkts-no-ts-decorators` + +**级别:error** + +ArkTS1.2中不支持将类作为对象,不能通过装饰器中对类做动态改变。 + +**ArkTS1.1** + +```typescript +function decorateKlass(target: Object) { + console.log("decorateKlass") +} + +@decorateKlass // 违反规则 +class Person { + age: number = 12 +} +``` + +**ArkTS1.2** + +```typescript +class Person { + age: number = 12 +} + +class PersonHelper { + static createPerson(): Person { + console.log("decorateKlass") + return new Person() + } +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe235.md b/ets2panda/linter/docs/rules-cn/recipe235.md new file mode 100644 index 0000000000000000000000000000000000000000..2f835382857962d944af75dcca57551d4853f08a --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe235.md @@ -0,0 +1,44 @@ +## 增强对联合类型属性访问的编译时检查 + +**规则:**`arkts-common-union-member-access` + +**级别:error** + +在ArkTS1.2中,对象的结构在编译时就确定了。为了避免访问联合类型后出现运行时错误,ArkTS1.2在编译时会对联合类型的同名属性进行编译检查,要求同名属性具有相同的类型。 + +**ArkTS1.1** + +```typescript +class A { + v: number = 1 +} + +class B { + u: string = '' +} + +function foo(a: A | B) { + console.log(a.v) // 违反规则 + console.log(a.u) // 违反规则 +} +``` + +**ArkTS1.2** + +```typescript +class A { + v: number = 1 +} + +class B { + u: string = '' +} + +function foo(a: A) { + console.log(a.v) +} + +function foo(a: B) { + console.log(a.u) +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe236.md b/ets2panda/linter/docs/rules-cn/recipe236.md new file mode 100644 index 0000000000000000000000000000000000000000..f36b1ae6fffca18d336a4b9c666f87a07aff2c1d --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe236.md @@ -0,0 +1,47 @@ +## 类实现接口时,不能用类方法替代对应interface属性 + +**规则:**`arkts-no-method-overriding-field` + +**级别:error** + +ArkTS1.2不支持structural type,属性和方法不能互相转换。 + +**ArkTS1.1** + +```typescript +interface Person { + cb: () => void +} + +class student implements Person{ + cb() {} +} + +interface Transformer { + transform: (value: T) => T; // 违反规则 +} + +class StringTransformer implements Transformer { + transform(value: string) { return value.toUpperCase(); } // 违反规则 +} +``` + +**ArkTS1.2** + +```typescript +interface Person { + cb(): void +} + +class student implements Person{ + cb() {} +} + +interface Transformer { + transform(value: T): T; // 变成方法 +} + +class StringTransformer implements Transformer { + transform(value: string) { return value.toUpperCase(); } // 正确 +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe238.md b/ets2panda/linter/docs/rules-cn/recipe238.md new file mode 100644 index 0000000000000000000000000000000000000000..d4ef752cf76e940d483c75e890b6c0a6636676b2 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe238.md @@ -0,0 +1,57 @@ +## 类的静态属性需要有初始值 + +**规则:**`arkts-class-static-initialization` + +**级别:error** + +ArkTS1.2遵循null-safety,需要为属性赋上初始值。 + +**ArkTS1.1** + +```typescript +class B {} + +class A { + static b: B +} + +class A { + static count: number; // 违反规则,必须初始化 +} + +class A { + static config: { theme: string }; // 违反规则,必须初始化 +} + +class A { + static name: string; + + constructor() { + A.name = "default"; // 违反规则,静态属性必须在定义时初始化 + } +} +``` + +**ArkTS1.2** + +```typescript +class B {} + +class A { + static b? : B + static b: B | undefined = undefined +} + +class A { + static count: number = 0; // 提供初始值 +} + +class A { + static config: { theme: string } = { theme: "light" }; // 提供初始值 +} + +class A { + static name: string = "default"; // 在定义时初始化 +} + +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe239.md b/ets2panda/linter/docs/rules-cn/recipe239.md new file mode 100644 index 0000000000000000000000000000000000000000..b87215a02cdc0db58e20b19230c1f8784ba7fff3 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe239.md @@ -0,0 +1,28 @@ +## Task的function属性改名为taskFunction + +**规则:** arkts-change-taskpool-Task-to-taskFunction + +**级别:** error + +function在ArkTS1.2中为关键字,不能作为类属性(限定关键字(arkts-invalid-identifier))。 + +**ArkTS1.1** +```typescript +import { taskpool } from '@kit.ArkTS'; + +function testString(str: string) { + console.info(str); + +} +let task: taskpool.Task = new taskpool.Task(testString, "hello"); +let func = task.function; +``` + +**ArkTS1.2** +```typescript +let func1 = (str: string): string => { + return str; +}; +let task: taskpool.Task = new taskpool.Task(func1, "hello"); +let func = task.taskFunction; +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe255.md b/ets2panda/linter/docs/rules-cn/recipe255.md new file mode 100644 index 0000000000000000000000000000000000000000..c131a1ce4c1d4f07a0c0277c2f505d78979b0ceb --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe255.md @@ -0,0 +1,85 @@ +## 禁止extends/implements表达式 + +**规则:**`arkts-no-extends-expression` + +**级别:error** + +ArkTS1.2中规范了类的继承,类不能作为对象来继承一个表达式。 + +**ArkTS1.1** + +```typescript +class A { + v: number = 0 +} + +let a = A; + +class B extends a { // 违反规则 + u: number = 0 +} + +function getBase() { + return class { + w: number = 0; + }; +} + +class B extends getBase() { // 违反规则 + u: number = 0; +} + +interface I { + w: number; +} + +let i = I; + +class B implements i { // 违反规则 + w: number = 0; +} + +class A { + v: number = 0; +} + +class B extends new A() { // 违反规则 + u: number = 0; +} +``` + +**ArkTS1.2** + +```typescript +class A { + v: number = 0 +} + +class B extends A { // 直接继承类 + u: number = 0 +} + +class Base { + w: number = 0; +} + +class B extends Base { // 直接继承类 + u: number = 0; +} + +interface I { + w: number; +} + +class B implements I { // 直接使用接口 + w: number = 0; +} + +class A { + v: number = 0; +} + +class B extends A { // 直接继承类 + u: number = 0; +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe265.md b/ets2panda/linter/docs/rules-cn/recipe265.md new file mode 100644 index 0000000000000000000000000000000000000000..669645672ebd6f9631e4791b94170b5e927be67b --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe265.md @@ -0,0 +1,33 @@ +### ArkTS1.2继承js的类 + +**规则:** arkts-interop-js2s-inherit-js-class + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.js +export class A {} + +// file2.ets +import { A } from './file1'; +class B extends A {} +let b = new B(); +``` + +**ArkTS1.2** +```typescript +// file1.js +export class A {} + +// file2.ets // ArkTS1.2 +'use static' +let mod = ESValue.load('./file1'); +let A = mod.getProperty('A'); +let fixArr: FixedArray = []; +let esvalueCB = (argThis: ESValue, argNewTgt: ESValue, args: FixedArray, data?: ESValueCallbackData) => { + return ESValue.Undefined; +}; +let B: ESValue = ESValue.defineClass('B', esvalueCB, undefined, undefined, A); +let b = B.instantiate(); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe266.md b/ets2panda/linter/docs/rules-cn/recipe266.md new file mode 100644 index 0000000000000000000000000000000000000000..a511d29f8d8eee09faca33f85bda0bd5348cb94a --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe266.md @@ -0,0 +1,36 @@ +### ArkTS1.2遍历js对象 + +**规则:** arkts-interop-js2s-traverse-js-instance + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.js +export let foo = { arr: [1, 2, 3] }; +// file2.ets +import { foo } from './file1'; +let arr = foo.arr; +let len = arr.length as number; +for (let i = 0; i < len; ++i) { + arr[i] as number; + arr[i] = 0; +} +``` + +**ArkTS1.2** +```typescript +// file1.js +export let foo = { arr: [1, 2, 3] }; + +// file2.ets ArkTS1.2 +'use static' +let mod = ESValue.load('./file1'); +let foo = mod.getProperty('foo'); +let arr = foo.getProerpty('arr'); +let len = arr.getProerpty('length').toNumber(); +for (let i = 0; i < len; ++i) { + arr.getProperty(i).toNumber(); + arr.setProperty(i, ESValue.wrap(0)); +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe268.md b/ets2panda/linter/docs/rules-cn/recipe268.md new file mode 100644 index 0000000000000000000000000000000000000000..05e25804452ed175bade60027ab334ab7ace82b4 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe268.md @@ -0,0 +1,30 @@ +### ArkTS1.2对js对象进行条件判断 + +**规则:** arkts-interop-js2s-condition-judgment + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.js +export let foo = { isGood: true }; + +// file2.ets +import { foo } from './file1'; + +if (foo.isGood) {} +``` + +**ArkTS1.2** +```typescript +// file1.js +export let foo = { isGood: true }; + +// file2.ets +'use static' +let mod = ESValue.load('./file1'); +let foo = mod.getProperty('foo'); + +let isGood = foo.getProperty('isGood').toBoolean(); +if (isGood) {} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe269.md b/ets2panda/linter/docs/rules-cn/recipe269.md new file mode 100644 index 0000000000000000000000000000000000000000..c819e89511fad3002d5574fbcd31183d52917d38 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe269.md @@ -0,0 +1,38 @@ +### js对ArkTS1.2对象进行展开语法 + +**规则:** arkts-interop-js2s-js-expand-static-instance + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.js +export function foo(obj) { +let x = {...obj} // x会是{ a = 1; b = 2; c = 3 } +let {a, b, ...rest} = obj // a会是1, b会是2, rest会是{c: 3} + +// file2.ets +import {foo} from "./file1" +class X { a = 1; b = 2; c = 3 } +foo(new X()) + +// class interface Record +``` + +**ArkTS1.2** +```typescript +// file1.js +export function foo(obj) { +let x = {...obj} // x会是空对象{},因为静态对象没有自有属性 +// 解决方案:let x = {a: obj.a, b: obj.b, c: obj.c} +// 或者使用keys + Reflect.get +let {a, b, ...rest} = obj // a会是1,b会是2,rest会是空对象{},因为静态对象没有自有属性 +// 解决方案: let rest = {c: obj.c} + +// file2.ets // ArkTS1.2 +'use static' +let mod = ESValue.load('./file1') +let foo = mod.getProperty('foo') +class X { a = 1; b = 2; c = 3 } +foo.invoke(ESValue.wrap(new X())) +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe270.md b/ets2panda/linter/docs/rules-cn/recipe270.md new file mode 100644 index 0000000000000000000000000000000000000000..9c76a6f2580cffafa87539fee35dfbf9492c5679 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe270.md @@ -0,0 +1,42 @@ +### ArkTS1.2处理js非常规异常 + +**规则:** arkts-interop-js2s-js-exception + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.js +export function foo() { + throw 123; +} + +// file2.ets +import { foo } from './file1'; + +try { + foo(); +} catch (e) { + console.log("result is " + (e as number)); //123 +} +``` + +**ArkTS1.2** +```typescript +// file1.js +export function foo() { + throw 123; +} + +// file2.ets +'use static' +let mod = ESValue.load('./file1'); +let foo = mod.getProperty('foo'); + +try { + foo.invoke(); +} catch (e) { + let err: ESValue = (e as ESError).getValue(); + err.toNumber(); // 123 +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe274.md b/ets2panda/linter/docs/rules-cn/recipe274.md new file mode 100644 index 0000000000000000000000000000000000000000..afd9563e76409338cd948c1074f43a044d15912d --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe274.md @@ -0,0 +1,33 @@ +## 子类有参构造函数需要显式定义,且必须调用父类的构造函数 + +**规则:**`arkts-subclass-must-call-super-constructor-with-args` + +**级别:error** + +1. ArkTS1.1在运行时没有对函数调用的检查,同时利用arguments机制获取所有参数(ArkTS1.2上不支持这个特性)并传入父类构造函数。ArkTS1.2对函数参数的个数和类型会进行编译时检查,确保程序的安全和正确性,因此ArkTS1.2上不支持这种写法。 + +2. ArkTS1.2支持方法重载,构造函数可能有多个实现体,在ArkTS1.2上支持这个特性会造成子类继承父类时的二义性。 + +**ArkTS1.1** + +```typescript +class A { + constructor(a: number) {} +} +class B extends A {} // ArkTS1.2上编译报错 +let b = new B(123); +``` + +**ArkTS1.2** + +```typescript +class A { + constructor(a: number) {} +} +class B extends A { + constructor(a: number) { + super(a) + } +} +let b = new B(123); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe29.md b/ets2panda/linter/docs/rules-cn/recipe29.md new file mode 100644 index 0000000000000000000000000000000000000000..3861c5deedccc309a9bf476ba7289e57c0213ac6 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe29.md @@ -0,0 +1,37 @@ +## 不支持[]访问对象属性 + +**规则:**`arkts-no-props-by-index` + +**级别:error** + +在ArkTS1.2中,对象结构在编译时已确定。为避免运行时出现错误和更好地提升性能,在ArkTS1.2中不能使用[]的方式动态访问object类型对象的属性。 + +**ArkTS1.1** + +```typescript +function foo(u: object) { + u['key'] // 违反规则 +} + +const person = { name: "Alice", age: 30 }; +console.log(person['name']); // 违反规则 + +const data = JSON.parse('{ "name": "Alice" }'); +console.log(data['name']); // 违反规则 +``` + +**ArkTS1.2** + +```typescript +function foo(m: Map) { + m.get('key') // 使用 `Map` +} + +console.log(person.name); // 直接使用 `.` 访问 + +interface UserData { + name: string; +} +const data: UserData = JSON.parse('{ "name": "Alice" }'); +console.log(data.name); // 直接使用点访问符 +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe30.md b/ets2panda/linter/docs/rules-cn/recipe30.md new file mode 100644 index 0000000000000000000000000000000000000000..809e77db21526580c4b0a54e90d2cd7464772eb7 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe30.md @@ -0,0 +1,96 @@ +## 不支持structural typing + +**规则:**`arkts-no-structural-typing` + +**级别:error** + +ArkTS1.2不支持structural typing,编译器无法比较两种类型的publicAPI并决定它们是否相同。使用其他机制,例如继承、接口或类型别名。 + +**ArkTS1.1** + +```typescript +// case1 +class A { + v: number = 0 +} + +class B { + v: number = 0 +} + +let a = new B() as A + +// case2 +class C { + u: T +} + +let b: C = new C() + +// case3 +class A { + u: number = 0 +} + +class B { + u: number = 0 +} + +(): A => { return new B() } + +class A { + v: number = 0 +} + +class B { + v: number = 0 +} +class C { + u: T; +} + +let b: C = new C(); // 违反规则 +``` + +**ArkTS1.2** + +```typescript +// case1 +class A { + v: number = 0 +} + +class B { + v: number = 0 +} + +let a = new B() + +// case2 +class C { + u: T +} + +let b: C = new C() + +// case3 +class A { + u: number = 0 +} + +class B { + u: number = 0 +} + +(): B => { return new B() } + +class A { + v: number = 0 +} + +class B { + v: number = 0 +} +let b: C = new C(); // 使用相同的泛型类型 + +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe300.md b/ets2panda/linter/docs/rules-cn/recipe300.md new file mode 100644 index 0000000000000000000000000000000000000000..71a8a5e419fd5646db5f6b157a56f78c4f637b69 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe300.md @@ -0,0 +1,50 @@ +## 不支持TS-like `Function`类型的调用方式 + +**规则:**`arkts-no-ts-like-function-call` + +**级别:error** + +ArkTS1.2会对函数类型进行更严格的编译器检查。函数返回类型需要严格定义来保证类型安全,因此不支持TS-like`Function`类型。 + +**ArkTS1.1** + +```typescript +let f: Function = () => {} // 违反规则 + +function run(fn: Function) { // 违反规则 + fn(); +} + +let fn: Function = (x: number) => x + 1; // 违反规则 + +class A { + func: Function = () => {}; // 违反规则 +} + +function getFunction(): Function { // 违反规则 + return () => {}; +} +``` + +**ArkTS1.2** + +```typescript +type F = () => R; +type F1 = (p: P) => R + +let f: F = () => {} + +function run(fn: () => void) { // 指定返回类型 + fn(); +} + +let fn: (x: number) => number = (x) => x + 1; // 明确参数类型 + +class A { + func: () => void = () => {}; // 明确类型 +} + +function getFunction(): () => void { // 明确返回类型 + return () => {}; +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe302.md b/ets2panda/linter/docs/rules-cn/recipe302.md new file mode 100644 index 0000000000000000000000000000000000000000..1500874327688c104a2b2a5a50e74866bc4681a4 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe302.md @@ -0,0 +1,40 @@ +### ArkTS1.2Object内置方法作用在ArkTS1.1对象 + +**规则:** arkts-interop-d2s-static-object-on-dynamic-instance + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.ets +export class X { + a = 1; +} + +// file2.ets +import { X } from 'file1'; +export function foo(prx: Object) { + Object.entries(prx); // [a, 1] + Object.keys(prx); // ["a"] + Object.values(prx); // [1] +} +foo(new X()); +``` + +**ArkTS1.2** +```typescript +// file1.ets ArkTS1.1 +export class X { + a = 1; +} + +// file2.ets ArkTS 1.2 +'use static' +import { X } from 'file1'; +export function foo(prx: Object) { + Object.entries(prx); // [a, 1] + Object.keys(prx); // ["a"] + Object.values(prx); // [1] +} +foo(new X()); // 编译报错 +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe303.md b/ets2panda/linter/docs/rules-cn/recipe303.md new file mode 100644 index 0000000000000000000000000000000000000000..5b378e5dea4501adf69349a603a227ce349111c7 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe303.md @@ -0,0 +1,47 @@ +### ArkTS1.2Reflect内置方法作用在ArkTS1.1对象 + +**规则:** arkts-interop-d2s-static-reflect-on-dynamic-instance + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.ets ArkTS1.1 +class X { + a: string = 'hello'; + getName() { + return this.a; + } +} + +// file2.ets ArkTS1.2 +'use static' +import { X } from './file1'; +export function foo(prx: Object) { + Reflect.get(prx, 'a'); // 'hello' + Reflect.set(prx, 'a', 'world'); // true + Reflect.ownKeys(prx); // ['a'] +} +foo(new X()); +``` + +**ArkTS1.2** +```typescript +// file1.ets ArkTS1.1 +class X { + a: string = 'hello'; + getName() { + return this.a; + } +} + +// file2.ets ArkTS1.2 +'use static' +import { X } from './file1'; +export function foo(prx: Object) { + Reflect.get(prx, 'a'); // 'hello' + Reflect.set(prx, 'a', 'world'); // true + Reflect.ownKeys(prx); // ['a'] +} +foo(new X()); // 编译报错 +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe304.md b/ets2panda/linter/docs/rules-cn/recipe304.md new file mode 100644 index 0000000000000000000000000000000000000000..910d614ede6de60ba9dd7a8ea180c9c5bbff825b --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe304.md @@ -0,0 +1,40 @@ +## namespace内方法不能重名 + +**规则:**`arkts-no-duplicate-function-name` + +**级别:error** + +由于ArkTS1.2中会将多个名称相同的namespace合并成一个namespace,所以namespace内方法不能重名,否则会导致冲突。 + +**ArkTS1.1** + +```typescript +namespace A { + export function foo() { // 错误:命名空间 'A' 中重复导出函数 'foo'. + console.log('test1'); + } +} + +namespace A { + export function foo() { // 错误:命名空间 'A' 中重复导出函数 'foo'. + console.log('test2'); + } +} + +``` + +**ArkTS1.2** + +```typescript +namespace A { + export function foo1() { // 重命名导出函数 + console.log('test1'); + } +} + +namespace A { + export function foo2() { + console.log('test2'); + } +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe306.md b/ets2panda/linter/docs/rules-cn/recipe306.md new file mode 100644 index 0000000000000000000000000000000000000000..afee2e00cfe5fdb919bf89c9bcd550468d2258ef --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe306.md @@ -0,0 +1,66 @@ +### ArkTS1.2访问TS独有类型的实体 + +**规则:** arkts-interop-ts2s-static-access-ts-type + +TS独有类型包括如下类型: +- any +- unknown +- symbol +- Function +- object literal (例如 {x: number, y: string}) +- mixing enum (例如 enum X {a = 0, b = '1'}) +- call signature (例如 {(arg: number): string}) +- constructor signature (例如 {new(): Object}) +- index signature (例如 {[index: number]: string}) +- intersection (例如 TypeA & TypeB) +- keyof (例如 interface X { props: keyof T}) +- typeof(例如 let p = {x: 1, y: ''}, let q: typeof p) +- indexed access type(例如 MyArray = [{ name: "Alice", age: 15 }] type Person = typeof MyArray[number]) +- conditional types (例如 type Swap = T extends A ? B : A) +- mapped types (例如 type A = {[K in keyof T]: T[K]}) +- template literal types (例如 type AB = "A" | "B", type AllLocaleIDs = `${AB}_id`) +- Pick +- Omit +- Exclude +- Extract +- NonNullable +- Parameters +- ConstructorParameters +- ReturnType +- InstanceType +- NoInfer +- ThisParameterType +- OmitThisParameter +- ThisType +- Uppercase +- Lowercase +- Capitalize +- Uncapitalize + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.ts +export let obj: Symbol; + +// file2.ets +import { obj } from './file1'; +let val = obj.prop; +obj.prop = 1; +obj.foo(); +let item = obj[0]; +``` + +**ArkTS1.2** +```typescript +// file1.ts +export let obj: Symbol; +// 从ArkTS1.2看来,这个声明为 +// export let obj: ESValue + +// file2.ets ArkTS1.2 +'use static' +import { obj } from './file1'; +obj.setProperty('prop', ESValue.wrap(1)); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe307.md b/ets2panda/linter/docs/rules-cn/recipe307.md new file mode 100644 index 0000000000000000000000000000000000000000..99303cceeded609d8c62ae551bdd189806332b21 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe307.md @@ -0,0 +1,41 @@ +### ArkTS1.2处理TS非常规异常 + +**规则:** arkts-interop-ts2s-ts-exception + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.ts +export function foo() { + throw 123; +} + +// file2.ets +import { foo } from './file1'; + +try { + foo(); +} catch (e) { + console.log("result is " + (e as number)); // 123 +} +``` + +**ArkTS1.2** +```typescript +// file1.ts +export function foo() { + throw 123; +} + +// file2.ets // ArkTS1.2 +'use static' +import { foo } from './file1'; + +try { + foo(); +} catch (e) { + let err: ESValue = (e as ESError).getValue(); + err.toNumber(); // 123 +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe317.md b/ets2panda/linter/docs/rules-cn/recipe317.md new file mode 100644 index 0000000000000000000000000000000000000000..ed695e7b175e3404eb81a6b992f792aa331cf0c1 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe317.md @@ -0,0 +1,21 @@ +## 共享模块不需要use shared修饰 + +**规则:** arkts-limited-stdlib-no-use-shared + +**级别:** error + +新增对象天然共享特性,无需添加use shared。 + +**ArkTS1.1** +```typescript +// test.ets +export let num = 1; +// shared.ets +'use shared' +export {num} from './test'; +``` + +**ArkTS1.2** +```typescript +export let num = 1; +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe318.md b/ets2panda/linter/docs/rules-cn/recipe318.md new file mode 100644 index 0000000000000000000000000000000000000000..d202675128f8fba9dc91ea044ec0d90ed8df5f7c --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe318.md @@ -0,0 +1,19 @@ +## 共享函数不需要use concurrent修饰 + +**规则:** arkts-limited-stdlib-no-use-concurrent + +**级别:** error + +新增对象天然共享特性,无需添加use concurrent。 + +**ArkTS1.1** +```typescript +function func() { +'use concurrent' +} +``` + +**ArkTS1.2** +```typescript +function func() {} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe319.md b/ets2panda/linter/docs/rules-cn/recipe319.md new file mode 100644 index 0000000000000000000000000000000000000000..b9ef4d7be95441c4a9f5b85c9ea4b481361e18aa --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe319.md @@ -0,0 +1,57 @@ +## 方法继承/实现参数遵循逆变原则,返回类型遵循协变原则 + +**规则:**`arkts-method-inherit-rule` + +**级别:error** + +ArkTS1.2子类方法覆写父类方法,参数类型须遵循逆变原则,可以通过编译时检查保证类型安全,将潜在的运行时错误提前到编译期,避免运行时失败,无需运行时检查,从而提高执行性能。 + +**逆变/协变:** 用来描述类型转换后的继承关系,如果A、B表示类型,f()表示类型转换,≤表示继承关系(A≤B表示A是由B派生出来的子类),则有: + +- f()为逆变时,当A≤B时有f(B)≤f(A)成立。 + +- f()为协变时,当A≤B时有f(A)≤f(B)成立。 + +**ArkTS1.1** + +```typescript +// ArkTS1.1 +class A { + a: number = 0; +} +class B { + b: number = 0; +} + +class Base { + foo(obj: A | B): void {} +} +class Derived extends Base { + override foo(obj: A): void { // 可以覆写父类方法,ArkTS1.2编译错误 + console.info(obj.a.toString()); + } +} +``` + +**ArkTS1.2** + +```typescript +// ArkTS1.2 +class A { + a: number = 0; +} +class B { + b: number = 0; +} + +class Base { + foo(obj: A | B): void {} +} +class Derived extends Base { + override foo(obj: A | B): void { + if (obj instanceof A) { + console.info(obj.a.toString()); + } + } +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe321.md b/ets2panda/linter/docs/rules-cn/recipe321.md new file mode 100644 index 0000000000000000000000000000000000000000..bd8047302c4139a3541034dfb53cddda71a1f322 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe321.md @@ -0,0 +1,24 @@ +## taskpool不需要import + +**规则:** arkts-limited-stdlib-no-import-concurrency + +**级别:** error + +taskpool实现基于ArkTS提供,不依赖其他模块,不再需要import。 + +**ArkTS1.1** +```typescript +import { taskpool } from '@kit.ArkTS'; + +@Concurrent +function test() {} + +taskpool.execute(test); +``` + +**ArkTS1.2** +```typescript +function test() {} + +taskpool.execute(test); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe322.md b/ets2panda/linter/docs/rules-cn/recipe322.md new file mode 100644 index 0000000000000000000000000000000000000000..05e36074f78dded9c886e51f9eda0fbc061b7988 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe322.md @@ -0,0 +1,18 @@ +## 不提供isConcurrent接口 + +**规则:** arkts-limited-stdlib-no-support-isConcurrent + +**级别:** error + +新增对象天然共享特性,所有函数都是共享的,不需要提供isConcurrent。 + +**ArkTS1.1** +```typescript +import { taskpool } from '@kit.ArkTS'; +@Concurrent +function test() {} +let result: Boolean = taskpool.isConcurrent(test); +``` + +**ArkTS1.2** +不支持isConcurrent接口。 diff --git a/ets2panda/linter/docs/rules-cn/recipe323.md b/ets2panda/linter/docs/rules-cn/recipe323.md new file mode 100644 index 0000000000000000000000000000000000000000..be425c289d49ad32f4bbaec36cbe0670dde5eff1 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe323.md @@ -0,0 +1,35 @@ +### ArkTS1.2导出js实体 + +**规则:** arkts-interop-js2s-export-js + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.js +export function foo() {} +export class A {} + +// file2.ets +import { foo } from './file1'; +export { foo }; + +export { A } from './file1'; + +// 函数、类、变量、枚举 +``` + +**ArkTS1.2** +```typescript +// file1.js +export function foo() {} +export class A {} + +// file2.ets // ArkTS1.2 +'use static' +let mod = ESValue.load('./file1'); +let foo = mod.getProperty('foo'); +let A = mod.getProperty('A'); + +export { foo, A }; +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe325.md b/ets2panda/linter/docs/rules-cn/recipe325.md new file mode 100644 index 0000000000000000000000000000000000000000..74eefad55b4270e67585dc9c985c0a509cb9b84b --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe325.md @@ -0,0 +1,23 @@ +## 默认参数必须放在必选参数之后 + +**规则:**`arkts-default-args-behind-required-args` + +**级别:error** + +默认参数放在必选参数之前没有意义,ArkTS1.1上调用该接口时仍须传递每个默认参数。 + +**ArkTS1.1** + +```typescript +function add(left: number = 0, right: number) { + return left + right; +} +``` + +**ArkTS1.2** + +```typescript +function add(left: number, right: number) { + return left + right; +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe326.md b/ets2panda/linter/docs/rules-cn/recipe326.md new file mode 100644 index 0000000000000000000000000000000000000000..fb658ad34e112f86a87d3f1e10d8ceb6056d6dec --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe326.md @@ -0,0 +1,56 @@ +### ArkTS1.1创建ArkTS1.2对象字面量 + +**规则:** arkts-interop-s2d-object-literal + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.ets +export class X { + name: string = ''; + constructor(arg: string) { + this.name = arg; + } +} +export interface Y { + data: number; +} +export type MyRecord = Record; +export function foo(arg: X) {} +export function bar(arg: Y) {} + +// file2.ets +import { X, Y } from './file1'; +let x = { name: 'hello' }; +let y: Y = { data: 123 }; +foo({ name: 'world' }); +bar({ data: 456 }); +// 返回值 zoo(): X { return {..}} +// 嵌套场景 +interface Z { + x: X; +} +let z: Z = {x: { name: 'hello' }}; +``` + +**ArkTS1.2** +```typescript +// file1.ets ArkTS1.2 +'use static' +export class X { name: string = '' } +export interface Y { data: number } +export function foo(arg: X) { } +export function bar(arg: Y) { } +export function createY(d: number): Y { + let y: Y = { data: d } + return y +} + +// file2.ets ArkTS1.1 +import { X, Y, createY } from "./file1" +let x: X = new X("hello") +let y: Y = createY(123) +foo(new X("world")) +bar(createY(456)) +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe327.md b/ets2panda/linter/docs/rules-cn/recipe327.md new file mode 100644 index 0000000000000000000000000000000000000000..137301896d90742ecb270eb46dabceda3435b4c0 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe327.md @@ -0,0 +1,41 @@ +### ArkTS1.2创建ArkTS1.1具有二义性的对象字面量 + +**规则:** arkts-interop-d2s-object-literal-no-ambiguity + +**级别:** error + +当一个对象的类型被声明为联合类型,而右侧实际赋值的是一个类的实例时,会引发类型系统的二义性(对象可以是联合类型的任一类型,但实际运行时明确是一个类的实例,这种差异会导致类型检查或运行时的不确定性)。 + +**ArkTS1.1** +```typescript +// file1.ets +export class X { + name: string = ''; +} +export interface Y { + name: string; + age?: number; +} + +// file2.ets +import { X, Y } from './file1'; +let x: X | Y = { name: 'hello' }; +``` + +**ArkTS1.2** +```typescript +// file1.ets // 1.0 +export class X { + name: string = ''; +} +export interface Y { + name: string; + age?: number; +} + +// file2.ets // 1.2 +'use static' +import { X, Y } from './file1'; +let x: X | Y = { name: 'hello' }; //编译报错 +let x: X | Y = new X('hello'); // OK +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe328.md b/ets2panda/linter/docs/rules-cn/recipe328.md new file mode 100644 index 0000000000000000000000000000000000000000..58519c0b1482358a3c942c6793afc75c658f8821 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe328.md @@ -0,0 +1,34 @@ +### ArkTS1.2创建ArkTS1.1的没有无参构造函数的类的对象字面量 + +**规则:** arkts-interop-d2s-object-literal-no-args-constructor + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.ets +export class X { + name: string; + constructor(arg: string) { + this.name = arg; + } +} +// file2.ets +import { X } from './file1'; +let x = new X('hello'); +``` + +**ArkTS1.2** +```typescript +// file1.ets ArkTS1.1 +export class X { + name: string; + constructor(arg: string) { + this.name = arg; + } +} +// file2.ets ArkTS1.2 +'use static' +import { X } from './file1'; +let x: X = new X('hello') // 编译报错 +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe329.md b/ets2panda/linter/docs/rules-cn/recipe329.md new file mode 100644 index 0000000000000000000000000000000000000000..375cbbb6f75b3e3133492c2c7d224a022f9f0a71 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe329.md @@ -0,0 +1,35 @@ +## Enum不可以通过索引访问成员 + +**规则:**`arkts-enum-no-props-by-index` + +**级别:error** + +1. ArkTS1.1上已对索引访问元素的语法做了限制,ArkTS1.2对枚举场景增强约束。具体内容请参考[不支持通过索引访问字段](typescript-to-arkts-migration-guide.md#不支持通过索引访问字段)。 + +2. ArkTS1.1上枚举是动态对象,ArkTS1.2是静态类型,枚举具有运行时类型。为获得更高的性能,对[]访问做了限制。 + +**ArkTS1.1** + +```typescript +enum TEST { + A, + B, + C +} + +TEST['A']; // ArkTS1.2上不支持这种语法 +TEST[0]; // ArkTS1.2上不支持这种语法 +``` + +**ArkTS1.2** + +```typescript +enum TEST { + A, + B, + C +} + +TEST.A; // 使用.操作符或者enum的值 +TEST.A.getName(); // 使用enum对应的方法获取enum的key +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe330.md b/ets2panda/linter/docs/rules-cn/recipe330.md new file mode 100644 index 0000000000000000000000000000000000000000..a5d8149d1674b8ec56c34fff40775d0aa17b986a --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe330.md @@ -0,0 +1,25 @@ +### ArkTS1.2导入js文件 + +**规则:** arkts-interop-js2s-import-js + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.js +export function foo() {} + +// file2.ets +import { foo } from './file1'; +``` + +**ArkTS1.2** +```typescript +// file1.js +export function foo() {} + +// file2.ets // ArkTS1.2 +'use static' +let mod = ESValue.load('./file1'); +let foo = mod.getProperty('foo'); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe331.md b/ets2panda/linter/docs/rules-cn/recipe331.md new file mode 100644 index 0000000000000000000000000000000000000000..c25c8d537d2eacd49ef2979da4c77c166b222d2b --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe331.md @@ -0,0 +1,32 @@ +### ArkTS1.2调用js函数和传参 + +**规则:** arkts-interop-js2s-call-js-func + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.js +export function foo() {} +export function bar(a) {} + +// file2.ets +import { foo, bar } from './file1'; +foo(); +bar(123); +``` + +**ArkTS1.2** +```typescript +// file1.js +export function foo() {} +export function bar(a) {} + +// file2.ets // ArkTS1.2 +'use static' +let mod = ESValue.load('./file1'); +let foo = mod.getProperty('foo'); +let bar = mod.getProperty('bar'); +foo.invoke(); +bar.invoke(ESValue.wrap(123)); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe332.md b/ets2panda/linter/docs/rules-cn/recipe332.md new file mode 100644 index 0000000000000000000000000000000000000000..da8b232e283da1382e8473c51a3b68c002a0cfa0 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe332.md @@ -0,0 +1,28 @@ +### ArkTS1.2访问js属性 + +**规则:** arkts-interop-js2s-access-js-prop + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.js +export let foo = { name: '123' }; +// file2.ets +import { foo } from './file1'; +foo.name; +foo.name = '456'; +``` + +**ArkTS1.2** +```typescript +// file1.js +export let foo = {name: "123"} + +// file2.ets // ArkTS1.2 +'use static' +let mod = ESValue.load('./file1') +let foo = mod.getProperty('foo') +foo.getProperty('name') +foo.setProperty('name', ESValue.wrap("456")) +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe333.md b/ets2panda/linter/docs/rules-cn/recipe333.md new file mode 100644 index 0000000000000000000000000000000000000000..9b1da1e7467d65ff3fdbcb0a7cc792ca5b31658d --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe333.md @@ -0,0 +1,49 @@ +### ArkTS1.2转换js对象类型 + +**规则:** arkts-interop-js2s-convert-js-type + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.js +export let foo1 = { num: 123 }; +export let foo2 = { bool: true }; +export let foo3 = { str: '123' }; +export let foo4 = { big: 123n }; + +// file2.ets +import { foo } from './file1'; +let a: number = foo1.num as number; +let b: boolean = foo2.bool as boolean; +let c: string = foo3.str as string; +let d: bigint = foo4.big as bigint; +``` + +**ArkTS1.2** +```typescript +// file1.js +export let foo1 = { num: 123 }; +export let foo2 = { bool: true }; +export let foo3 = { str: '123' }; +export let foo4 = { big: 123n }; + +// file2.ets // ArkTS1.2 +'use static' +let mod = ESValue.load('./file1'); +let foo1 = mod.getProperty('foo1'); +let num = foo1.getProperty('num'); +let a1: number = num.toNumber(); + +let foo2 = mod.getProperty('foo2'); +let bool = foo2.getProperty('bool'); +let a2: boolean = bool.toBoolean(); + +let foo3 = mod.getProperty('foo3'); +let str = foo3.getProperty('str'); +let a3: string = str.toString(); + +let foo4 = mod.getProperty('foo4'); +let big = foo4.getProperty('big'); +let a4: bigint = big.toBigInt(); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe334.md b/ets2panda/linter/docs/rules-cn/recipe334.md new file mode 100644 index 0000000000000000000000000000000000000000..e713d8e4d5bd778e9ee9341bcbdd5b5feb52f666 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe334.md @@ -0,0 +1,29 @@ +### ArkTS1.2获取js对象类型 + +**规则:** arkts-interop-js2s-typeof-js-type + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.js +export let foo = { num: 123 }; + +// file2.ets +import { foo } from './file1'; +typeof foo.num; // 'number' +``` + +**ArkTS1.2** +```typescript +// file1.js +export let foo = 123; + +// file2.ets // ArkTS1.2 +'use static' +let mod = ESValue.load('./file1'); +let foo = mod.getProperty('foo'); +let num = foo.getProperty('num'); + +num.typeOf(); // 'number' +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe335.md b/ets2panda/linter/docs/rules-cn/recipe335.md new file mode 100644 index 0000000000000000000000000000000000000000..546ecc685bf33ecdd589cb1f4e55ec7ae5849ab8 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe335.md @@ -0,0 +1,37 @@ +### ArkTS1.2对js对象进行一元运算 + +**规则:** arkts-interop-js2s-unary-op + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.js +export let foo = { num: 0 }; +// file2.ets +import { foo } from './file1'; ++foo.num; +-foo.num; +!foo.num; +~foo.num; +``` + +**ArkTS1.2** +```typescript +// file1.js +export let foo = { num: 0 }; + +// file2.ets // ArkTS1.2 +'use static' +let mod = ESValue.load('./file1'); +let foo = mod.getProperty('foo'); +let num = foo.getProperty('num'); +// +foo.num ++num.toNumber(); +// -foo.num +-num.toNumber(); +// !foo.num +!num.toNumber(); +// ~foo.num +~num.toNumber(); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe336.md b/ets2panda/linter/docs/rules-cn/recipe336.md new file mode 100644 index 0000000000000000000000000000000000000000..c81548e27f860046072efb8eb30545984235ce43 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe336.md @@ -0,0 +1,41 @@ +### ArkTS1.2对js对象进行二元运算 + +**规则:** arkts-interop-js2s-binary-op + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.js +export let foo = { a: 1, b: 2 }; + +// file2.ets +import { foo } from './file1'; +let a = foo.a; +let b = foo.b; +a + b; +a - b; +a * b; +a / b; +a % b; +a ** b; +``` + +**ArkTS1.2** +```typescript +// file1.js +export let foo = { a: 1, b: 2 }; + +// file2.ets // ArkTS1.2 +'use static' +let mod = ESValue.load('./file1'); +let foo = mod.getProperty('foo'); +let a = foo.getProperty('a').toNumber(); +let b = foo.getProperty('b').toNumber(); +a + b; +a - b; +a * b; +a / b; +a % b; +a ** b; +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe337.md b/ets2panda/linter/docs/rules-cn/recipe337.md new file mode 100644 index 0000000000000000000000000000000000000000..125ac990e95cc73b35700949daab010a87c645bd --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe337.md @@ -0,0 +1,39 @@ +### ArkTS1.2对js数据进行比较 + +**规则:** arkts-interop-js2s-compare-js-data + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.js +export let foo = { a: 1, b: 2 }; + +// file2.ets +import { foo } from './file1'; +let a = foo.a; +let b = foo.b; +a > b; +a < b; +a >= b; +a <= b; +``` + +**ArkTS1.2** +```typescript +// file1.js +export let a = 1; +export let b = 2; + +// file2.ets // ArkTS1.2 +'use static' +let mod = ESValue.load('./file1'); +let foo = mod.getProperty('foo'); +let a = foo.getProperty('a').toNumber(); +let b = foo.getProperty('b').toNumber(); + +a > b; +a < b; +a >= b; +a <= b; +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe338.md b/ets2panda/linter/docs/rules-cn/recipe338.md new file mode 100644 index 0000000000000000000000000000000000000000..7db945140c6d5d167b183229f6c2ff44008be2ac --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe338.md @@ -0,0 +1,39 @@ +### ArkTS1.2对js数据进行相等判断 + +**规则:** arkts-interop-js2s-equality-judgment + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.js +class A {} +export let a = new A(); +export let b = new A(); + +// file2.ets +import { a, b } from './file1'; +a == b; +a != b; +a === b; +a !== b; +``` + +**ArkTS1.2** +```typescript +// file1.js +class A {} +export let a = new A(); +export let b = new A(); + +// file2.ets // ArkTS1.2 +'use static' +let mod = ESValue.load('./file1'); +let a = mod.getProperty('a'); +let b = mod.getProperty('b'); + +a.isEqualTo(b); +!a.isEqualTo(b); +a.isStrictlyEqualTo(b); +!a.isStrictlyEqualTo(b); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe339.md b/ets2panda/linter/docs/rules-cn/recipe339.md new file mode 100644 index 0000000000000000000000000000000000000000..929aadf9c2a260791f69f772730e1c5a25997451 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe339.md @@ -0,0 +1,30 @@ +### ArkTS1.2访问js索引 + +**规则:** arkts-interop-js2s-access-js-index + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.js +export let foo = { arr: [1, 2, 3] }; +// file2.ets +import { foo } from './file1'; +let arr = foo.arr; +arr[1]; +arr[3] = 4; +``` + +**ArkTS1.2** +```typescript +// file1.js +export let foo = [1, 2, 3]; + +// file2.ets // ArkTS1.2 +'use static' +let mod = ESValue.load('./file1'); +let foo = mod.getProperty('foo'); +let arr = foo.getProperty('arr'); +arr.getProperty(1); +arr.setProperty(3, ESValue.wrap(4)); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe34.md b/ets2panda/linter/docs/rules-cn/recipe34.md new file mode 100644 index 0000000000000000000000000000000000000000..85ff8aa03dcd353d140ccf72949ad79536cdb36c --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe34.md @@ -0,0 +1,34 @@ +## 创建泛型实例需要类型实参 + +**规则:**`arkts-no-inferred-generic-params` + +**级别:error** + +ArkTS1.2中,创建泛型实例时需要类型实参。 + +**ArkTS1.1** + +```typescript +new Array() // 违反规则 + +new Map(); // 违反规则 + +class Box { + value: T; + constructor(value: T) { + this.value = value; + } +} + +let box = new Box(42); // 违反规则 +``` + +**ArkTS1.2** + +```typescript +new Array() // 指定类型 + +new Map(); // 显式指定键值类型 + +let box = new Box(42); // 明确指定类型 +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe340.md b/ets2panda/linter/docs/rules-cn/recipe340.md new file mode 100644 index 0000000000000000000000000000000000000000..4aed1d919801b9b6ce1680c09f2de663eb8d7978 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe340.md @@ -0,0 +1,34 @@ +### ArkTS1.2 await js Promise对象 + +**规则:** arkts-interop-js2s-await-js-promise + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.js +async function foo(){} +export let p = foo() + +// file2.ets +import {p} from "./file1" +async function bar() { + await p.toPromise(); +} +``` + +**ArkTS1.2** +```typescript +// file1.js +async function foo(){} +export let p = foo() + +// file2.ets // ArkTS1.2 +'use static' +let mod = ESValue.load('./file1') +let p = mod.getProperty('p') + +async function bar() { + await p.toPromise(); +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe341.md b/ets2panda/linter/docs/rules-cn/recipe341.md new file mode 100644 index 0000000000000000000000000000000000000000..15ba9c732fd1696b5590b5fd9b58882f3779459c --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe341.md @@ -0,0 +1,30 @@ +### ArkTS1.2实例化js对象 + +**规则:** arkts-interop-js2s-create-js-instance + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.js +class foo { + constructor(a) {} +} +// file2.ets +import { foo } from './file1'; +new foo(123); +``` + +**ArkTS1.2** +```typescript +// file1.js +class foo { + constructor(a) {} +} + +// file2.ets // ArkTS1.2 +'use static' +let mod = ESValue.load('./file1'); +let foo = mod.getProperty('foo'); +foo.instantiate(ESValue.wrap(123)); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe342.md b/ets2panda/linter/docs/rules-cn/recipe342.md new file mode 100644 index 0000000000000000000000000000000000000000..8c0b819f4e1f5250c8a8a766d10894f2b9ae295a --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe342.md @@ -0,0 +1,31 @@ +### ArkTS1.2调用js方法和传参 + +**规则:** arkts-interop-js2s-call-js-method + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.js +class Foo { + bar(a) {} +} +export let foo = new Foo(); +// file2.ets +import { foo } from './file1'; +foo.bar(123); +``` + +**ArkTS1.2** +```typescript +// file1.js +class Foo { + bar(a) {} +} + +// file2.ets // ArkTS1.2 +'use static' +let mod = ESValue.load('./file1'); +let foo = mod.getProperty('foo'); +foo.invokeMethod('bar', ESValue.wrap(123)); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe343.md b/ets2panda/linter/docs/rules-cn/recipe343.md new file mode 100644 index 0000000000000000000000000000000000000000..513a10a46371df09a2de3ee792b547d03b179314 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe343.md @@ -0,0 +1,31 @@ +### ArkTS1.2判断js对象类型 + +**规则:** arkts-interop-js2s-instanceof-js-type + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.js +export class Foo {} +export let foo = new Foo(); + +// file2.ets +import { Foo, foo } from './file1'; +foo instanceof Foo; +``` + +**ArkTS1.2** +```typescript +// file1.js +export class Foo {} +export let foo = new Foo(); + +// file2.ets // ArkTS1.2 +'use static' +let mod = ESValue.load('./file1'); +let Foo = mod.getProperty('Foo'); +let foo = mod.getProperty('foo'); + +foo.isInstanceOf(Foo); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe344.md b/ets2panda/linter/docs/rules-cn/recipe344.md new file mode 100644 index 0000000000000000000000000000000000000000..1797cfc140be9267235b1de395404fc8a2f1349f --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe344.md @@ -0,0 +1,46 @@ +### ArkTS1.2对js对象自增自减 + +**规则:** arkts-interop-js2s-self-addtion-reduction + +**级别:** error + +**ArkTS1.1** +```typescript +// file1.js +export let foo = { num: 0 }; + +// file2.ets +import { foo } from './file1'; +let a: number = 0; +a = foo.num++; +a = ++foo.num; +a = foo.num--; +a = --foo.num; +``` + +**ArkTS1.2** +```typescript +// file1.js +export let foo = { num: 0 }; + +// file2.ets // ArkTS1.2 +'use static' +let mod = ESValue.load('./file1'); +let foo = mod.getProperty('foo'); +let a: number = 0; + +// a = foo.num++ +let num = foo.getProperty('num'); +let tmp: number = num.toNumber(); +a = tmp; +foo.setProperty('num', ESValue(tmp + 1)); + +// a = ++foo.num + +num = foo.getProperty('num'); +tmp = num.toNumber() + 1; +foo.setProperty('num', ESValue(tmp)); +a = tmp; + +// the cases "foo.num--" and "--foo.num" are similar +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe349.md b/ets2panda/linter/docs/rules-cn/recipe349.md new file mode 100644 index 0000000000000000000000000000000000000000..792ea62fea9afbb43aebaf87a54c14ded688c66b --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe349.md @@ -0,0 +1,19 @@ +## 内存默认共享,不提供SharedArrayBuffer + +**规则:** arkts-no-need-stdlib-sharedArrayBuffer + +**级别:** error + +新增对象天然共享特性,ArrayBuffer默认共享,不需要SharedArrayBuffer。 + +**ArkTS1.1** +```typescript +let sab: SharedArrayBuffer = new SharedArrayBuffer(20); +let int32 = new Int32Array(sab); +``` + +**ArkTS1.2** +```typescript +let sab: ArrayBuffer = new ArrayBuffer(20); +let int32 = new Int32Array(sab); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe350.md b/ets2panda/linter/docs/rules-cn/recipe350.md new file mode 100644 index 0000000000000000000000000000000000000000..f28e758abddae553171cddcb30855d1e2ac177a5 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe350.md @@ -0,0 +1,55 @@ +## 移除taskpool setCloneList接口 + +**规则:** arkts-limited-stdlib-no-setCloneList + +**级别:** error + +内存默认共享,不需要提供setCloneList来拷贝传递对象。 + +**ArkTS1.1** +```typescript +import { taskpool } from '@kit.ArkTS'; + +@Sendable +class BaseClass { + public str: string = 'sendable: BaseClass'; +} + +@Concurrent +function testFunc(array: Array) { + let baseInstance = array[0]; + console.info('sendable: str1 is: ' + baseInstance.str); + return baseInstance.str; +} + +let baseInstance: BaseClass = new BaseClass(); +let array = new Array(); +array.push(baseInstance); +let task = new taskpool.Task(testFunc, array); +task.setCloneList(array); +taskpool.execute(task).then((res: Object):void => { + console.info('sendable: task res is: ' + res) +}); +``` + +**ArkTS1.2** +```typescript +class BaseClass { + public str: string = 'BaseClass'; +} + +function testFunc(array: Array) { + let baseInstance = array[0]; + console.info('str1 is: ' + baseInstance.str); + return baseInstance.str; +} + + +let baseInstance: BaseClass = new BaseClass(); +let array = new Array(); +array.push(baseInstance); +let task = new taskpool.Task(testFunc, array); +taskpool.execute(task).then((res: NullishType):void => { + console.info('task res is: ' + res) +}); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe351.md b/ets2panda/linter/docs/rules-cn/recipe351.md new file mode 100644 index 0000000000000000000000000000000000000000..bd95ad170bf09a2c8c853d24a2d72d2666db1e8f --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe351.md @@ -0,0 +1,68 @@ +## 移除taskpool setTransferList接口 + +**规则:** arkts-limited-stdlib-no-setTransferList + +**级别:** error + +内存默认共享,不需要提供setTransferList来跨线程传递ArrayBuffer对象。 + +**ArkTS1.1** +```typescript +import { taskpool } from '@kit.ArkTS'; + +@Concurrent +function testTransfer(arg1: ArrayBuffer, arg2: ArrayBuffer): number { + console.info('testTransfer arg1 byteLength: ' + arg1.byteLength); + console.info('testTransfer arg2 byteLength: ' + arg2.byteLength); + return 100; +} + +let buffer: ArrayBuffer = new ArrayBuffer(8); +let view: Uint8Array = new Uint8Array(buffer); +let buffer1: ArrayBuffer = new ArrayBuffer(16); +let view1: Uint8Array = new Uint8Array(buffer1); + +console.info('testTransfer view byteLength: ' + view.byteLength); +console.info('testTransfer view1 byteLength: ' + view1.byteLength); +// 执行结果为: +// testTransfer view byteLength: 8 +// testTransfer view1 byteLength: 16 + +let task: taskpool.Task = new taskpool.Task(testTransfer, view, view1); +task.setTransferList([view.buffer, view1.buffer]); +taskpool.execute(task).then((res: Object) => { + console.info('test result: ' + res); +}).catch((e: string) => { + console.error('test catch: ' + e); +}) +console.info('testTransfer view2 byteLength: ' + view.byteLength); +console.info('testTransfer view3 byteLength: ' + view1.byteLength); +// 经过transfer转移之后值为0,执行结果为: +// testTransfer view2 byteLength: 0 +// testTransfer view3 byteLength: 0 +``` + +**ArkTS1.2** +```typescript +function testTransfer(arg1: Uint8Array, arg2: Uint8Array): number { + console.info('testTransfer arg1 byteLength: ' + arg1.byteLength); + console.info('testTransfer arg2 byteLength: ' + arg2.byteLength); + return 100.0; +} + +let buffer: ArrayBuffer = new ArrayBuffer(8); +let view: Uint8Array = new Uint8Array(buffer); +let buffer1: ArrayBuffer = new ArrayBuffer(16); +let view1: Uint8Array = new Uint8Array(buffer1); + +let task: taskpool.Task = new taskpool.Task(testTransfer, view, view1); +taskpool.execute(task).then((res: NullishType):void => { + console.info('test result: ' + res); +}).catch((e: Error): void => { + console.error('test catch: ' + e); +}) +// 内存共享,此处可直接访问view,view1的内容,不需要使用setTransferList +// 执行结果为: +// testTransfer arg1 byteLength: 8 +// testTransfer arg2 byteLength: 16 +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe355.md b/ets2panda/linter/docs/rules-cn/recipe355.md new file mode 100644 index 0000000000000000000000000000000000000000..ae7a8b470b828f703eaf3084096e81cf65c89aa5 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe355.md @@ -0,0 +1,18 @@ +## 共享对象不添加装饰器@Sendable + +**规则:** arkts-limited-stdlib-no-sendable-decorator + +**级别:** error + +新增对象天然共享特性,不再依赖Sendable特性,无需添加@Sendable装饰器。 + +**ArkTS1.1** +```typescript +@Sendable +class A {} +``` + +**ArkTS1.2** +```typescript +class A {} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe356.md b/ets2panda/linter/docs/rules-cn/recipe356.md new file mode 100644 index 0000000000000000000000000000000000000000..453b81ec8d4c888300fbe863fedf4a429b8b9a28 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe356.md @@ -0,0 +1,18 @@ +## 共享函数不添加装饰器@Concurrent + +**规则:** arkts-limited-stdlib-no-concurrent-decorator + +**级别:** error + +新增对象天然共享特性,不再依赖Concurrent特性,无需添加@Concurrent装饰器。 + +**ArkTS1.1** +```typescript +@Concurrent +function func() {} +``` + +**ArkTS1.2** +```typescript +function func() {} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe357.md b/ets2panda/linter/docs/rules-cn/recipe357.md new file mode 100644 index 0000000000000000000000000000000000000000..ab498bbf0bb557831d552f405d30d20e87a30edc --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe357.md @@ -0,0 +1,24 @@ +## 不支持Worker + +**规则:** arkts-no-need-stdlib-worker + +**级别:** error + +内存天然共享,不需要基于Actor模型实现ThreadWorker。使用ArkTS1.2提供的新线程api-EAWorker。 + +**ArkTS1.1** +```typescript +import { worker } from '@kit.ArkTS'; + +const workerInstance: worker.ThreadWorker = new worker.ThreadWorker('entry/ets/workers/Worker.ets') +``` + +**ArkTS1.2** +```typescript +let eaw = new EAWorker(); +eaw.run(():void => { + console.info('hello, eaworker!'); +}); + +eaw.join(); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe37.md b/ets2panda/linter/docs/rules-cn/recipe37.md new file mode 100644 index 0000000000000000000000000000000000000000..24a573c8b6a4c1ff201bbdcf4276facc18789f31 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe37.md @@ -0,0 +1,40 @@ +## 不支持正则表达式 + +**规则:**`arkts-no-regexp-literals` + +**级别:error** + +ArkTS1.2不支持正则表达式字面量。 + +**ArkTS1.1** + +```typescript +let regex: RegExp = /bc*d/; +let regex = /\d{2,4}-\w+/g; // 违反规则 +function matchPattern(str: string) { + return str.match(/hello\s+world/i); // 违反规则 +} + +let text = "Hello world!"; +let result = text.replace(/world/, "ArkTS"); // 违反规则 + +let items = "apple,banana, cherry".split(/\s*,\s*/); // 违反规则 +``` + +**ArkTS1.2** + +```typescript +let regex: RegExp = new RegExp('bc*d'); +let regex = new RegExp('\\d{2,4}-\\w+', 'g'); // 使用 `RegExp` 类 +function matchPattern(str: string) { + let regex = new RegExp('hello\\s+world', 'i'); // 使用 `RegExp` + return str.match(regex); +} + +let text = "Hello world!"; +let regex = new RegExp('world'); // 使用 `RegExp` 类 +let result = text.replace(regex, "ArkTS"); + +let regex = new RegExp('\\s*,\\s*'); // 使用 `RegExp` +let items = "apple,banana, cherry".split(regex); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe370.md b/ets2panda/linter/docs/rules-cn/recipe370.md new file mode 100644 index 0000000000000000000000000000000000000000..1e974f94fafb759dd5e57250e5948d461f0b1bb0 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe370.md @@ -0,0 +1,26 @@ +## 不支持空数组/稀疏数组 + +**规则:**`arkts-no-sparse-array` + +**级别:error** + +1. ArkTS1.2遵循静态类型,空数组需要能根据上下文推导出数组元素的类型,否则会有编译错误。 + +2. ArkTS1.2的数组是连续存储的,空位(如 [1, , , 2])会浪费内存。‌ + +3. ArkTS1.2遵循空值安全,无法使用默认undefined表示空缺。 + +**ArkTS1.1** + +```typescript +let a = []; // ArkTS1.2,编译错误,需要从上下文中推导数组类型 +let b = [1, , , 2]; // 不支持数组中的空位 +b[1]; // undefined +``` + +**ArkTS1.2** + +```typescript +let a: number[] = []; // 支持,ArkTS1.2上可以从上下文推导出类型 +let b = [1, undefined, undefined, 2]; +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe371.md b/ets2panda/linter/docs/rules-cn/recipe371.md new file mode 100644 index 0000000000000000000000000000000000000000..35094b1d9578581007d2075e7a22b4cfc5582d0f --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe371.md @@ -0,0 +1,25 @@ +## enum的元素不能作为类型 + +**规则:**`arkts-no-enum-prop-as-type` + +**级别:error** + +ArkTS1.1上的枚举是编译时概念,在运行时仍是普通对象。ArkTS1.2遵循静态类型,需要在运行时为enum提供类型。因此,ArkTS1.2上枚举的每个元素是枚举类的实例(在运行时才确定),无法成为编译时的静态类型信息。这与ArkTS1.2整体类型设计上不支持实例类型相违背。 + +**ArkTS1.1** + +```typescript +enum A { E = 'A' } +function foo(a: A.E) {} +``` + +**ArkTS1.2** + +```typescript +enum A { E = 'A' } +function foo(a: 'A') {} + +// ... +enum A { E = 'A' } +function foo(a: A) {} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe372.md b/ets2panda/linter/docs/rules-cn/recipe372.md new file mode 100644 index 0000000000000000000000000000000000000000..3e966558830bc3f948313cc9cbea64bc523a7000 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe372.md @@ -0,0 +1,41 @@ +## 不支持编译阶段根据PromiseSettledResult的status值确定其实际类型 + +**规则:** arkts-not-support-PromiseSettledResult-smartcast + +**级别:** error + +arkts1.2中不支持对类的成员变量进行智能转换(智能类型差异arkts-no-ts-like-smart-type)。 + +**智能转换:** 编译器会在某些场景下(如instanceof、null检查、上下文推导等)识别出对象的具体类型,自动将变量转换为相应类型,而无需手动转换。 + +**ArkTS1.1** +```typescript +let f1 = Promise.resolve('fulfilled 1'); +Promise.allSettled([f1]) + .then((results: PromiseSettledResult[]) => { + results.forEach((result: PromiseSettledResult) => { + if (result.status === 'fulfilled') { + console.log(`${result.value} `); + } else { + console.log(`${result.reason.message} `); + } + }); + }) +``` + +**ArkTS1.2** +```typescript +let f1 = Promise.resolve('fulfilled 1'); +Promise.allSettled([f1]) + .then((results: PromiseSettledResult[]) => { + results.forEach((result: PromiseSettledResult) => { + if (result.status === 'fulfilled') { + let result1 = result as PromiseFulfilledResult; + console.log(result1.value); + } else { + let result1 = result as PromiseRejectedResult; + console.log(result1.reason.message); + } + }); + }) +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe373.md b/ets2panda/linter/docs/rules-cn/recipe373.md new file mode 100644 index 0000000000000000000000000000000000000000..581e9430b1c4f002a84d8c676c47cf1cae3b1fad --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe373.md @@ -0,0 +1,39 @@ +## 数组/元组类型在继承关系中遵循不变性原则 + +**规则:**`arkts-array-type-immutable` + +**级别:error** + +ArkTS1.2上数组在继承关系中遵循不变性原则,可以通过编译时检查保证类型安全,将潜在的运行时错误提前到编译期,避免运行时失败,从而提高执行性能。 + +**ArkTS1.1** + +```typescript +class A { + a: number = 0; +} + +class B { + b: number = 0; +} + +// ArkTS1.1 +let arr1: A[] = [new A()]; +let arr2: (A | B)[] = arr1; // ArkTS1.2编译错误 +``` + +**ArkTS1.2** + +```typescript +class A { + a: number = 0; +} + +class B { + b: number = 0; +} + +// ArkTS1.2 +let arr1: [ A | B ] = [new A()]; +let arr2: [ A | B ] = arr1; // 需要相同类型的元组 +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe374.md b/ets2panda/linter/docs/rules-cn/recipe374.md new file mode 100644 index 0000000000000000000000000000000000000000..32d237362a7193c2a06f6fc675cc6c3d821a0276 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe374.md @@ -0,0 +1,27 @@ +## new Number/Boolean/String不再是"object"类型 + +**规则:**`arkts-primitive-type-normalization` + +**级别:error** + +1. 在ArkTS1.2中primitive type和boxed type是相同的类型,这样可以提高语言一致性和性能。 + 比较Number/Boolean/String时比较的是值而不是对象。 + +2. 在ArkTS1.1上,boxed类型通过new创建。在获取其类型、比较boxed类型对象时会产生意外行为,这是因为对象比较时是通过引用进行比较,而不是值。通常直接使用primitive + type性能更高效,内存占用更少(相比之下对象会占用更多内存)。 + +**ArkTS1.1** + +```typescript +typeof new Number(1) // 结果: "object" +new Number(1) == new Number(1);  //结果: false +if (new Boolean(false)) {} // 在if语句中new Boolean(false)为true +``` + +**ArkTS1.2** + +```typescript +typeof new Number(1)// 结果: "number" +new Number(1) == new Number(1);  //结果: true +if (new Boolean(false)) {} // 在if语句中new Boolean(false)为false +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe375.md b/ets2panda/linter/docs/rules-cn/recipe375.md new file mode 100644 index 0000000000000000000000000000000000000000..f3453ed62789eb250942286056ae085e02be233f --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe375.md @@ -0,0 +1,31 @@ +## catch语句中是error类型 + +**规则:**`arkts-no-ts-like-catch-type` + +**级别:error** + +在ArkTS1.1上catch语句中的e是any类型。因此,编译器不会对catch语句中的异常进行编译时类型检查。当ArkTS1.1上限制throw时,只能抛出Error类型。 + +在ArkTS1.2的静态模式中,类型必须明确,同时需考虑与ArkTS1.1的兼容性。对于catch(e)的语法,默认e为Error类型。 + +**ArkTS1.1** + +```typescript +try { + throw new Error(); +} catch(e) { // e是any类型 + e.message; // ArkTS1.1编译通过,运行正常 + e.prop; // ArkTS1.1编译通过,输出undefined +} +``` + +**ArkTS1.2** + +```typescript +try { + throw new Error(); +} catch(e:Error) { // e是Error类型 + e.message; // ArkTS1.2编译通过,运行正常 + e.prop; // ArkTS1.2编译错误,需要将e转换成需要处理的异常类型,例如:(e as SomeError).prop +} +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe376.md b/ets2panda/linter/docs/rules-cn/recipe376.md new file mode 100644 index 0000000000000000000000000000000000000000..40ad96807f5efbd4b1f4ef3b6986b492c0cfe931 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe376.md @@ -0,0 +1,29 @@ +## 数值类型和bigint类型的比较 + +**规则:**`arkts-numeric-bigint-compare` + +**级别:error** + + 当前暂不支持数值类型和bigint类型的比较,迁移工具将提示开发者修改源码,不提供自动修复能力。 + +**ArkTS1.1** + +```typescript +let n1: number = 123; +let n2: bigint = 456n; + +n1 <= n2; // 编译通过 +n1 == n2; // 编译失败 +n1 >= n2; // 编译通过 +``` + +**ArkTS1.2** + +```typescript +let n1: number = 123; +let n2: bigint = 456n; + +BigInt(n1) <= n2; +BigInt(n1) == n2; +BigInt(n1) >= n2; +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe377.md b/ets2panda/linter/docs/rules-cn/recipe377.md new file mode 100644 index 0000000000000000000000000000000000000000..8e6437bb920f871a8a686701987c9c7385a07ad1 --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe377.md @@ -0,0 +1,23 @@ +## 非十进制bigint字面量 + +**规则:**`arkts-only-support-decimal-bigint-literal` + +**级别:error** + + 当前暂不支持非十进制bigint字面量,通过迁移工具提示开发者修改源码,不提供自动修复能力。 + +**ArkTS1.1** + +```typescript +let a1: bigint = 0xBAD3n; // 十六进制字面量,ArkTS1.2暂不支持 +let a2: bigint = 0o777n; // 八进制字面量,ArkTS1.2暂不支持 +let a3: bigint = 0b101n; // 二进制字面量,ArkTS1.2暂不支持 +``` + +**ArkTS1.2** + +```typescript +let a1: bigint = BigInt(0xBAD3); +let a2: bigint = BigInt(0o777); +let a3: bigint = BigInt(0b101); +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe378.md b/ets2panda/linter/docs/rules-cn/recipe378.md new file mode 100644 index 0000000000000000000000000000000000000000..529097ba0f970f10434b461071bffb93f39efd5b --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe378.md @@ -0,0 +1,25 @@ +## 不支持逻辑赋值运算 + +**规则:**`arkts-unsupport-operator` + +**级别:error** + +1. 当前暂不支持&&=, ||=, ??=逻辑赋值运算符,通过迁移工具提示开发者修改源码,不提供自动修复能力。 + +**ArkTS1.1** + +```typescript +let a = 1; +a &&= 2; // 结果: 2,ArkTS1.2暂不支持 +a ||= 3; // 结果: 2,ArkTS1.2暂不支持 +a ??= 4; // 结果: 2,ArkTS1.2暂不支持 +``` + +**ArkTS1.2** + +```typescript +let a = 1; +a = a && 2; // 结果: 2 +a = a || 3; // 结果: 2 +a = a ?? 4; // 结果: 2 +``` diff --git a/ets2panda/linter/docs/rules-cn/recipe382.md b/ets2panda/linter/docs/rules-cn/recipe382.md new file mode 100644 index 0000000000000000000000000000000000000000..f39e4f8c8ebde25d56e98a336026d23088cd37aa --- /dev/null +++ b/ets2panda/linter/docs/rules-cn/recipe382.md @@ -0,0 +1,25 @@ +## Promise\构造器中只支持使用resolve(undefined) + +**规则:** arkts-promise-with-void-type-need-undefined-as-resolve-arg + +**级别:** error + +ArkTS1.2中void不能作为变量类型声明;作为泛型时,在类实例化时会自动转换为undefined。 +**ArkTS1.1** +```typescript +let p1 = new Promise((resolve, reject) => { + resolve(); +}) +let p2 = new Promise((resolve, reject) => { + setTimeout(resolve, 10); +}) +``` + +**ArkTS1.2** +```typescript +let p1 = new Promise((resolve, reject) => { + resolve(); +}) +let p2 = new Promise((resolve, reject) => { + setTimeout(() => {resolve(undefined)}, 10); +}) \ No newline at end of file diff --git a/ets2panda/linter/package.json b/ets2panda/linter/package.json index 79b9616cacddffea520e2f4b40a491ba4737a2cf..40daf9b4c9d35420967ced60799d2274f5a2a1cb 100644 --- a/ets2panda/linter/package.json +++ b/ets2panda/linter/package.json @@ -4,7 +4,7 @@ "main": "dist/tslinter.js", "bin": "bin/tslinter.js", "files": [ - "dist/*","rule-config.json" + "dist/*","rule-config.json","docs/rules-cn/*" ], "private": true, "license": "Apache-2.0",