From 3bbe0c1a786e3bdb25f4432b48ce653158e6b751 Mon Sep 17 00:00:00 2001 From: Armano Date: Mon, 6 Jun 2022 23:43:52 +0200 Subject: [PATCH 1/4] fix(eslint-plugin): [space-infix-ops] add missing handling for optional property --- .../src/rules/space-infix-ops.ts | 23 ++++++----- .../tests/rules/space-infix-ops.test.ts | 40 +++++++++++++++---- 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/packages/eslint-plugin/src/rules/space-infix-ops.ts b/packages/eslint-plugin/src/rules/space-infix-ops.ts index a43ba5c30ab3..0e1626394853 100644 --- a/packages/eslint-plugin/src/rules/space-infix-ops.ts +++ b/packages/eslint-plugin/src/rules/space-infix-ops.ts @@ -69,17 +69,16 @@ export default util.createRule({ function isSpaceChar(token: TSESTree.Token): boolean { return ( - token.type === AST_TOKEN_TYPES.Punctuator && - /^[=|?|:]$/.test(token.value) + token.type === AST_TOKEN_TYPES.Punctuator && /^[=?:]$/.test(token.value) ); } function checkAndReportAssignmentSpace( node: TSESTree.Node, - leftNode: TSESTree.Token, + leftNode: TSESTree.Token | null, rightNode?: TSESTree.Token | null, ): void { - if (!rightNode) { + if (!rightNode || !leftNode) { return; } @@ -109,7 +108,7 @@ export default util.createRule({ return; } - const leftNode = sourceCode.getTokenByRangeStart(node.id.range[0])!; + const leftNode = sourceCode.getTokenByRangeStart(node.id.range[0]); const rightNode = sourceCode.getTokenByRangeStart( node.initializer.range[0], )!; @@ -124,9 +123,11 @@ export default util.createRule({ function checkForPropertyDefinitionAssignmentSpace( node: TSESTree.PropertyDefinition, ): void { - const leftNode = sourceCode.getLastToken( - node.typeAnnotation ?? node.key, - )!; + const leftNode = + node.optional && !node.typeAnnotation + ? sourceCode.getTokenAfter(node.key) + : sourceCode.getLastToken(node.typeAnnotation ?? node.key); + const rightNode = node.value ? sourceCode.getTokenByRangeStart(node.value.range[0]) : undefined; @@ -174,7 +175,7 @@ export default util.createRule({ function checkForTypeAliasAssignment( node: TSESTree.TSTypeAliasDeclaration, ): void { - const leftNode = sourceCode.getLastToken(node.typeParameters ?? node.id)!; + const leftNode = sourceCode.getLastToken(node.typeParameters ?? node.id); const rightNode = sourceCode.getFirstToken(node.typeAnnotation); checkAndReportAssignmentSpace(node, leftNode, rightNode); @@ -182,8 +183,8 @@ export default util.createRule({ function checkForTypeConditional(node: TSESTree.TSConditionalType): void { const extendsLastToken = sourceCode.getLastToken(node.extendsType)!; - const trueFirstToken = sourceCode.getFirstToken(node.trueType)!; - const trueLastToken = sourceCode.getLastToken(node.trueType)!; + const trueFirstToken = sourceCode.getFirstToken(node.trueType); + const trueLastToken = sourceCode.getLastToken(node.trueType); const falseFirstToken = sourceCode.getFirstToken(node.falseType)!; checkAndReportAssignmentSpace(node, extendsLastToken, trueFirstToken); diff --git a/packages/eslint-plugin/tests/rules/space-infix-ops.test.ts b/packages/eslint-plugin/tests/rules/space-infix-ops.test.ts index e8b5fa2bc930..0feeccdc4747 100644 --- a/packages/eslint-plugin/tests/rules/space-infix-ops.test.ts +++ b/packages/eslint-plugin/tests/rules/space-infix-ops.test.ts @@ -165,6 +165,20 @@ ruleTester.run('space-infix-ops', rule, { } `, }, + { + code: ` + class Test { + value: string & number; + } + `, + }, + { + code: ` + class Test { + optional? = false; + } + `, + }, { code: ` type Test = @@ -379,13 +393,6 @@ ruleTester.run('space-infix-ops', rule, { const x: string & (((() => void))); `, }, - { - code: ` - class Test { - value: string & number; - } - `, - }, { code: ` function foo() {} @@ -1861,6 +1868,25 @@ ruleTester.run('space-infix-ops', rule, { }, ], }, + { + code: ` + class Test { + optional?= false; + } + `, + output: ` + class Test { + optional? = false; + } + `, + errors: [ + { + messageId: 'missingSpace', + column: 20, + line: 3, + }, + ], + }, { code: ` function foo() {} From d1cc86ae5e910816da5fb2f637d1756c9282fbe1 Mon Sep 17 00:00:00 2001 From: Armano Date: Tue, 7 Jun 2022 00:14:57 +0200 Subject: [PATCH 2/4] fix(eslint-plugin): [space-infix-ops] simplify code and add more test cases --- .../src/rules/space-infix-ops.ts | 53 ++++++------------ .../tests/rules/space-infix-ops.test.ts | 55 +++++++++++++++++++ 2 files changed, 73 insertions(+), 35 deletions(-) diff --git a/packages/eslint-plugin/src/rules/space-infix-ops.ts b/packages/eslint-plugin/src/rules/space-infix-ops.ts index 0e1626394853..da0e1cf1bec5 100644 --- a/packages/eslint-plugin/src/rules/space-infix-ops.ts +++ b/packages/eslint-plugin/src/rules/space-infix-ops.ts @@ -75,8 +75,8 @@ export default util.createRule({ function checkAndReportAssignmentSpace( node: TSESTree.Node, - leftNode: TSESTree.Token | null, - rightNode?: TSESTree.Token | null, + leftNode: TSESTree.Token | TSESTree.Node | null, + rightNode?: TSESTree.Token | TSESTree.Node | null, ): void { if (!rightNode || !leftNode) { return; @@ -86,16 +86,16 @@ export default util.createRule({ leftNode, rightNode, isSpaceChar, - ); + )!; - const prev = sourceCode.getTokenBefore(operator!); - const next = sourceCode.getTokenAfter(operator!); + const prev = sourceCode.getTokenBefore(operator)!; + const next = sourceCode.getTokenAfter(operator)!; if ( - !sourceCode.isSpaceBetween!(prev!, operator!) || - !sourceCode.isSpaceBetween!(operator!, next!) + !sourceCode.isSpaceBetween!(prev, operator) || + !sourceCode.isSpaceBetween!(operator, next) ) { - report(node, operator!); + report(node, operator); } } @@ -104,16 +104,7 @@ export default util.createRule({ * @param node The node to report */ function checkForEnumAssignmentSpace(node: TSESTree.TSEnumMember): void { - if (!node.initializer) { - return; - } - - const leftNode = sourceCode.getTokenByRangeStart(node.id.range[0]); - const rightNode = sourceCode.getTokenByRangeStart( - node.initializer.range[0], - )!; - - checkAndReportAssignmentSpace(node, leftNode, rightNode); + checkAndReportAssignmentSpace(node, node.id, node.initializer); } /** @@ -126,13 +117,9 @@ export default util.createRule({ const leftNode = node.optional && !node.typeAnnotation ? sourceCode.getTokenAfter(node.key) - : sourceCode.getLastToken(node.typeAnnotation ?? node.key); - - const rightNode = node.value - ? sourceCode.getTokenByRangeStart(node.value.range[0]) - : undefined; + : node.typeAnnotation ?? node.key; - checkAndReportAssignmentSpace(node, leftNode, rightNode); + checkAndReportAssignmentSpace(node, leftNode, node.value); } /** @@ -175,20 +162,16 @@ export default util.createRule({ function checkForTypeAliasAssignment( node: TSESTree.TSTypeAliasDeclaration, ): void { - const leftNode = sourceCode.getLastToken(node.typeParameters ?? node.id); - const rightNode = sourceCode.getFirstToken(node.typeAnnotation); - - checkAndReportAssignmentSpace(node, leftNode, rightNode); + checkAndReportAssignmentSpace( + node, + node.typeParameters ?? node.id, + node.typeAnnotation, + ); } function checkForTypeConditional(node: TSESTree.TSConditionalType): void { - const extendsLastToken = sourceCode.getLastToken(node.extendsType)!; - const trueFirstToken = sourceCode.getFirstToken(node.trueType); - const trueLastToken = sourceCode.getLastToken(node.trueType); - const falseFirstToken = sourceCode.getFirstToken(node.falseType)!; - - checkAndReportAssignmentSpace(node, extendsLastToken, trueFirstToken); - checkAndReportAssignmentSpace(node, trueLastToken, falseFirstToken); + checkAndReportAssignmentSpace(node, node.extendsType, node.trueType); + checkAndReportAssignmentSpace(node, node.trueType, node.falseType); } return { diff --git a/packages/eslint-plugin/tests/rules/space-infix-ops.test.ts b/packages/eslint-plugin/tests/rules/space-infix-ops.test.ts index 0feeccdc4747..90a85d8a6cc9 100644 --- a/packages/eslint-plugin/tests/rules/space-infix-ops.test.ts +++ b/packages/eslint-plugin/tests/rules/space-infix-ops.test.ts @@ -991,6 +991,61 @@ ruleTester.run('space-infix-ops', rule, { }, ], }, + { + code: ` + type Test = |string|(((() => void)))|string; + `, + output: ` + type Test = | string | (((() => void))) | string; + `, + errors: [ + { + messageId: 'missingSpace', + column: 21, + line: 2, + }, + { + messageId: 'missingSpace', + column: 28, + line: 2, + }, + { + messageId: 'missingSpace', + column: 45, + line: 2, + }, + ], + }, + { + code: ` + type Test=(string&number)|string|(((() => void))); + `, + output: ` + type Test = (string & number) | string | (((() => void))); + `, + errors: [ + { + messageId: 'missingSpace', + column: 18, + line: 2, + }, + { + messageId: 'missingSpace', + column: 26, + line: 2, + }, + { + messageId: 'missingSpace', + column: 34, + line: 2, + }, + { + messageId: 'missingSpace', + column: 41, + line: 2, + }, + ], + }, { code: ` type Test = From b09c698562aa60a4b5072598bcdfd0a8f58d05c0 Mon Sep 17 00:00:00 2001 From: Armano Date: Tue, 7 Jun 2022 00:46:39 +0200 Subject: [PATCH 3/4] fix(eslint-plugin): [space-infix-ops] report correct node to reduce amount of multi-passes --- .../src/rules/space-infix-ops.ts | 24 ++++++--------- .../tests/rules/space-infix-ops.test.ts | 30 +++++++++++++++++++ 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/packages/eslint-plugin/src/rules/space-infix-ops.ts b/packages/eslint-plugin/src/rules/space-infix-ops.ts index da0e1cf1bec5..9cab8d27f529 100644 --- a/packages/eslint-plugin/src/rules/space-infix-ops.ts +++ b/packages/eslint-plugin/src/rules/space-infix-ops.ts @@ -36,13 +36,9 @@ export default util.createRule({ const rules = baseRule.create(context); const sourceCode = context.getSourceCode(); - const report = ( - node: TSESTree.Node | TSESTree.Token, - operator: TSESTree.Token, - ): void => { + function report(operator: TSESTree.Token): void { context.report({ - node: node, - loc: operator.loc, + node: operator, messageId: 'missingSpace', data: { operator: operator.value, @@ -65,7 +61,7 @@ export default util.createRule({ return fixer.replaceText(operator, fixString); }, }); - }; + } function isSpaceChar(token: TSESTree.Token): boolean { return ( @@ -74,7 +70,6 @@ export default util.createRule({ } function checkAndReportAssignmentSpace( - node: TSESTree.Node, leftNode: TSESTree.Token | TSESTree.Node | null, rightNode?: TSESTree.Token | TSESTree.Node | null, ): void { @@ -95,7 +90,7 @@ export default util.createRule({ !sourceCode.isSpaceBetween!(prev, operator) || !sourceCode.isSpaceBetween!(operator, next) ) { - report(node, operator); + report(operator); } } @@ -104,7 +99,7 @@ export default util.createRule({ * @param node The node to report */ function checkForEnumAssignmentSpace(node: TSESTree.TSEnumMember): void { - checkAndReportAssignmentSpace(node, node.id, node.initializer); + checkAndReportAssignmentSpace(node.id, node.initializer); } /** @@ -119,7 +114,7 @@ export default util.createRule({ ? sourceCode.getTokenAfter(node.key) : node.typeAnnotation ?? node.key; - checkAndReportAssignmentSpace(node, leftNode, node.value); + checkAndReportAssignmentSpace(leftNode, node.value); } /** @@ -149,7 +144,7 @@ export default util.createRule({ !sourceCode.isSpaceBetween!(prev!, operator) || !sourceCode.isSpaceBetween!(operator, next!) ) { - report(typeAnnotation, operator); + report(operator); } } }); @@ -163,15 +158,14 @@ export default util.createRule({ node: TSESTree.TSTypeAliasDeclaration, ): void { checkAndReportAssignmentSpace( - node, node.typeParameters ?? node.id, node.typeAnnotation, ); } function checkForTypeConditional(node: TSESTree.TSConditionalType): void { - checkAndReportAssignmentSpace(node, node.extendsType, node.trueType); - checkAndReportAssignmentSpace(node, node.trueType, node.falseType); + checkAndReportAssignmentSpace(node.extendsType, node.trueType); + checkAndReportAssignmentSpace(node.trueType, node.falseType); } return { diff --git a/packages/eslint-plugin/tests/rules/space-infix-ops.test.ts b/packages/eslint-plugin/tests/rules/space-infix-ops.test.ts index 90a85d8a6cc9..18afdc9529b0 100644 --- a/packages/eslint-plugin/tests/rules/space-infix-ops.test.ts +++ b/packages/eslint-plugin/tests/rules/space-infix-ops.test.ts @@ -1016,6 +1016,36 @@ ruleTester.run('space-infix-ops', rule, { }, ], }, + { + code: ` + type Test=|string|(((() => void)))|string; + `, + output: ` + type Test = | string | (((() => void))) | string; + `, + errors: [ + { + messageId: 'missingSpace', + column: 18, + line: 2, + }, + { + messageId: 'missingSpace', + column: 19, + line: 2, + }, + { + messageId: 'missingSpace', + column: 26, + line: 2, + }, + { + messageId: 'missingSpace', + column: 43, + line: 2, + }, + ], + }, { code: ` type Test=(string&number)|string|(((() => void))); From 47e7a2b25473ed66e3df8bda6d1b48c648424c16 Mon Sep 17 00:00:00 2001 From: Armano Date: Tue, 7 Jun 2022 01:21:33 +0200 Subject: [PATCH 4/4] fix(eslint-plugin): [space-infix-ops] correct test result --- packages/eslint-plugin/tests/rules/space-infix-ops.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/tests/rules/space-infix-ops.test.ts b/packages/eslint-plugin/tests/rules/space-infix-ops.test.ts index 18afdc9529b0..37060fab7457 100644 --- a/packages/eslint-plugin/tests/rules/space-infix-ops.test.ts +++ b/packages/eslint-plugin/tests/rules/space-infix-ops.test.ts @@ -1021,7 +1021,7 @@ ruleTester.run('space-infix-ops', rule, { type Test=|string|(((() => void)))|string; `, output: ` - type Test = | string | (((() => void))) | string; + type Test = |string | (((() => void))) | string; `, errors: [ {