UNPKG

yini-parser

Version:

Node.js parser for YINI — a clean, structured INI alternative with types, simple section nesting, comments, and strict mode.

204 lines (202 loc) 10.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ErrorDataHandler = void 0; const env_1 = require("../config/env"); const print_1 = require("../utils/print"); // All the issue titles are defined here to get a quick overview of all // titles, and to easier check that all titles match with relation to // the other titles. const issueTitle = [ 'FATAL ERROR!', 'Internal error!', // 'Internal-Error'. 'Syntax error.', // 'Syntax-Error'. 'Syntax warning.', 'Notice:', 'Info:', ]; /** * This class handles all error/notice reporting and processes exit/throwing. */ class ErrorDataHandler { /** '1-Abort-on-Errors' is the default. Below is from the YINI spec: **Abort Sensitivity Levels** while parsing a YINI document: (AKA severity threshold) - Level 0 = ignore errors and try parse anyway (may remap falty key/section names) - Level 1 = abort on errors only - Level 2 = abort even on warnings */ constructor(threshold = '1-Abort-on-Errors') { this.numFatalErrors = 0; this.numInternalErrors = 0; this.numSyntaxErrors = 0; this.numSyntaxWarnings = 0; this.numNotices = 0; this.numInfos = 0; this.makeIssuePayload = (type, msgWhat, lineNum, startCol, endCol) => { const issue = { type, msgWhat, // msgHintOrFix: string = '', // Hint or wow to fix. start: { line: lineNum, column: startCol, }, end: { line: lineNum, column: endCol, }, }; (0, print_1.debugPrint)('issue:'); (0, env_1.isDebug)() && console.log(issue); return issue; }; /** * After pushing processing may continue or exit, depending on the error * and/or the bail threshold (that can be optionally set my the user). * * @note This function MIGHT result in a return, throw, or exit depending * on the bail policy (set my the user). * * @param ctx * @param type * @param msgWhat Name of the specific error or what failed. E.g. "Key already exists in this section scope". * @param msgWhy More details and more specific info about the issue/error. * @param msgHint Hint or HUMBLE description on how to fix the issue. */ this.pushOrBail = (ctx, type, msgWhat, msgWhy = '', msgHint = '') => { var _a, _b, _c, _d, _e, _f; (0, print_1.debugPrint)('-> pushOrBail(..)'); (0, print_1.debugPrint)('ctx.exception?.name =' + ((_a = ctx === null || ctx === void 0 ? void 0 : ctx.exception) === null || _a === void 0 ? void 0 : _a.name)); (0, print_1.debugPrint)('ctx.exception?.message = ' + ((_b = ctx === null || ctx === void 0 ? void 0 : ctx.exception) === null || _b === void 0 ? void 0 : _b.message)); (0, print_1.debugPrint)('exception?.offendingToken = ' + ((_c = ctx === null || ctx === void 0 ? void 0 : ctx.exception) === null || _c === void 0 ? void 0 : _c.offendingToken)); (0, print_1.debugPrint)(); (0, print_1.debugPrint)('ctx.ruleIndex = ' + (ctx === null || ctx === void 0 ? void 0 : ctx.start.channel)); (0, print_1.debugPrint)('ctx.ruleIndex = ' + (ctx === null || ctx === void 0 ? void 0 : ctx.ruleIndex)); (0, print_1.debugPrint)('ctx.ruleContext = ' + (ctx === null || ctx === void 0 ? void 0 : ctx.ruleContext)); (0, print_1.debugPrint)('ctx.stop?.line = ' + ((_d = ctx === null || ctx === void 0 ? void 0 : ctx.stop) === null || _d === void 0 ? void 0 : _d.line)); (0, print_1.debugPrint)('ctx.stop?.column = ' + ((_e = ctx === null || ctx === void 0 ? void 0 : ctx.stop) === null || _e === void 0 ? void 0 : _e.column)); const lineNum = (ctx === null || ctx === void 0 ? void 0 : ctx.start.line) || 0; // Column (1-based). const startCol = !ctx ? 0 : ++ctx.start.column; // Column (0-based). const endCol = (((_f = ctx === null || ctx === void 0 ? void 0 : ctx.stop) === null || _f === void 0 ? void 0 : _f.column) || 0) + 1; // Column (0-based). // Patch message with the offending line number. msgWhat += ', at line: ' + lineNum; if (process.env.NODE_ENV === 'test') { msgWhat += `\nAt line: ${lineNum}, column(s): ${startCol}-${endCol}`; } (0, print_1.debugPrint)('persistThreshold = ' + this.persistThreshold); (0, print_1.debugPrint)('lineNum = ' + lineNum); (0, print_1.debugPrint)(); const issue = this.makeIssuePayload(type, msgWhat, lineNum, startCol, endCol); switch (type) { case 'Internal-Error': this.numInternalErrors++; this.emitInternalError(msgWhat, msgWhy, msgHint); if (this.persistThreshold === '1-Abort-on-Errors' || this.persistThreshold === '2-Abort-Even-on-Warnings') { // if (process.env.NODE_ENV === 'test') { // In test, throw an error instead of exiting. throw new Error(`Internal-Error: ${msgWhat}`); // } else { // process.exit(2) // } } break; case 'Syntax-Error': this.numSyntaxErrors++; this.emitSyntaxError(msgWhat, msgWhy, msgHint); if (this.persistThreshold === '1-Abort-on-Errors' || this.persistThreshold === '2-Abort-Even-on-Warnings') { // if (process.env.NODE_ENV === 'test') { // In test, throw an error instead of exiting. throw new Error(`Syntax-Error: ${'' + msgWhat}`); // } else { // process.exit(3) // } } break; case 'Syntax-Warning': this.numSyntaxWarnings++; this.emitSyntaxWarning(msgWhat, msgWhy, msgHint); if (this.persistThreshold === '2-Abort-Even-on-Warnings') { // if (process.env.NODE_ENV === 'test') { // In test, throw an error instead of exiting. throw new Error(`Syntax-Warning: ${msgWhat}`); // } else { // process.exit(4) // } } break; case 'Notice': this.numNotices++; this.emitNotice(msgWhat, msgWhy, msgHint); break; case 'Info': this.numInfos++; this.emitInfo(msgWhat, msgWhy, msgHint); break; default: // Including 'Internal-Error'. this.numFatalErrors++; this.emitFatalError(msgWhat, msgWhy, msgHint); // CANNOT recover fatal errors, will lead to an exit! // if (process.env.NODE_ENV === 'test') { // In test, throw an error instead of exiting. throw new Error(`Internal-Error: ${msgWhat}`); // } else { // process.exit(1) // (!) Not sure about the below yet, if it's preferable in this case... // Use this instead of process.exit(1), this will // lead to that the current thread(s) will exit as well. // process.exitCode = 1 // } } }; this.emitFatalError = (msgWhat = 'Something went wrong!', msgWhy = '', msgHint = '') => { console.error(issueTitle[0]); // Print the issue title. msgWhat && console.error(msgWhat); msgWhy && console.log(msgWhy); msgHint && console.log(msgHint); }; this.emitInternalError = (msgWhat = 'Something went wrong!', msgWhy = '', msgHint = '') => { console.error(issueTitle[1]); // Print the issue title. msgWhat && console.error(msgWhat); msgWhy && console.log(msgWhy); msgHint && console.log(msgHint); }; this.emitSyntaxError = (msgWhat, msgWhy = '', msgHint = '') => { console.error(issueTitle[2]); // Print the issue title. msgWhat && console.error(msgWhat); msgWhy && console.log(msgWhy); msgHint && console.log(msgHint); }; this.emitSyntaxWarning = (msgWhat, msgWhy = '', msgHint = '') => { console.warn(issueTitle[3]); // Print the issue title. msgWhat && console.warn(msgWhat); msgWhy && console.log(msgWhy); msgHint && console.log(msgHint); }; this.emitNotice = (msgWhat, msgWhy = '', msgHint = '') => { console.warn(issueTitle[4]); // Print the issue title. msgWhat && console.warn(msgWhat); msgWhy && console.log(msgWhy); msgHint && console.log(msgHint); }; this.emitInfo = (msgWhat, msgWhy = '', msgHint = '') => { console.info(issueTitle[5]); // Print the issue title. msgWhat && console.info(msgWhat); msgWhy && console.log(msgWhy); msgHint && console.log(msgHint); }; this.persistThreshold = threshold; } getNumOfErrors() { return (this.numFatalErrors + this.numInternalErrors + this.numSyntaxErrors); } getNumOfWarnings() { return this.numSyntaxWarnings; } getNumOfInfoAndNotices() { return this.numNotices + this.numInfos; } } exports.ErrorDataHandler = ErrorDataHandler;