110 lines
3.0 KiB
JavaScript
110 lines
3.0 KiB
JavaScript
import { getNodeRange } from './get-node-range.js'
|
|
/**
|
|
* Generates fixes for reordering nodes to their sorted positions.
|
|
*
|
|
* Creates text replacement fixes that swap node positions to achieve the
|
|
* desired sort order. The function handles several important edge cases:
|
|
*
|
|
* - Preserves leading comments and documentation
|
|
* - Maintains file-level block comments for the first node
|
|
* - Adds safety semicolons when needed to prevent ASI issues
|
|
* - Respects partition boundaries defined by comments.
|
|
*
|
|
* The function iterates through each node position and replaces the original
|
|
* node text with the text from the node that should be in that position
|
|
* according to the sorted order.
|
|
*
|
|
* @example
|
|
*
|
|
* ```ts
|
|
* // Original order:
|
|
* const b = 2
|
|
* const a = 1
|
|
*
|
|
* // After applying order fixes:
|
|
* const a = 1
|
|
* const b = 2
|
|
* ```
|
|
*
|
|
* @example
|
|
*
|
|
* ```ts
|
|
* // Safety semicolon example
|
|
* // Original:
|
|
* const b = 2
|
|
* const a = 1 // 'a' will move to first position
|
|
*
|
|
* // After fix (semicolon added to prevent ASI issues):
|
|
* const a = 1
|
|
* const b = 2
|
|
* ```
|
|
*
|
|
* @param params - Parameters for generating order fixes.
|
|
* @returns Array of ESLint fix operations to reorder nodes.
|
|
*/
|
|
function makeOrderFixes({
|
|
ignoreFirstNodeHighestBlockComment,
|
|
sortedNodes,
|
|
sourceCode,
|
|
options,
|
|
fixer,
|
|
nodes,
|
|
}) {
|
|
let fixes = []
|
|
for (let max = nodes.length, i = 0; i < max; i++) {
|
|
let sortingNode = nodes.at(i)
|
|
let sortedSortingNode = sortedNodes.at(i)
|
|
let { node } = sortingNode
|
|
let { addSafetySemicolonWhenInline, node: sortedNode } = sortedSortingNode
|
|
let isNodeFirstNode = node === nodes.at(0).node
|
|
let isSortedNodeFirstNode = sortedNode === nodes.at(0).node
|
|
if (node === sortedNode) {
|
|
continue
|
|
}
|
|
let sortedNodeCode = sourceCode.text.slice(
|
|
...getNodeRange({
|
|
ignoreHighestBlockComment:
|
|
ignoreFirstNodeHighestBlockComment && isSortedNodeFirstNode,
|
|
node: sortedNode,
|
|
sourceCode,
|
|
options,
|
|
}),
|
|
)
|
|
let sortedNodeText = sourceCode.getText(sortedNode)
|
|
let nextToken = sourceCode
|
|
.getTokensAfter(node, {
|
|
includeComments: false,
|
|
count: 1,
|
|
})
|
|
.at(0)
|
|
let sortedNextNodeEndsWithSafeCharacter =
|
|
sortedNodeText.endsWith(';') || sortedNodeText.endsWith(',')
|
|
let isNextTokenOnSameLineAsNode =
|
|
nextToken?.loc.start.line === node.loc.end.line
|
|
let isNextTokenSafeCharacter =
|
|
nextToken?.value === ';' || nextToken?.value === ','
|
|
if (
|
|
addSafetySemicolonWhenInline &&
|
|
isNextTokenOnSameLineAsNode &&
|
|
!sortedNextNodeEndsWithSafeCharacter &&
|
|
!isNextTokenSafeCharacter
|
|
) {
|
|
sortedNodeCode += ';'
|
|
}
|
|
fixes.push(
|
|
fixer.replaceTextRange(
|
|
getNodeRange({
|
|
ignoreHighestBlockComment:
|
|
ignoreFirstNodeHighestBlockComment && isNodeFirstNode,
|
|
sourceCode,
|
|
options,
|
|
node,
|
|
}),
|
|
sortedNodeCode,
|
|
),
|
|
)
|
|
}
|
|
return fixes
|
|
}
|
|
export { makeOrderFixes }
|