@plugjs/plug
Version:
PlugJS Build System ===================
296 lines (294 loc) • 11.8 kB
JavaScript
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// logging/report.ts
var report_exports = {};
__export(report_exports, {
ReportImpl: () => ReportImpl
});
module.exports = __toCommonJS(report_exports);
var import_asserts = require("../asserts.cjs");
var import_fs = require("../fs.cjs");
var import_colors = require("./colors.cjs");
var import_github = require("./github.cjs");
var import_levels = require("./levels.cjs");
var import_options = require("./options.cjs");
var _showSources = import_options.logOptions.showSources;
var _githubAnnotations = import_options.logOptions.githubAnnotations;
import_options.logOptions.on("changed", (options) => {
_showSources = options.showSources;
_githubAnnotations = options.githubAnnotations;
});
var nul = "\u2400";
var ReportImpl = class {
constructor(_title, _task, _emitter) {
this._title = _title;
this._task = _task;
this._emitter = _emitter;
}
_sources = /* @__PURE__ */ new Map();
_annotations = /* @__PURE__ */ new Map();
_records = /* @__PURE__ */ new Map();
_noticeRecords = 0;
_warningRecords = 0;
_errorRecords = 0;
_noticeAnnotations = 0;
_warningAnnotations = 0;
_errorAnnotations = 0;
get notices() {
return this._noticeRecords + this._noticeAnnotations;
}
get warnings() {
return this._warningRecords + this._warningAnnotations;
}
get errors() {
return this._errorRecords + this._errorAnnotations;
}
get noticeRecords() {
return this._noticeRecords;
}
get warningRecords() {
return this._warningRecords;
}
get errorRecords() {
return this._errorRecords;
}
get noticeAnnotations() {
return this._noticeAnnotations;
}
get warningAnnotations() {
return this._warningAnnotations;
}
get errorAnnotations() {
return this._errorAnnotations;
}
get records() {
return this._noticeRecords + this._warningRecords + this._errorRecords;
}
get annotations() {
return this._noticeAnnotations + this._warningAnnotations + this._errorAnnotations;
}
get empty() {
return !(this.records + this.annotations);
}
annotate(annotationLevel, file, note) {
if (note) {
const level = annotationLevel;
this._annotations.set(file, { level, note });
switch (level) {
case import_levels.NOTICE:
this._noticeRecords++;
break;
case import_levels.WARN:
this._warningRecords++;
break;
case import_levels.ERROR:
this._errorRecords++;
break;
}
}
return this;
}
add(...records) {
for (const record of records) {
let messages = Array.isArray(record.message) ? [...record.message.map((msg) => msg.split("\n")).flat(1)] : record.message.split("\n");
messages = messages.filter((message) => !!message);
if (!messages.length) {
const options = { taskName: this._task, level: import_levels.ERROR };
this._emitter(options, ["No message for report record"]);
throw import_asserts.BuildFailure.fail();
}
const level = record.level;
const file = record.file;
const source = record.source || void 0;
const tags = record.tags ? Array.isArray(record.tags) ? [...record.tags] : [record.tags] : [];
switch (level) {
case import_levels.NOTICE:
this._noticeRecords++;
break;
case import_levels.WARN:
this._warningRecords++;
break;
case import_levels.ERROR:
this._errorRecords++;
break;
}
let line = 0;
let column = 0;
let length = 1;
if (file && record.line) {
line = record.line;
if (record.column) {
column = record.column;
if (record.length) {
length = record.length;
if (length < 0) {
length = Number.MAX_SAFE_INTEGER;
}
}
}
}
if (file && source && !this._sources.has(file)) {
this._sources.set(file, source.split("\n"));
}
let reports = this._records.get(file || nul);
if (!reports) this._records.set(file || nul, reports = /* @__PURE__ */ new Set());
reports.add({ level, messages, tags, line, column, length });
}
return this;
}
async loadSources() {
const promises = [];
for (const file of this._records.keys()) {
if (!file) continue;
if (file === nul) continue;
if (this._sources.has(file)) continue;
promises.push((0, import_fs.readFile)(file, "utf-8").then((source) => source.split("\n")).then((lines) => this._sources.set(file, lines)));
}
await Promise.allSettled(promises);
}
done(showSources) {
if (showSources == null) showSources = _showSources;
if (!this.empty) this._emit(showSources);
if (this.errors) throw import_asserts.BuildFailure.fail();
}
_emit(showSources) {
let fPad = 0;
let aPad = 0;
let mPad = 0;
let lPad = 0;
let cPad = 0;
if (this._annotations.size === 0 && this._records.size === 0) return;
const entries = [...this._annotations.keys(), ...this._records.keys()].filter((file, i, a) => a.indexOf(file) === i).sort((a, b) => {
return (a || "") < (b || "") ? -1 : (a || "") > (b || "") ? 1 : 0;
}).map((file) => {
const ann = file && file !== nul && this._annotations.get(file);
const records = [...this._records.get(file) || []].sort(({ line: al, column: ac }, { line: bl, column: bc }) => (al || Number.MAX_SAFE_INTEGER) - (bl || Number.MAX_SAFE_INTEGER) || (ac || Number.MAX_SAFE_INTEGER) - (bc || Number.MAX_SAFE_INTEGER)).map((record) => {
if (record.line && record.line > lPad) lPad = record.line;
if (record.column && record.column > cPad) cPad = record.column;
for (const message of record.messages) {
if (message.length > mPad) mPad = message.length;
}
return record;
});
if (file && file.length > fPad) fPad = file.length;
if (ann && ann.note.length > aPad) aPad = ann.note.length;
return { file, records, annotation: ann };
});
mPad = mPad <= 100 ? mPad : 0;
lPad = lPad.toString().length;
cPad = cPad.toString().length;
const options = { taskName: this._task, level: import_levels.NOTICE };
this._emitter(options, [""]);
this._emitter(options, [(0, import_colors.$und)((0, import_colors.$wht)(this._title))]);
for (let f = 0; f < entries.length; f++) {
const { file, records, annotation } = entries[f];
const source = file && file != nul && this._sources.get(file);
if (f === 0 || entries[f - 1]?.records.length) {
this._emitter(options, [""]);
}
if (file && file !== nul && annotation) {
const { level, note } = annotation;
const $col = level === import_levels.NOTICE ? import_colors.$blu : level === import_levels.WARN ? import_colors.$ylw : import_colors.$red;
const ann = `${(0, import_colors.$gry)("[")}${$col(note)}${(0, import_colors.$gry)("]")}`;
const pad = "".padStart(fPad + aPad - (file.length + note.length));
this._emitter({ ...options, level }, [(0, import_colors.$wht)((0, import_colors.$und)(file)), pad, ann]);
} else if (file !== nul) {
this._emitter(options, [(0, import_colors.$wht)((0, import_colors.$und)(file))]);
} else if (f > 0) {
this._emitter(options, [""]);
}
for (let r = 0; r < records.length; r++) {
const { level, messages, tags, line, column, length = 1 } = records[r];
let pfx;
if (file && line) {
if (column) {
pfx = ` ${line.toString().padStart(lPad)}:${column.toString().padEnd(cPad)} `;
} else {
pfx = ` ${line.toString().padStart(lPad)}:${"-".padEnd(cPad)} `;
}
} else if (file != nul) {
pfx = ` ${"-".padStart(lPad)}:${"-".padEnd(cPad)} `;
} else {
pfx = " ~ ";
}
const prefix = "".padStart(pfx.length + 1);
const tag = tags.length == 0 ? "" : `${(0, import_colors.$gry)("[")}${tags.map((tag2) => (0, import_colors.$cyn)(tag2)).join((0, import_colors.$gry)("|"))}${(0, import_colors.$gry)("]")}`;
if (messages.length === 1) {
this._emitter({ ...options, level }, [(0, import_colors.$gry)(pfx), messages[0].padEnd(mPad), tag]);
} else {
for (let m = 0; m < messages.length; m++) {
if (!m) {
this._emitter({ ...options, level }, [(0, import_colors.$gry)(pfx), messages[m]]);
} else if (m === messages.length - 1) {
this._emitter({ ...options, level, prefix }, [messages[m].padEnd(mPad), tag]);
} else {
this._emitter({ ...options, level, prefix }, [messages[m]]);
}
}
}
if (showSources && source && source[line - 1]) {
if (column) {
const $col = level === import_levels.NOTICE ? import_colors.$blu : level === import_levels.WARN ? import_colors.$ylw : import_colors.$red;
const offset = column - 1;
const text = source[line - 1] || "";
const head = (0, import_colors.$gry)(text.substring(0, offset));
const body = (0, import_colors.$und)($col(text.substring(offset, offset + length)));
const tail = (0, import_colors.$gry)(text.substring(offset + length));
this._emitter({ ...options, level, prefix }, [(0, import_colors.$gry)(`| ${head}${body}${tail}`)]);
} else {
this._emitter({ ...options, level, prefix }, [(0, import_colors.$gry)(`| ${source[line - 1]}`)]);
}
}
}
}
this._emitter(options, [""]);
const status = ["Found"];
if (this.errors) {
status.push((0, import_colors.$plur)(this.errors, "error", "errors"));
}
if (this.warnings) {
if (this.errors) status.push("and");
status.push((0, import_colors.$plur)(this.warnings, "warning", "warnings"));
}
if (this.errors || this.warnings) {
this._emitter(options, status);
this._emitter(options, [""]);
}
if (_githubAnnotations) {
for (const entry of entries) {
const file = entry.file === nul ? void 0 : entry.file;
for (const report of entry.records) {
const type = report.level === import_levels.logLevels.ERROR ? "error" : report.level === import_levels.logLevels.WARN ? "warning" : null;
if (!type) continue;
const title = `${this._title} (task "${this._task}")`;
const col = report.column || void 0;
const line = report.line || void 0;
const endColumn = report.column ? report.length >= Number.MAX_SAFE_INTEGER ? void 0 : report.column + report.length || void 0 : void 0;
const message = report.messages.join("\n");
(0, import_github.githubAnnotation)({ type, title, file, col, line, endColumn }, message);
}
}
}
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
ReportImpl
});
//# sourceMappingURL=report.cjs.map