@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
JavaScript
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;
;