Skip to content

Commit 5bcad29

Browse files
committed
better error messages for building dictionary
1 parent d412a7b commit 5bcad29

File tree

7 files changed

+74
-37
lines changed

7 files changed

+74
-37
lines changed

build/build.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,17 @@ const BUILD_OPTIONS: ESBuild.BuildOptions = {
99
minify: true,
1010
define: { LIVE_RELOAD: "false" },
1111
};
12-
if (import.meta.main) {
12+
async function main(): Promise<void> {
1313
const start = performance.now();
14-
await Dictionary.build();
14+
if (!await Dictionary.build()) {
15+
Deno.exitCode = 1;
16+
return;
17+
}
1518
await ESBuild.build(BUILD_OPTIONS);
1619
const end = performance.now();
1720
// deno-lint-ignore no-console
1821
console.log(`Total time took: ${Math.floor(end - start)}ms`);
1922
}
23+
if (import.meta.main) {
24+
await main();
25+
}

build/dev.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ async function watchDictionary(): Promise<number> {
2323
const command = new Deno.Command(Deno.execPath(), {
2424
args: [
2525
"run",
26+
"-E=NO_COLOR",
2627
"-R=./dictionary/dictionary",
2728
"-W=./dictionary/dictionary.ts",
2829
"--no-prompt",
@@ -42,18 +43,20 @@ async function watchDictionary(): Promise<number> {
4243
assert(!status.success);
4344
return status.code;
4445
}
45-
if (import.meta.main) {
46-
let statusCode: number;
47-
{
48-
if (
49-
!await exists(new URL("../dictionary/dictionary.ts", import.meta.url))
50-
) {
51-
const Dictionary = await import("../dictionary/build.ts");
52-
await Dictionary.build();
46+
async function main(): Promise<void> {
47+
if (
48+
!await exists(new URL("../dictionary/dictionary.ts", import.meta.url))
49+
) {
50+
const Dictionary = await import("../dictionary/build.ts");
51+
if (!await Dictionary.build()) {
52+
Deno.exitCode = 1;
53+
return;
5354
}
54-
const statusCodePromise = watchDictionary();
55-
await using _ = await watchMain();
56-
statusCode = await statusCodePromise;
5755
}
58-
Deno.exit(statusCode);
56+
const statusCodePromise = watchDictionary();
57+
await using _ = await watchMain();
58+
Deno.exitCode = await statusCodePromise;
59+
}
60+
if (import.meta.main) {
61+
await main();
5962
}

deno.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
},
2323
"build-dictionary": {
2424
"description": "Builds the dictionary at `./dictionary/dictionary.ts`",
25-
"command": "deno run -R=./dictionary/dictionary -W=./dictionary/dictionary.ts --no-prompt --frozen --cached-only ./dictionary/build.ts"
25+
"command": "deno run -E=NO_COLOR -R=./dictionary/dictionary -W=./dictionary/dictionary.ts --no-prompt --frozen --cached-only ./dictionary/build.ts"
2626
}
2727
},
2828
"fmt": {

dictionary/build.ts

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,29 @@
11
// This code is Deno only
22

3-
import { parseDictionary } from "./parser.ts";
3+
// deno-lint-ignore-file no-console
4+
5+
import { ArrayResultError } from "../src/mod.ts";
6+
import { PositionedError } from "../src/parser/parser_lib.ts";
7+
import { dictionaryParser } from "./parser.ts";
8+
import { Dictionary } from "./type.ts";
49

510
const SOURCE = new URL("./dictionary", import.meta.url);
611
const DESTINATION = new URL("./dictionary.ts", import.meta.url);
712

8-
export async function build(): Promise<void> {
9-
// deno-lint-ignore no-console
13+
export async function build(): Promise<boolean> {
1014
console.log("Building dictionary...");
1115
const start = performance.now();
1216
const text = await Deno.readTextFile(SOURCE);
1317
const startDictionary = performance.now();
14-
const dictionary = parseDictionary(text);
18+
const result = dictionaryParser.parse(text);
1519
const endDictionary = performance.now();
20+
let dictionary: Dictionary;
21+
if (!result.isError()) {
22+
dictionary = result.array[0];
23+
} else {
24+
displayError(text, result.errors);
25+
return false;
26+
}
1627
const json = JSON.stringify(
1728
Object.fromEntries(dictionary),
1829
undefined,
@@ -29,11 +40,37 @@ export const dictionary: Dictionary = new Map(Object.entries(${json}));
2940
const end = performance.now();
3041
const total = Math.floor(end - start);
3142
const parsing = Math.floor(endDictionary - startDictionary);
32-
// deno-lint-ignore no-console
3343
console.log(
3444
`Building dictionary done in ${total}ms (parsing dictionary took ${parsing}ms)`,
3545
);
46+
return true;
47+
}
48+
function displayError(
49+
source: string,
50+
errors: ReadonlyArray<ArrayResultError>,
51+
): void {
52+
let color: boolean;
53+
try {
54+
color = Deno.env.get("NO_COLOR") !== "1";
55+
} catch (error) {
56+
if (error instanceof Deno.errors.NotCapable) {
57+
color = true;
58+
} else {
59+
throw error;
60+
}
61+
}
62+
for (const error of errors) {
63+
console.error(`Error: ${error.message}`);
64+
if (error instanceof PositionedError) {
65+
const position = error.position;
66+
const lines = source.slice(0, position?.position).split(/\r?\n/);
67+
const line = lines.length;
68+
const column = lines[lines.length - 1].length + 1;
69+
console.error(` at ${SOURCE}:${line}:${column}`);
70+
console.error();
71+
}
72+
}
3673
}
3774
if (import.meta.main) {
38-
await build();
75+
Deno.exitCode = await build() ? 0 : 1;
3976
}

dictionary/parser.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {
2323
UnexpectedError,
2424
withSource,
2525
} from "../src/parser/parser_lib.ts";
26-
import { Definition, Dictionary, Noun, PartialVerb } from "./type.ts";
26+
import { Definition, Noun, PartialVerb } from "./type.ts";
2727

2828
const RESERVED_SYMBOLS = "#()*+/:;<=>@[\\]^`{|}~";
2929

@@ -581,7 +581,7 @@ const entry = withSource(
581581
),
582582
)
583583
.map(([definitions, source]) => ({ definitions, source: source.trimEnd() }));
584-
const dictionaryParser = ignore
584+
export const dictionaryParser = ignore
585585
.with(allWithCheck(new CheckedParser(notEnd, sequence(head, entry))))
586586
.map((entries) =>
587587
new Map(
@@ -590,6 +590,3 @@ const dictionaryParser = ignore
590590
),
591591
)
592592
);
593-
export function parseDictionary(sourceText: string): Dictionary {
594-
return dictionaryParser.parse(sourceText).unwrap()[0];
595-
}

dictionary/watch.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,15 @@ import { debounce } from "@std/async/debounce";
55
import { AsyncDisposableStack } from "../misc/async_disposable_stack.ts";
66
import { build } from "./build.ts";
77

8-
async function tryBuild(): Promise<void> {
9-
try {
10-
await build();
11-
} catch (error) {
12-
// deno-lint-ignore no-console
13-
console.log(error);
14-
}
15-
}
168
if (import.meta.main) {
179
await using stack = new AsyncDisposableStack();
1810
using watcher = Deno.watchFs("./dictionary/dictionary");
1911
let task = Promise.resolve();
2012
stack.defer(async () => await task);
2113
const buildDebounced = debounce(() => {
22-
task = task.then(tryBuild);
14+
task = task.then(async () => {
15+
await build();
16+
});
2317
}, 200);
2418
buildDebounced();
2519
buildDebounced.flush();

src/dictionary.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { dictionary as globalDictionary } from "../dictionary/dictionary.ts";
2-
import { parseDictionary } from "../dictionary/parser.ts";
2+
import { dictionaryParser } from "../dictionary/parser.ts";
33
import { Definition, Dictionary } from "../dictionary/type.ts";
44
import { load } from "../telo_misikeke/telo_misikeke.js";
55

@@ -18,7 +18,7 @@ export const tokiPonaWordSet: Set<string> = new Set();
1818
update();
1919

2020
export function loadCustomDictionary(dictionaryText: string): void {
21-
const dictionary = parseDictionary(dictionaryText);
21+
const dictionary = dictionaryParser.parse(dictionaryText).unwrap()[0];
2222
customDictionary.clear();
2323
for (const [key, value] of dictionary) {
2424
customDictionary.set(key, value);

0 commit comments

Comments
 (0)