From 9caa9ebf0a3d23781eab3f9cadd91eb356c0c460 Mon Sep 17 00:00:00 2001 From: cherryblossom Date: Tue, 29 Nov 2022 09:29:17 +1100 Subject: [PATCH] chore: create typeNodeRequiresParentheses utility --- .../src/rules/sort-type-constituents.ts | 25 ++++++------------- .../sort-type-union-intersection-members.ts | 25 ++++++------------- packages/eslint-plugin/src/util/misc.ts | 13 ++++++++++ 3 files changed, 27 insertions(+), 36 deletions(-) diff --git a/packages/eslint-plugin/src/rules/sort-type-constituents.ts b/packages/eslint-plugin/src/rules/sort-type-constituents.ts index aa1f5223181d..e0b3f4f7d378 100644 --- a/packages/eslint-plugin/src/rules/sort-type-constituents.ts +++ b/packages/eslint-plugin/src/rules/sort-type-constituents.ts @@ -2,7 +2,7 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as util from '../util'; -import { getEnumNames } from '../util'; +import { getEnumNames, typeNodeRequiresParentheses } from '../util'; enum Group { conditional = 'conditional', @@ -96,21 +96,6 @@ function getGroup(node: TSESTree.TypeNode): Group { } } -interface Constituent { - group: number; - node: TSESTree.TypeNode; - text: string; -} - -function requiresParentheses({ node, text }: Constituent): boolean { - return ( - node.type === AST_NODE_TYPES.TSFunctionType || - node.type === AST_NODE_TYPES.TSConstructorType || - (node.type === AST_NODE_TYPES.TSUnionType && text.startsWith('|')) || - (node.type === AST_NODE_TYPES.TSIntersectionType && text.startsWith('&')) - ); -} - export type Options = [ { checkIntersections?: boolean; @@ -191,7 +176,7 @@ export default util.createRule({ function checkSorting( node: TSESTree.TSIntersectionType | TSESTree.TSUnionType, ): void { - const sourceOrder = node.types.map((type): Constituent => { + const sourceOrder = node.types.map(type => { const group = groupOrder?.indexOf(getGroup(type)) ?? -1; return { group: group === -1 ? Number.MAX_SAFE_INTEGER : group, @@ -234,7 +219,11 @@ export default util.createRule({ const fix: TSESLint.ReportFixFunction = fixer => { const sorted = expectedOrder - .map(t => (requiresParentheses(t) ? `(${t.text})` : t.text)) + .map(t => + typeNodeRequiresParentheses(t.node, t.text) + ? `(${t.text})` + : t.text, + ) .join( node.type === AST_NODE_TYPES.TSIntersectionType ? ' & ' : ' | ', ); diff --git a/packages/eslint-plugin/src/rules/sort-type-union-intersection-members.ts b/packages/eslint-plugin/src/rules/sort-type-union-intersection-members.ts index 0ceed5e6ec1d..29a27f5c603d 100644 --- a/packages/eslint-plugin/src/rules/sort-type-union-intersection-members.ts +++ b/packages/eslint-plugin/src/rules/sort-type-union-intersection-members.ts @@ -2,7 +2,7 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as util from '../util'; -import { getEnumNames } from '../util'; +import { getEnumNames, typeNodeRequiresParentheses } from '../util'; enum Group { conditional = 'conditional', @@ -96,21 +96,6 @@ function getGroup(node: TSESTree.TypeNode): Group { } } -interface Constituent { - group: number; - node: TSESTree.TypeNode; - text: string; -} - -function requiresParentheses({ node, text }: Constituent): boolean { - return ( - node.type === AST_NODE_TYPES.TSFunctionType || - node.type === AST_NODE_TYPES.TSConstructorType || - (node.type === AST_NODE_TYPES.TSUnionType && text.startsWith('|')) || - (node.type === AST_NODE_TYPES.TSIntersectionType && text.startsWith('&')) - ); -} - export type Options = [ { checkIntersections?: boolean; @@ -193,7 +178,7 @@ export default util.createRule({ function checkSorting( node: TSESTree.TSIntersectionType | TSESTree.TSUnionType, ): void { - const sourceOrder = node.types.map((type): Constituent => { + const sourceOrder = node.types.map(type => { const group = groupOrder?.indexOf(getGroup(type)) ?? -1; return { group: group === -1 ? Number.MAX_SAFE_INTEGER : group, @@ -236,7 +221,11 @@ export default util.createRule({ const fix: TSESLint.ReportFixFunction = fixer => { const sorted = expectedOrder - .map(t => (requiresParentheses(t) ? `(${t.text})` : t.text)) + .map(t => + typeNodeRequiresParentheses(t.node, t.text) + ? `(${t.text})` + : t.text, + ) .join( node.type === AST_NODE_TYPES.TSIntersectionType ? ' & ' : ' | ', ); diff --git a/packages/eslint-plugin/src/util/misc.ts b/packages/eslint-plugin/src/util/misc.ts index 2bdc8ee0f591..61cbbb32d07e 100644 --- a/packages/eslint-plugin/src/util/misc.ts +++ b/packages/eslint-plugin/src/util/misc.ts @@ -180,6 +180,18 @@ function formatWordList(words: string[]): string { return [words.slice(0, -1).join(', '), words.slice(-1)[0]].join(' and '); } +function typeNodeRequiresParentheses( + node: TSESTree.TypeNode, + text: string, +): boolean { + return ( + node.type === AST_NODE_TYPES.TSFunctionType || + node.type === AST_NODE_TYPES.TSConstructorType || + (node.type === AST_NODE_TYPES.TSUnionType && text.startsWith('|')) || + (node.type === AST_NODE_TYPES.TSIntersectionType && text.startsWith('&')) + ); +} + export { arrayGroupByToMap, arraysAreEqual, @@ -193,5 +205,6 @@ export { isDefinitionFile, MemberNameType, RequireKeys, + typeNodeRequiresParentheses, upperCaseFirst, };