From ed1fca3adf7c3f4080785c529f4647f65b430447 Mon Sep 17 00:00:00 2001 From: Nazarov Konstantin Date: Tue, 26 Sep 2023 16:40:12 +0300 Subject: [PATCH 1/2] [arkts-linter] add flags to process js imports from special folders Signed-off-by: Nazarov Konstantin --- linter-4.2/src/CompilerWrapper.ts | 8 +++++++- linter-4.2/test/interop_import.ts | 14 ++++++++++++++ linter-4.2/test/interop_import.ts.relax.json | 16 +++++++++++++++- linter-4.2/test/interop_import.ts.strict.json | 16 +++++++++++++++- linter/src/ts-compiler/FormTscOptions.ts | 8 +++++++- linter/test/interop_import.ts | 14 ++++++++++++++ linter/test/interop_import.ts.relax.json | 16 +++++++++++++++- linter/test/interop_import.ts.strict.json | 16 +++++++++++++++- 8 files changed, 102 insertions(+), 6 deletions(-) diff --git a/linter-4.2/src/CompilerWrapper.ts b/linter-4.2/src/CompilerWrapper.ts index fd1ed25e9..99c7ea86c 100644 --- a/linter-4.2/src/CompilerWrapper.ts +++ b/linter-4.2/src/CompilerWrapper.ts @@ -57,7 +57,13 @@ function formTscOptions(cmdOptions: CommandLineOptions, extraOptions?: any): ts. let options: ts.CreateProgramOptions = { rootNames: cmdOptions.inputFiles, - options: { target: ts.ScriptTarget.Latest, module: ts.ModuleKind.CommonJS, checkJs: true }, + options: { + target: ts.ScriptTarget.Latest, + module: ts.ModuleKind.CommonJS, + allowJs: true, + checkJs: true, + maxNodeModuleJsDepth: 2 + }, }; if (extraOptions) { diff --git a/linter-4.2/test/interop_import.ts b/linter-4.2/test/interop_import.ts index 12a5e6ed4..9dfe68a0c 100644 --- a/linter-4.2/test/interop_import.ts +++ b/linter-4.2/test/interop_import.ts @@ -19,6 +19,8 @@ import { CNode } from "./node_modules/node_import"; import { COh } from "./oh_modules/oh_import"; import { CGood } from "./ignore_files/good"; import { CHvigor } from "./ignore_files/hvigorfile"; +import { Cjs2 } from "./node_modules/2"; +import { Cjs1 } from "./node_modules/node_lib1/1"; CPreview.prototype; CBuild.prototype; @@ -26,3 +28,15 @@ CNode.prototype; COh.prototype; CGood.prototype; CHvigor.prototype; +Cjs1.prototype; +Cjs2.prototype; + +class B { + f: number = 1; +} + +let cjs1 = new Cjs1(); +let f1: B = cjs1; + +let cjs2 = new Cjs2(); +let f2: B = cjs2; diff --git a/linter-4.2/test/interop_import.ts.relax.json b/linter-4.2/test/interop_import.ts.relax.json index 4a0fd4f54..83b1603cf 100644 --- a/linter-4.2/test/interop_import.ts.relax.json +++ b/linter-4.2/test/interop_import.ts.relax.json @@ -15,11 +15,25 @@ ], "nodes": [ { - "line": 27, + "line": 29, "column": 7, "problem": "Prototype", "suggest": "", "rule": "Prototype assignment is not supported (arkts-no-prototype-assignment)" + }, + { + "line": 39, + "column": 5, + "problem": "StructuralIdentity", + "suggest": "", + "rule": "Structural typing is not supported (arkts-no-structural-typing)" + }, + { + "line": 42, + "column": 5, + "problem": "StructuralIdentity", + "suggest": "", + "rule": "Structural typing is not supported (arkts-no-structural-typing)" } ] } diff --git a/linter-4.2/test/interop_import.ts.strict.json b/linter-4.2/test/interop_import.ts.strict.json index 4a0fd4f54..83b1603cf 100644 --- a/linter-4.2/test/interop_import.ts.strict.json +++ b/linter-4.2/test/interop_import.ts.strict.json @@ -15,11 +15,25 @@ ], "nodes": [ { - "line": 27, + "line": 29, "column": 7, "problem": "Prototype", "suggest": "", "rule": "Prototype assignment is not supported (arkts-no-prototype-assignment)" + }, + { + "line": 39, + "column": 5, + "problem": "StructuralIdentity", + "suggest": "", + "rule": "Structural typing is not supported (arkts-no-structural-typing)" + }, + { + "line": 42, + "column": 5, + "problem": "StructuralIdentity", + "suggest": "", + "rule": "Structural typing is not supported (arkts-no-structural-typing)" } ] } diff --git a/linter/src/ts-compiler/FormTscOptions.ts b/linter/src/ts-compiler/FormTscOptions.ts index 7b89e3593..dc7a04d18 100644 --- a/linter/src/ts-compiler/FormTscOptions.ts +++ b/linter/src/ts-compiler/FormTscOptions.ts @@ -31,7 +31,13 @@ export function formTscOptions(cmdOptions: CommandLineOptions, extraOptions?: an } let options: ts.CreateProgramOptions = { rootNames: cmdOptions.inputFiles, - options: { target: ts.ScriptTarget.Latest, module: ts.ModuleKind.CommonJS, checkJs: true }, + options: { + target: ts.ScriptTarget.Latest, + module: ts.ModuleKind.CommonJS, + allowJs: true, + checkJs: true, + maxNodeModuleJsDepth: 2 + }, }; if (extraOptions) { options.options = Object.assign(options.options, extraOptions); diff --git a/linter/test/interop_import.ts b/linter/test/interop_import.ts index 12a5e6ed4..9dfe68a0c 100644 --- a/linter/test/interop_import.ts +++ b/linter/test/interop_import.ts @@ -19,6 +19,8 @@ import { CNode } from "./node_modules/node_import"; import { COh } from "./oh_modules/oh_import"; import { CGood } from "./ignore_files/good"; import { CHvigor } from "./ignore_files/hvigorfile"; +import { Cjs2 } from "./node_modules/2"; +import { Cjs1 } from "./node_modules/node_lib1/1"; CPreview.prototype; CBuild.prototype; @@ -26,3 +28,15 @@ CNode.prototype; COh.prototype; CGood.prototype; CHvigor.prototype; +Cjs1.prototype; +Cjs2.prototype; + +class B { + f: number = 1; +} + +let cjs1 = new Cjs1(); +let f1: B = cjs1; + +let cjs2 = new Cjs2(); +let f2: B = cjs2; diff --git a/linter/test/interop_import.ts.relax.json b/linter/test/interop_import.ts.relax.json index 4a0fd4f54..83b1603cf 100644 --- a/linter/test/interop_import.ts.relax.json +++ b/linter/test/interop_import.ts.relax.json @@ -15,11 +15,25 @@ ], "nodes": [ { - "line": 27, + "line": 29, "column": 7, "problem": "Prototype", "suggest": "", "rule": "Prototype assignment is not supported (arkts-no-prototype-assignment)" + }, + { + "line": 39, + "column": 5, + "problem": "StructuralIdentity", + "suggest": "", + "rule": "Structural typing is not supported (arkts-no-structural-typing)" + }, + { + "line": 42, + "column": 5, + "problem": "StructuralIdentity", + "suggest": "", + "rule": "Structural typing is not supported (arkts-no-structural-typing)" } ] } diff --git a/linter/test/interop_import.ts.strict.json b/linter/test/interop_import.ts.strict.json index 4a0fd4f54..83b1603cf 100644 --- a/linter/test/interop_import.ts.strict.json +++ b/linter/test/interop_import.ts.strict.json @@ -15,11 +15,25 @@ ], "nodes": [ { - "line": 27, + "line": 29, "column": 7, "problem": "Prototype", "suggest": "", "rule": "Prototype assignment is not supported (arkts-no-prototype-assignment)" + }, + { + "line": 39, + "column": 5, + "problem": "StructuralIdentity", + "suggest": "", + "rule": "Structural typing is not supported (arkts-no-structural-typing)" + }, + { + "line": 42, + "column": 5, + "problem": "StructuralIdentity", + "suggest": "", + "rule": "Structural typing is not supported (arkts-no-structural-typing)" } ] } -- Gitee From f3ee9e852f66b2add8f472495f985a2f0632c131 Mon Sep 17 00:00:00 2001 From: Nazarov Konstantin Date: Wed, 27 Sep 2023 17:31:36 +0300 Subject: [PATCH 2/2] [arkts-linter] fix #13760 - update logic for determining if entity is of library type Signed-off-by: Nazarov Konstantin --- linter-4.2/src/Utils.ts | 11 +- linter/src/utils/TsUtils.ts | 11 +- linter/test/ignore_files/good.ts | 6 + linter/test/node_modules/node_import.ts | 6 + linter/test/oh_modules/oh_import.ts | 6 + linter/test/optional_library_types.ts | 178 ++++++++++++++++++ .../optional_library_types.ts.autofix.skip | 0 .../test/optional_library_types.ts.relax.json | 0 .../optional_library_types.ts.strict.json | 0 9 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 linter/test/optional_library_types.ts create mode 100644 linter/test/optional_library_types.ts.autofix.skip create mode 100644 linter/test/optional_library_types.ts.relax.json create mode 100644 linter/test/optional_library_types.ts.strict.json diff --git a/linter-4.2/src/Utils.ts b/linter-4.2/src/Utils.ts index b52e3275e..6a4744a98 100644 --- a/linter-4.2/src/Utils.ts +++ b/linter-4.2/src/Utils.ts @@ -1141,7 +1141,16 @@ export class TsUtils { } public isLibraryType(type: ts.Type): boolean { - return this.isLibrarySymbol(type.aliasSymbol ?? type.getSymbol()); + const nonNullableType = type.getNonNullableType(); + if (nonNullableType.isUnion()) { + for (const componentType of nonNullableType.types) { + if (!this.isLibraryType(componentType)) { + return false; + } + } + return true; + } + return this.isLibrarySymbol(nonNullableType.aliasSymbol ?? nonNullableType.getSymbol()); } public hasLibraryType(node: ts.Node): boolean { diff --git a/linter/src/utils/TsUtils.ts b/linter/src/utils/TsUtils.ts index a4968f7c2..c4737dcbd 100644 --- a/linter/src/utils/TsUtils.ts +++ b/linter/src/utils/TsUtils.ts @@ -950,7 +950,16 @@ export class TsUtils { } public isLibraryType(type: ts.Type): boolean { - return this.isLibrarySymbol(type.aliasSymbol ?? type.getSymbol()); + const nonNullableType = type.getNonNullableType(); + if (nonNullableType.isUnion()) { + for (const componentType of nonNullableType.types) { + if (!this.isLibraryType(componentType)) { + return false; + } + } + return true; + } + return this.isLibrarySymbol(nonNullableType.aliasSymbol ?? nonNullableType.getSymbol()); } public hasLibraryType(node: ts.Node): boolean { diff --git a/linter/test/ignore_files/good.ts b/linter/test/ignore_files/good.ts index 9ba24518b..f5d498e9b 100644 --- a/linter/test/ignore_files/good.ts +++ b/linter/test/ignore_files/good.ts @@ -1 +1,7 @@ export class CGood {} + +export type Cb1Good = (a: number, f?: string) => number; +export type Cb2Good = (a: any, f?: string) => number; + +export function F1Good(cb?: Cb1Good) {} +export function F2Good(cb?: Cb2Good) {} diff --git a/linter/test/node_modules/node_import.ts b/linter/test/node_modules/node_import.ts index 78d8a3199..73712edb7 100644 --- a/linter/test/node_modules/node_import.ts +++ b/linter/test/node_modules/node_import.ts @@ -1 +1,7 @@ export class CNode {} + +export type Cb1Node = (a: number, f?: string) => number; +export type Cb2Node = (a: any, f?: string) => number; + +export function F1Node(cb?: Cb1Node) {} +export function F2Node(cb?: Cb2Node) {} diff --git a/linter/test/oh_modules/oh_import.ts b/linter/test/oh_modules/oh_import.ts index d6a500ca6..054775a27 100644 --- a/linter/test/oh_modules/oh_import.ts +++ b/linter/test/oh_modules/oh_import.ts @@ -1 +1,7 @@ export class COh {} + +export type Cb1Oh = (a: number, f?: string) => number; +export type Cb2Oh = (a: any, f?: string) => number; + +export function F1Oh(cb?: Cb1Oh) {} +export function F2Oh(cb?: Cb2Oh) {} diff --git a/linter/test/optional_library_types.ts b/linter/test/optional_library_types.ts new file mode 100644 index 000000000..82fa9e423 --- /dev/null +++ b/linter/test/optional_library_types.ts @@ -0,0 +1,178 @@ +/* + * 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. + */ + +import { COh, Cb1Oh, Cb2Oh, F1Oh, F2Oh } from "./oh_modules/oh_import"; +import { CGood, Cb1Good, Cb2Good, F1Good, F2Good } from "./ignore_files/good"; +import { + CNode, + Cb1Node, + Cb2Node, + F1Node, + F2Node, +} from "./node_modules/node_import"; + +class CLoc {} + +export type Cb1Loc = (a: number, f?: string) => number; +export type Cb2Loc = (a: any, f?: string) => number; + +export function F1Loc(cb?: Cb1Loc) {} +export function F2Loc(cb?: Cb2Loc) {} + +// ==================== +// #13760.1 +let cb1: Cb1Oh = (arg) => arg; +let cb2: Cb2Oh = (arg) => arg; + +let cb3: Cb1Good = (arg) => arg; +let cb4: Cb2Good = (arg) => arg; + +let cb5: Cb1Node = (arg) => arg; +let cb6: Cb2Node = (arg) => arg; + +let cb7: Cb1Loc = (arg) => arg; +let cb8: Cb2Loc = (arg) => arg; + +F1Oh(cb1); +F1Oh((arg) => arg); +F2Oh(cb2); +F2Oh((arg) => arg); +F2Oh((arg: number) => arg); + +F1Good(cb3); +F1Good((arg) => arg); +F2Good(cb4); +F2Good((arg) => arg); +F2Good((arg: number) => arg); + +F1Good(cb5); +F1Good((arg) => arg); +F2Good(cb6); +F2Good((arg) => arg); +F2Good((arg: number) => arg); + +F1Loc(cb7); +F1Loc((arg) => arg); +F2Loc(cb8); +F2Loc((arg) => arg); +F2Loc((arg: number) => arg); +// #13760.1 +// ==================== + +// ==================== +// #13760.2 +export interface ILoc { + fld1: number; + fld2?: COh; + fld3?: CGood; + fld4?: CNode; + fld5?: CLoc; +} + +function f1(a: ILoc) { + let v1 = a.fld1; + let v2 = a.fld2; + let v3 = a.fld3; + let v4 = a.fld4; + let v5 = a.fld5; +} +// #13760.2 +// ==================== + +// additional tests + +function fg1l1(cb: Cb1Good | Cb1Loc) {} +function fg1l2(cb: Cb1Good | Cb2Loc) {} +function fg2l1(cb: Cb2Good | Cb1Loc) {} +function fg2l2(cb: Cb2Good | Cb2Loc) {} + +fg1l1((arg) => arg); +fg1l2((arg) => arg); +fg2l1((arg) => arg); +fg2l2((arg) => arg); +fg1l1((arg: number) => arg); +fg1l2((arg: number) => arg); +fg2l1((arg: number) => arg); +fg2l2((arg: number) => arg); + +function fo1l1(cb: Cb1Oh | Cb1Loc) {} +function fo1l2(cb: Cb1Oh | Cb2Loc) {} +function fo2l1(cb: Cb2Oh | Cb1Loc) {} +function fo2l2(cb: Cb2Oh | Cb2Loc) {} + +fo1l1((arg) => arg); +fo1l2((arg) => arg); +fo2l1((arg) => arg); +fo2l2((arg) => arg); +fo1l1((arg: number) => arg); +fo1l2((arg: number) => arg); +fo2l1((arg: number) => arg); +fo2l2((arg: number) => arg); + +function fo1n1(cb: Cb1Oh | Cb1Node) {} +function fo1n2(cb: Cb1Oh | Cb2Node) {} +function fo2n1(cb: Cb2Oh | Cb1Node) {} +function fo2n2(cb: Cb2Oh | Cb2Node) {} + +fo1n1((arg) => arg); +fo1n2((arg) => arg); +fo2n1((arg) => arg); +fo2n2((arg) => arg); +fo1n1((arg: number) => arg); +fo1n2((arg: number) => arg); +fo2n1((arg: number) => arg); +fo2n2((arg: number) => arg); + +function fg1l1opt(cb?: Cb1Good | Cb1Loc) {} +function fg1l2opt(cb?: Cb1Good | Cb2Loc) {} +function fg2l1opt(cb?: Cb2Good | Cb1Loc) {} +function fg2l2opt(cb?: Cb2Good | Cb2Loc) {} + +fg1l1opt((arg) => arg); +fg1l2opt((arg) => arg); +fg2l1opt((arg) => arg); +fg2l2opt((arg) => arg); +fg1l1opt((arg: number) => arg); +fg1l2opt((arg: number) => arg); +fg2l1opt((arg: number) => arg); +fg2l2opt((arg: number) => arg); + +function fo1l1opt(cb?: Cb1Oh | Cb1Loc) {} +function fo1l2opt(cb?: Cb1Oh | Cb2Loc) {} +function fo2l1opt(cb?: Cb2Oh | Cb1Loc) {} +function fo2l2opt(cb?: Cb2Oh | Cb2Loc) {} + +fo1l1opt((arg) => arg); +fo1l2opt((arg) => arg); +fo2l1opt((arg) => arg); +fo2l2opt((arg) => arg); +fo1l1opt((arg: number) => arg); +fo1l2opt((arg: number) => arg); +fo2l1opt((arg: number) => arg); +fo2l2opt((arg: number) => arg); + +function fo1n1opt(cb?: Cb1Oh | Cb1Node) {} +function fo1n2opt(cb?: Cb1Oh | Cb2Node) {} +function fo2n1opt(cb?: Cb2Oh | Cb1Node) {} +function fo2n2opt(cb?: Cb2Oh | Cb2Node) {} + +fo1n1opt((arg) => arg); +fo1n2opt((arg) => arg); +fo2n1opt((arg) => arg); +fo2n2opt((arg) => arg); +fo1n1opt((arg: number) => arg); +fo1n2opt((arg: number) => arg); +fo2n1opt((arg: number) => arg); +fo2n2opt((arg: number) => arg); diff --git a/linter/test/optional_library_types.ts.autofix.skip b/linter/test/optional_library_types.ts.autofix.skip new file mode 100644 index 000000000..e69de29bb diff --git a/linter/test/optional_library_types.ts.relax.json b/linter/test/optional_library_types.ts.relax.json new file mode 100644 index 000000000..e69de29bb diff --git a/linter/test/optional_library_types.ts.strict.json b/linter/test/optional_library_types.ts.strict.json new file mode 100644 index 000000000..e69de29bb -- Gitee