core/parsers/tool.clang-tidy.parser.ts

core/parsers/tool.clang-tidy.parser.ts is a file in GovLab Quality. 30 lines of code and 13 definitions.

import { parseLines, parseLocation } from "#core/parsers/location.parser";
import type { Finding } from "#types/finding.types";
import { advisoryFinding } from "#core/factories/finding.factory";

const TOOL = "clang-tidy";
const DIAGNOSTIC_MARKERS = [": error: ", ": warning: "];

const findMarker = function findMarker(raw: string): { idx: number; marker: string } | null {
    const found = DIAGNOSTIC_MARKERS.map((marker) => ({ idx: raw.indexOf(marker), marker }))
        .filter((entry) => entry.idx !== -1)
        .toSorted((a, b) => a.idx - b.idx);
    return found[0] ?? null;
};

const extractCheck = function extractCheck(rest: string): { message: string; ruleId: string } {
    const open = rest.lastIndexOf("[");
    const close = rest.lastIndexOf("]");
    const ruleId = open !== -1 && close > open ? rest.slice(open + 1, close) : TOOL;
    const message = (open === -1 ? rest : rest.slice(0, open)).trim();
    return { message, ruleId };
};

const parseLine = function parseLine(raw: string, ecosystem: string): Finding | null {
    const found = findMarker(raw);
    const location = found === null ? null : parseLocation(raw.slice(0, found.idx));
    if (found === null || location === null) {
        return null;
    }
    const { message, ruleId } = extractCheck(raw.slice(found.idx + found.marker.length));
    return advisoryFinding({ ...location, ecosystem, message, ruleId, tool: TOOL });
};

export const parseClangTidyOutput = function parseClangTidyOutput(stdout: string, ecosystem: string): Finding[] {
    return parseLines(stdout, (line) => parseLine(line, ecosystem));
};