UNPKG

@codeque/core

Version:

Multiline code search for every language. Structural code search for JavaScript, TypeScript, HTML and CSS

212 lines (163 loc) 6.36 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getExtendedCodeFrame = exports.dedupMatches = exports.decomposeString = exports.asyncFilter = exports.SPACE_CHAR = void 0; exports.getKeyFromObject = getKeyFromObject; exports.uniqueItems = exports.runNodesComparators = exports.regExpTest = exports.print = exports.prepareCodeResult = exports.normalizeText = exports.noopLogger = exports.nonIdentifierOrKeywordGlobal = exports.nonIdentifierOrKeyword = exports.logMetrics = exports.isNullOrUndef = exports.groupMatchesByFile = exports.groupBy = exports.getMode = void 0; const getMode = (mode = 'include') => { const modes = ['include', 'exact', 'include-with-order', 'text']; if (!modes.includes(mode)) { console.error('Invalid mode: ', mode, '\nValid modes: ', ...modes); process.exit(0); } return mode; }; exports.getMode = getMode; const metrics = {}; const logMetrics = () => { if (process.env.NODE_ENV !== 'test') { Object.entries(metrics).forEach(kv => print(...kv)); } }; exports.logMetrics = logMetrics; const print = console.log; // to distinguish intended logs exports.print = print; const asyncFilter = async (arr, predicate) => { const results = await Promise.all(arr.map(predicate)); return arr.filter((_v, index) => results[index]); }; exports.asyncFilter = asyncFilter; const regExpTest = (regExp, text) => { if (!text) { return false; } const matches = text.match(regExp); return matches !== null && matches.length > 0; }; exports.regExpTest = regExpTest; const uniqueItems = (...arrays) => { return [...new Set(arrays.flat())]; }; exports.uniqueItems = uniqueItems; const reverse = text => { return text.split('').reverse().join(''); }; const newLineCharLength = '\n'.length; const getExtendedCodeFrame = ({ start, end }, fileContent) => { const basicMatch = fileContent.substring(start, end); const numberOfLines = 1 + (basicMatch.match(/\n/g)?.length ?? 0); const suffixContent = fileContent.substring(end); const positionOfNextLineEndInSuffix = suffixContent.search(/\n/g); let positionOfNextLineEnd = end + (positionOfNextLineEndInSuffix > -1 ? positionOfNextLineEndInSuffix : suffixContent.length); const prefixContent = fileContent.substring(0, start); const positionOfPrevLineEndInPrefix = reverse(prefixContent).search(/\n/g); let positionOfPrevLineEnd = start - (positionOfPrevLineEndInPrefix > -1 ? positionOfPrevLineEndInPrefix : prefixContent.length); let moveStartLine = 0; if (numberOfLines < 3) { const movePrevLineEndBy = reverse(prefixContent.substring(0, positionOfPrevLineEnd - newLineCharLength)).search(/\n/g) + newLineCharLength; positionOfPrevLineEnd -= movePrevLineEndBy; if (movePrevLineEndBy > 0) { moveStartLine = -1; } positionOfNextLineEnd += suffixContent.substring(positionOfNextLineEnd - end + newLineCharLength).search(/\n/g) + newLineCharLength; } const newCodeFrame = fileContent.substring(positionOfPrevLineEnd, positionOfNextLineEnd); return [newCodeFrame, moveStartLine]; }; exports.getExtendedCodeFrame = getExtendedCodeFrame; const groupMatchesByFile = matches => { return matches.reduce((grouped, match) => { if (grouped[match.filePath] === undefined) { grouped[match.filePath] = []; } grouped[match.filePath].push(match); return grouped; }, {}); }; exports.groupMatchesByFile = groupMatchesByFile; function getKeyFromObject(object, key) { const keyParts = key.split('.'); let val = object; for (const keyPart of keyParts) { val = val[keyPart]; } return val; } // We process '$' (wildcards) separately const nonIdentifierOrKeyword = /([^\w\s$])/; exports.nonIdentifierOrKeyword = nonIdentifierOrKeyword; const nonIdentifierOrKeywordGlobal = new RegExp(nonIdentifierOrKeyword, 'g'); exports.nonIdentifierOrKeywordGlobal = nonIdentifierOrKeywordGlobal; const dedupMatches = matches => { const deduped = []; matches.forEach(match => { const alreadyIn = deduped.some(_match => { const filePathMatch = match.filePath === undefined || match.filePath === _match.filePath; return filePathMatch && match.start === _match.start && match.end === _match.end; }); if (!alreadyIn) { deduped.push(match); } }); return deduped; }; exports.dedupMatches = dedupMatches; const prepareCodeResult = ({ fileContent, start, end, loc }) => { const frame = fileContent.substring(start - loc.start.column, end); const firstLineWhiteCharsCountRegExp = new RegExp(`^\\s*`); const firstLine = frame.split('\n')[0]; const lines = frame.substr(loc.start.column).split('\n'); const firstLineWhiteCharsCount = (firstLine?.match(firstLineWhiteCharsCountRegExp))[0]?.length; const replaceRegex = new RegExp(`^\\s{0,${firstLineWhiteCharsCount}}`); if (firstLineWhiteCharsCount > 0) { const code = lines.map(line => line.replace(replaceRegex, '')).join('\n'); return { code, indentationBase: firstLineWhiteCharsCount }; } return { code: lines.join('\n'), indentationBase: 0 }; }; exports.prepareCodeResult = prepareCodeResult; const isNullOrUndef = val => val === null || val === undefined; exports.isNullOrUndef = isNullOrUndef; const SPACE_CHAR = ' '; exports.SPACE_CHAR = SPACE_CHAR; const normalizeText = text => text ? text.trim().replace(/\s+/g, SPACE_CHAR) : text; exports.normalizeText = normalizeText; const runNodesComparators = (nodesComparators, nodesComparatorParams) => { for (const nodesComparator of nodesComparators) { const compareResult = nodesComparator(...nodesComparatorParams); if (compareResult) { return compareResult; } } }; exports.runNodesComparators = runNodesComparators; const noopLogger = { log: () => undefined, logStepEnd: () => undefined, logStepStart: () => undefined }; exports.noopLogger = noopLogger; const groupBy = (arr, key) => { return Object.values(arr.reduce((grouped, duplicate) => { const maybeExistingGroup = grouped[duplicate[key]] ?? []; grouped[duplicate[key]] = [...maybeExistingGroup, duplicate]; return grouped; }, {})); }; exports.groupBy = groupBy; const decomposeString = (str, splitter) => str.split(splitter).map(part => normalizeText(part).split(SPACE_CHAR)).flat(1); exports.decomposeString = decomposeString;