UNPKG

@textlint/kernel

Version:
141 lines (133 loc) 4.78 kB
// LICENSE : MIT "use strict"; import type { TextlintRuleContextFixCommand, TextlintRuleErrorDetails, TextlintRuleError } from "@textlint/types"; import { TextlintRuleErrorPaddingLocation } from "@textlint/types"; import { throwIfTesting } from "@textlint/feature-flag"; import { isTextlintRuleErrorPaddingLocation } from "./TextlintRulePaddingLocator"; const assertTextlintRuleErrorDetail = (details: TextlintRuleErrorDetails) => { // reject wrong usage if ("at" in details) { throw new Error( `RuleError details should not have "loc" property. Please use { padding: locator.at(index) } instead.` ); } if ("range" in details) { throw new Error( `RuleError details should not have "range" property. Please use { padding: locator.range([start, end]) } instead.` ); } if ("loc" in details) { throw new Error( `RuleError details should not have "loc" property. Please use { padding: locator.loc({ start, end }) } instead.` ); } // wrong mixed usage const useIndex = "index" in details; const useLineColumn = "line" in details || "column" in details; const usePadding = "padding" in details; if ([useIndex, useLineColumn, usePadding].filter(Boolean).length > 1) { throwIfTesting(`RuleError details can not mixed usage: ${JSON.stringify(details)} You can not set { index, line, column, padding } at same time. `); } // legacy usage if (useIndex) { if (typeof details.index !== "number" || Number.isNaN(details.index)) { throwIfTesting(`index should be number: ${JSON.stringify(details)}`); } return; } if (useLineColumn) { // TODO: make throw error in next version const shouldHaveLineAndColumn = "line" in details && "column" in details; if (!shouldHaveLineAndColumn) { throwIfTesting("line and column should be set both"); } if (typeof details.line !== "number" || Number.isNaN(details.line)) { throwIfTesting(`line should be number: ${JSON.stringify(details)}`); } if (typeof details.column !== "number" || Number.isNaN(details.column)) { throwIfTesting(`column should be number: ${JSON.stringify(details)}`); } return; } // modern usage if (usePadding) { // padding assertion is done in locator function if (!isTextlintRuleErrorPaddingLocation(details.padding)) { throwIfTesting(`padding should be created locator function: ${JSON.stringify(details)}`); } return; } }; export class TextlintRuleErrorImpl implements TextlintRuleError { public message: string; /** * @deprecated use `padding` property */ public readonly line?: number; /** * @deprecated use `padding` property */ public readonly column?: number; /** * @deprecated use `padding` property */ public readonly index?: number; /** * padding location object * You can create padding value using `locator` */ public readonly padding?: TextlintRuleErrorPaddingLocation; public readonly fix?: TextlintRuleContextFixCommand; /** * RuleError is like Error object. * It's used for adding to TextlintResult. * @param message error message should start with lowercase letter * @param [details] - the object has padding and fix info * @constructor */ constructor(message: string, details?: number | TextlintRuleErrorDetails) { this.message = message; if (typeof details === "object") { assertTextlintRuleErrorDetail(details); /** * padding lineNumber * @type {number} */ this.line = details.line; /** * padding column * @type {number} */ this.column = details.column; /** * padding index * @type {number} */ this.index = details.index; /** * fixCommand object * @type {TextlintRuleContextFixCommand} */ this.fix = details.fix; /** * padding location object */ this.padding = details.padding; } else if (typeof details === "number") { // this is deprecated // should pass padding as object. this.column = details; } } toString() { return JSON.stringify({ message: this.message, line: this.line, column: this.column, index: this.index, fix: this.fix }); } }