AK-21/Graphite-Industrial-Intelligence
0
1/**2 * @import {Node, Point, Position} from 'unist'3 */4 5/**6 * @typedef {object & {type: string, position?: Position | undefined}} NodeLike7 *8 * @typedef Options9 * Configuration.10 * @property {Array<Node> | null | undefined} [ancestors]11 * Stack of (inclusive) ancestor nodes surrounding the message (optional).12 * @property {Error | null | undefined} [cause]13 * Original error cause of the message (optional).14 * @property {Point | Position | null | undefined} [place]15 * Place of message (optional).16 * @property {string | null | undefined} [ruleId]17 * Category of message (optional, example: `'my-rule'`).18 * @property {string | null | undefined} [source]19 * Namespace of who sent the message (optional, example: `'my-package'`).20 */21 22import {stringifyPosition} from 'unist-util-stringify-position'23 24/**25 * Message.26 */27export class VFileMessage extends Error {28 /**29 * Create a message for `reason`.30 *31 * > 🪦 **Note**: also has obsolete signatures.32 *33 * @overload34 * @param {string} reason35 * @param {Options | null | undefined} [options]36 * @returns37 *38 * @overload39 * @param {string} reason40 * @param {Node | NodeLike | null | undefined} parent41 * @param {string | null | undefined} [origin]42 * @returns43 *44 * @overload45 * @param {string} reason46 * @param {Point | Position | null | undefined} place47 * @param {string | null | undefined} [origin]48 * @returns49 *50 * @overload51 * @param {string} reason52 * @param {string | null | undefined} [origin]53 * @returns54 *55 * @overload56 * @param {Error | VFileMessage} cause57 * @param {Node | NodeLike | null | undefined} parent58 * @param {string | null | undefined} [origin]59 * @returns60 *61 * @overload62 * @param {Error | VFileMessage} cause63 * @param {Point | Position | null | undefined} place64 * @param {string | null | undefined} [origin]65 * @returns66 *67 * @overload68 * @param {Error | VFileMessage} cause69 * @param {string | null | undefined} [origin]70 * @returns71 *72 * @param {Error | VFileMessage | string} causeOrReason73 * Reason for message, should use markdown.74 * @param {Node | NodeLike | Options | Point | Position | string | null | undefined} [optionsOrParentOrPlace]75 * Configuration (optional).76 * @param {string | null | undefined} [origin]77 * Place in code where the message originates (example:78 * `'my-package:my-rule'` or `'my-rule'`).79 * @returns80 * Instance of `VFileMessage`.81 */82 // eslint-disable-next-line complexity83 constructor(causeOrReason, optionsOrParentOrPlace, origin) {84 super()85 86 if (typeof optionsOrParentOrPlace === 'string') {87 origin = optionsOrParentOrPlace88 optionsOrParentOrPlace = undefined89 }90 91 /** @type {string} */92 let reason = ''93 /** @type {Options} */94 let options = {}95 let legacyCause = false96 97 if (optionsOrParentOrPlace) {98 // Point.99 if (100 'line' in optionsOrParentOrPlace &&101 'column' in optionsOrParentOrPlace102 ) {103 options = {place: optionsOrParentOrPlace}104 }105 // Position.106 else if (107 'start' in optionsOrParentOrPlace &&108 'end' in optionsOrParentOrPlace109 ) {110 options = {place: optionsOrParentOrPlace}111 }112 // Node.113 else if ('type' in optionsOrParentOrPlace) {114 options = {115 ancestors: [optionsOrParentOrPlace],116 place: optionsOrParentOrPlace.position117 }118 }119 // Options.120 else {121 options = {...optionsOrParentOrPlace}122 }123 }124 125 if (typeof causeOrReason === 'string') {126 reason = causeOrReason127 }128 // Error.129 else if (!options.cause && causeOrReason) {130 legacyCause = true131 reason = causeOrReason.message132 options.cause = causeOrReason133 }134 135 if (!options.ruleId && !options.source && typeof origin === 'string') {136 const index = origin.indexOf(':')137 138 if (index === -1) {139 options.ruleId = origin140 } else {141 options.source = origin.slice(0, index)142 options.ruleId = origin.slice(index + 1)143 }144 }145 146 if (!options.place && options.ancestors && options.ancestors) {147 const parent = options.ancestors[options.ancestors.length - 1]148 149 if (parent) {150 options.place = parent.position151 }152 }153 154 const start =155 options.place && 'start' in options.place156 ? options.place.start157 : options.place158 159 /**160 * Stack of ancestor nodes surrounding the message.161 *162 * @type {Array<Node> | undefined}163 */164 this.ancestors = options.ancestors || undefined165 166 /**167 * Original error cause of the message.168 *169 * @type {Error | undefined}170 */171 this.cause = options.cause || undefined172 173 /**174 * Starting column of message.175 *176 * @type {number | undefined}177 */178 this.column = start ? start.column : undefined179 180 /**181 * State of problem.182 *183 * * `true` — error, file not usable184 * * `false` — warning, change may be needed185 * * `undefined` — change likely not needed186 *187 * @type {boolean | null | undefined}188 */189 this.fatal = undefined190 191 /**192 * Path of a file (used throughout the `VFile` ecosystem).193 *194 * @type {string | undefined}195 */196 this.file = ''197 198 // Field from `Error`.199 /**200 * Reason for message.201 *202 * @type {string}203 */204 this.message = reason205 206 /**207 * Starting line of error.208 *209 * @type {number | undefined}210 */211 this.line = start ? start.line : undefined212 213 // Field from `Error`.214 /**215 * Serialized positional info of message.216 *217 * On normal errors, this would be something like `ParseError`, buit in218 * `VFile` messages we use this space to show where an error happened.219 */220 this.name = stringifyPosition(options.place) || '1:1'221 222 /**223 * Place of message.224 *225 * @type {Point | Position | undefined}226 */227 this.place = options.place || undefined228 229 /**230 * Reason for message, should use markdown.231 *232 * @type {string}233 */234 this.reason = this.message235 236 /**237 * Category of message (example: `'my-rule'`).238 *239 * @type {string | undefined}240 */241 this.ruleId = options.ruleId || undefined242 243 /**244 * Namespace of message (example: `'my-package'`).245 *246 * @type {string | undefined}247 */248 this.source = options.source || undefined249 250 // Field from `Error`.251 /**252 * Stack of message.253 *254 * This is used by normal errors to show where something happened in255 * programming code, irrelevant for `VFile` messages,256 *257 * @type {string}258 */259 this.stack =260 legacyCause && options.cause && typeof options.cause.stack === 'string'261 ? options.cause.stack262 : ''263 264 // The following fields are “well known”.265 // Not standard.266 // Feel free to add other non-standard fields to your messages.267 268 /**269 * Specify the source value that’s being reported, which is deemed270 * incorrect.271 *272 * @type {string | undefined}273 */274 this.actual = undefined275 276 /**277 * Suggest acceptable values that can be used instead of `actual`.278 *279 * @type {Array<string> | undefined}280 */281 this.expected = undefined282 283 /**284 * Long form description of the message (you should use markdown).285 *286 * @type {string | undefined}287 */288 this.note = undefined289 290 /**291 * Link to docs for the message.292 *293 * > 👉 **Note**: this must be an absolute URL that can be passed as `x`294 * > to `new URL(x)`.295 *296 * @type {string | undefined}297 */298 this.url = undefined299 }300}301 302VFileMessage.prototype.file = ''303VFileMessage.prototype.name = ''304VFileMessage.prototype.reason = ''305VFileMessage.prototype.message = ''306VFileMessage.prototype.stack = ''307VFileMessage.prototype.column = undefined308VFileMessage.prototype.line = undefined309VFileMessage.prototype.ancestors = undefined310VFileMessage.prototype.cause = undefined311VFileMessage.prototype.fatal = undefined312VFileMessage.prototype.place = undefined313VFileMessage.prototype.ruleId = undefined314VFileMessage.prototype.source = undefined315 