UNPKG

eslint-plugin-comment-length

Version:

An ESLint plugin that provides rules that limit the line length of your comments

128 lines (114 loc) 4.2 kB
import type { TSESTree } from "@typescript-eslint/utils"; import type { RuleContext } from "@typescript-eslint/utils/ts-eslint"; import { MessageIds } from "../../const.message-ids.js"; import type { Context } from "../../typings.context.js"; import type { Options } from "../../typings.options.js"; import { isCodeInComment } from "../../utils/is-code-in-comment.js"; import { isCommentInComment } from "../../utils/is-comment-in-comment.js"; import { isLineOverflowing } from "../../utils/is-line-overflowing.js"; import { isCommentOnOwnLine } from "../../utils/is-on-own-line.js"; import { isSemanticComment } from "../../utils/is-semantic-comment.js"; import { SINGLE_LINE_COMMENT_BOILERPLATE_SIZE } from "./const.boilerplate-size.js"; import { fixOverflow } from "./fix.overflow.js"; import { canBlockBeCompated } from "./util.can-block-be-compacted.js"; import { captureNearbyComments } from "./util.capture-nearby-comments.js"; import { captureRelevantCommentsIntoBlock } from "./util.capture-relevant-comments.js"; export function limitSingleLineComments( ruleContext: RuleContext<string, unknown[]>, options: Options, comments: TSESTree.LineComment[], ) { const sourceCode = ruleContext.sourceCode; const lines = sourceCode.getLines(); for (let i = 0; i < comments.length; i++) { const currentCommentLine = comments[i]; if ( !currentCommentLine?.range || !currentCommentLine.value || !isCommentOnOwnLine(sourceCode, currentCommentLine) || isSemanticComment(currentCommentLine, options.semanticComments) ) { continue; } const line = lines[currentCommentLine.loc.start.line - 1]; const whitespaceString = line?.split("//")[0] ?? ""; let context = { ...options, whitespace: { string: whitespaceString, size: whitespaceString .split("") .reduce( (acc, curr) => acc + (curr === "\t" ? options.tabSize : 1), 0, ), }, boilerplateSize: SINGLE_LINE_COMMENT_BOILERPLATE_SIZE, comment: { range: currentCommentLine.range, lines: [currentCommentLine.value], value: currentCommentLine.value, }, } satisfies Context; const currentBlock = captureRelevantCommentsIntoBlock( sourceCode, comments, i, context, ); const fixableComment = currentBlock.mergedComment; // ensure that we only visit a captured block once i += currentBlock.endIndex - currentBlock.startIndex; const nearbyComments = captureNearbyComments(comments, i); const wrappedByBackticks = (nearbyComments?.value.trimStart().startsWith("` ") || nearbyComments?.value.trimStart().startsWith("``")) && nearbyComments?.value.trimEnd().endsWith("`"); if ( !fixableComment || wrappedByBackticks || isCommentInComment(fixableComment.value) || isCodeInComment(nearbyComments?.value, context) ) { continue; } // Update our context to reflect that we may have merged multiple comment // lines into a singular block. context = { ...context, comment: { range: fixableComment.range, lines: [fixableComment.value], value: fixableComment.value, }, }; // In case any lines in our current block overflows, then we need to warn // that overflow has been detected if ( comments .slice(currentBlock.startIndex, currentBlock.endIndex + 1) .some((line) => isLineOverflowing(line.value, context)) ) { ruleContext.report({ loc: fixableComment.loc, messageId: MessageIds.EXCEEDS_MAX_LENGTH, data: { maxLength: context.maxLength, }, fix: (fixer) => fixOverflow(fixer, fixableComment, context), }); } else if ( context.mode === "compact" && canBlockBeCompated(comments, currentBlock, context) ) { ruleContext.report({ loc: fixableComment.loc, messageId: MessageIds.CAN_COMPACT, data: { maxLength: context.maxLength, }, fix: (fixer) => fixOverflow(fixer, fixableComment, context), }); } } }