Files

89 lines
2.5 KiB
JavaScript

/**
* Generates fixes to move inline trailing comments with their associated nodes.
*
* When a node is moved during sorting, this function ensures that any inline
* comment on the same line (trailing comment) is moved along with it. This
* preserves the relationship between code and its inline documentation.
*
* The function:
*
* - Detects inline comments after the sorted node
* - Skips processing if nodes would end up on the same line
* - Removes the comment from its original position
* - Inserts it after the node's new position.
*
* @example
*
* ```ts
* // Original:
* const b = 2 // second value
* const a = 1 // first value
*
* // After sorting (with comment fixes):
* const a = 1 // first value
* const b = 2 // second value
* ```
*
* @param params - Parameters for generating comment fixes.
* @returns Array of ESLint fix operations, empty if no inline comment exists.
*/
function makeSingleNodeCommentAfterFixes({
sortedNode,
sourceCode,
fixer,
node,
}) {
let commentAfter = getCommentAfter(sortedNode, sourceCode)
let areNodesOnSameLine = node.loc.start.line === sortedNode.loc.end.line
if (!commentAfter || areNodesOnSameLine) {
return []
}
let fixes = []
let range = [
sourceCode.getTokenBefore(commentAfter).range.at(1),
commentAfter.range.at(1),
]
fixes.push(fixer.replaceTextRange(range, ''))
let tokenAfterNode = sourceCode.getTokenAfter(node)
fixes.push(
fixer.insertTextAfter(
tokenAfterNode?.loc.end.line === node.loc.end.line ?
tokenAfterNode
: node,
sourceCode.text.slice(...range),
),
)
return fixes
}
/**
* Retrieves an inline comment that appears after a node on the same line.
*
* Searches for a comment token that:
*
* - Appears after the given node
* - Is on the same line as the node's end
* - Skips over punctuation like commas, semicolons, and colons.
*
* This helps identify inline trailing comments that should move with the node
* during sorting operations.
*
* @param node - The node to check for trailing comments.
* @param source - ESLint source code object.
* @returns The inline comment if found, null otherwise.
*/
function getCommentAfter(node, source) {
let token = source.getTokenAfter(node, {
filter: ({ value, type }) =>
type !== 'Punctuator' || ![',', ';', ':'].includes(value),
includeComments: true,
})
if (
(token?.type === 'Block' || token?.type === 'Line') &&
node.loc.end.line === token.loc.end.line
) {
return token
}
return null
}
export { makeSingleNodeCommentAfterFixes }