From 14ec73d963587409a1465ddd33ce180b4251cfeb Mon Sep 17 00:00:00 2001 From: Omri Luzon Date: Fri, 9 Dec 2022 23:15:34 +0200 Subject: [PATCH 01/18] feat/issue5990-extend-base-block-spacing --- .../eslint-plugin/docs/rules/block-spacing.md | 12 +++ .../eslint-plugin/src/rules/block-spacing.ts | 40 ++++++++++ .../src/util/getESLintCoreRule.ts | 1 + .../tests/rules/block-spacing.test.ts | 80 +++++++++++++++++++ .../eslint-plugin/typings/eslint-rules.d.ts | 15 ++++ 5 files changed, 148 insertions(+) create mode 100644 packages/eslint-plugin/docs/rules/block-spacing.md create mode 100644 packages/eslint-plugin/src/rules/block-spacing.ts create mode 100644 packages/eslint-plugin/tests/rules/block-spacing.test.ts diff --git a/packages/eslint-plugin/docs/rules/block-spacing.md b/packages/eslint-plugin/docs/rules/block-spacing.md new file mode 100644 index 00000000000..667c8b9bc84 --- /dev/null +++ b/packages/eslint-plugin/docs/rules/block-spacing.md @@ -0,0 +1,12 @@ +--- +description: 'Enforce consistent spacing before and after keywords.' +--- + +> 🛑 This file is source code, not the primary documentation location! 🛑 +> +> See **https://typescript-eslint.io/rules/block-spacing** for documentation. + +## Examples + +This rule extends the base [`eslint/block-spacing`](https://eslint.org/docs/rules/block-spacing) rule. +This version adds support for generic type parameters on function calls. diff --git a/packages/eslint-plugin/src/rules/block-spacing.ts b/packages/eslint-plugin/src/rules/block-spacing.ts new file mode 100644 index 00000000000..523cd949eca --- /dev/null +++ b/packages/eslint-plugin/src/rules/block-spacing.ts @@ -0,0 +1,40 @@ +import type { TSESTree } from '@typescript-eslint/utils'; +import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; + +import * as util from '../util'; +import { getESLintCoreRule } from '../util/getESLintCoreRule'; + +const baseRule = getESLintCoreRule('block-spacing'); + +export type Options = util.InferOptionsTypeFromRule; +export type MessageIds = util.InferMessageIdsTypeFromRule; + +export default util.createRule({ + name: 'block-spacing', + meta: { + type: 'layout', + docs: { + description: 'Enforce consistent spacing before and after keywords', + recommended: false, + extendsBaseRule: true, + }, + fixable: 'whitespace', + hasSuggestions: baseRule.meta.hasSuggestions, + schema: baseRule.meta.schema, + messages: baseRule.meta.messages, + }, + defaultOptions: ['always'], + + create(context, [whenToApplyOption]) { + const sourceCode = context.getSourceCode(); + const baseRules = baseRule.create(context); + return { + ...baseRules, + // TSInterfaceBody(node): void {}, + // TSTypeLiteral(node): void {}, + + TSInterfaceBody: baseRules.BlockStatement as never, + TSTypeLiteral: baseRules.BlockStatement as never, + }; + }, +}); diff --git a/packages/eslint-plugin/src/util/getESLintCoreRule.ts b/packages/eslint-plugin/src/util/getESLintCoreRule.ts index 1678903acd3..a4bad9c00af 100644 --- a/packages/eslint-plugin/src/util/getESLintCoreRule.ts +++ b/packages/eslint-plugin/src/util/getESLintCoreRule.ts @@ -7,6 +7,7 @@ const isESLintV8 = semver.major(version) >= 8; interface RuleMap { /* eslint-disable @typescript-eslint/consistent-type-imports -- more concise to use inline imports */ 'arrow-parens': typeof import('eslint/lib/rules/arrow-parens'); + 'block-spacing': typeof import('eslint/lib/rules/block-spacing'); 'brace-style': typeof import('eslint/lib/rules/brace-style'); 'comma-dangle': typeof import('eslint/lib/rules/comma-dangle'); 'dot-notation': typeof import('eslint/lib/rules/dot-notation'); diff --git a/packages/eslint-plugin/tests/rules/block-spacing.test.ts b/packages/eslint-plugin/tests/rules/block-spacing.test.ts new file mode 100644 index 00000000000..1ab625ea9c3 --- /dev/null +++ b/packages/eslint-plugin/tests/rules/block-spacing.test.ts @@ -0,0 +1,80 @@ +/* eslint-disable eslint-comments/no-use */ +// this rule tests the spacing, which prettier will want to fix and break the tests +/* eslint "@typescript-eslint/internal/plugin-test-formatting": ["error", { formatWithPrettier: false }] */ +/* eslint-enable eslint-comments/no-use */ +import { AST_NODE_TYPES, TSESLint } from '@typescript-eslint/utils'; + +import type { MessageIds, Options } from '../../src/rules/block-spacing'; +import rule from '../../src/rules/block-spacing'; +import type { InvalidTestCase } from '../RuleTester'; +import { RuleTester } from '../RuleTester'; + +const ruleTester = new RuleTester({ + parser: '@typescript-eslint/parser', +}); + +type InvalidBlockSpacingTestCase = InvalidTestCase< + 'missing' | 'extra', + ['always' | 'never'] +>; + +const options = [['always'], ['never']] as const; +const typeDeclaration = [ + { + nodeType: AST_NODE_TYPES.TSInterfaceBody, + stringPrefix: 'interface Foo ', + }, + { + nodeType: AST_NODE_TYPES.TSTypeLiteral, + stringPrefix: 'type Foo = ', + }, +]; +const emptyBlocks = ['{}', '{ }']; +const singlePropertyBlocks = ['{bar: true}', '{ bar: true }']; + +ruleTester.run('block-spacing', rule, { + valid: [ + // Empty blocks don't apply + ...options.flatMap(options => + typeDeclaration.flatMap(typeDec => + emptyBlocks.map(blockType => ({ + code: typeDec.stringPrefix + blockType, + options, + })), + ), + ), + ], + invalid: [ + ...options.flatMap(options => + typeDeclaration.flatMap(typeDec => + singlePropertyBlocks.map( + (blockType, blockIndex) => { + return { + code: typeDec.stringPrefix + blockType, + options, + output: + typeDec.stringPrefix + singlePropertyBlocks[1 - blockIndex], + errors: [ + { + type: typeDec.nodeType, + // line: 1, + // column: 1, + messageId: 'missing', + data: { location: 'after', token: '{' }, + }, + { + type: typeDec.nodeType, + // line: 1, + // column: 8, + messageId: 'missing', + data: { location: 'before', token: '}' }, + }, + ], + }; + }, + ), + ), + ), + // .filter(_case => JSON.stringify(_case).includes('type ')), + ], +}); diff --git a/packages/eslint-plugin/typings/eslint-rules.d.ts b/packages/eslint-plugin/typings/eslint-rules.d.ts index 09b54ae4a51..77ca513d1fb 100644 --- a/packages/eslint-plugin/typings/eslint-rules.d.ts +++ b/packages/eslint-plugin/typings/eslint-rules.d.ts @@ -609,6 +609,21 @@ declare module 'eslint/lib/rules/quotes' { export = rule; } +declare module 'eslint/lib/rules/block-spacing' { + import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; + + const rule: TSESLint.RuleModule< + 'missing' | 'extra', + ['always' | 'never'], + { + BlockStatement(node: TSESTree.BlockStatement): void; + StaticBlock(node: TSESTree.StaticBlock): void; + SwitchStatement(node: TSESTree.SwitchStatement): void; + } + >; + export = rule; +} + declare module 'eslint/lib/rules/brace-style' { import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; From f39392891527842760555dc93c66ea1b17f092d5 Mon Sep 17 00:00:00 2001 From: Omri Luzon Date: Sat, 10 Dec 2022 00:02:22 +0200 Subject: [PATCH 02/18] for history --- .../eslint-plugin/src/rules/block-spacing.ts | 155 +++++++++++++++++- 1 file changed, 151 insertions(+), 4 deletions(-) diff --git a/packages/eslint-plugin/src/rules/block-spacing.ts b/packages/eslint-plugin/src/rules/block-spacing.ts index 523cd949eca..6d05ea22e3a 100644 --- a/packages/eslint-plugin/src/rules/block-spacing.ts +++ b/packages/eslint-plugin/src/rules/block-spacing.ts @@ -28,13 +28,160 @@ export default util.createRule({ create(context, [whenToApplyOption]) { const sourceCode = context.getSourceCode(); const baseRules = baseRule.create(context); + const always = whenToApplyOption !== 'never'; + const messageId = always ? 'missing' : 'extra'; + /** + * Gets the open brace token from a given node. + * @returns The token of the open brace. + */ + function getOpenBrace( + node: TSESTree.TSInterfaceBody | TSESTree.TSTypeLiteral, + ): + | TSESTree.BooleanToken + | TSESTree.IdentifierToken + | TSESTree.JSXIdentifierToken + | TSESTree.JSXTextToken + | TSESTree.KeywordToken + | TSESTree.NullToken + | TSESTree.NumericToken + | TSESTree.PunctuatorToken + | TSESTree.RegularExpressionToken + | TSESTree.StringToken + | TSESTree.TemplateToken { + if (node.type === AST_NODE_TYPES.TSInterfaceBody) { + return sourceCode.getFirstToken(node, { skip: 0 })!; + } + if (node.type === AST_NODE_TYPES.TSTypeLiteral) { + return sourceCode.getFirstToken(node, { skip: 0 })!; + } + + return sourceCode.getFirstToken(node)!; + } + + /** + * Checks whether or not: + * - given tokens are on same line. + * - there is/isn't a space between given tokens. + * @param left A token to check. + * @param right The token which is next to `left`. + * @returns + * When the option is `"always"`, `true` if there are one or more spaces between given tokens. + * When the option is `"never"`, `true` if there are not any spaces between given tokens. + * If given tokens are not on same line, it's always `true`. + */ + function isValid(left: TSESTree.Token, right: TSESTree.Token): boolean { + // console.log({ + // 'sourceCode.text,': sourceCode.text, + // 'whenToApplyOption,': whenToApplyOption, + // 'always,': always, + // 'messageId,': messageId, + // 'left,': left, + // 'right,': right, + // '!util.isTokenOnSameLine(left, right),': !util.isTokenOnSameLine(left, right), + // 'sourceCode.isSpaceBetween!(left, right) === always': sourceCode.isSpaceBetween!(left, right) === always + // }); + return ( + !util.isTokenOnSameLine(left, right) || + sourceCode.isSpaceBetween!(left, right) === always + ); + } + + /** + * Checks and reports invalid spacing style inside braces. + * @param {ASTNode} node A BlockStatement/StaticBlock/SwitchStatement node to check. + * @returns + */ + function checkSpacingInsideBraces( + node: TSESTree.TSInterfaceBody | TSESTree.TSTypeLiteral, + ): void { + // Gets braces and the first/last token of content. + const openBrace = getOpenBrace(node); + const closeBrace = sourceCode.getLastToken(node)!; + const firstToken = sourceCode.getTokenAfter(openBrace, { + includeComments: true, + })!; + const lastToken = sourceCode.getTokenBefore(closeBrace, { + includeComments: true, + })!; + + // Skip if the node is invalid or empty. + if ( + openBrace.type !== AST_TOKEN_TYPES.Punctuator || + openBrace.value !== '{' || + closeBrace.type !== AST_TOKEN_TYPES.Punctuator || + closeBrace.value !== '}' || + firstToken === closeBrace + ) { + return; + } + + // Skip line comments for option never + if (!always && firstToken.type === AST_TOKEN_TYPES.Line) { + return; + } + + // Check. + if (!isValid(openBrace, firstToken)) { + let loc = openBrace.loc; + + if (messageId === 'extra') { + loc = { + start: openBrace.loc.end, + end: firstToken.loc.start, + }; + } + + context.report({ + node, + loc, + messageId, + data: { + location: 'after', + token: openBrace.value, + }, + fix(fixer) { + if (always) { + return fixer.insertTextBefore(firstToken, ' '); + } + + return fixer.removeRange([openBrace.range[1], firstToken.range[0]]); + }, + }); + } + if (!isValid(lastToken, closeBrace)) { + let loc = closeBrace.loc; + + if (messageId === 'extra') { + loc = { + start: lastToken.loc.end, + end: closeBrace.loc.start, + }; + } + context.report({ + node, + loc, + messageId, + data: { + location: 'before', + token: closeBrace.value, + }, + fix(fixer) { + if (always) { + return fixer.insertTextAfter(lastToken, ' '); + } + + return fixer.removeRange([lastToken.range[1], closeBrace.range[0]]); + }, + }); + } + } return { ...baseRules, - // TSInterfaceBody(node): void {}, - // TSTypeLiteral(node): void {}, + TSInterfaceBody: checkSpacingInsideBraces, + TSTypeLiteral: checkSpacingInsideBraces, - TSInterfaceBody: baseRules.BlockStatement as never, - TSTypeLiteral: baseRules.BlockStatement as never, + // TSInterfaceBody: baseRules.BlockStatement as never, + // TSTypeLiteral: baseRules.BlockStatement as never, }; }, }); From 0067b46e14ba2d38583fb3c51c886748d16ad558 Mon Sep 17 00:00:00 2001 From: Omri Luzon Date: Sat, 10 Dec 2022 00:03:51 +0200 Subject: [PATCH 03/18] fixes --- .../eslint-plugin/src/rules/block-spacing.ts | 159 +----------------- .../tests/rules/block-spacing.test.ts | 13 +- 2 files changed, 12 insertions(+), 160 deletions(-) diff --git a/packages/eslint-plugin/src/rules/block-spacing.ts b/packages/eslint-plugin/src/rules/block-spacing.ts index 6d05ea22e3a..4a4004efed4 100644 --- a/packages/eslint-plugin/src/rules/block-spacing.ts +++ b/packages/eslint-plugin/src/rules/block-spacing.ts @@ -1,6 +1,3 @@ -import type { TSESTree } from '@typescript-eslint/utils'; -import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; - import * as util from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; @@ -25,163 +22,13 @@ export default util.createRule({ }, defaultOptions: ['always'], - create(context, [whenToApplyOption]) { - const sourceCode = context.getSourceCode(); + create(context) { const baseRules = baseRule.create(context); - const always = whenToApplyOption !== 'never'; - const messageId = always ? 'missing' : 'extra'; - /** - * Gets the open brace token from a given node. - * @returns The token of the open brace. - */ - function getOpenBrace( - node: TSESTree.TSInterfaceBody | TSESTree.TSTypeLiteral, - ): - | TSESTree.BooleanToken - | TSESTree.IdentifierToken - | TSESTree.JSXIdentifierToken - | TSESTree.JSXTextToken - | TSESTree.KeywordToken - | TSESTree.NullToken - | TSESTree.NumericToken - | TSESTree.PunctuatorToken - | TSESTree.RegularExpressionToken - | TSESTree.StringToken - | TSESTree.TemplateToken { - if (node.type === AST_NODE_TYPES.TSInterfaceBody) { - return sourceCode.getFirstToken(node, { skip: 0 })!; - } - if (node.type === AST_NODE_TYPES.TSTypeLiteral) { - return sourceCode.getFirstToken(node, { skip: 0 })!; - } - - return sourceCode.getFirstToken(node)!; - } - - /** - * Checks whether or not: - * - given tokens are on same line. - * - there is/isn't a space between given tokens. - * @param left A token to check. - * @param right The token which is next to `left`. - * @returns - * When the option is `"always"`, `true` if there are one or more spaces between given tokens. - * When the option is `"never"`, `true` if there are not any spaces between given tokens. - * If given tokens are not on same line, it's always `true`. - */ - function isValid(left: TSESTree.Token, right: TSESTree.Token): boolean { - // console.log({ - // 'sourceCode.text,': sourceCode.text, - // 'whenToApplyOption,': whenToApplyOption, - // 'always,': always, - // 'messageId,': messageId, - // 'left,': left, - // 'right,': right, - // '!util.isTokenOnSameLine(left, right),': !util.isTokenOnSameLine(left, right), - // 'sourceCode.isSpaceBetween!(left, right) === always': sourceCode.isSpaceBetween!(left, right) === always - // }); - return ( - !util.isTokenOnSameLine(left, right) || - sourceCode.isSpaceBetween!(left, right) === always - ); - } - - /** - * Checks and reports invalid spacing style inside braces. - * @param {ASTNode} node A BlockStatement/StaticBlock/SwitchStatement node to check. - * @returns - */ - function checkSpacingInsideBraces( - node: TSESTree.TSInterfaceBody | TSESTree.TSTypeLiteral, - ): void { - // Gets braces and the first/last token of content. - const openBrace = getOpenBrace(node); - const closeBrace = sourceCode.getLastToken(node)!; - const firstToken = sourceCode.getTokenAfter(openBrace, { - includeComments: true, - })!; - const lastToken = sourceCode.getTokenBefore(closeBrace, { - includeComments: true, - })!; - - // Skip if the node is invalid or empty. - if ( - openBrace.type !== AST_TOKEN_TYPES.Punctuator || - openBrace.value !== '{' || - closeBrace.type !== AST_TOKEN_TYPES.Punctuator || - closeBrace.value !== '}' || - firstToken === closeBrace - ) { - return; - } - - // Skip line comments for option never - if (!always && firstToken.type === AST_TOKEN_TYPES.Line) { - return; - } - - // Check. - if (!isValid(openBrace, firstToken)) { - let loc = openBrace.loc; - - if (messageId === 'extra') { - loc = { - start: openBrace.loc.end, - end: firstToken.loc.start, - }; - } - - context.report({ - node, - loc, - messageId, - data: { - location: 'after', - token: openBrace.value, - }, - fix(fixer) { - if (always) { - return fixer.insertTextBefore(firstToken, ' '); - } - - return fixer.removeRange([openBrace.range[1], firstToken.range[0]]); - }, - }); - } - if (!isValid(lastToken, closeBrace)) { - let loc = closeBrace.loc; - - if (messageId === 'extra') { - loc = { - start: lastToken.loc.end, - end: closeBrace.loc.start, - }; - } - context.report({ - node, - loc, - messageId, - data: { - location: 'before', - token: closeBrace.value, - }, - fix(fixer) { - if (always) { - return fixer.insertTextAfter(lastToken, ' '); - } - - return fixer.removeRange([lastToken.range[1], closeBrace.range[0]]); - }, - }); - } - } return { ...baseRules, - TSInterfaceBody: checkSpacingInsideBraces, - TSTypeLiteral: checkSpacingInsideBraces, - // TSInterfaceBody: baseRules.BlockStatement as never, - // TSTypeLiteral: baseRules.BlockStatement as never, + TSInterfaceBody: baseRules.BlockStatement as never, + TSTypeLiteral: baseRules.BlockStatement as never, }; }, }); diff --git a/packages/eslint-plugin/tests/rules/block-spacing.test.ts b/packages/eslint-plugin/tests/rules/block-spacing.test.ts index 1ab625ea9c3..b2394b5e814 100644 --- a/packages/eslint-plugin/tests/rules/block-spacing.test.ts +++ b/packages/eslint-plugin/tests/rules/block-spacing.test.ts @@ -47,8 +47,14 @@ ruleTester.run('block-spacing', rule, { invalid: [ ...options.flatMap(options => typeDeclaration.flatMap(typeDec => - singlePropertyBlocks.map( + singlePropertyBlocks.flatMap( (blockType, blockIndex) => { + if ( + (options[0] === 'always' && blockType.startsWith('{ ')) || + (options[0] === 'never' && blockType.startsWith('{bar')) + ) { + return []; + } return { code: typeDec.stringPrefix + blockType, options, @@ -59,14 +65,14 @@ ruleTester.run('block-spacing', rule, { type: typeDec.nodeType, // line: 1, // column: 1, - messageId: 'missing', + messageId: options[0] === 'always' ? 'missing' : 'extra', data: { location: 'after', token: '{' }, }, { type: typeDec.nodeType, // line: 1, // column: 8, - messageId: 'missing', + messageId: options[0] === 'always' ? 'missing' : 'extra', data: { location: 'before', token: '}' }, }, ], @@ -75,6 +81,5 @@ ruleTester.run('block-spacing', rule, { ), ), ), - // .filter(_case => JSON.stringify(_case).includes('type ')), ], }); From 7e8b5403d0c48b3b7beb6f0a81993ee8c942e636 Mon Sep 17 00:00:00 2001 From: Omri Luzon Date: Sat, 10 Dec 2022 00:28:50 +0200 Subject: [PATCH 04/18] cleanup --- .../tests/rules/block-spacing.test.ts | 34 +++++++------------ 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/block-spacing.test.ts b/packages/eslint-plugin/tests/rules/block-spacing.test.ts index b2394b5e814..4935f715bea 100644 --- a/packages/eslint-plugin/tests/rules/block-spacing.test.ts +++ b/packages/eslint-plugin/tests/rules/block-spacing.test.ts @@ -1,12 +1,7 @@ -/* eslint-disable eslint-comments/no-use */ -// this rule tests the spacing, which prettier will want to fix and break the tests -/* eslint "@typescript-eslint/internal/plugin-test-formatting": ["error", { formatWithPrettier: false }] */ -/* eslint-enable eslint-comments/no-use */ -import { AST_NODE_TYPES, TSESLint } from '@typescript-eslint/utils'; +import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import type { MessageIds, Options } from '../../src/rules/block-spacing'; import rule from '../../src/rules/block-spacing'; -import type { InvalidTestCase } from '../RuleTester'; +import type { InvalidTestCase, ValidTestCase } from '../RuleTester'; import { RuleTester } from '../RuleTester'; const ruleTester = new RuleTester({ @@ -18,7 +13,7 @@ type InvalidBlockSpacingTestCase = InvalidTestCase< ['always' | 'never'] >; -const options = [['always'], ['never']] as const; +const options = ['always', 'never'] as const; const typeDeclaration = [ { nodeType: AST_NODE_TYPES.TSInterfaceBody, @@ -35,44 +30,41 @@ const singlePropertyBlocks = ['{bar: true}', '{ bar: true }']; ruleTester.run('block-spacing', rule, { valid: [ // Empty blocks don't apply - ...options.flatMap(options => + ...options.flatMap(option => typeDeclaration.flatMap(typeDec => - emptyBlocks.map(blockType => ({ + emptyBlocks.map>(blockType => ({ code: typeDec.stringPrefix + blockType, - options, + options: [option], })), ), ), ], invalid: [ - ...options.flatMap(options => + ...options.flatMap(option => typeDeclaration.flatMap(typeDec => singlePropertyBlocks.flatMap( (blockType, blockIndex) => { + // These are actually valid, so filter them out if ( - (options[0] === 'always' && blockType.startsWith('{ ')) || - (options[0] === 'never' && blockType.startsWith('{bar')) + (option === 'always' && blockType.startsWith('{ ')) || + (option === 'never' && blockType.startsWith('{bar')) ) { return []; } return { code: typeDec.stringPrefix + blockType, - options, + options: [option], output: typeDec.stringPrefix + singlePropertyBlocks[1 - blockIndex], errors: [ { type: typeDec.nodeType, - // line: 1, - // column: 1, - messageId: options[0] === 'always' ? 'missing' : 'extra', + messageId: option === 'always' ? 'missing' : 'extra', data: { location: 'after', token: '{' }, }, { type: typeDec.nodeType, - // line: 1, - // column: 8, - messageId: options[0] === 'always' ? 'missing' : 'extra', + messageId: option === 'always' ? 'missing' : 'extra', data: { location: 'before', token: '}' }, }, ], From 3cd0d6f96f5ce0725f98e1500f6b54469c74827f Mon Sep 17 00:00:00 2001 From: Omri Luzon Date: Sat, 10 Dec 2022 00:30:58 +0200 Subject: [PATCH 05/18] with a comment for the option --- .../eslint-plugin/tests/rules/block-spacing.test.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/block-spacing.test.ts b/packages/eslint-plugin/tests/rules/block-spacing.test.ts index 4935f715bea..162a3791b47 100644 --- a/packages/eslint-plugin/tests/rules/block-spacing.test.ts +++ b/packages/eslint-plugin/tests/rules/block-spacing.test.ts @@ -51,11 +51,17 @@ ruleTester.run('block-spacing', rule, { ) { return []; } + const code = + typeDec.stringPrefix + blockType + `; /* ${option} */`; + const output = + typeDec.stringPrefix + + singlePropertyBlocks[1 - blockIndex] + + `; /* ${option} */`; + return { - code: typeDec.stringPrefix + blockType, + code, options: [option], - output: - typeDec.stringPrefix + singlePropertyBlocks[1 - blockIndex], + output, errors: [ { type: typeDec.nodeType, From 590d9f893174c03e6d6c3d6a957a24fe61ad82c6 Mon Sep 17 00:00:00 2001 From: Omri Luzon Date: Sat, 10 Dec 2022 00:49:45 +0200 Subject: [PATCH 06/18] support enums as well --- .../eslint-plugin/src/rules/block-spacing.ts | 133 +++++++++++++++++- .../tests/rules/block-spacing.test.ts | 25 +++- 2 files changed, 150 insertions(+), 8 deletions(-) diff --git a/packages/eslint-plugin/src/rules/block-spacing.ts b/packages/eslint-plugin/src/rules/block-spacing.ts index 4a4004efed4..1a8d074e6d9 100644 --- a/packages/eslint-plugin/src/rules/block-spacing.ts +++ b/packages/eslint-plugin/src/rules/block-spacing.ts @@ -1,3 +1,6 @@ +import type { TSESTree } from '@typescript-eslint/utils'; +import { AST_TOKEN_TYPES } from '@typescript-eslint/utils'; + import * as util from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; @@ -22,13 +25,141 @@ export default util.createRule({ }, defaultOptions: ['always'], - create(context) { + create(context, [whenToApplyOption]) { + const sourceCode = context.getSourceCode(); const baseRules = baseRule.create(context); + const always = whenToApplyOption !== 'never'; + const messageId = always ? 'missing' : 'extra'; + /** + * Gets the open brace token from a given node. + * @returns The token of the open brace. + */ + function getOpenBrace( + node: TSESTree.TSEnumDeclaration, + ): TSESTree.PunctuatorToken { + // guaranteed for enums + // This is the only change made here from the base rule + return sourceCode.getFirstToken(node, { + filter: token => + token.type === AST_TOKEN_TYPES.Punctuator && token.value == '{', + }) as TSESTree.PunctuatorToken; + } + + /** + * Checks whether or not: + * - given tokens are on same line. + * - there is/isn't a space between given tokens. + * @param left A token to check. + * @param right The token which is next to `left`. + * @returns + * When the option is `"always"`, `true` if there are one or more spaces between given tokens. + * When the option is `"never"`, `true` if there are not any spaces between given tokens. + * If given tokens are not on same line, it's always `true`. + */ + function isValid(left: TSESTree.Token, right: TSESTree.Token): boolean { + return ( + !util.isTokenOnSameLine(left, right) || + sourceCode.isSpaceBetween!(left, right) === always + ); + } + + /** + * Checks and reports invalid spacing style inside braces. + * @param {ASTNode} node A BlockStatement/StaticBlock/SwitchStatement node to check. + * @returns + */ + function checkSpacingInsideBraces(node: TSESTree.TSEnumDeclaration): void { + // Gets braces and the first/last token of content. + const openBrace = getOpenBrace(node); + const closeBrace = sourceCode.getLastToken(node)!; + const firstToken = sourceCode.getTokenAfter(openBrace, { + includeComments: true, + })!; + const lastToken = sourceCode.getTokenBefore(closeBrace, { + includeComments: true, + })!; + + // Skip if the node is invalid or empty. + if ( + openBrace.type !== AST_TOKEN_TYPES.Punctuator || + openBrace.value !== '{' || + closeBrace.type !== AST_TOKEN_TYPES.Punctuator || + closeBrace.value !== '}' || + firstToken === closeBrace + ) { + return; + } + + // Skip line comments for option never + if (!always && firstToken.type === AST_TOKEN_TYPES.Line) { + return; + } + + // Check. + if (!isValid(openBrace, firstToken)) { + let loc = openBrace.loc; + + if (messageId === 'extra') { + loc = { + start: openBrace.loc.end, + end: firstToken.loc.start, + }; + } + + context.report({ + node, + loc, + messageId, + data: { + location: 'after', + token: openBrace.value, + }, + fix(fixer) { + if (always) { + return fixer.insertTextBefore(firstToken, ' '); + } + + return fixer.removeRange([openBrace.range[1], firstToken.range[0]]); + }, + }); + } + if (!isValid(lastToken, closeBrace)) { + let loc = closeBrace.loc; + + if (messageId === 'extra') { + loc = { + start: lastToken.loc.end, + end: closeBrace.loc.start, + }; + } + context.report({ + node, + loc, + messageId, + data: { + location: 'before', + token: closeBrace.value, + }, + fix(fixer) { + if (always) { + return fixer.insertTextAfter(lastToken, ' '); + } + + return fixer.removeRange([lastToken.range[1], closeBrace.range[0]]); + }, + }); + } + } return { ...baseRules, + // This code worked "out of the box" for interface and type literal + // Enums were very close to match as well, the only reason they it not is that was that enums don't have a body node in the parser + // So the opening brace punctuator starts in the middle of the node + // `getFirstToken` in the base rule did not filter for the first opening brace punctuator TSInterfaceBody: baseRules.BlockStatement as never, TSTypeLiteral: baseRules.BlockStatement as never, + TSEnumDeclaration: checkSpacingInsideBraces, }; }, }); diff --git a/packages/eslint-plugin/tests/rules/block-spacing.test.ts b/packages/eslint-plugin/tests/rules/block-spacing.test.ts index 162a3791b47..2471939f372 100644 --- a/packages/eslint-plugin/tests/rules/block-spacing.test.ts +++ b/packages/eslint-plugin/tests/rules/block-spacing.test.ts @@ -23,6 +23,14 @@ const typeDeclaration = [ nodeType: AST_NODE_TYPES.TSTypeLiteral, stringPrefix: 'type Foo = ', }, + { + nodeType: AST_NODE_TYPES.TSEnumDeclaration, + stringPrefix: 'enum Foo ', + }, + { + nodeType: AST_NODE_TYPES.TSEnumDeclaration, + stringPrefix: 'const enum Foo ', + }, ]; const emptyBlocks = ['{}', '{ }']; const singlePropertyBlocks = ['{bar: true}', '{ bar: true }']; @@ -41,8 +49,8 @@ ruleTester.run('block-spacing', rule, { ], invalid: [ ...options.flatMap(option => - typeDeclaration.flatMap(typeDec => - singlePropertyBlocks.flatMap( + typeDeclaration.flatMap(typeDec => { + return singlePropertyBlocks.flatMap( (blockType, blockIndex) => { // These are actually valid, so filter them out if ( @@ -51,12 +59,15 @@ ruleTester.run('block-spacing', rule, { ) { return []; } - const code = - typeDec.stringPrefix + blockType + `; /* ${option} */`; - const output = + let code = typeDec.stringPrefix + blockType + `; /* ${option} */`; + let output = typeDec.stringPrefix + singlePropertyBlocks[1 - blockIndex] + `; /* ${option} */`; + if (typeDec.nodeType === AST_NODE_TYPES.TSEnumDeclaration) { + output = output.replace(':', '='); + code = code.replace(':', '='); + } return { code, @@ -76,8 +87,8 @@ ruleTester.run('block-spacing', rule, { ], }; }, - ), - ), + ); + }), ), ], }); From ab64e29abe3ec0b8483294ea2cf0d5951f1df02a Mon Sep 17 00:00:00 2001 From: Omri Luzon Date: Sat, 10 Dec 2022 00:53:03 +0200 Subject: [PATCH 07/18] template string --- packages/eslint-plugin/tests/rules/block-spacing.test.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/block-spacing.test.ts b/packages/eslint-plugin/tests/rules/block-spacing.test.ts index 2471939f372..c5f4dd22316 100644 --- a/packages/eslint-plugin/tests/rules/block-spacing.test.ts +++ b/packages/eslint-plugin/tests/rules/block-spacing.test.ts @@ -59,11 +59,9 @@ ruleTester.run('block-spacing', rule, { ) { return []; } - let code = typeDec.stringPrefix + blockType + `; /* ${option} */`; - let output = - typeDec.stringPrefix + - singlePropertyBlocks[1 - blockIndex] + - `; /* ${option} */`; + const reverseBlockType = singlePropertyBlocks[1 - blockIndex]; + let code = `${typeDec.stringPrefix}${blockType}; /* ${option} */`; + let output = `${typeDec.stringPrefix}${reverseBlockType}; /* ${option} */`; if (typeDec.nodeType === AST_NODE_TYPES.TSEnumDeclaration) { output = output.replace(':', '='); code = code.replace(':', '='); From 65fa0e6f4bd498c90e27505f16f09ad4c3dd685e Mon Sep 17 00:00:00 2001 From: Omri Luzon Date: Sat, 10 Dec 2022 00:58:57 +0200 Subject: [PATCH 08/18] fix doc --- packages/eslint-plugin/docs/rules/block-spacing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/docs/rules/block-spacing.md b/packages/eslint-plugin/docs/rules/block-spacing.md index 667c8b9bc84..d4e25bafe45 100644 --- a/packages/eslint-plugin/docs/rules/block-spacing.md +++ b/packages/eslint-plugin/docs/rules/block-spacing.md @@ -9,4 +9,4 @@ description: 'Enforce consistent spacing before and after keywords.' ## Examples This rule extends the base [`eslint/block-spacing`](https://eslint.org/docs/rules/block-spacing) rule. -This version adds support for generic type parameters on function calls. +This version adds support for typescript related blocks (interfaces, object type literals and enums). From d38b80e5dd9e830466a64387ca5d0de35057dd9e Mon Sep 17 00:00:00 2001 From: Omri Luzon Date: Sat, 10 Dec 2022 01:00:21 +0200 Subject: [PATCH 09/18] fix doc --- packages/eslint-plugin/src/rules/block-spacing.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/eslint-plugin/src/rules/block-spacing.ts b/packages/eslint-plugin/src/rules/block-spacing.ts index 1a8d074e6d9..3224afb8337 100644 --- a/packages/eslint-plugin/src/rules/block-spacing.ts +++ b/packages/eslint-plugin/src/rules/block-spacing.ts @@ -14,7 +14,8 @@ export default util.createRule({ meta: { type: 'layout', docs: { - description: 'Enforce consistent spacing before and after keywords', + description: + 'Disallow or enforce spaces inside of blocks after opening block and before closing block', recommended: false, extendsBaseRule: true, }, From dbe273ccf4a5e0ec62b386106845201832ac0937 Mon Sep 17 00:00:00 2001 From: Omri Luzon Date: Sat, 10 Dec 2022 01:13:46 +0200 Subject: [PATCH 10/18] typescript -> TypeScript --- packages/eslint-plugin/docs/rules/block-spacing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/docs/rules/block-spacing.md b/packages/eslint-plugin/docs/rules/block-spacing.md index d4e25bafe45..e0d59fd8284 100644 --- a/packages/eslint-plugin/docs/rules/block-spacing.md +++ b/packages/eslint-plugin/docs/rules/block-spacing.md @@ -9,4 +9,4 @@ description: 'Enforce consistent spacing before and after keywords.' ## Examples This rule extends the base [`eslint/block-spacing`](https://eslint.org/docs/rules/block-spacing) rule. -This version adds support for typescript related blocks (interfaces, object type literals and enums). +This version adds support for TypeScript related blocks (interfaces, object type literals and enums). From 2496815c002016966b3b5b857730f0cc1a2a99ab Mon Sep 17 00:00:00 2001 From: Omri Luzon Date: Sat, 10 Dec 2022 02:10:30 +0200 Subject: [PATCH 11/18] add missing things --- packages/eslint-plugin/docs/rules/block-spacing.md | 2 +- packages/eslint-plugin/src/configs/all.ts | 2 ++ packages/eslint-plugin/src/rules/index.ts | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/eslint-plugin/docs/rules/block-spacing.md b/packages/eslint-plugin/docs/rules/block-spacing.md index e0d59fd8284..6a902214bbb 100644 --- a/packages/eslint-plugin/docs/rules/block-spacing.md +++ b/packages/eslint-plugin/docs/rules/block-spacing.md @@ -1,5 +1,5 @@ --- -description: 'Enforce consistent spacing before and after keywords.' +description: 'Disallow or enforce spaces inside of blocks after opening block and before closing block.' --- > 🛑 This file is source code, not the primary documentation location! 🛑 diff --git a/packages/eslint-plugin/src/configs/all.ts b/packages/eslint-plugin/src/configs/all.ts index 20ea892f581..a7e246de2d3 100644 --- a/packages/eslint-plugin/src/configs/all.ts +++ b/packages/eslint-plugin/src/configs/all.ts @@ -11,6 +11,8 @@ export = { '@typescript-eslint/ban-ts-comment': 'error', '@typescript-eslint/ban-tslint-comment': 'error', '@typescript-eslint/ban-types': 'error', + 'block-spacing': 'off', + '@typescript-eslint/block-spacing': 'error', 'brace-style': 'off', '@typescript-eslint/brace-style': 'error', '@typescript-eslint/class-literal-property-style': 'error', diff --git a/packages/eslint-plugin/src/rules/index.ts b/packages/eslint-plugin/src/rules/index.ts index 8a3c2bbf437..468c60954a1 100644 --- a/packages/eslint-plugin/src/rules/index.ts +++ b/packages/eslint-plugin/src/rules/index.ts @@ -4,6 +4,7 @@ import awaitThenable from './await-thenable'; import banTsComment from './ban-ts-comment'; import banTslintComment from './ban-tslint-comment'; import banTypes from './ban-types'; +import blockSpacing from './block-spacing'; import braceStyle from './brace-style'; import classLiteralPropertyStyle from './class-literal-property-style'; import commaDangle from './comma-dangle'; @@ -135,6 +136,7 @@ export default { 'ban-ts-comment': banTsComment, 'ban-tslint-comment': banTslintComment, 'ban-types': banTypes, + 'block-spacing': blockSpacing, 'brace-style': braceStyle, 'class-literal-property-style': classLiteralPropertyStyle, 'comma-dangle': commaDangle, From 21a44faacee36a128ff20433e618170ab1d522a1 Mon Sep 17 00:00:00 2001 From: Omri Luzon Date: Sat, 17 Dec 2022 01:03:51 +0200 Subject: [PATCH 12/18] CR: remove jsdoc types --- packages/eslint-plugin/src/rules/block-spacing.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/eslint-plugin/src/rules/block-spacing.ts b/packages/eslint-plugin/src/rules/block-spacing.ts index 3224afb8337..224dec2a119 100644 --- a/packages/eslint-plugin/src/rules/block-spacing.ts +++ b/packages/eslint-plugin/src/rules/block-spacing.ts @@ -66,8 +66,6 @@ export default util.createRule({ /** * Checks and reports invalid spacing style inside braces. - * @param {ASTNode} node A BlockStatement/StaticBlock/SwitchStatement node to check. - * @returns */ function checkSpacingInsideBraces(node: TSESTree.TSEnumDeclaration): void { // Gets braces and the first/last token of content. @@ -96,7 +94,6 @@ export default util.createRule({ return; } - // Check. if (!isValid(openBrace, firstToken)) { let loc = openBrace.loc; From 82ec70db405a8435919a16429e2df91c5aa897c4 Mon Sep 17 00:00:00 2001 From: Omri Luzon Date: Sat, 17 Dec 2022 01:18:25 +0200 Subject: [PATCH 13/18] rename typeDeclaration -> typeDeclarations --- packages/eslint-plugin/tests/rules/block-spacing.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/block-spacing.test.ts b/packages/eslint-plugin/tests/rules/block-spacing.test.ts index c5f4dd22316..9674e91797b 100644 --- a/packages/eslint-plugin/tests/rules/block-spacing.test.ts +++ b/packages/eslint-plugin/tests/rules/block-spacing.test.ts @@ -14,7 +14,7 @@ type InvalidBlockSpacingTestCase = InvalidTestCase< >; const options = ['always', 'never'] as const; -const typeDeclaration = [ +const typeDeclarations = [ { nodeType: AST_NODE_TYPES.TSInterfaceBody, stringPrefix: 'interface Foo ', @@ -39,7 +39,7 @@ ruleTester.run('block-spacing', rule, { valid: [ // Empty blocks don't apply ...options.flatMap(option => - typeDeclaration.flatMap(typeDec => + typeDeclarations.flatMap(typeDec => emptyBlocks.map>(blockType => ({ code: typeDec.stringPrefix + blockType, options: [option], @@ -49,7 +49,7 @@ ruleTester.run('block-spacing', rule, { ], invalid: [ ...options.flatMap(option => - typeDeclaration.flatMap(typeDec => { + typeDeclarations.flatMap(typeDec => { return singlePropertyBlocks.flatMap( (blockType, blockIndex) => { // These are actually valid, so filter them out From cef520c561356bc021cfc59ab8be30eb45663d27 Mon Sep 17 00:00:00 2001 From: Omri Luzon Date: Sat, 17 Dec 2022 01:20:13 +0200 Subject: [PATCH 14/18] more valid cases with comments --- .../tests/rules/block-spacing.test.ts | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/packages/eslint-plugin/tests/rules/block-spacing.test.ts b/packages/eslint-plugin/tests/rules/block-spacing.test.ts index 9674e91797b..be16269f2a6 100644 --- a/packages/eslint-plugin/tests/rules/block-spacing.test.ts +++ b/packages/eslint-plugin/tests/rules/block-spacing.test.ts @@ -46,6 +46,28 @@ ruleTester.run('block-spacing', rule, { })), ), ), + ...typeDeclarations.flatMap>( + typeDec => { + const property = + typeDec.nodeType === AST_NODE_TYPES.TSEnumDeclaration + ? 'bar = 1' + : 'bar: true;'; + return [ + { + code: `${typeDec.stringPrefix}{ /* comment */ ${property} /* comment */ } // always`, + options: ['always'], + }, + { + code: `${typeDec.stringPrefix}{/* comment */ ${property} /* comment */} // never`, + options: ['never'], + }, + { + code: `${typeDec.stringPrefix}{ //comment\n ${property}}`, + options: ['never'], + }, + ]; + }, + ), ], invalid: [ ...options.flatMap(option => From 415733a51ad2736d9c869a8e158b493b19af5dbd Mon Sep 17 00:00:00 2001 From: Omri Luzon Date: Sat, 17 Dec 2022 01:27:49 +0200 Subject: [PATCH 15/18] invalid cases with block comments --- .../tests/rules/block-spacing.test.ts | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/packages/eslint-plugin/tests/rules/block-spacing.test.ts b/packages/eslint-plugin/tests/rules/block-spacing.test.ts index be16269f2a6..64840461adb 100644 --- a/packages/eslint-plugin/tests/rules/block-spacing.test.ts +++ b/packages/eslint-plugin/tests/rules/block-spacing.test.ts @@ -110,5 +110,49 @@ ruleTester.run('block-spacing', rule, { ); }), ), + + // With block comments + ...typeDeclarations.flatMap(typeDec => { + const property = + typeDec.nodeType === AST_NODE_TYPES.TSEnumDeclaration + ? 'bar = 1' + : 'bar: true;'; + return [ + { + code: `${typeDec.stringPrefix}{ /* comment */ ${property} /* comment */ } /* never */`, + output: `${typeDec.stringPrefix}{/* comment */ ${property} /* comment */} /* never */`, + options: ['never'], + errors: [ + { + type: typeDec.nodeType, + messageId: 'extra', + data: { location: 'after', token: '{' }, + }, + { + type: typeDec.nodeType, + messageId: 'extra', + data: { location: 'before', token: '}' }, + }, + ], + }, + { + code: `${typeDec.stringPrefix}{/* comment */ ${property} /* comment */} /* always */`, + output: `${typeDec.stringPrefix}{ /* comment */ ${property} /* comment */ } /* always */`, + options: ['always'], + errors: [ + { + type: typeDec.nodeType, + messageId: 'missing', + data: { location: 'after', token: '{' }, + }, + { + type: typeDec.nodeType, + messageId: 'missing', + data: { location: 'before', token: '}' }, + }, + ], + }, + ]; + }), ], }); From 725d8a9bae5181b955145ca08a0334cc6da58e2c Mon Sep 17 00:00:00 2001 From: Omri Luzon Date: Sat, 17 Dec 2022 01:42:23 +0200 Subject: [PATCH 16/18] more concise --- .../tests/rules/block-spacing.test.ts | 73 ++++++++----------- 1 file changed, 30 insertions(+), 43 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/block-spacing.test.ts b/packages/eslint-plugin/tests/rules/block-spacing.test.ts index 64840461adb..49578b8c061 100644 --- a/packages/eslint-plugin/tests/rules/block-spacing.test.ts +++ b/packages/eslint-plugin/tests/rules/block-spacing.test.ts @@ -34,6 +34,7 @@ const typeDeclarations = [ ]; const emptyBlocks = ['{}', '{ }']; const singlePropertyBlocks = ['{bar: true}', '{ bar: true }']; +const blockComment = '/* comment */'; ruleTester.run('block-spacing', rule, { valid: [ @@ -110,49 +111,35 @@ ruleTester.run('block-spacing', rule, { ); }), ), - // With block comments - ...typeDeclarations.flatMap(typeDec => { - const property = - typeDec.nodeType === AST_NODE_TYPES.TSEnumDeclaration - ? 'bar = 1' - : 'bar: true;'; - return [ - { - code: `${typeDec.stringPrefix}{ /* comment */ ${property} /* comment */ } /* never */`, - output: `${typeDec.stringPrefix}{/* comment */ ${property} /* comment */} /* never */`, - options: ['never'], - errors: [ - { - type: typeDec.nodeType, - messageId: 'extra', - data: { location: 'after', token: '{' }, - }, - { - type: typeDec.nodeType, - messageId: 'extra', - data: { location: 'before', token: '}' }, - }, - ], - }, - { - code: `${typeDec.stringPrefix}{/* comment */ ${property} /* comment */} /* always */`, - output: `${typeDec.stringPrefix}{ /* comment */ ${property} /* comment */ } /* always */`, - options: ['always'], - errors: [ - { - type: typeDec.nodeType, - messageId: 'missing', - data: { location: 'after', token: '{' }, - }, - { - type: typeDec.nodeType, - messageId: 'missing', - data: { location: 'before', token: '}' }, - }, - ], - }, - ]; - }), + ...options.flatMap(option => + typeDeclarations.flatMap(typeDec => { + const property = + typeDec.nodeType === AST_NODE_TYPES.TSEnumDeclaration + ? 'bar = 1' + : 'bar: true;'; + const alwaysSpace = option === 'always' ? '' : ' '; + const neverSpace = option === 'always' ? ' ' : ''; + return [ + { + code: `${typeDec.stringPrefix}{${alwaysSpace}${blockComment}${property}${blockComment}${alwaysSpace}} /* ${option} */`, + output: `${typeDec.stringPrefix}{${neverSpace}${blockComment}${property}${blockComment}${neverSpace}} /* ${option} */`, + options: [option], + errors: [ + { + type: typeDec.nodeType, + messageId: option === 'always' ? 'missing' : 'extra', + data: { location: 'after', token: '{' }, + }, + { + type: typeDec.nodeType, + messageId: option === 'always' ? 'missing' : 'extra', + data: { location: 'before', token: '}' }, + }, + ], + }, + ]; + }), + ), ], }); From 6fd6ffbc4cca5b388c8408439300c86caef957c4 Mon Sep 17 00:00:00 2001 From: Omri Luzon Date: Thu, 22 Dec 2022 07:14:48 +0200 Subject: [PATCH 17/18] fix comment --- packages/eslint-plugin/src/rules/block-spacing.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/eslint-plugin/src/rules/block-spacing.ts b/packages/eslint-plugin/src/rules/block-spacing.ts index 224dec2a119..45e6eb2bfd5 100644 --- a/packages/eslint-plugin/src/rules/block-spacing.ts +++ b/packages/eslint-plugin/src/rules/block-spacing.ts @@ -152,9 +152,9 @@ export default util.createRule({ ...baseRules, // This code worked "out of the box" for interface and type literal - // Enums were very close to match as well, the only reason they it not is that was that enums don't have a body node in the parser - // So the opening brace punctuator starts in the middle of the node - // `getFirstToken` in the base rule did not filter for the first opening brace punctuator + // Enums were very close to match as well, the only reason they are not is that was that enums don't have a body node in the parser + // So the opening brace punctuator starts in the middle of the node - `getFirstToken` in + // the base rule did not filter for the first opening brace punctuator TSInterfaceBody: baseRules.BlockStatement as never, TSTypeLiteral: baseRules.BlockStatement as never, TSEnumDeclaration: checkSpacingInsideBraces, From b6b1140b3ff246a1d8c3dbb233be67c5b43820b8 Mon Sep 17 00:00:00 2001 From: Omri Luzon Date: Tue, 7 Feb 2023 22:15:42 +0200 Subject: [PATCH 18/18] fix lint error --- packages/eslint-plugin/src/rules/block-spacing.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/src/rules/block-spacing.ts b/packages/eslint-plugin/src/rules/block-spacing.ts index 45e6eb2bfd5..745132978f7 100644 --- a/packages/eslint-plugin/src/rules/block-spacing.ts +++ b/packages/eslint-plugin/src/rules/block-spacing.ts @@ -42,7 +42,7 @@ export default util.createRule({ // This is the only change made here from the base rule return sourceCode.getFirstToken(node, { filter: token => - token.type === AST_TOKEN_TYPES.Punctuator && token.value == '{', + token.type === AST_TOKEN_TYPES.Punctuator && token.value === '{', }) as TSESTree.PunctuatorToken; }