UNPKG

prettier-plugin-multiline-arrays

Version:
169 lines (168 loc) 6.63 kB
import { getObjectTypedKeys } from '@augment-vir/common'; import { nextLinePatternComment, nextWrapThresholdComment, resetComment, setLinePatternComment, setWrapThresholdComment, untilNextLinePatternCommentRegExp, untilNextWrapThresholdCommentRegExp, untilSetLinePatternCommentRegExp, untilSetWrapThresholdCommentRegExp, } from '../options.js'; import { extractComments } from './comments.js'; const mappedCommentTriggers = new WeakMap(); export function getCommentTriggers(key, debug) { const alreadyExisting = mappedCommentTriggers.get(key); if (!alreadyExisting) { return setCommentTriggers(key, debug); } return alreadyExisting; } function setCommentTriggers(rootNode, debug) { // parse comments only on the root node so it only happens once const comments = extractComments(rootNode); if (debug) { console.info({ comments }); } const starterTriggers = { nextLineCounts: {}, setLineCounts: {}, nextWrapThresholds: {}, setWrapThresholds: {}, resets: [], }; const internalCommentTriggers = comments.reduce((accum, currentComment) => { const commentText = currentComment.value?.replace(/\n/g, ' '); if (!currentComment.loc) { throw new Error(`Cannot read line location for comment ${currentComment.value}`); } const nextLineCounts = getLineCounts(commentText, true, debug); if (nextLineCounts.length) { accum.nextLineCounts[currentComment.loc.end.line] = nextLineCounts; } const nextWrapThreshold = getWrapThreshold(commentText, true); if (nextWrapThreshold != undefined) { accum.nextWrapThresholds[currentComment.loc.end.line] = nextWrapThreshold; } const setLineCounts = getLineCounts(commentText, false, debug); if (setLineCounts.length) { accum.setLineCounts[currentComment.loc.end.line] = { data: setLineCounts, lineEnd: Infinity, }; } const setWrapThreshold = getWrapThreshold(commentText, false); if (setWrapThreshold != undefined) { accum.setWrapThresholds[currentComment.loc.end.line] = { data: setWrapThreshold, lineEnd: Infinity, }; } const resetComment = isResetComment(commentText); if (resetComment) { accum.resets.push(currentComment.loc.end.line); } return accum; }, starterTriggers); internalCommentTriggers.resets.sort(); setResets(internalCommentTriggers); const commentTriggers = { ...internalCommentTriggers }; delete commentTriggers.resets; // save to a map so we don't have to recalculate these every time mappedCommentTriggers.set(rootNode, commentTriggers); return commentTriggers; } function setResets(internalCommentTriggers) { if (!internalCommentTriggers.resets.length) { return; } const setLineCountLineNumbers = getObjectTypedKeys(internalCommentTriggers.setLineCounts); if (setLineCountLineNumbers.length) { setLineCountLineNumbers.forEach((lineNumber) => { const currentLineNumberStats = internalCommentTriggers.setLineCounts[lineNumber]; if (!currentLineNumberStats) { throw new Error(`Line number stats were undefined for "${lineNumber}" in "${JSON.stringify(internalCommentTriggers.setLineCounts)}"`); } const endLineNumber = internalCommentTriggers.resets.find((resetLineNumber) => { return lineNumber < resetLineNumber; }) ?? currentLineNumberStats.lineEnd; currentLineNumberStats.lineEnd = endLineNumber; }); } } function getWrapThreshold(commentText, nextOnly) { const searchText = nextOnly ? nextWrapThresholdComment : setWrapThresholdComment; const searchRegExp = nextOnly ? untilNextWrapThresholdCommentRegExp : untilSetWrapThresholdCommentRegExp; if (commentText?.toLowerCase().includes(searchText)) { const thresholdValue = Number(commentText.toLowerCase().replace(searchRegExp, '').trim()); if (isNaN(thresholdValue)) { return undefined; } else { return thresholdValue; } } else { return undefined; } } export function parseNextLineCounts(input, nextOnly, debug) { if (!input) { return []; } const searchRegExp = nextOnly ? untilNextLinePatternCommentRegExp : untilSetLinePatternCommentRegExp; const split = input .toLowerCase() .replace(searchRegExp, '') .replace(/,/g, '') .split(' ') .filter((entry) => !!entry); const firstSplit = split[0]; if (firstSplit === '[') { split.splice(0, 1); } else if (firstSplit?.startsWith('[')) { split[0] = firstSplit.replace(/^\[/, ''); } const lastSplitIndex = split.length - 1; const lastSplit = split[lastSplitIndex]; if (lastSplit === ']') { split.splice(split.length - 1, 1); } else if (lastSplit?.endsWith(']')) { split[lastSplitIndex] = lastSplit.replace(/\]$/, ''); } const numbers = split.map((entry) => entry && !!entry.trim().match(/^\d+$/) ? Number(entry.trim()) : NaN); const invalidNumbers = numbers .map((entry, index) => ({ index, entry, original: split[index] })) .filter((entry) => { return isNaN(entry.entry); }); if (invalidNumbers.length) { if (debug) { console.error(invalidNumbers.map((entry) => ({ index: entry.index, original: entry.original, parsed: entry, split, input, numbers, trim: entry.original?.trim(), match: entry.original?.trim().match(/^\d+$/), matched: !!entry.original?.trim().match(/^\d+$/), }))); } console.error(`Invalid number(s) for elements per line option/comment: ${invalidNumbers .map((entry) => entry.original) .join()}`); return []; } return numbers; } function isResetComment(commentText) { return !!commentText?.toLowerCase().includes(resetComment); } function getLineCounts(commentText, nextOnly, debug) { const searchText = nextOnly ? nextLinePatternComment : setLinePatternComment; if (commentText?.toLowerCase().includes(searchText)) { return parseNextLineCounts(commentText, nextOnly, debug); } else { return []; } }