From 4574caace5fb935a0c69eab527b5f1dc6ae92213 Mon Sep 17 00:00:00 2001 From: Azat S Date: Mon, 5 Jun 2023 00:14:14 +0300 Subject: [PATCH] perf: do not compute options if rule is not used --- rules/sort-array-includes.ts | 14 +-- rules/sort-enums.ts | 12 +- rules/sort-interfaces.ts | 111 ++++++++--------- rules/sort-jsx-props.ts | 228 ++++++++++++++++++----------------- rules/sort-map-elements.ts | 15 +-- rules/sort-named-exports.ts | 12 +- rules/sort-named-imports.ts | 12 +- 7 files changed, 204 insertions(+), 200 deletions(-) diff --git a/rules/sort-array-includes.ts b/rules/sort-array-includes.ts index f46120314..5784e173d 100644 --- a/rules/sort-array-includes.ts +++ b/rules/sort-array-includes.ts @@ -82,19 +82,19 @@ export default createEslintRule({ node.property.type === AST_NODE_TYPES.Identifier && node.property.name === 'includes' ) { - let options = complete(context.options.at(0), { - type: SortType.alphabetical, - order: SortOrder.asc, - 'ignore-case': false, - 'spread-last': false, - }) - let elements = node.object.type === AST_NODE_TYPES.ArrayExpression ? node.object.elements : node.object.arguments if (elements.length > 1) { + let options = complete(context.options.at(0), { + type: SortType.alphabetical, + order: SortOrder.asc, + 'ignore-case': false, + 'spread-last': false, + }) + let source = context.getSourceCode() let nodes: (SortingNode & { type: string })[] = elements diff --git a/rules/sort-enums.ts b/rules/sort-enums.ts index 953e64052..2b34c0dff 100644 --- a/rules/sort-enums.ts +++ b/rules/sort-enums.ts @@ -69,13 +69,13 @@ export default createEslintRule({ ], create: context => ({ TSEnumDeclaration: node => { - let options = complete(context.options.at(0), { - type: SortType.alphabetical, - order: SortOrder.asc, - 'ignore-case': false, - }) - if (node.members.length > 1) { + let options = complete(context.options.at(0), { + type: SortType.alphabetical, + order: SortOrder.asc, + 'ignore-case': false, + }) + let source = context.getSourceCode() let nodes: SortingNode[] = node.members.map(member => ({ diff --git a/rules/sort-interfaces.ts b/rules/sort-interfaces.ts index 26fd0c50b..3b2cd30d6 100644 --- a/rules/sort-interfaces.ts +++ b/rules/sort-interfaces.ts @@ -76,69 +76,70 @@ export default createEslintRule({ ], create: context => ({ TSInterfaceDeclaration: node => { - let options = complete(context.options.at(0), { - type: SortType.alphabetical, - 'ignore-case': false, - order: SortOrder.asc, - 'ignore-pattern': [], - }) + if (node.body.body.length > 1) { + let options = complete(context.options.at(0), { + type: SortType.alphabetical, + 'ignore-case': false, + order: SortOrder.asc, + 'ignore-pattern': [], + }) - if ( - !options['ignore-pattern'].some(pattern => - minimatch(node.id.name, pattern), - ) && - node.body.body.length > 1 - ) { - let source = context.getSourceCode() + if ( + !options['ignore-pattern'].some(pattern => + minimatch(node.id.name, pattern), + ) + ) { + let source = context.getSourceCode() - let nodes: SortingNode[] = node.body.body.map(element => { - let name: string + let nodes: SortingNode[] = node.body.body.map(element => { + let name: string - if (element.type === AST_NODE_TYPES.TSPropertySignature) { - if (element.key.type === AST_NODE_TYPES.Identifier) { - ;({ name } = element.key) - } else if (element.key.type === AST_NODE_TYPES.Literal) { - name = `${element.key.value}` - } else { - let end: number = - element.typeAnnotation?.range.at(0) ?? - element.range.at(1)! - (element.optional ? '?'.length : 0) + if (element.type === AST_NODE_TYPES.TSPropertySignature) { + if (element.key.type === AST_NODE_TYPES.Identifier) { + ;({ name } = element.key) + } else if (element.key.type === AST_NODE_TYPES.Literal) { + name = `${element.key.value}` + } else { + let end: number = + element.typeAnnotation?.range.at(0) ?? + element.range.at(1)! - (element.optional ? '?'.length : 0) - name = source.text.slice(element.range.at(0), end) - } - } else if (element.type === AST_NODE_TYPES.TSIndexSignature) { - let endIndex: number = - element.typeAnnotation?.range.at(0) ?? element.range.at(1)! + name = source.text.slice(element.range.at(0), end) + } + } else if (element.type === AST_NODE_TYPES.TSIndexSignature) { + let endIndex: number = + element.typeAnnotation?.range.at(0) ?? element.range.at(1)! - name = source.text.slice(element.range.at(0), endIndex) - } else { - let endIndex: number = - element.returnType?.range.at(0) ?? element.range.at(1)! + name = source.text.slice(element.range.at(0), endIndex) + } else { + let endIndex: number = + element.returnType?.range.at(0) ?? element.range.at(1)! - name = source.text.slice(element.range.at(0), endIndex) - } + name = source.text.slice(element.range.at(0), endIndex) + } - return { - size: rangeToDiff(element.range), - node: element, - name, - } - }) + return { + size: rangeToDiff(element.range), + node: element, + name, + } + }) - pairwise(nodes, (first, second) => { - if (compare(first, second, options)) { - context.report({ - messageId: 'unexpectedInterfacePropertiesOrder', - data: { - first: toSingleLine(first.name), - second: toSingleLine(second.name), - }, - node: second.node, - fix: fixer => - makeFixes(fixer, nodes, sortNodes(nodes, options), source), - }) - } - }) + pairwise(nodes, (first, second) => { + if (compare(first, second, options)) { + context.report({ + messageId: 'unexpectedInterfacePropertiesOrder', + data: { + first: toSingleLine(first.name), + second: toSingleLine(second.name), + }, + node: second.node, + fix: fixer => + makeFixes(fixer, nodes, sortNodes(nodes, options), source), + }) + } + }) + } } }, }), diff --git a/rules/sort-jsx-props.ts b/rules/sort-jsx-props.ts index f54539a07..2a2fbceea 100644 --- a/rules/sort-jsx-props.ts +++ b/rules/sort-jsx-props.ts @@ -97,132 +97,134 @@ export default createEslintRule({ ], create: context => ({ JSXElement: node => { - let options = complete(context.options.at(0), { - type: SortType.alphabetical, - shorthand: Position.ignore, - multiline: Position.ignore, - callback: Position.ignore, - 'always-on-top': [], - 'ignore-case': false, - order: SortOrder.asc, - }) - - let source = context.getSourceCode() - - let parts: SortingNodeWithPosition[][] = - node.openingElement.attributes.reduce( - ( - accumulator: SortingNodeWithPosition[][], - attribute: TSESTree.JSXSpreadAttribute | TSESTree.JSXAttribute, - ) => { - if (attribute.type === AST_NODE_TYPES.JSXSpreadAttribute) { - accumulator.push([]) - return accumulator - } - - let position: Position = Position.ignore + if (node.openingElement.attributes.length > 1) { + let options = complete(context.options.at(0), { + type: SortType.alphabetical, + shorthand: Position.ignore, + multiline: Position.ignore, + callback: Position.ignore, + 'always-on-top': [], + 'ignore-case': false, + order: SortOrder.asc, + }) - if ( - attribute.name.type === AST_NODE_TYPES.JSXIdentifier && - options['always-on-top'].includes(attribute.name.name) - ) { - position = Position.exception - } else { - if ( - options.shorthand !== Position.ignore && - attribute.value === null - ) { - position = options.shorthand + let source = context.getSourceCode() + + let parts: SortingNodeWithPosition[][] = + node.openingElement.attributes.reduce( + ( + accumulator: SortingNodeWithPosition[][], + attribute: TSESTree.JSXSpreadAttribute | TSESTree.JSXAttribute, + ) => { + if (attribute.type === AST_NODE_TYPES.JSXSpreadAttribute) { + accumulator.push([]) + return accumulator } + let position: Position = Position.ignore + if ( - options.callback !== Position.ignore && attribute.name.type === AST_NODE_TYPES.JSXIdentifier && - attribute.name.name.indexOf('on') === 0 && - attribute.value !== null - ) { - position = options.callback - } else if ( - options.multiline !== Position.ignore && - attribute.loc.start.line !== attribute.loc.end.line + options['always-on-top'].includes(attribute.name.name) ) { - position = options.multiline + position = Position.exception + } else { + if ( + options.shorthand !== Position.ignore && + attribute.value === null + ) { + position = options.shorthand + } + + if ( + options.callback !== Position.ignore && + attribute.name.type === AST_NODE_TYPES.JSXIdentifier && + attribute.name.name.indexOf('on') === 0 && + attribute.value !== null + ) { + position = options.callback + } else if ( + options.multiline !== Position.ignore && + attribute.loc.start.line !== attribute.loc.end.line + ) { + position = options.multiline + } } - } - let jsxNode = { - name: - attribute.name.type === AST_NODE_TYPES.JSXNamespacedName - ? `${attribute.name.namespace.name}:${attribute.name.name.name}` - : attribute.name.name, - size: rangeToDiff(attribute.range), - node: attribute, - position, - } + let jsxNode = { + name: + attribute.name.type === AST_NODE_TYPES.JSXNamespacedName + ? `${attribute.name.namespace.name}:${attribute.name.name.name}` + : attribute.name.name, + size: rangeToDiff(attribute.range), + node: attribute, + position, + } - accumulator.at(-1)!.push(jsxNode) + accumulator.at(-1)!.push(jsxNode) - return accumulator - }, - [[]], - ) - - parts.forEach(nodes => { - pairwise(nodes, (first, second) => { - let comparison: boolean - - if ( - first.position === Position.exception && - second.position === Position.exception - ) { - comparison = - options['always-on-top'].indexOf(first.name) > - options['always-on-top'].indexOf(second.name) - } else if (first.position === second.position) { - comparison = compare(first, second, options) - } else { - let positionPower = { - [Position.exception]: 2, - [Position.first]: 1, - [Position.ignore]: 0, - [Position.last]: -1, + return accumulator + }, + [[]], + ) + + parts.forEach(nodes => { + pairwise(nodes, (first, second) => { + let comparison: boolean + + if ( + first.position === Position.exception && + second.position === Position.exception + ) { + comparison = + options['always-on-top'].indexOf(first.name) > + options['always-on-top'].indexOf(second.name) + } else if (first.position === second.position) { + comparison = compare(first, second, options) + } else { + let positionPower = { + [Position.exception]: 2, + [Position.first]: 1, + [Position.ignore]: 0, + [Position.last]: -1, + } + + comparison = + positionPower[first.position] < positionPower[second.position] } - comparison = - positionPower[first.position] < positionPower[second.position] - } - - if (comparison) { - context.report({ - messageId: 'unexpectedJSXPropsOrder', - data: { - first: first.name, - second: second.name, - }, - node: second.node, - fix: fixer => { - let groups = groupBy(nodes, ({ position }) => position) - - let getGroup = (index: string) => - index in groups ? groups[index] : [] - - let sortedNodes = [ - getGroup(Position.exception).sort( - (aNode, bNode) => - options['always-on-top'].indexOf(aNode.name) - - options['always-on-top'].indexOf(bNode.name), - ), - sortNodes(getGroup(Position.first), options), - sortNodes(getGroup(Position.ignore), options), - sortNodes(getGroup(Position.last), options), - ].flat() - - return makeFixes(fixer, nodes, sortedNodes, source) - }, - }) - } + if (comparison) { + context.report({ + messageId: 'unexpectedJSXPropsOrder', + data: { + first: first.name, + second: second.name, + }, + node: second.node, + fix: fixer => { + let groups = groupBy(nodes, ({ position }) => position) + + let getGroup = (index: string) => + index in groups ? groups[index] : [] + + let sortedNodes = [ + getGroup(Position.exception).sort( + (aNode, bNode) => + options['always-on-top'].indexOf(aNode.name) - + options['always-on-top'].indexOf(bNode.name), + ), + sortNodes(getGroup(Position.first), options), + sortNodes(getGroup(Position.ignore), options), + sortNodes(getGroup(Position.last), options), + ].flat() + + return makeFixes(fixer, nodes, sortedNodes, source) + }, + }) + } + }) }) - }) + } }, }), }) diff --git a/rules/sort-map-elements.ts b/rules/sort-map-elements.ts index 08fff05d5..61cc7acc4 100644 --- a/rules/sort-map-elements.ts +++ b/rules/sort-map-elements.ts @@ -76,16 +76,17 @@ export default createEslintRule({ node.callee.name === 'Map' && node.arguments[0].type === AST_NODE_TYPES.ArrayExpression ) { - let options = complete(context.options.at(0), { - type: SortType.alphabetical, - 'ignore-case': false, - order: SortOrder.asc, - }) - let [{ elements }] = node.arguments - let source = context.getSourceCode() if (elements.length > 1) { + let options = complete(context.options.at(0), { + type: SortType.alphabetical, + 'ignore-case': false, + order: SortOrder.asc, + }) + + let source = context.getSourceCode() + let parts: TSESTree.Expression[][] = elements.reduce( ( accumulator: TSESTree.Expression[][], diff --git a/rules/sort-named-exports.ts b/rules/sort-named-exports.ts index d51f2b313..14e02287b 100644 --- a/rules/sort-named-exports.ts +++ b/rules/sort-named-exports.ts @@ -67,13 +67,13 @@ export default createEslintRule({ ], create: context => ({ ExportNamedDeclaration: node => { - let options = complete(context.options.at(0), { - type: SortType.alphabetical, - 'ignore-case': false, - order: SortOrder.asc, - }) - if (node.specifiers.length > 1) { + let options = complete(context.options.at(0), { + type: SortType.alphabetical, + 'ignore-case': false, + order: SortOrder.asc, + }) + let source = context.getSourceCode() let nodes: SortingNode[] = node.specifiers.map(specifier => ({ diff --git a/rules/sort-named-imports.ts b/rules/sort-named-imports.ts index b7d86d493..0859ede74 100644 --- a/rules/sort-named-imports.ts +++ b/rules/sort-named-imports.ts @@ -67,13 +67,13 @@ export default createEslintRule({ ], create: context => ({ ImportDeclaration: node => { - let options = complete(context.options.at(0), { - type: SortType.alphabetical, - 'ignore-case': false, - order: SortOrder.asc, - }) - if (node.specifiers.length > 1) { + let options = complete(context.options.at(0), { + type: SortType.alphabetical, + 'ignore-case': false, + order: SortOrder.asc, + }) + let source = context.getSourceCode() let nodes: SortingNode[] = node.specifiers.map(specifier => ({