@dev-build-deploy/diagnose-it
Version:
Expressive Diagnostics library
153 lines (152 loc) • 6.43 kB
JavaScript
;
/*
* SPDX-FileCopyrightText: 2023 Kevin de Jong <monkaii@hotmail.com>
* SPDX-License-Identifier: MIT
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractFromFile = exports.extractFromSarif = void 0;
const readline_1 = __importDefault(require("readline"));
const fs_1 = __importDefault(require("fs"));
const diagnosticsMessage_1 = require("./diagnosticsMessage");
const sarif = __importStar(require("@dev-build-deploy/sarif-it"));
const LLVM_EXPRESSIVE_DIAGNOSTICS_REGEX = new RegExp("(?:\\s*)(?<file>[\\w,-.]+):(?<lineNumber>[0-9]+):(?<columnNumber>[0-9]+): (?<messageType>(error|warning|note)): (?<message>(.*))");
function getDiagnosticsLevelFromString(value) {
if (value === "error")
return diagnosticsMessage_1.DiagnosticsLevelEnum.Error;
if (value === "warning")
return diagnosticsMessage_1.DiagnosticsLevelEnum.Warning;
return diagnosticsMessage_1.DiagnosticsLevelEnum.Note;
}
/**
* Extracts Expressive Diagnostic messages from SARIF.
*
* NOTE: currently we only support:
* - plain text files
* - the results of the last run
*
* @param sarif The SARIF to extract messages from.
* @param run Index of run, defaults to the last run.
*
* @returns Async Generator of Expressive Messages.
*/
function* extractFromSarif(sarif, run = undefined) {
var _a, _b, _c, _d, _e, _f, _g, _h;
const sarifObj = sarif.properties();
if (run === undefined) {
run = sarifObj.runs.length - 1;
}
const results = (_a = sarifObj.runs[run].results) !== null && _a !== void 0 ? _a : [];
for (const result of results) {
for (const location of (_b = result.locations) !== null && _b !== void 0 ? _b : []) {
if (result.message.text === undefined || location.physicalLocation === undefined) {
continue;
}
const region = location.physicalLocation.region;
const line = (_c = region === null || region === void 0 ? void 0 : region.startLine) !== null && _c !== void 0 ? _c : 1;
const column = (_d = region === null || region === void 0 ? void 0 : region.startColumn) !== null && _d !== void 0 ? _d : 1;
const snippet = (_e = region === null || region === void 0 ? void 0 : region.snippet) === null || _e === void 0 ? void 0 : _e.text;
const msg = new diagnosticsMessage_1.DiagnosticsMessage({
file: (_g = (_f = location.physicalLocation.artifactLocation) === null || _f === void 0 ? void 0 : _f.uri) !== null && _g !== void 0 ? _g : "",
message: {
text: result.message.text,
linenumber: line,
column,
},
level: getDiagnosticsLevelFromString((_h = result.level) !== null && _h !== void 0 ? _h : "warning"),
});
if (snippet !== undefined) {
msg.setContext(line, snippet);
}
yield msg;
}
}
}
exports.extractFromSarif = extractFromSarif;
/**
* Extracts Expressive Diagnostic messages from a raw file.
* This can be used to extract messages from compiler output
*
* @param filePath Path to file to extract messages from.
*/
async function* extractRaw(filePath) {
let currentMessage = undefined;
let matchIndex = 0;
const lineReader = readline_1.default.createInterface({
input: fs_1.default.createReadStream(filePath),
crlfDelay: Infinity,
});
for await (const line of lineReader) {
const match = LLVM_EXPRESSIVE_DIAGNOSTICS_REGEX.exec(line);
if (match && match.groups) {
currentMessage = new diagnosticsMessage_1.DiagnosticsMessage({
file: match.groups.file,
message: {
text: match.groups.message,
linenumber: parseInt(match.groups.lineNumber),
column: parseInt(match.groups.columnNumber),
},
level: getDiagnosticsLevelFromString(match.groups.messageType),
});
matchIndex = line.length - line.trimStart().length;
}
else if (currentMessage) {
const lineNumber = currentMessage.message.linenumber;
if (lineNumber !== undefined) {
currentMessage = currentMessage.setContext(lineNumber, line.substring(matchIndex));
}
yield currentMessage;
currentMessage = undefined;
}
}
if (currentMessage) {
yield currentMessage;
}
}
/**
* Extracts Expressive Diagnostic messages from a file.
* This can be used to extract messages from compile output
*
* @param filePath Path to file to extract messages from.
* @returns Async Generator of Expressive Messages.
*
* @see https://clang.llvm.org/diagnostics.html
*/
async function* extractFromFile(filePath) {
if (filePath.endsWith(".sarif") || filePath.endsWith(".json.sarif")) {
const sarifData = sarif.Log.fromFile(filePath);
for (const message of extractFromSarif(sarifData)) {
yield message;
}
return;
}
for await (const message of extractRaw(filePath)) {
yield message;
}
}
exports.extractFromFile = extractFromFile;