From 75a099d96119f61ac417515ff1d3ef3663f1bbf0 Mon Sep 17 00:00:00 2001 From: Vsevolod Pukhov Date: Tue, 19 Sep 2023 18:23:59 +0300 Subject: [PATCH] [ArkTS Linter] Restore strict null checks for non-interop calls Signed-off-by: Vsevolod Pukhov --- linter-4.2/src/TypeScriptLinter.ts | 19 +++++++++---- linter-4.2/test/null_check_calls.ts | 8 ++++++ .../test/null_check_calls.ts.relax.json | 23 +++++++++++---- .../test/null_check_calls.ts.strict.json | 28 +++++++++++++++---- linter/src/TypeScriptLinter.ts | 19 +++++++++---- linter/test/null_check_calls.ts | 8 ++++++ linter/test/null_check_calls.ts.relax.json | 23 +++++++++++---- linter/test/null_check_calls.ts.strict.json | 28 +++++++++++++++---- 8 files changed, 120 insertions(+), 36 deletions(-) diff --git a/linter-4.2/src/TypeScriptLinter.ts b/linter-4.2/src/TypeScriptLinter.ts index c2a79bc87..2c505db75 100644 --- a/linter-4.2/src/TypeScriptLinter.ts +++ b/linter-4.2/src/TypeScriptLinter.ts @@ -1942,18 +1942,25 @@ export class TypeScriptLinter { const ARGUMENT_OF_TYPE_NULL_IS_NOT_ASSIGNABLE_TO_PARAMETER_OF_TYPE_1_RE = /^Argument of type 'null' is not assignable to parameter of type '.*'\.$/; const ARGUMENT_OF_TYPE_UNDEFINED_IS_NOT_ASSIGNABLE_TO_PARAMETER_OF_TYPE_1_RE = /^Argument of type 'undefined' is not assignable to parameter of type '.*'\.$/; + let inLibCall = this.tsUtils.isLibraryType(this.tsTypeChecker.getTypeAtLocation(callExpr.expression)); + const chainCheck = (n: ts.DiagnosticMessageChain): boolean => { - if (n.code == TYPE_0_IS_NOT_ASSIGNABLE_TO_TYPE_1_ERROR_CODE && - (n.messageText.match(TYPE_UNKNOWN_IS_NOT_ASSIGNABLE_TO_TYPE_1_RE) || - n.messageText.match(TYPE_NULL_IS_NOT_ASSIGNABLE_TO_TYPE_1_RE) || - n.messageText.match(TYPE_UNDEFINED_IS_NOT_ASSIGNABLE_TO_TYPE_1_RE))) { - return false; + if (n.code == TYPE_0_IS_NOT_ASSIGNABLE_TO_TYPE_1_ERROR_CODE) { + if (n.messageText.match(TYPE_UNKNOWN_IS_NOT_ASSIGNABLE_TO_TYPE_1_RE)) { + return false; + } + if (n.messageText.match(TYPE_UNDEFINED_IS_NOT_ASSIGNABLE_TO_TYPE_1_RE)) { + return false; + } + if (inLibCall && n.messageText.match(TYPE_NULL_IS_NOT_ASSIGNABLE_TO_TYPE_1_RE)) { + return false; + } } return n.next == undefined ? true : chainCheck(n.next[0]); }; const msgCheck = (msg: string): boolean => { - if (this.tsUtils.isLibraryType(this.tsTypeChecker.getTypeAtLocation(callExpr.expression))) { + if (inLibCall) { const match = msg.match(ARGUMENT_OF_TYPE_NULL_IS_NOT_ASSIGNABLE_TO_PARAMETER_OF_TYPE_1_RE) || msg.match(ARGUMENT_OF_TYPE_UNDEFINED_IS_NOT_ASSIGNABLE_TO_PARAMETER_OF_TYPE_1_RE); return !match; diff --git a/linter-4.2/test/null_check_calls.ts b/linter-4.2/test/null_check_calls.ts index 18bcaa037..b79ac3409 100644 --- a/linter-4.2/test/null_check_calls.ts +++ b/linter-4.2/test/null_check_calls.ts @@ -37,3 +37,11 @@ function fff(a: Array): void {} fff(null); ff(null); f(null); + + +((a: number) => a)(null); +(a: null | number) => ((b: number) => b)(a); + +function inc(a: number) { return a + 1 } +function neg2null(x: number) { return x > 0 ? x : null } +inc(neg2null(-1)); diff --git a/linter-4.2/test/null_check_calls.ts.relax.json b/linter-4.2/test/null_check_calls.ts.relax.json index 9d5793764..b40e140ba 100644 --- a/linter-4.2/test/null_check_calls.ts.relax.json +++ b/linter-4.2/test/null_check_calls.ts.relax.json @@ -17,16 +17,27 @@ { "line": 33, "column": 12, - "problem": "StrictDiagnostic", - "suggest": "No overload matches this call.\n Overload 1 of 2, '(func: Function, ...args: unknown[]): Promise', gave the following error.\n Argument of type 'null' is not assignable to parameter of type 'Function'.\n Overload 2 of 2, '(group: TaskGroup, priority?: Priority | undefined): Promise', gave the following error.\n Argument of type 'null' is not assignable to parameter of type 'TaskGroup'.", - "rule": "No overload matches this call.\n Overload 1 of 2, '(func: Function, ...args: unknown[]): Promise', gave the following error.\n Argument of type 'null' is not assignable to parameter of type 'Function'.\n Overload 2 of 2, '(group: TaskGroup, priority?: Priority | undefined): Promise', gave the following error.\n Argument of type 'null' is not assignable to parameter of type 'TaskGroup'." + "problem": "StrictDiagnostic" }, { "line": 37, "column": 5, - "problem": "StrictDiagnostic", - "suggest": "Argument of type 'null' is not assignable to parameter of type 'number[]'.", - "rule": "Argument of type 'null' is not assignable to parameter of type 'number[]'." + "problem": "StrictDiagnostic" + }, + { + "line": 42, + "column": 20, + "problem": "StrictDiagnostic" + }, + { + "line": 43, + "column": 42, + "problem": "StrictDiagnostic" + }, + { + "line": 47, + "column": 5, + "problem": "StrictDiagnostic" } ] } \ No newline at end of file diff --git a/linter-4.2/test/null_check_calls.ts.strict.json b/linter-4.2/test/null_check_calls.ts.strict.json index 9d5793764..4b6f2852d 100644 --- a/linter-4.2/test/null_check_calls.ts.strict.json +++ b/linter-4.2/test/null_check_calls.ts.strict.json @@ -14,19 +14,35 @@ "limitations under the License." ], "nodes": [ + { + "line": 43, + "column": 1, + "problem": "LimitedReturnTypeInference" + }, { "line": 33, "column": 12, - "problem": "StrictDiagnostic", - "suggest": "No overload matches this call.\n Overload 1 of 2, '(func: Function, ...args: unknown[]): Promise', gave the following error.\n Argument of type 'null' is not assignable to parameter of type 'Function'.\n Overload 2 of 2, '(group: TaskGroup, priority?: Priority | undefined): Promise', gave the following error.\n Argument of type 'null' is not assignable to parameter of type 'TaskGroup'.", - "rule": "No overload matches this call.\n Overload 1 of 2, '(func: Function, ...args: unknown[]): Promise', gave the following error.\n Argument of type 'null' is not assignable to parameter of type 'Function'.\n Overload 2 of 2, '(group: TaskGroup, priority?: Priority | undefined): Promise', gave the following error.\n Argument of type 'null' is not assignable to parameter of type 'TaskGroup'." + "problem": "StrictDiagnostic" }, { "line": 37, "column": 5, - "problem": "StrictDiagnostic", - "suggest": "Argument of type 'null' is not assignable to parameter of type 'number[]'.", - "rule": "Argument of type 'null' is not assignable to parameter of type 'number[]'." + "problem": "StrictDiagnostic" + }, + { + "line": 42, + "column": 20, + "problem": "StrictDiagnostic" + }, + { + "line": 43, + "column": 42, + "problem": "StrictDiagnostic" + }, + { + "line": 47, + "column": 5, + "problem": "StrictDiagnostic" } ] } \ No newline at end of file diff --git a/linter/src/TypeScriptLinter.ts b/linter/src/TypeScriptLinter.ts index ea461af04..94be3f3bf 100644 --- a/linter/src/TypeScriptLinter.ts +++ b/linter/src/TypeScriptLinter.ts @@ -1564,18 +1564,25 @@ export class TypeScriptLinter { const ARGUMENT_OF_TYPE_NULL_IS_NOT_ASSIGNABLE_TO_PARAMETER_OF_TYPE_1_RE = /^Argument of type 'null' is not assignable to parameter of type '.*'\.$/; const ARGUMENT_OF_TYPE_UNDEFINED_IS_NOT_ASSIGNABLE_TO_PARAMETER_OF_TYPE_1_RE = /^Argument of type 'undefined' is not assignable to parameter of type '.*'\.$/; + let inLibCall = this.tsUtils.isLibraryType(this.tsTypeChecker.getTypeAtLocation(callExpr.expression)); + const chainCheck = (n: ts.DiagnosticMessageChain): boolean => { - if (n.code == TYPE_0_IS_NOT_ASSIGNABLE_TO_TYPE_1_ERROR_CODE && - (n.messageText.match(TYPE_UNKNOWN_IS_NOT_ASSIGNABLE_TO_TYPE_1_RE) || - n.messageText.match(TYPE_NULL_IS_NOT_ASSIGNABLE_TO_TYPE_1_RE) || - n.messageText.match(TYPE_UNDEFINED_IS_NOT_ASSIGNABLE_TO_TYPE_1_RE))) { - return false; + if (n.code == TYPE_0_IS_NOT_ASSIGNABLE_TO_TYPE_1_ERROR_CODE) { + if (n.messageText.match(TYPE_UNKNOWN_IS_NOT_ASSIGNABLE_TO_TYPE_1_RE)) { + return false; + } + if (n.messageText.match(TYPE_UNDEFINED_IS_NOT_ASSIGNABLE_TO_TYPE_1_RE)) { + return false; + } + if (inLibCall && n.messageText.match(TYPE_NULL_IS_NOT_ASSIGNABLE_TO_TYPE_1_RE)) { + return false; + } } return n.next == undefined ? true : chainCheck(n.next[0]); }; const msgCheck = (msg: string): boolean => { - if (this.tsUtils.isLibraryType(this.tsTypeChecker.getTypeAtLocation(callExpr.expression))) { + if (inLibCall) { const match = msg.match(ARGUMENT_OF_TYPE_NULL_IS_NOT_ASSIGNABLE_TO_PARAMETER_OF_TYPE_1_RE) || msg.match(ARGUMENT_OF_TYPE_UNDEFINED_IS_NOT_ASSIGNABLE_TO_PARAMETER_OF_TYPE_1_RE); return !match; diff --git a/linter/test/null_check_calls.ts b/linter/test/null_check_calls.ts index 18bcaa037..b79ac3409 100644 --- a/linter/test/null_check_calls.ts +++ b/linter/test/null_check_calls.ts @@ -37,3 +37,11 @@ function fff(a: Array): void {} fff(null); ff(null); f(null); + + +((a: number) => a)(null); +(a: null | number) => ((b: number) => b)(a); + +function inc(a: number) { return a + 1 } +function neg2null(x: number) { return x > 0 ? x : null } +inc(neg2null(-1)); diff --git a/linter/test/null_check_calls.ts.relax.json b/linter/test/null_check_calls.ts.relax.json index 9d5793764..b40e140ba 100644 --- a/linter/test/null_check_calls.ts.relax.json +++ b/linter/test/null_check_calls.ts.relax.json @@ -17,16 +17,27 @@ { "line": 33, "column": 12, - "problem": "StrictDiagnostic", - "suggest": "No overload matches this call.\n Overload 1 of 2, '(func: Function, ...args: unknown[]): Promise', gave the following error.\n Argument of type 'null' is not assignable to parameter of type 'Function'.\n Overload 2 of 2, '(group: TaskGroup, priority?: Priority | undefined): Promise', gave the following error.\n Argument of type 'null' is not assignable to parameter of type 'TaskGroup'.", - "rule": "No overload matches this call.\n Overload 1 of 2, '(func: Function, ...args: unknown[]): Promise', gave the following error.\n Argument of type 'null' is not assignable to parameter of type 'Function'.\n Overload 2 of 2, '(group: TaskGroup, priority?: Priority | undefined): Promise', gave the following error.\n Argument of type 'null' is not assignable to parameter of type 'TaskGroup'." + "problem": "StrictDiagnostic" }, { "line": 37, "column": 5, - "problem": "StrictDiagnostic", - "suggest": "Argument of type 'null' is not assignable to parameter of type 'number[]'.", - "rule": "Argument of type 'null' is not assignable to parameter of type 'number[]'." + "problem": "StrictDiagnostic" + }, + { + "line": 42, + "column": 20, + "problem": "StrictDiagnostic" + }, + { + "line": 43, + "column": 42, + "problem": "StrictDiagnostic" + }, + { + "line": 47, + "column": 5, + "problem": "StrictDiagnostic" } ] } \ No newline at end of file diff --git a/linter/test/null_check_calls.ts.strict.json b/linter/test/null_check_calls.ts.strict.json index 9d5793764..4b6f2852d 100644 --- a/linter/test/null_check_calls.ts.strict.json +++ b/linter/test/null_check_calls.ts.strict.json @@ -14,19 +14,35 @@ "limitations under the License." ], "nodes": [ + { + "line": 43, + "column": 1, + "problem": "LimitedReturnTypeInference" + }, { "line": 33, "column": 12, - "problem": "StrictDiagnostic", - "suggest": "No overload matches this call.\n Overload 1 of 2, '(func: Function, ...args: unknown[]): Promise', gave the following error.\n Argument of type 'null' is not assignable to parameter of type 'Function'.\n Overload 2 of 2, '(group: TaskGroup, priority?: Priority | undefined): Promise', gave the following error.\n Argument of type 'null' is not assignable to parameter of type 'TaskGroup'.", - "rule": "No overload matches this call.\n Overload 1 of 2, '(func: Function, ...args: unknown[]): Promise', gave the following error.\n Argument of type 'null' is not assignable to parameter of type 'Function'.\n Overload 2 of 2, '(group: TaskGroup, priority?: Priority | undefined): Promise', gave the following error.\n Argument of type 'null' is not assignable to parameter of type 'TaskGroup'." + "problem": "StrictDiagnostic" }, { "line": 37, "column": 5, - "problem": "StrictDiagnostic", - "suggest": "Argument of type 'null' is not assignable to parameter of type 'number[]'.", - "rule": "Argument of type 'null' is not assignable to parameter of type 'number[]'." + "problem": "StrictDiagnostic" + }, + { + "line": 42, + "column": 20, + "problem": "StrictDiagnostic" + }, + { + "line": 43, + "column": 42, + "problem": "StrictDiagnostic" + }, + { + "line": 47, + "column": 5, + "problem": "StrictDiagnostic" } ] } \ No newline at end of file -- Gitee