feat: improve error rendering on code snippets
This commit is contained in:
parent
a476fffe2c
commit
25a5b20d5f
@ -4,5 +4,5 @@ const { error_type = "Unknown", error_message } = Astro.props;
|
||||
|
||||
<div class="px-4 py-2 rounded bg-red-200 dark:bg-red-950">
|
||||
<span class="inline-block font-bold">{error_type} error:</span>
|
||||
<span class="inline-block whitespace-pre-wrap">{error_message}</span>
|
||||
<span class="whitespace-pre-wrap">{error_message}</span>
|
||||
</div>
|
||||
|
@ -1,6 +1,12 @@
|
||||
import { spawn } from "node:child_process";
|
||||
import { leftTrimDedent } from "../components/utils";
|
||||
|
||||
export type ReferenceItem = {
|
||||
symbol_start: number
|
||||
symbol_end: number
|
||||
reference: string
|
||||
}
|
||||
|
||||
export interface Token {
|
||||
token_type: TokenType
|
||||
value: string
|
||||
@ -55,13 +61,13 @@ export interface SemanticError {
|
||||
}
|
||||
|
||||
export interface TokenizeResult {
|
||||
Ok?: Token[],
|
||||
Ok?: [Array<Token>, Array<ReferenceItem>],
|
||||
SyntaxOnly?: [Token[], Err],
|
||||
TokensOnly?: [Token[], Err],
|
||||
Err?: Err,
|
||||
}
|
||||
|
||||
const error_classes = "underline decoration-wavy decoration-red-500";
|
||||
const error_classes = "underline underline-offset-4 decoration-wavy decoration-red-500";
|
||||
|
||||
export async function native_highlighter(code: string): Promise<[string, string, string | null]> {
|
||||
let formatted_code = leftTrimDedent(code).join("\n");
|
||||
@ -85,7 +91,12 @@ export async function native_highlighter(code: string): Promise<[string, string,
|
||||
return semantic_error_highlighter(formatted_code, tokens, error.Semantic!);
|
||||
}
|
||||
|
||||
const tokens = result.Ok!;
|
||||
const tokens = result.Ok! as unknown as Array<Token>;
|
||||
// TODO: this is disable because the compiler has not
|
||||
// implemented this feature yet
|
||||
// const [tokens, references] = result.Ok!;
|
||||
// console.log("refs:");
|
||||
// console.log(references);
|
||||
|
||||
const output = highlight_tokens(formatted_code, tokens);
|
||||
|
||||
@ -107,22 +118,25 @@ function lex_error_highlighter(code: string, error: LexError): [string, string,
|
||||
const token = `<span class="token ${error_classes}">${err_str}</span>`;
|
||||
|
||||
const all = `${before_err}${token}${after_err}`;
|
||||
const [error_line, error_column] = absolute_to_line_column(code, error.position);
|
||||
|
||||
// TODO: Transform absolute posijion (error.position) into line:column
|
||||
return [all, "Lexical", error.reason + " at position " + error.position]
|
||||
return [all, "Lexical", error.reason + ` at line ${error_line}:${error_column} `]
|
||||
}
|
||||
|
||||
function syntax_error_highlighter(code: string, tokens: Array<Token>, error: SyntaxError): [string, string, string] {
|
||||
const highlighted = highlight_tokens(code, tokens, error.error_start, error.error_end);
|
||||
const [error_line, error_column] = absolute_to_line_column(code, error.error_start);
|
||||
|
||||
const error_message = `${error.reason} from position ${error.error_start} to ${error.error_end}`;
|
||||
const error_message = `${error.reason} at line ${error_line}:${error_column}`;
|
||||
return [highlighted, "Syntax", error_message];
|
||||
}
|
||||
|
||||
function semantic_error_highlighter(code: string, tokens: Array<Token>, error: SyntaxError): [string, string, string] {
|
||||
const highlighted = highlight_tokens(code, tokens, error.error_start, error.error_end);
|
||||
const [error_line, error_column] = absolute_to_line_column(code, error.error_start);
|
||||
|
||||
const error_message = `${error.reason} from position ${error.error_start} to ${error.error_end}`;
|
||||
const error_message = `${error.reason} at line ${error_line}:${error_column}`;
|
||||
return [highlighted, "Semantic", error_message];
|
||||
}
|
||||
|
||||
@ -149,7 +163,7 @@ function highlight_tokens(input: string, tokens: Array<Token>, error_start = -1,
|
||||
const token_start = t.position;
|
||||
const token_end = t.position + t.value.length;
|
||||
|
||||
let is_errored = (token_start == error_start);
|
||||
let is_errored = (token_start >= error_start && token_end <= error_end);
|
||||
|
||||
// Some tokens require processing (like multiline comments)
|
||||
|
||||
@ -172,6 +186,33 @@ function highlight_tokens(input: string, tokens: Array<Token>, error_start = -1,
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform an absolute position in source code to a line:column combination.
|
||||
*
|
||||
* Both line and column are 1-based
|
||||
*
|
||||
* @param input the source code
|
||||
* @param absolute the absolute position
|
||||
*/
|
||||
function absolute_to_line_column(input: string, absolute: number): [number, number] {
|
||||
let line_count = 1;
|
||||
let last_newline_pos = 0;
|
||||
|
||||
// Count lines
|
||||
for (let i = 0; i < input.length; i += 1) {
|
||||
if (i === absolute) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (input[i] === "\n") {
|
||||
line_count += 1;
|
||||
last_newline_pos = i;
|
||||
}
|
||||
}
|
||||
|
||||
return [line_count, absolute - last_newline_pos];
|
||||
}
|
||||
|
||||
/**
|
||||
* Certain tokens store values that differ from the source code representation.
|
||||
* For example, the multiline comment token stores the content of the comment
|
||||
|
@ -30,6 +30,9 @@ Int char_code = 0b01000110
|
||||
Int not_octal = 032 // This is 32, not 26
|
||||
`} />
|
||||
|
||||
// TODO: Make it a compile error to have leading zeroes,
|
||||
and force users to use `0o` for octal
|
||||
|
||||
|
||||
## Float
|
||||
|
||||
|
@ -27,7 +27,8 @@ number /= 1
|
||||
number %= 2
|
||||
`} />
|
||||
|
||||
**There are no prefix/postfix increment**, use `+=` or `-=`.
|
||||
**There are no prefix/postfix increment operators** (`++`, `--`),
|
||||
use `+=` or `-=` instead.
|
||||
|
||||
<Code thpcode={`
|
||||
// Use
|
||||
|
@ -64,9 +64,9 @@ val first = get_first_item(numbers)
|
||||
|
||||
<Code thpcode={`
|
||||
() -> ()
|
||||
() -> Int
|
||||
(Int, Int) -> Int
|
||||
[T](Array[T]) -> T
|
||||
() -> (Int)
|
||||
(Int, Int) -> (Int)
|
||||
[T](Array[T]) -> (T)
|
||||
`} />
|
||||
|
||||
|
||||
|
@ -10,7 +10,7 @@ import Code from "../../../components/Code.astro"
|
||||
## Function as parameter
|
||||
|
||||
<Code thpcode={`
|
||||
fun map[A, B](Array[A] input, (A) -> B function) -> Array[B]
|
||||
fun map[A, B](Array[A] input, (A) -> (B) function) -> Array[B]
|
||||
{
|
||||
// implementation
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user