From 5b1da9656f3eaa04efea6ad10840110f4d22227b Mon Sep 17 00:00:00 2001 From: Ajani Bilby <11359344+AjaniBilby@users.noreply.github.com> Date: Sun, 12 May 2024 13:11:22 +1000 Subject: [PATCH] fixed SourceView rendering incorrect region --- source/compiler/codegen/expression/helper.ts | 2 +- source/parser.ts | 107 +++++++++++------- .../syntaxes/salient.tmLanguage.json | 14 +++ 3 files changed, 79 insertions(+), 44 deletions(-) diff --git a/source/compiler/codegen/expression/helper.ts b/source/compiler/codegen/expression/helper.ts index bfb1341..07be5c0 100644 --- a/source/compiler/codegen/expression/helper.ts +++ b/source/compiler/codegen/expression/helper.ts @@ -60,7 +60,7 @@ export function ResolveLinearType(ctx: Context, type: LinearType, ref: Reference if (strict) { const errs = type.getCompositionErrors(); if (errs) { - console.error(`Unable to compose value due to some arguments being uninitialized since:\n` + console.error(`Unable to compose value due to some arguments being uninitialized since: ${errs.map(x => x.start.toString()).join(", ")}\n` + errs.map(x => SourceView(ctx.file.path, ctx.file.name, x, true)).join("") + SourceView(ctx.file.path, ctx.file.name, ref, false) ); diff --git a/source/parser.ts b/source/parser.ts index 34b6b9f..cf8c6ca 100644 --- a/source/parser.ts +++ b/source/parser.ts @@ -47,57 +47,78 @@ function RemapRefRange(syntax: SyntaxNode) { export function SourceView(path: string, name: string, range: ReferenceRange, compact?: boolean) { - const source = ReadByteRange(path, range.start.index-200, range.end.index+200); - if (source === null) return `${name}: ${range.toString()}\n`; - - const begin = ExtractLine(source, range.start).replace(/\t/g, " "); - let body = ""; - - if (range.start.line === range.end.line) { - const margin = ` ${range.start.line} | `; - - const trimmed = begin.trim(); - const trimDiff = begin.length - trimmed.length; - - const underline = "\n" - + " ".repeat(margin.length + range.start.col - trimDiff) - + "^".repeat(Math.max(1, range.end.col - range.start.col)); - - body = margin + trimmed + underline; - } else { - const eLine = " " + range.end.line.toString(); - const sLine = range.start.line.toString().padStart(eLine.length, " "); - - const finish = ExtractLine(source, range.end).replace(/\t/g, " ");; - - body = sLine + " | " + begin + "\n" - + eLine + " | " + finish; - } - - body += compact ? "\n" : `\n ${name}: ${range.toString()}\n`; - - return body; + return range.start.line == range.end.line + ? SingleLine(path, name, range, compact) + : MultiLine(path, name, range, compact); } -function ExtractLine(source: string, ref: Reference) { - const begin = FindNewLine(source, ref.index, -1); - const end = FindNewLine(source, ref.index, 1); - - return source.slice(begin, end); +function SingleLine(path: string, name: string, range: ReferenceRange, compact?: boolean) { + const offset = Math.max(0, range.start.index - 200); + const slice = ReadByteRange(path, offset, range.end.index+200); + if (slice === null) return `${name}: ${range.toString()}\n`; + + let s = slice.lastIndexOf("\n", range.start.index-offset); + if (s === -1) s = 0; + let e = slice.indexOf("\n", range.end.index-offset); + if (e === -1) e = slice.length; + + let line = slice.slice(s, e).trimEnd(); + let pad = line.length; + line = line.trimStart(); + pad -= line.length; + + const margin = `${range.start.line} │ `; + const underline = "\n" + + " ".repeat(margin.length + range.start.col - pad) + + "^".repeat(Math.max(1, range.end.col - range.start.col)) + + "\n"; + + const body = margin + line + underline; + return compact ? body : ` ${name}: ${range.toString()}\n`; } -function FindNewLine(source: string, index: number, step: number) { - index += step; - - while (index >= 0 && index < source.length && source[index] !== "\n") { - index += step; +function MultiLine(path: string, name: string, range: ReferenceRange, compact?: boolean) { + const offset = Math.max(0, range.start.index - 200); + const slice = ReadByteRange(path, offset, range.end.index+200); + if (slice === null) return `${name}: ${range.toString()}\n`; + + let s = slice.lastIndexOf("\n", range.start.index-offset); + if (s === -1) s = 0; + else s ++; + let e = slice.indexOf("\n", range.end.index-offset); + if (e === -1) e = slice.length; + + const lines = slice.slice(s, e).split("\n"); + const digits = Math.floor(Math.log10(range.end.line)) + 1; + + let maxLen = 0; + function RenderLine(line: string, lnOff: number,) { + const ln = lnOff + range.start.line; + const src = line.replaceAll("\t", " "); + maxLen = Math.max(src.length, maxLen); + return ` ${ln.toString().padStart(digits, " ")} │ ${src}\n`; } - if (source[index] === "\n") { - index -= step; + let body = ""; + if (lines.length <= 5) { + body += lines.map(RenderLine).join("\n"); + } else { + let begin = ""; + for (let i=0; i<2; i++) { + begin += RenderLine(lines[i], i); + } + + let end = ""; + for (let i=lines.length-2; i