Skip to content

Commit 6d594a2

Browse files
committed
Include source snippet in resolution errors
1 parent b83e170 commit 6d594a2

4 files changed

Lines changed: 38 additions & 26 deletions

File tree

src/transpilation/diagnostics.ts

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as ts from "typescript";
2-
import { escapeString } from "../LuaPrinter";
32
import { createSerialDiagnosticFactory } from "../utils";
3+
import { Module } from "./module";
44

55
const createDiagnosticFactory = <TArgs extends any[]>(getMessage: (...args: TArgs) => string) =>
66
createSerialDiagnosticFactory((...args: TArgs) => ({ messageText: getMessage(...args) }));
@@ -41,13 +41,10 @@ export const usingLuaBundleWithInlineMightGenerateDuplicateCode = createSerialDi
4141

4242
const sourceFileStub = ts.createSourceFile("", "", ts.ScriptTarget.ES3);
4343
export const createResolutionErrorDiagnostic = createSerialDiagnosticFactory(
44-
(messageText: string, request: string, fileName: string) => {
45-
const text = `__TS__Resolve(${escapeString(request)})`;
46-
return {
47-
messageText,
48-
file: { ...sourceFileStub, fileName, text },
49-
start: 0,
50-
length: text.length,
51-
};
52-
}
44+
(messageText: string, module: Module, position: ts.ReadonlyTextRange) => ({
45+
messageText,
46+
file: { ...sourceFileStub, fileName: module.request, text: module.source.toString() },
47+
start: position.pos,
48+
length: position.end - position.pos,
49+
})
5350
);

src/transpilation/module.ts

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export interface Module {
99
sourceFiles?: ts.SourceFile[];
1010
}
1111

12-
export type ModuleDependencyResolver = (request: string) => string | { error: string };
12+
export type ModuleDependencyResolver = (request: string, position: ts.ReadonlyTextRange) => string | { error: string };
1313

1414
export function buildModule(module: Module, dependencyResolver: ModuleDependencyResolver) {
1515
if (module.isBuilt) return;
@@ -18,22 +18,36 @@ export function buildModule(module: Module, dependencyResolver: ModuleDependency
1818
}
1919

2020
function replaceResolveRequests(rootNode: SourceNode, dependencyResolver: ModuleDependencyResolver) {
21+
let currentPosition = 0;
22+
2123
function replaceInString(source: string) {
22-
return source.replace(/__TS__Resolve\((".*?")\)/g, (_, match) => {
23-
const request = unescapeLuaString(match);
24-
const replacement = dependencyResolver(request);
25-
return typeof replacement === "string"
26-
? escapeString(replacement)
27-
: `--[[ ${request} ]] error(${escapeString(replacement.error)})`;
28-
});
24+
const matches = source.matchAll(/__TS__Resolve\((".*?")\)/g);
25+
for (const match of [...matches].reverse()) {
26+
const request = unescapeLuaString(match[1]);
27+
const pos = currentPosition + match.index!;
28+
const end = pos + match[0].length;
29+
const result = dependencyResolver(request, { pos, end });
30+
const replacement =
31+
typeof result === "string"
32+
? escapeString(result)
33+
: `--[[ ${request} ]] error(${escapeString(result.error)})`;
34+
35+
source = source.slice(0, match.index) + replacement + source.slice(end);
36+
}
37+
38+
return source;
2939
}
3040

3141
function walkSourceNode(node: SourceNode, parent: SourceNode) {
3242
for (const child of node.children as Array<SourceNode | string>) {
3343
if (typeof child === "object") {
3444
walkSourceNode(child, node);
35-
} else if (child.includes("__TS__Resolve")) {
36-
parent.children = [replaceInString(parent.toString()) as any];
45+
} else {
46+
if (child.includes("__TS__Resolve")) {
47+
parent.children = [replaceInString(parent.toString()) as any];
48+
}
49+
50+
currentPosition += child.length;
3751
}
3852
}
3953
}

src/transpilation/transpilation.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,12 @@ export class Transpilation {
7070
}
7171

7272
private buildModule(module: Module) {
73-
buildModule(module, request => {
73+
buildModule(module, (request, position) => {
7474
const result = this.resolveRequestToModule(module.request, request);
7575
if ("error" in result) {
76-
this.diagnostics.push(result.error);
77-
return { error: ts.flattenDiagnosticMessageText(result.error.messageText, "\n") };
76+
const diagnostic = createResolutionErrorDiagnostic(result.error, module, position);
77+
this.diagnostics.push(diagnostic);
78+
return result;
7879
}
7980

8081
return this.getModuleId(result);
@@ -89,14 +90,14 @@ export class Transpilation {
8990
resolvedPath = result;
9091
} catch (error) {
9192
if (!isResolveError(error)) throw error;
92-
return { error: createResolutionErrorDiagnostic(error.message, request, issuer) };
93+
return { error: error.message };
9394
}
9495

9596
let module = this.modules.find(m => m.request === resolvedPath);
9697
if (!module) {
9798
if (!resolvedPath.endsWith(".lua")) {
9899
const messageText = `Resolved source file '${resolvedPath}' is not a part of the project.`;
99-
return { error: createResolutionErrorDiagnostic(messageText, request, issuer) };
100+
return { error: messageText };
100101
}
101102

102103
// TODO: Load source map files

tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"compilerOptions": {
33
"target": "es2019",
4-
"lib": ["es2019"],
4+
"lib": ["es2019", "es2020.promise", "es2020.bigint", "es2020.string"],
55
"types": ["node"],
66
"module": "commonjs",
77
"experimentalDecorators": true,

0 commit comments

Comments
 (0)