From 93d1b4247ea84bdd6cd87150eb66c2229aba0d2d Mon Sep 17 00:00:00 2001 From: Evgeniy Okolnov Date: Tue, 5 Sep 2023 01:08:56 +0300 Subject: [PATCH] [ArkTS Linter] Issue 13220: Object literals initializing intrinsic 'object' type within library API. Change-Id: I7866f438f08267ca2714c4aeceda31e099d0c350 Signed-off-by: Evgeniy Okolnov --- linter-4.2/src/Utils.ts | 12 ++++++++---- linter-4.2/test/dynamic_lib.d.ts | 8 ++++++++ linter-4.2/test/dynamic_object_literals.ts | 11 ++++++++++- linter/src/utils/TsUtils.ts | 10 +++++++--- .../{IsBuiltinType.ts => isIntrinsicObjectType.ts} | 4 ++-- linter/test/dynamic_lib.d.ts | 8 ++++++++ linter/test/dynamic_object_literals.ts | 11 ++++++++++- 7 files changed, 53 insertions(+), 11 deletions(-) rename linter/src/utils/functions/{IsBuiltinType.ts => isIntrinsicObjectType.ts} (84%) diff --git a/linter-4.2/src/Utils.ts b/linter-4.2/src/Utils.ts index 2ca1cdc8a..cf929d500 100644 --- a/linter-4.2/src/Utils.ts +++ b/linter-4.2/src/Utils.ts @@ -1072,8 +1072,8 @@ export class TsUtils { return false; } - public isBuiltinType(type: ts.Type): boolean { - return !(type.flags & ts.TypeFlags.NonPrimitive); + public isIntrinsicObjectType(type: ts.Type): boolean { + return !!(type.flags & ts.TypeFlags.NonPrimitive); } public isDynamicType(type: ts.Type | undefined): boolean | undefined { @@ -1085,13 +1085,17 @@ export class TsUtils { // return 'false' if it is not an object of standard library type one. // In the case of standard library type we need to determine context. + // Check the non-nullable version of type to eliminate 'undefined' type + // from the union type elements. + type = type.getNonNullableType(); + if (type.isUnion()) { for (let compType of type.types) { if (this.isLibraryType(compType)) { return true; } - if (!this.isStdLibraryType(compType) && !this.isBuiltinType(compType)) { + if (!this.isStdLibraryType(compType) && !this.isIntrinsicObjectType(compType) && !this.isAnyType(compType)) { return false; } } @@ -1102,7 +1106,7 @@ export class TsUtils { return true; } - if (!this.isStdLibraryType(type) && !this.isBuiltinType(type)) { + if (!this.isStdLibraryType(type) && !this.isIntrinsicObjectType(type) && !this.isAnyType(type)) { return false; } diff --git a/linter-4.2/test/dynamic_lib.d.ts b/linter-4.2/test/dynamic_lib.d.ts index b5eecaeef..669198041 100644 --- a/linter-4.2/test/dynamic_lib.d.ts +++ b/linter-4.2/test/dynamic_lib.d.ts @@ -11,3 +11,11 @@ export declare interface I2 { f2?: Array; f3?: any; } + +export declare interface I3 { + f1: object; + f2?: object; + f3: Array; +} + +export declare function bar(p: object, q?: object): void \ No newline at end of file diff --git a/linter-4.2/test/dynamic_object_literals.ts b/linter-4.2/test/dynamic_object_literals.ts index 88a429917..ab2613f97 100644 --- a/linter-4.2/test/dynamic_object_literals.ts +++ b/linter-4.2/test/dynamic_object_literals.ts @@ -13,7 +13,7 @@ * limitations under the License. */ -import { I, foo, I2 } from "./dynamic_lib" +import { I, foo, I2, I3, bar } from "./dynamic_lib" function main(): void { let obj: I = { @@ -38,4 +38,13 @@ function main(): void { f2: [{c: 30}, {d: 40}], f3: {a: '11', b: 444, c: {f: {d: [1, 2]}}} } + + bar({f2: 'abc', f3: 30}) + bar([{b1: 1, b2: 2}, {b3: '3'}], {c: 4, d: 5}) + + let obj3: I3 = { + f1: {a: 10, b: 20}, + f2: {a: '11', b: 444, c: {f: {d: [1, 2]}}}, + f3: [{c: 30}, {d: 40}] + } } diff --git a/linter/src/utils/TsUtils.ts b/linter/src/utils/TsUtils.ts index 0ded4c929..4cab1e859 100644 --- a/linter/src/utils/TsUtils.ts +++ b/linter/src/utils/TsUtils.ts @@ -19,7 +19,7 @@ import { STANDARD_LIBRARIES } from './consts/StandardLibraries'; import { STATEMENT_KINDS } from './consts/StatementKinds'; import { TYPED_ARRAYS } from './consts/TypedArrays'; import { getScriptKind } from './functions/GetScriptKind'; -import { isBuiltinType } from './functions/IsBuiltinType'; +import { isIntrinsicObjectType } from './functions/isIntrinsicObjectType'; import { isStdLibraryType } from './functions/IsStdLibrary'; import { isStructDeclaration } from './functions/IsStruct'; @@ -876,13 +876,17 @@ export class TsUtils { // return 'false' if it is not an object of standard library type one. // In the case of standard library type we need to determine context. + // Check the non-nullable version of type to eliminate 'undefined' type + // from the union type elements. + type = type.getNonNullableType(); + if (type.isUnion()) { for (let compType of type.types) { if (this.isLibraryType(compType)) { return true; } - if (!isStdLibraryType(compType) && !isBuiltinType(compType)) { + if (!isStdLibraryType(compType) && !isIntrinsicObjectType(compType) && !this.isAnyType(compType)) { return false; } } @@ -893,7 +897,7 @@ export class TsUtils { return true; } - if (!isStdLibraryType(type) && !isBuiltinType(type)) { + if (!isStdLibraryType(type) && !isIntrinsicObjectType(type) && !this.isAnyType(type)) { return false; } diff --git a/linter/src/utils/functions/IsBuiltinType.ts b/linter/src/utils/functions/isIntrinsicObjectType.ts similarity index 84% rename from linter/src/utils/functions/IsBuiltinType.ts rename to linter/src/utils/functions/isIntrinsicObjectType.ts index fb046d5bc..a7ea04301 100644 --- a/linter/src/utils/functions/IsBuiltinType.ts +++ b/linter/src/utils/functions/isIntrinsicObjectType.ts @@ -15,6 +15,6 @@ import * as ts from 'typescript'; -export function isBuiltinType(type: ts.Type): boolean { - return !(type.flags & ts.TypeFlags.NonPrimitive); +export function isIntrinsicObjectType(type: ts.Type): boolean { + return !!(type.flags & ts.TypeFlags.NonPrimitive); } diff --git a/linter/test/dynamic_lib.d.ts b/linter/test/dynamic_lib.d.ts index b5eecaeef..669198041 100644 --- a/linter/test/dynamic_lib.d.ts +++ b/linter/test/dynamic_lib.d.ts @@ -11,3 +11,11 @@ export declare interface I2 { f2?: Array; f3?: any; } + +export declare interface I3 { + f1: object; + f2?: object; + f3: Array; +} + +export declare function bar(p: object, q?: object): void \ No newline at end of file diff --git a/linter/test/dynamic_object_literals.ts b/linter/test/dynamic_object_literals.ts index 88a429917..ab2613f97 100644 --- a/linter/test/dynamic_object_literals.ts +++ b/linter/test/dynamic_object_literals.ts @@ -13,7 +13,7 @@ * limitations under the License. */ -import { I, foo, I2 } from "./dynamic_lib" +import { I, foo, I2, I3, bar } from "./dynamic_lib" function main(): void { let obj: I = { @@ -38,4 +38,13 @@ function main(): void { f2: [{c: 30}, {d: 40}], f3: {a: '11', b: 444, c: {f: {d: [1, 2]}}} } + + bar({f2: 'abc', f3: 30}) + bar([{b1: 1, b2: 2}, {b3: '3'}], {c: 4, d: 5}) + + let obj3: I3 = { + f1: {a: 10, b: 20}, + f2: {a: '11', b: 444, c: {f: {d: [1, 2]}}}, + f3: [{c: 30}, {d: 40}] + } } -- Gitee