Skip to content

Commit

Permalink
feat(sort-imports): adds utility function makeNewlineFixes
Browse files Browse the repository at this point in the history
  • Loading branch information
hugop95 committed Oct 15, 2024
1 parent cf89fe9 commit 45e82ac
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 97 deletions.
122 changes: 25 additions & 97 deletions rules/sort-imports.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { TSESTree } from '@typescript-eslint/types'
import type { TSESLint } from '@typescript-eslint/utils'

import { builtinModules } from 'node:module'

Expand All @@ -9,11 +8,11 @@ import { validateGroupsConfiguration } from '../utils/validate-groups-configurat
import { getOptionsWithCleanGroups } from '../utils/get-options-with-clean-groups'
import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
import { getCommentsBefore } from '../utils/get-comments-before'
import { makeNewlinesFixes } from '../utils/make-newlines-fixes'
import { getNewlinesErrors } from '../utils/get-newlines-errors'
import { createEslintRule } from '../utils/create-eslint-rule'
import { getLinesBetween } from '../utils/get-lines-between'
import { getGroupNumber } from '../utils/get-group-number'
import { getSourceCode } from '../utils/get-source-code'
import { getNodeRange } from '../utils/get-node-range'
import { rangeToDiff } from '../utils/range-to-diff'
import { getSettings } from '../utils/get-settings'
import { useGroups } from '../utils/use-groups'
Expand Down Expand Up @@ -596,28 +595,19 @@ export default createEslintRule<Options<string[]>, MESSAGE_ID>({
)
}

let numberOfEmptyLinesBetween = getLinesBetween(
sourceCode,
left,
right,
)
if (
options.newlinesBetween === 'never' &&
numberOfEmptyLinesBetween > 0
) {
messageIds.push('extraSpacingBetweenImports')
}

if (options.newlinesBetween === 'always') {
if (leftNum < rightNum && numberOfEmptyLinesBetween === 0) {
messageIds.push('missedSpacingBetweenImports')
} else if (
numberOfEmptyLinesBetween > 1 ||
(leftNum === rightNum && numberOfEmptyLinesBetween > 0)
) {
messageIds.push('extraSpacingBetweenImports')
}
}
messageIds = [
...messageIds,
...getNewlinesErrors({
left,
leftNum,
right,
rightNum,
sourceCode,
missedSpacingError: 'missedSpacingBetweenImports',
extraSpacingError: 'extraSpacingBetweenImports',
options,
}),
]

for (let messageId of messageIds) {
context.report({
Expand All @@ -629,78 +619,16 @@ export default createEslintRule<Options<string[]>, MESSAGE_ID>({
rightGroup: right.group,
},
node: right.node,
fix: fixer => {
let newlinesFixes: TSESLint.RuleFix[] = []

for (let max = sortedNodes.length, i = 0; i < max; i++) {
let node = sortedNodes.at(i)!
let nextNode = sortedNodes.at(i + 1)

if (options.newlinesBetween === 'ignore' || !nextNode) {
continue
}

let nodeGroupNumber = getGroupNumber(options.groups, node)
let nextNodeGroupNumber = getGroupNumber(
options.groups,
nextNode,
)
let currentNodeRange = getNodeRange(
nodeList.at(i)!.node,
sourceCode,
options,
)
let nextNodeRange =
getNodeRange(
nodeList.at(i + 1)!.node,
sourceCode,
options,
).at(0)! - 1

let linesBetweenImports = getLinesBetween(
sourceCode,
nodeList.at(i)!,
nodeList.at(i + 1)!,
)

if (
(options.newlinesBetween === 'always' &&
nodeGroupNumber === nextNodeGroupNumber &&
linesBetweenImports !== 0) ||
(options.newlinesBetween === 'never' &&
linesBetweenImports > 0)
) {
newlinesFixes.push(
fixer.removeRange([
currentNodeRange.at(1)!,
nextNodeRange,
]),
)
}
if (
options.newlinesBetween === 'always' &&
nodeGroupNumber !== nextNodeGroupNumber
) {
if (linesBetweenImports > 1) {
newlinesFixes.push(
fixer.replaceTextRange(
[currentNodeRange.at(1)!, nextNodeRange],
'\n',
),
)
} else if (linesBetweenImports === 0) {
newlinesFixes.push(
fixer.insertTextAfterRange(currentNodeRange, '\n'),
)
}
}
}

return [
...makeFixes(fixer, nodeList, sortedNodes, sourceCode),
...newlinesFixes,
]
},
fix: fixer => [
...makeFixes(fixer, nodeList, sortedNodes, sourceCode),
...makeNewlinesFixes(
fixer,
nodeList,
sortedNodes,
sourceCode,
options,
),
],
})
}
})
Expand Down
51 changes: 51 additions & 0 deletions utils/get-newlines-errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import type { TSESLint } from '@typescript-eslint/utils'

import type { SortingNode } from '../typings'

import { getLinesBetween } from './get-lines-between'

interface Options {
newlinesBetween: 'ignore' | 'always' | 'never'
}

interface Props<T extends string> {
sourceCode: TSESLint.SourceCode
missedSpacingError: T
extraSpacingError: T
right: SortingNode
left: SortingNode
rightNum: number
options: Options
leftNum: number
}

export let getNewlinesErrors = <T extends string>({
missedSpacingError,
extraSpacingError,
sourceCode,
rightNum,
leftNum,
options,
right,
left,
}: Props<T>) => {
let errors: T[] = []

let numberOfEmptyLinesBetween = getLinesBetween(sourceCode, left, right)
if (options.newlinesBetween === 'never' && numberOfEmptyLinesBetween > 0) {
errors.push(extraSpacingError)
}

if (options.newlinesBetween === 'always') {
if (leftNum < rightNum && numberOfEmptyLinesBetween === 0) {
errors.push(missedSpacingError)
} else if (
numberOfEmptyLinesBetween > 1 ||
(leftNum === rightNum && numberOfEmptyLinesBetween > 0)
) {
errors.push(extraSpacingError)
}
}

return errors
}
67 changes: 67 additions & 0 deletions utils/make-newlines-fixes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import type { TSESLint } from '@typescript-eslint/utils'

import type { SortingNode } from '../typings'

import { getLinesBetween } from './get-lines-between'
import { getGroupNumber } from './get-group-number'
import { getNodeRange } from './get-node-range'

interface Options {
newlinesBetween: 'ignore' | 'always' | 'never'
groups: (string[] | string)[]
}

export let makeNewlinesFixes = (
fixer: TSESLint.RuleFixer,
nodes: SortingNode[],
sortedNodes: SortingNode[],
source: TSESLint.SourceCode,
options: Options,
) => {
let fixes: TSESLint.RuleFix[] = []

for (let max = sortedNodes.length, i = 0; i < max; i++) {
let node = sortedNodes.at(i)!
let nextNode = sortedNodes.at(i + 1)

if (options.newlinesBetween === 'ignore' || !nextNode) {
continue
}

let nodeGroupNumber = getGroupNumber(options.groups, node)
let nextNodeGroupNumber = getGroupNumber(options.groups, nextNode)
let currentNodeRange = getNodeRange(nodes.at(i)!.node, source)
let nextNodeRange = getNodeRange(nodes.at(i + 1)!.node, source).at(0)! - 1

let linesBetweenImports = getLinesBetween(
source,
nodes.at(i)!,
nodes.at(i + 1)!,
)

if (
(options.newlinesBetween === 'always' &&
nodeGroupNumber === nextNodeGroupNumber &&
linesBetweenImports !== 0) ||
(options.newlinesBetween === 'never' && linesBetweenImports > 0)
) {
fixes.push(fixer.removeRange([currentNodeRange.at(1)!, nextNodeRange]))
}
if (
options.newlinesBetween === 'always' &&
nodeGroupNumber !== nextNodeGroupNumber
) {
if (linesBetweenImports > 1) {
fixes.push(
fixer.replaceTextRange(
[currentNodeRange.at(1)!, nextNodeRange],
'\n',
),
)
} else if (linesBetweenImports === 0) {
fixes.push(fixer.insertTextAfterRange(currentNodeRange, '\n'))
}
}
}
return fixes
}

0 comments on commit 45e82ac

Please sign in to comment.