Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | 330x 330x 330x 330x 330x 330x 330x 330x 330x 330x 330x 330x 330x 330x 82x 82x 82x 82x 82x 82x 82x 82x 82x 82x 82x 82x 82x 82x 82x 82x 82x 154x 154x 154x 154x 154x 82x 82x 82x 82x 82x 82x 154x 82x 82x 82x 330x 330x 330x 330x 330x 330x 330x 330x 76x 76x 76x 76x 76x 76x 76x 76x 330x 330x 330x 330x 330x 330x 330x 330x 330x 330x 330x 330x 330x 266x 266x 266x 266x 263x 263x 263x 263x 263x 263x 1x 263x 1x 1x 1x 263x 266x 266x 266x 266x 266x 266x 266x 266x 266x 1x 1x 266x 330x 330x 330x 330x 330x 330x 330x 80x 80x 80x 80x 74x 74x 74x 74x 80x 80x 80x 80x 80x 74x 74x 80x 80x 80x 80x 80x 80x 80x 80x 80x 80x 330x 330x 330x 330x 330x 330x 330x 330x 330x 330x 330x 330x 330x 330x 330x 330x 330x 330x 330x | import { AvenxError } from '../../core/runtime/AvenxError.js';
/**
* Formats a code frame snippet highlighting an error location with carets (^).
* @param {string} source - The source code or template content.
* @param {number} line - 1-based line number of the error.
* @param {number} column - 1-based column offset of the error.
* @param {object} [options]
* @param {number} [options.linesBefore] - Context lines to include before.
* @param {number} [options.linesAfter] - Context lines to include after.
* @param {number} [options.length] - Number of carets to render under the error (e.g. ^^^).
* @returns {string} The formatted visual code frame string.
*/
export function formatCodeFrame(source, line, column, options = {}) {
if (!source || typeof source !== 'string' || !line || line < 1) {
return '';
}
const lines = source.split(/\r?\n/);
const totalLines = lines.length;
if (line > totalLines) {
return '';
}
const linesBefore = options.linesBefore !== undefined ? options.linesBefore : 1;
const linesAfter = options.linesAfter !== undefined ? options.linesAfter : 1;
const caretLength = Math.max(1, options.length || 1);
const startLine = Math.max(1, line - linesBefore);
const endLine = Math.min(totalLines, line + linesAfter);
const maxLineNumWidth = String(endLine).length;
const result = [];
for (let l = startLine; l <= endLine; l++) {
const lineNumStr = String(l).padStart(maxLineNumWidth, ' ');
const lineContent = lines[l - 1];
result.push(` ${lineNumStr} | ${lineContent}`);
if (l === line) {
const col = Math.max(1, Math.min(column || 1, lineContent.length + 1));
const gutterPadding = ' '.repeat(maxLineNumWidth);
const spacePadding = ' '.repeat(col - 1);
const carets = '^'.repeat(caretLength);
result.push(` ${gutterPadding} | ${spacePadding}${carets}`);
}
}
return result.join('\n');
}
/**
* Computes 1-based line and column coordinates from a character index in a source string.
* @param {string} source - The source code or template string.
* @param {number} index - Character offset.
* @returns {{ line: number, column: number }}
*/
export function getLineAndColumn(source, index) {
if (!source || typeof source !== 'string' || index === undefined || index < 0) {
return { line: 1, column: 1 };
}
const safeIndex = Math.min(index, source.length);
const substring = source.slice(0, safeIndex);
const lines = substring.split(/\r?\n/);
const line = lines.length;
const column = lines[lines.length - 1].length + 1;
return { line, column };
}
/**
* Base error class for all compiler-related errors and warnings in Avenx-JS.
* Subclasses AvenxError to maintain compatibility with standard error handling.
* @augments AvenxError
*/
export class CompilerError extends AvenxError {
/**
* Creates an instance of CompilerError.
* @param {string} code - The AvenxErrorCode identifier.
* @param {...any} args - Arguments to format within the template message, optionally ending with a location options object.
*/
constructor(code, ...args) {
let locOptions = null;
let formatArgs = args;
if (args.length > 0) {
const lastArg = args[args.length - 1];
if (
lastArg &&
typeof lastArg === 'object' &&
!Array.isArray(lastArg) &&
!(lastArg instanceof Error) &&
(lastArg.line !== undefined || lastArg.source !== undefined || lastArg.location !== undefined)
) {
locOptions = lastArg.location || lastArg;
formatArgs = args.slice(0, -1);
}
}
super(code, ...formatArgs);
/**
* Custom name identifier for compiler errors.
* @type {string}
*/
this.name = 'CompilerError';
if (locOptions) {
this.setLocation(locOptions);
}
}
/**
* Attaches source location information and generates a code frame with carets (^).
* @param {object} loc - Location options object containing { line, column, source, filename, index, length }.
* @returns {CompilerError} Returns this error instance for chaining.
*/
setLocation(loc = {}) {
const { source, filename, index, length } = loc;
let { line, column } = loc;
if (source && index !== undefined && (!line || !column)) {
const pos = getLineAndColumn(source, index);
line = pos.line;
column = pos.column;
}
this.line = line;
this.column = column;
this.source = source;
if (filename) {
this.filename = filename;
}
if (source && line && column) {
this.frame = formatCodeFrame(source, line, column, { length });
if (this.frame && !this.message.includes(this.frame)) {
this.message += `\n\n${this.frame}`;
}
}
return this;
}
/**
* Helper static method to format code frames.
* @param {string} source
* @param {number} line
* @param {number} column
* @param {object} [options]
* @returns {string}
*/
static formatCodeFrame(source, line, column, options) {
return formatCodeFrame(source, line, column, options);
}
/**
* Helper static method to compute line and column coordinates.
* @param {string} source
* @param {number} index
* @returns {{ line: number, column: number }}
*/
static getLineAndColumn(source, index) {
return getLineAndColumn(source, index);
}
}
|