Skip to content

Commit 3567987

Browse files
committed
Add transpilation-related plugin hooks
1 parent deefc88 commit 3567987

8 files changed

Lines changed: 111 additions & 16 deletions

File tree

src/LuaPrinter.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -99,16 +99,6 @@ export interface PrintResult {
9999
sourceMapNode: SourceNode;
100100
}
101101

102-
export function createPrinter(printers: Printer[]): Printer {
103-
if (printers.length === 0) {
104-
return (program, host, fileName, ...args) => new LuaPrinter(host, program, fileName).print(...args);
105-
} else if (printers.length === 1) {
106-
return printers[0];
107-
} else {
108-
throw new Error("Only one plugin can specify 'printer'");
109-
}
110-
}
111-
112102
export class LuaPrinter {
113103
private static operatorMap: Record<lua.Operator, string> = {
114104
[lua.SyntaxKind.AdditionOperator]: "+",

src/transpilation/plugins.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
import { Plugin as ResolvePlugin } from "enhanced-resolve";
12
import { Printer } from "../LuaPrinter";
23
import { Visitors } from "../transformation/context";
4+
import { Chunk } from "./chunk";
5+
import { Module } from "./module";
36
import { Transpilation } from "./transpilation";
47
import { getConfigDirectory, resolvePlugin } from "./utils";
58

@@ -17,6 +20,23 @@ export interface Plugin {
1720
* At most one custom printer can be provided across all plugins.
1821
*/
1922
printer?: Printer;
23+
24+
/**
25+
* Provide extra [enhanced-resolve](https://github.com/webpack/enhanced-resolve) plugins,
26+
* used for `.lua` module resolution.
27+
*/
28+
getResolvePlugins?(transpilation: Transpilation): ResolvePlugin[];
29+
30+
/**
31+
* Transform modules into chunks.
32+
*/
33+
mapModulesToChunks?(modules: Module[], transpilation: Transpilation): Chunk[];
34+
35+
/**
36+
* Produce a unique identifier for a module, which would be used as `require` call parameter,
37+
* and may be used for chunk naming.
38+
*/
39+
getModuleId?(module: Module, transpilation: Transpilation): string | undefined;
2040
}
2141

2242
export function getPlugins(transpilation: Transpilation, customPlugins: Plugin[]): Plugin[] {
@@ -42,3 +62,21 @@ export function getPlugins(transpilation: Transpilation, customPlugins: Plugin[]
4262

4363
return [...customPlugins, ...pluginsFromOptions];
4464
}
65+
66+
export function applyBailPlugin<T>(plugins: Plugin[], callback: (plugin: Plugin) => T | undefined): T | undefined {
67+
for (const plugin of plugins) {
68+
const result = callback(plugin);
69+
if (result !== undefined) {
70+
return result;
71+
}
72+
}
73+
}
74+
75+
export function applySinglePlugin<P extends keyof Plugin>(plugins: Plugin[], property: P): Plugin[P] | undefined {
76+
const results = plugins.filter(p => p[property] !== undefined);
77+
if (results.length === 1) {
78+
return results[0][property];
79+
} else if (results.length > 1) {
80+
throw new Error(`Only one plugin can specify '${property}'`);
81+
}
82+
}

src/transpilation/transpilation.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { assert, cast, isNonNull, normalizeSlashes, trimExtension } from "../uti
88
import { Chunk, modulesToBundleChunks, modulesToChunks } from "./chunk";
99
import { createResolutionErrorDiagnostic } from "./diagnostics";
1010
import { buildModule, Module } from "./module";
11-
import { getPlugins, Plugin } from "./plugins";
11+
import { applyBailPlugin, applySinglePlugin, getPlugins, Plugin } from "./plugins";
1212
import { Transpiler, TranspilerHost } from "./transpiler";
1313

1414
export class Transpilation {
@@ -35,14 +35,15 @@ export class Transpilation {
3535

3636
this.outDir = this.options.outDir ?? this.rootDir;
3737

38+
this.plugins = getPlugins(this, extraPlugins);
39+
3840
this.resolver = ResolverFactory.createResolver({
3941
extensions: [".lua", ...this.implicitScriptExtensions],
4042
conditionNames: ["lua", `lua:${this.options.luaTarget ?? LuaTarget.Universal}`],
4143
fileSystem: this.host.resolutionFileSystem ?? fs,
4244
useSyncFileSystemCalls: true,
45+
plugins: this.plugins.flatMap(p => p.getResolvePlugins?.(this) ?? []),
4346
});
44-
45-
this.plugins = getPlugins(this, extraPlugins);
4647
}
4748

4849
public emit(): Chunk[] {
@@ -99,6 +100,9 @@ export class Transpilation {
99100
}
100101

101102
public getModuleId(module: Module) {
103+
const pluginResult = applyBailPlugin(this.plugins, p => p.getModuleId?.(module, this));
104+
if (pluginResult !== undefined) return pluginResult;
105+
102106
const result = path.relative(this.rootDir, trimExtension(module.request));
103107
// TODO: handle files on other drives
104108
assert(!path.isAbsolute(result), `Invalid path: ${result}`);
@@ -109,6 +113,9 @@ export class Transpilation {
109113
}
110114

111115
private mapModulesToChunks(modules: Module[]): Chunk[] {
112-
return isBundleEnabled(this.options) ? modulesToBundleChunks(this, modules) : modulesToChunks(this, modules);
116+
return (
117+
applySinglePlugin(this.plugins, "mapModulesToChunks")?.(modules, this) ??
118+
(isBundleEnabled(this.options) ? modulesToBundleChunks(this, modules) : modulesToChunks(this, modules))
119+
);
113120
}
114121
}

src/transpilation/transpile/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import * as path from "path";
22
import * as ts from "typescript";
33
import { CompilerOptions, validateOptions } from "../../CompilerOptions";
4-
import { createPrinter } from "../../LuaPrinter";
4+
import { LuaPrinter } from "../../LuaPrinter";
55
import { createVisitorMap, transformSourceFile } from "../../transformation";
66
import { assert, isNonNull } from "../../utils";
7+
import { applySinglePlugin } from "../plugins";
78
import { Transpilation } from "../transpilation";
89
import { getTransformers } from "./transformers";
910

@@ -46,7 +47,10 @@ export function emitProgramModules(
4647
}
4748

4849
const visitorMap = createVisitorMap(transpilation.plugins.map(p => p.visitors).filter(isNonNull));
49-
const printer = createPrinter(transpilation.plugins.map(p => p.printer).filter(isNonNull));
50+
const printer =
51+
applySinglePlugin(transpilation.plugins, "printer") ??
52+
((program, host, fileName, ...args) => new LuaPrinter(host, program, fileName).print(...args));
53+
5054
const processSourceFile = (sourceFile: ts.SourceFile) => {
5155
const { luaAst, luaLibFeatures, diagnostics: transformDiagnostics } = transformSourceFile(
5256
program,
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`getModuleId 1`] = `
4+
"local ____exports = {}
5+
require(\\"5d05566c99dac259f6ff5742a268d405157a0d7c\\")
6+
return ____exports"
7+
`;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { createHash } from "crypto";
2+
import * as path from "path";
3+
import * as tstl from "../../../src";
4+
5+
const plugin: tstl.Plugin = {
6+
getModuleId: (module, transpilation) =>
7+
createHash("sha1")
8+
.update(module.code)
9+
.update(path.relative(transpilation.rootDir, module.request))
10+
.digest("hex"),
11+
};
12+
13+
// eslint-disable-next-line import/no-default-export
14+
export default plugin;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// @ts-expect-error Could not find a declaration file for module 'enhanced-resolve/lib/AliasPlugin'.
2+
import * as AliasPlugin from "enhanced-resolve/lib/AliasPlugin";
3+
import * as tstl from "../../../src";
4+
5+
const plugin: tstl.Plugin = {
6+
getResolvePlugins: () => [
7+
new AliasPlugin("described-resolve", { name: "foo", alias: "/bar.ts" }, "internal-resolve"),
8+
],
9+
};
10+
11+
// eslint-disable-next-line import/no-default-export
12+
export default plugin;

test/transpile/plugins/plugins.spec.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,26 @@ test("visitor using super", () => {
2222
.setOptions({ luaPlugins: [{ name: path.join(__dirname, "visitor-super.ts") }] })
2323
.expectToEqual("bar");
2424
});
25+
26+
test("getModuleId", () => {
27+
util.testModule`
28+
export { value } from "./foo";
29+
`
30+
.addExtraFile("foo.ts", "export const value = true;")
31+
.setOptions({ luaPlugins: [{ name: path.join(__dirname, "getModuleId.ts") }] })
32+
.expectToEqual({ value: true })
33+
.expectLuaToMatchSnapshot();
34+
});
35+
36+
test("getResolvePlugins", () => {
37+
util.testModule`
38+
export { value } from "foo";
39+
`
40+
.addExtraFile("bar.ts", "export const value = true;")
41+
.setOptions({
42+
luaPlugins: [{ name: path.join(__dirname, "getResolvePlugins.ts") }],
43+
baseUrl: ".",
44+
paths: { foo: ["bar"] },
45+
})
46+
.expectToEqual({ value: true });
47+
});

0 commit comments

Comments
 (0)