From 0a7ccac19834364ecefd819de0b4fd1b34d722fe Mon Sep 17 00:00:00 2001 From: kazizi55 Date: Tue, 20 Sep 2022 01:11:16 +0900 Subject: [PATCH 01/11] feat: allow using void as a default type for a generic argument --- .../src/rules/no-invalid-void-type.ts | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts index 6b9960e9d16..35aeebffd3f 100644 --- a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts +++ b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts @@ -127,6 +127,20 @@ export default util.createRule<[Options], MessageIds>({ } } + /** + * @brief checks if the generic type parameter extends void + */ + function checkExtendedVoid(node: TSESTree.TSVoidKeyword): void { + if (node.parent.constraint?.type !== AST_NODE_TYPES.TSVoidKeyword) { + return; + } + + context.report({ + messageId: 'invalidVoidNotReturnOrGeneric', + node: node.parent.constraint, + }); + } + /** * @brief checks that a union containing void is valid * @return true if every member of the union is specified as a valid type in @@ -162,6 +176,15 @@ export default util.createRule<[Options], MessageIds>({ return; } + // allow if allowInGenericTypeArguments is specified, and report if the generic type parameter extends void + if ( + allowInGenericTypeArguments && + node.parent.default?.type === AST_NODE_TYPES.TSVoidKeyword + ) { + checkExtendedVoid(node); + return; + } + // union w/ void must contain types from validUnionMembers, or a valid generic void type if ( node.parent.type === AST_NODE_TYPES.TSUnionType && From 86b42da8d9ac726d513018c0bd4d13ce27c6e893 Mon Sep 17 00:00:00 2001 From: kazizi55 Date: Tue, 20 Sep 2022 01:12:56 +0900 Subject: [PATCH 02/11] test: allow using void as a default type for a generic argument --- .../tests/rules/no-invalid-void-type.test.ts | 38 +++---------------- 1 file changed, 5 insertions(+), 33 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/no-invalid-void-type.test.ts b/packages/eslint-plugin/tests/rules/no-invalid-void-type.test.ts index 0141da093b5..b35c9582368 100644 --- a/packages/eslint-plugin/tests/rules/no-invalid-void-type.test.ts +++ b/packages/eslint-plugin/tests/rules/no-invalid-void-type.test.ts @@ -119,6 +119,8 @@ ruleTester.run('allowInGenericTypeArguments: true', rule, { 'type Generic = [T];', 'type voidPromiseUnion = void | Promise;', 'type promiseNeverUnion = Promise | never;', + 'const arrowGeneric1 = (arg: T) => {};', + 'declare function functionDeclaration1(arg: T): void;', ], invalid: [ { @@ -141,16 +143,6 @@ ruleTester.run('allowInGenericTypeArguments: true', rule, { }, ], }, - { - code: 'const arrowGeneric1 = (arg: T) => {};', - errors: [ - { - messageId: 'invalidVoidNotReturnOrGeneric', - line: 1, - column: 28, - }, - ], - }, { code: 'const arrowGeneric2 = (arg: T) => {};', errors: [ @@ -162,7 +154,7 @@ ruleTester.run('allowInGenericTypeArguments: true', rule, { { messageId: 'invalidVoidNotReturnOrGeneric', line: 1, - column: 41, + column: 34, }, ], }, @@ -176,16 +168,6 @@ ruleTester.run('allowInGenericTypeArguments: true', rule, { }, ], }, - { - code: 'function functionGeneric1(arg: T) {}', - errors: [ - { - messageId: 'invalidVoidNotReturnOrGeneric', - line: 1, - column: 31, - }, - ], - }, { code: 'function functionGeneric2(arg: T) {}', errors: [ @@ -197,7 +179,7 @@ ruleTester.run('allowInGenericTypeArguments: true', rule, { { messageId: 'invalidVoidNotReturnOrGeneric', line: 1, - column: 44, + column: 37, }, ], }, @@ -211,16 +193,6 @@ ruleTester.run('allowInGenericTypeArguments: true', rule, { }, ], }, - { - code: 'declare function functionDeclaration1(arg: T): void;', - errors: [ - { - messageId: 'invalidVoidNotReturnOrGeneric', - line: 1, - column: 43, - }, - ], - }, { code: 'declare function functionDeclaration2(arg: T): void;', errors: [ @@ -232,7 +204,7 @@ ruleTester.run('allowInGenericTypeArguments: true', rule, { { messageId: 'invalidVoidNotReturnOrGeneric', line: 1, - column: 56, + column: 49, }, ], }, From d889d9f24c9adeea438136cfaa7777fab69a9fca Mon Sep 17 00:00:00 2001 From: kazizi55 Date: Tue, 20 Sep 2022 02:36:37 +0900 Subject: [PATCH 03/11] fix: build error --- .../src/rules/no-invalid-void-type.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts index 35aeebffd3f..2217bba5bde 100644 --- a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts +++ b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts @@ -130,17 +130,24 @@ export default util.createRule<[Options], MessageIds>({ /** * @brief checks if the generic type parameter extends void */ - function checkExtendedVoid(node: TSESTree.TSVoidKeyword): void { - if (node.parent.constraint?.type !== AST_NODE_TYPES.TSVoidKeyword) { + function checkExtendedVoid(parentNode: TSESTree.TSTypeParameter): void { + if (parentNode.constraint?.type !== AST_NODE_TYPES.TSVoidKeyword) { return; } context.report({ messageId: 'invalidVoidNotReturnOrGeneric', - node: node.parent.constraint, + node: parentNode.constraint, }); } + /** + * @brief checks if the type of given argument is TSESTree.TSTypeParameter + */ + function isTSTypeParameter(node: any): node is TSESTree.TSTypeParameter { + return node.type === AST_NODE_TYPES.TSTypeParameter; + } + /** * @brief checks that a union containing void is valid * @return true if every member of the union is specified as a valid type in @@ -179,9 +186,10 @@ export default util.createRule<[Options], MessageIds>({ // allow if allowInGenericTypeArguments is specified, and report if the generic type parameter extends void if ( allowInGenericTypeArguments && + isTSTypeParameter(node.parent) && node.parent.default?.type === AST_NODE_TYPES.TSVoidKeyword ) { - checkExtendedVoid(node); + checkExtendedVoid(node.parent); return; } From d03c941ad600f233f82ef98428a6377318a68f57 Mon Sep 17 00:00:00 2001 From: kazizi55 Date: Sat, 24 Sep 2022 18:58:03 +0900 Subject: [PATCH 04/11] fix: replace any --- packages/eslint-plugin/src/rules/no-invalid-void-type.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts index 2217bba5bde..cb9a39c98f9 100644 --- a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts +++ b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts @@ -144,7 +144,9 @@ export default util.createRule<[Options], MessageIds>({ /** * @brief checks if the type of given argument is TSESTree.TSTypeParameter */ - function isTSTypeParameter(node: any): node is TSESTree.TSTypeParameter { + function isTSTypeParameter( + node: TSESTree.Node, + ): node is TSESTree.TSTypeParameter { return node.type === AST_NODE_TYPES.TSTypeParameter; } From 5225063e5a5a13a6a831c49b16a43bf703bdee4a Mon Sep 17 00:00:00 2001 From: kazizi55 Date: Tue, 27 Sep 2022 22:41:44 +0900 Subject: [PATCH 05/11] test: remove duplicate error --- .../tests/rules/no-invalid-void-type.test.ts | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/no-invalid-void-type.test.ts b/packages/eslint-plugin/tests/rules/no-invalid-void-type.test.ts index b35c9582368..8164e85b2bd 100644 --- a/packages/eslint-plugin/tests/rules/no-invalid-void-type.test.ts +++ b/packages/eslint-plugin/tests/rules/no-invalid-void-type.test.ts @@ -151,11 +151,6 @@ ruleTester.run('allowInGenericTypeArguments: true', rule, { line: 1, column: 34, }, - { - messageId: 'invalidVoidNotReturnOrGeneric', - line: 1, - column: 34, - }, ], }, { @@ -176,11 +171,6 @@ ruleTester.run('allowInGenericTypeArguments: true', rule, { line: 1, column: 37, }, - { - messageId: 'invalidVoidNotReturnOrGeneric', - line: 1, - column: 37, - }, ], }, { @@ -201,11 +191,6 @@ ruleTester.run('allowInGenericTypeArguments: true', rule, { line: 1, column: 49, }, - { - messageId: 'invalidVoidNotReturnOrGeneric', - line: 1, - column: 49, - }, ], }, { From 2ed96e1f5f84d749b1dfcf3b11a85abd9f0dded1 Mon Sep 17 00:00:00 2001 From: kazizi55 Date: Tue, 27 Sep 2022 22:43:59 +0900 Subject: [PATCH 06/11] fix: report invalidVoidNotReturnOrGeneric only one time --- .../eslint-plugin/src/rules/no-invalid-void-type.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts index cb9a39c98f9..efdfa291e8d 100644 --- a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts +++ b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts @@ -130,8 +130,14 @@ export default util.createRule<[Options], MessageIds>({ /** * @brief checks if the generic type parameter extends void */ - function checkExtendedVoid(parentNode: TSESTree.TSTypeParameter): void { - if (parentNode.constraint?.type !== AST_NODE_TYPES.TSVoidKeyword) { + function checkExtendedVoid( + node: TSESTree.TSVoidKeyword, + parentNode: TSESTree.TSTypeParameter, + ): void { + if ( + parentNode.constraint?.type !== AST_NODE_TYPES.TSVoidKeyword || + JSON.stringify(parentNode.default?.range) !== JSON.stringify(node.range) + ) { return; } @@ -191,7 +197,7 @@ export default util.createRule<[Options], MessageIds>({ isTSTypeParameter(node.parent) && node.parent.default?.type === AST_NODE_TYPES.TSVoidKeyword ) { - checkExtendedVoid(node.parent); + checkExtendedVoid(node, node.parent); return; } From be5c6f406011fc55a7d4793059099e358be4104c Mon Sep 17 00:00:00 2001 From: kazizi <50566849+kazizi55@users.noreply.github.com> Date: Sun, 2 Oct 2022 11:28:24 +0900 Subject: [PATCH 07/11] Update packages/eslint-plugin/src/rules/no-invalid-void-type.ts Co-authored-by: Josh Goldberg --- packages/eslint-plugin/src/rules/no-invalid-void-type.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts index efdfa291e8d..b1c11df0f08 100644 --- a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts +++ b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts @@ -136,7 +136,7 @@ export default util.createRule<[Options], MessageIds>({ ): void { if ( parentNode.constraint?.type !== AST_NODE_TYPES.TSVoidKeyword || - JSON.stringify(parentNode.default?.range) !== JSON.stringify(node.range) + parentNode.default?.range === node.range ) { return; } From a1421824ec0864690a1e6ebf3750e0e75e39096d Mon Sep 17 00:00:00 2001 From: kazizi <50566849+kazizi55@users.noreply.github.com> Date: Sun, 2 Oct 2022 11:28:34 +0900 Subject: [PATCH 08/11] Update packages/eslint-plugin/src/rules/no-invalid-void-type.ts Co-authored-by: Josh Goldberg --- packages/eslint-plugin/src/rules/no-invalid-void-type.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts index b1c11df0f08..5804e6e5c80 100644 --- a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts +++ b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts @@ -128,9 +128,9 @@ export default util.createRule<[Options], MessageIds>({ } /** - * @brief checks if the generic type parameter extends void + * @brief checks if the generic type parameter defaults to void */ - function checkExtendedVoid( + function checkDefaultVoid( node: TSESTree.TSVoidKeyword, parentNode: TSESTree.TSTypeParameter, ): void { From e0b9b0a956ff9b48db8c8eb99570a3cb2939cae0 Mon Sep 17 00:00:00 2001 From: kazizi55 Date: Sun, 2 Oct 2022 11:38:14 +0900 Subject: [PATCH 09/11] fix: rename function name --- packages/eslint-plugin/src/rules/no-invalid-void-type.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts index 5804e6e5c80..3656e09c297 100644 --- a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts +++ b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts @@ -136,7 +136,7 @@ export default util.createRule<[Options], MessageIds>({ ): void { if ( parentNode.constraint?.type !== AST_NODE_TYPES.TSVoidKeyword || - parentNode.default?.range === node.range + parentNode.default?.range === node.range ) { return; } @@ -197,7 +197,7 @@ export default util.createRule<[Options], MessageIds>({ isTSTypeParameter(node.parent) && node.parent.default?.type === AST_NODE_TYPES.TSVoidKeyword ) { - checkExtendedVoid(node, node.parent); + checkDefaultVoid(node, node.parent); return; } From 4b7ad4127dae4c6f05623ae86eac77c157bcee36 Mon Sep 17 00:00:00 2001 From: kazizi55 Date: Sun, 2 Oct 2022 11:41:35 +0900 Subject: [PATCH 10/11] refactor: delete isTSTypeParameter and inline --- .../eslint-plugin/src/rules/no-invalid-void-type.ts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts index 3656e09c297..6d0a8d37817 100644 --- a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts +++ b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts @@ -147,15 +147,6 @@ export default util.createRule<[Options], MessageIds>({ }); } - /** - * @brief checks if the type of given argument is TSESTree.TSTypeParameter - */ - function isTSTypeParameter( - node: TSESTree.Node, - ): node is TSESTree.TSTypeParameter { - return node.type === AST_NODE_TYPES.TSTypeParameter; - } - /** * @brief checks that a union containing void is valid * @return true if every member of the union is specified as a valid type in @@ -194,7 +185,7 @@ export default util.createRule<[Options], MessageIds>({ // allow if allowInGenericTypeArguments is specified, and report if the generic type parameter extends void if ( allowInGenericTypeArguments && - isTSTypeParameter(node.parent) && + node.parent.type === AST_NODE_TYPES.TSTypeParameter && node.parent.default?.type === AST_NODE_TYPES.TSVoidKeyword ) { checkDefaultVoid(node, node.parent); From 508ab8f52d939b10480b97a6cc1f47f85bd95768 Mon Sep 17 00:00:00 2001 From: kazizi55 Date: Sun, 2 Oct 2022 13:06:58 +0900 Subject: [PATCH 11/11] refactor: checkDefaultVoid --- .../src/rules/no-invalid-void-type.ts | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts index 6d0a8d37817..7cda184e4fd 100644 --- a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts +++ b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts @@ -134,17 +134,12 @@ export default util.createRule<[Options], MessageIds>({ node: TSESTree.TSVoidKeyword, parentNode: TSESTree.TSTypeParameter, ): void { - if ( - parentNode.constraint?.type !== AST_NODE_TYPES.TSVoidKeyword || - parentNode.default?.range === node.range - ) { - return; + if (parentNode.default !== node) { + context.report({ + messageId: 'invalidVoidNotReturnOrGeneric', + node, + }); } - - context.report({ - messageId: 'invalidVoidNotReturnOrGeneric', - node: parentNode.constraint, - }); } /**