UNPKG

eslint-plugin-perfectionist

Version:

ESLint plugin for sorting various data such as objects, imports, types, enums, JSX props, etc.

224 lines (223 loc) 7.54 kB
import { computeDependenciesOutsideFunctionsBySortingNode } from '../../utils/compute-dependencies-outside-functions-by-sorting-node.js' import { populateSortingNodeGroupsWithDependencies } from '../../utils/populate-sorting-node-groups-with-dependencies.js' import { validateNewlinesAndPartitionConfiguration } from '../../utils/validate-newlines-and-partition-configuration.js' import { buildOptionsByGroupIndexComputer } from '../../utils/build-options-by-group-index-computer.js' import { validateCustomSortConfiguration } from '../../utils/validate-custom-sort-configuration.js' import { validateGroupsConfiguration } from '../../utils/validate-groups-configuration.js' import { generatePredefinedGroups } from '../../utils/generate-predefined-groups.js' import { sortNodesByDependencies } from '../../utils/sort-nodes-by-dependencies.js' import { getEslintDisabledLines } from '../../utils/get-eslint-disabled-lines.js' import { doesCustomGroupMatch } from '../../utils/does-custom-group-match.js' import { isNodeEslintDisabled } from '../../utils/is-node-eslint-disabled.js' import { sortNodesByGroups } from '../../utils/sort-nodes-by-groups.js' import { reportAllErrors } from '../../utils/report-all-errors.js' import { shouldPartition } from '../../utils/should-partition.js' import { computeGroup } from '../../utils/compute-group.js' import { rangeToDiff } from '../../utils/range-to-diff.js' import { getSettings } from '../../utils/get-settings.js' import { isSortable } from '../../utils/is-sortable.js' import { complete } from '../../utils/complete.js' import { isNodeOnSingleLine } from '../../utils/is-node-on-single-line.js' import { DEPENDENCY_ORDER_ERROR_ID, EXTRA_SPACING_ERROR_ID, GROUP_ORDER_ERROR_ID, MISSED_SPACING_ERROR_ID, ORDER_ERROR_ID, allModifiers, allSelectors, } from './types.js' import { computePropertyOrVariableDeclaratorName } from './compute-property-or-variable-declarator-name.js' import { computeMatchedContextOptions } from './compute-matched-context-options.js' import { comparatorByOptionsComputer } from './comparator-by-options-computer.js' import { computeDependencyNames } from './compute-dependency-names.js' import { computeDependencies } from './compute-dependencies.js' import { isStyleComponent } from './is-style-component.js' import { computeNodeValue } from './compute-node-value.js' import { AST_NODE_TYPES } from '@typescript-eslint/utils' /** * Cache computed groups by modifiers and selectors for performance. */ var cachedGroupsByModifiersAndSelectors = /* @__PURE__ */ new Map() var defaultOptions = { useExperimentalDependencyDetection: true, fallbackSort: { type: 'unsorted' }, newlinesInside: 'newlinesBetween', partitionByComputedKey: false, partitionByNewLine: false, partitionByComment: false, newlinesBetween: 'ignore', specialCharacters: 'keep', styledComponents: true, useConfigurationIf: {}, type: 'alphabetical', ignoreCase: true, customGroups: [], locales: 'en-US', sortBy: 'name', alphabet: '', order: 'asc', groups: [], } function sortObject({ matchedAstSelectors, context, node }) { if (!isSortable(node.properties)) { return } let { sourceCode, id } = context let settings = getSettings(context.settings) let isDestructuredObject = node.type === AST_NODE_TYPES.ObjectPattern let options = complete( computeMatchedContextOptions({ isDestructuredObject, matchedAstSelectors, nodeObject: node, sourceCode, context, }), settings, defaultOptions, ) validateCustomSortConfiguration(options) validateGroupsConfiguration({ selectors: allSelectors, modifiers: allModifiers, options, }) validateNewlinesAndPartitionConfiguration(options) if (!options.styledComponents && isStyleComponent(node)) { return } let eslintDisabledLines = getEslintDisabledLines({ ruleName: id, sourceCode, }) let optionsByGroupIndexComputer = buildOptionsByGroupIndexComputer(options) let sortingNodeGroups = [[]] for (let property of node.properties) { if ( property.type === AST_NODE_TYPES.SpreadElement || property.type === AST_NODE_TYPES.RestElement ) { sortingNodeGroups.push([]) continue } if ( options.partitionByComputedKey && !isDestructuredObject && property.computed ) { sortingNodeGroups.push([]) continue } let lastSortingNode = sortingNodeGroups.at(-1)?.at(-1) let selectors = [] let modifiers = [] if ( property.value.type === AST_NODE_TYPES.ArrowFunctionExpression || property.value.type === AST_NODE_TYPES.FunctionExpression ) { selectors.push('method') } else { selectors.push('property') } selectors.push('member') if (!isNodeOnSingleLine(property)) { modifiers.push('multiline') } let name = computePropertyOrVariableDeclaratorName({ node: property, sourceCode, }) let dependencyNames = [name] if (isDestructuredObject) { dependencyNames = [...new Set(computeDependencyNames(property.value))] } let value = computeNodeValue({ isDestructuredObject, sourceCode, property, }) let group = computeGroup({ customGroupMatcher: customGroup => doesCustomGroupMatch({ elementValue: value, elementName: name, customGroup, selectors, modifiers, }), predefinedGroups: generatePredefinedGroups({ cache: cachedGroupsByModifiersAndSelectors, selectors, modifiers, }), options, }) let sortingNode = { dependencies: options.useExperimentalDependencyDetection ? [] : computeDependencies(property), isEslintDisabled: isNodeEslintDisabled(property, eslintDisabledLines), size: rangeToDiff(property, sourceCode), value: value ?? '', dependencyNames, node: property, group, name, } if ( shouldPartition({ lastSortingNode, sortingNode, sourceCode, options, }) ) { sortingNodeGroups.push([]) } sortingNodeGroups.at(-1).push({ ...sortingNode, partitionId: sortingNodeGroups.length, }) } if (options.useExperimentalDependencyDetection) { sortingNodeGroups = populateSortingNodeGroupsWithDependencies({ dependenciesBySortingNode: computeDependenciesOutsideFunctionsBySortingNode({ sortingNodes: sortingNodeGroups.flat(), sourceCode, }), sortingNodeGroups, }) } let sortingNodes = sortingNodeGroups.flat() reportAllErrors({ availableMessageIds: { missedSpacingBetweenMembers: MISSED_SPACING_ERROR_ID, unexpectedDependencyOrder: DEPENDENCY_ORDER_ERROR_ID, extraSpacingBetweenMembers: EXTRA_SPACING_ERROR_ID, unexpectedGroupOrder: GROUP_ORDER_ERROR_ID, unexpectedOrder: ORDER_ERROR_ID, }, sortNodesExcludingEslintDisabled, nodes: sortingNodes, options, context, }) function sortNodesExcludingEslintDisabled(ignoreEslintDisabledNodes) { return sortNodesByDependencies( sortingNodeGroups.flatMap(nodes => sortNodesByGroups({ comparatorByOptionsComputer, optionsByGroupIndexComputer, ignoreEslintDisabledNodes, groups: options.groups, nodes, }), ), { ignoreEslintDisabledNodes }, ) } } export { defaultOptions, sortObject }