From 0441fe487735a8d7f97285a7cc42a0c07257b3b3 Mon Sep 17 00:00:00 2001 From: Perryvw Date: Sat, 19 Mar 2022 21:05:43 +0100 Subject: [PATCH 1/2] Added BeforeEmit plugin hook --- src/index.ts | 2 +- src/transpilation/plugins.ts | 23 ++++++++++--- src/transpilation/transpile.ts | 10 ++---- src/transpilation/transpiler.ts | 31 +++++++++++------ src/transpilation/utils.ts | 1 - test/transpile/plugins/afterPrint.ts | 2 +- test/transpile/plugins/beforeEmit.ts | 17 ++++++++++ test/transpile/plugins/plugins.spec.ts | 47 +++++++++++++++++++++++++- 8 files changed, 106 insertions(+), 27 deletions(-) create mode 100644 test/transpile/plugins/beforeEmit.ts diff --git a/src/index.ts b/src/index.ts index 0b994c7f6..2d2e3de54 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,4 +8,4 @@ export { LuaLibFeature } from "./LuaLib"; export * from "./LuaPrinter"; export * from "./transformation/context"; export * from "./transpilation"; -export { ProcessedFile } from "./transpilation/utils"; +export { EmitHost, EmitFile, ProcessedFile } from "./transpilation/utils"; diff --git a/src/transpilation/plugins.ts b/src/transpilation/plugins.ts index 8b4070591..399caba5c 100644 --- a/src/transpilation/plugins.ts +++ b/src/transpilation/plugins.ts @@ -3,7 +3,7 @@ import { EmitHost } from ".."; import { CompilerOptions } from "../CompilerOptions"; import { Printer } from "../LuaPrinter"; import { Visitors } from "../transformation/context"; -import { getConfigDirectory, ProcessedFile, resolvePlugin } from "./utils"; +import { EmitFile, getConfigDirectory, ProcessedFile, resolvePlugin } from "./utils"; export interface Plugin { /** @@ -26,7 +26,7 @@ export interface Plugin { beforeTransform?: (program: ts.Program, options: CompilerOptions, emitHost: EmitHost) => ts.Diagnostic[] | void; /** - * This function is called after TypeScriptToLua has translated the input program to Lua. + * This function is called after translating the input program to Lua, but before resolving dependencies or bundling. */ afterPrint?: ( program: ts.Program, @@ -34,9 +34,20 @@ export interface Plugin { emitHost: EmitHost, result: ProcessedFile[] ) => ts.Diagnostic[] | void; + + /** + * This function is called after translating the input program to Lua, after resolving dependencies and after bundling. + */ + beforeEmit?: ( + program: ts.Program, + options: CompilerOptions, + emitHost: EmitHost, + result: EmitFile[] + ) => ts.Diagnostic[] | void; } -export function getPlugins(program: ts.Program, diagnostics: ts.Diagnostic[], customPlugins: Plugin[]): Plugin[] { +export function getPlugins(program: ts.Program): { diagnostics: ts.Diagnostic[]; plugins: Plugin[] } { + const diagnostics: ts.Diagnostic[] = []; const pluginsFromOptions: Plugin[] = []; const options = program.getCompilerOptions() as CompilerOptions; @@ -58,5 +69,9 @@ export function getPlugins(program: ts.Program, diagnostics: ts.Diagnostic[], cu pluginsFromOptions.push(plugin); } - return [...customPlugins, ...pluginsFromOptions]; + if (options.tstlVerbose) { + console.log(`Successfully loaded ${pluginsFromOptions.length} plugins`); + } + + return { diagnostics, plugins: pluginsFromOptions }; } diff --git a/src/transpilation/transpile.ts b/src/transpilation/transpile.ts index bf226992f..c693fa35a 100644 --- a/src/transpilation/transpile.ts +++ b/src/transpilation/transpile.ts @@ -4,7 +4,7 @@ import { CompilerOptions, validateOptions } from "../CompilerOptions"; import { createPrinter } from "../LuaPrinter"; import { createVisitorMap, transformSourceFile } from "../transformation"; import { isNonNull } from "../utils"; -import { getPlugins, Plugin } from "./plugins"; +import { Plugin } from "./plugins"; import { getTransformers } from "./transformers"; import { EmitHost, ProcessedFile } from "./utils"; @@ -23,7 +23,7 @@ export interface TranspileResult { export function getProgramTranspileResult( emitHost: EmitHost, writeFileResult: ts.WriteFileCallback, - { program, sourceFiles: targetSourceFiles, customTransformers = {}, plugins: customPlugins = [] }: TranspileOptions + { program, sourceFiles: targetSourceFiles, customTransformers = {}, plugins = [] }: TranspileOptions ): TranspileResult { const options = program.getCompilerOptions() as CompilerOptions; @@ -60,12 +60,6 @@ export function getProgramTranspileResult( } } - const plugins = getPlugins(program, diagnostics, customPlugins); - - if (options.tstlVerbose) { - console.log(`Successfully loaded ${plugins.length} plugins`); - } - for (const plugin of plugins) { if (plugin.beforeTransform) { const pluginDiagnostics = plugin.beforeTransform(program, options, emitHost) ?? []; diff --git a/src/transpilation/transpiler.ts b/src/transpilation/transpiler.ts index 22491ac7a..f16b6614e 100644 --- a/src/transpilation/transpiler.ts +++ b/src/transpilation/transpiler.ts @@ -4,6 +4,7 @@ import { CompilerOptions, isBundleEnabled } from "../CompilerOptions"; import { getLuaLibBundle } from "../LuaLib"; import { normalizeSlashes, trimExtension } from "../utils"; import { getBundleResult } from "./bundle"; +import { getPlugins } from "./plugins"; import { resolveDependencies } from "./resolve"; import { getProgramTranspileResult, TranspileOptions } from "./transpile"; import { EmitFile, EmitHost, ProcessedFile } from "./utils"; @@ -29,23 +30,31 @@ export class Transpiler { public emit(emitOptions: EmitOptions): EmitResult { const { program, writeFile = this.emitHost.writeFile } = emitOptions; - const verbose = (program.getCompilerOptions() as CompilerOptions).tstlVerbose; - const { diagnostics, transpiledFiles: freshFiles } = getProgramTranspileResult( - this.emitHost, - writeFile, - emitOptions - ); + const options = program.getCompilerOptions() as CompilerOptions; + + const { diagnostics: getPluginsDiagnostics, plugins } = getPlugins(program); + + const { diagnostics, transpiledFiles: freshFiles } = getProgramTranspileResult(this.emitHost, writeFile, { + ...emitOptions, + plugins, + }); const { emitPlan } = this.getEmitPlan(program, diagnostics, freshFiles); - if (verbose) { + if (options.tstlVerbose) { console.log("Emitting output"); } - const options = program.getCompilerOptions(); + for (const plugin of plugins) { + if (plugin.beforeEmit) { + const beforeEmitPluginDiagnostics = plugin.beforeEmit(program, options, this.emitHost, emitPlan) ?? []; + diagnostics.push(...beforeEmitPluginDiagnostics); + } + } + const emitBOM = options.emitBOM ?? false; for (const { outputPath, code, sourceMap, sourceFiles } of emitPlan) { - if (verbose) { + if (options.tstlVerbose) { console.log(`Emitting ${normalizeSlashes(outputPath)}`); } @@ -55,11 +64,11 @@ export class Transpiler { } } - if (verbose) { + if (options.tstlVerbose) { console.log("Emit finished!"); } - return { diagnostics, emitSkipped: emitPlan.length === 0 }; + return { diagnostics: getPluginsDiagnostics.concat(diagnostics), emitSkipped: emitPlan.length === 0 }; } protected getEmitPlan( diff --git a/src/transpilation/utils.ts b/src/transpilation/utils.ts index 0bf8075d2..cef3af310 100644 --- a/src/transpilation/utils.ts +++ b/src/transpilation/utils.ts @@ -24,7 +24,6 @@ interface BaseFile { export interface ProcessedFile extends BaseFile { fileName: string; luaAst?: lua.File; - /** @internal */ sourceMapNode?: SourceNode; } diff --git a/test/transpile/plugins/afterPrint.ts b/test/transpile/plugins/afterPrint.ts index 5d0d3e78d..1c2529361 100644 --- a/test/transpile/plugins/afterPrint.ts +++ b/test/transpile/plugins/afterPrint.ts @@ -13,7 +13,7 @@ const plugin: tstl.Plugin = { void emitHost; for (const file of result) { - file.code = "-- Commented added by afterPrint plugin\n" + file.code; + file.code = "-- Comment added by afterPrint plugin\n" + file.code; } }, }; diff --git a/test/transpile/plugins/beforeEmit.ts b/test/transpile/plugins/beforeEmit.ts new file mode 100644 index 000000000..973024ba4 --- /dev/null +++ b/test/transpile/plugins/beforeEmit.ts @@ -0,0 +1,17 @@ +import * as ts from "typescript"; +import * as tstl from "../../../src"; + +const plugin: tstl.Plugin = { + beforeEmit(program: ts.Program, options: tstl.CompilerOptions, emitHost: tstl.EmitHost, result: tstl.EmitFile[]) { + void program; + void options; + void emitHost; + + for (const file of result) { + file.code = "-- Comment added by beforeEmit plugin\n" + file.code; + } + }, +}; + +// eslint-disable-next-line import/no-default-export +export default plugin; diff --git a/test/transpile/plugins/plugins.spec.ts b/test/transpile/plugins/plugins.spec.ts index 614e2f1ca..3fc4b63cf 100644 --- a/test/transpile/plugins/plugins.spec.ts +++ b/test/transpile/plugins/plugins.spec.ts @@ -112,6 +112,51 @@ test("afterPrint plugin", () => { expect(transpiledFiles).toHaveLength(2); for (const f of transpiledFiles) { // Expect plugin inserted extra lua at start of file - expect(f.lua).toContain("-- Commented added by afterPrint plugin"); + expect(f.lua).toContain("-- Comment added by afterPrint plugin"); + } +}); + +test("beforeEmit plugin", () => { + const { transpiledFiles } = util.testModule` + console.log("Hello, World!"); + [].push(1,2,3); // Use lualib code + ` + .addExtraFile( + "extrafile.ts", + ` + console.log("Hello, Mars!"); + ` + ) + .setOptions({ luaPlugins: [{ name: path.join(__dirname, "beforeEmit.ts") }] }) + .getLuaResult(); + + // 2 input files + 1 lualib_bundle + expect(transpiledFiles).toHaveLength(3); + expect(transpiledFiles.find(f => f.outPath.endsWith("lualib_bundle.lua"))).toBeDefined(); + for (const f of transpiledFiles) { + // Expect plugin inserted extra lua at start of all files including lualib bundle + expect(f.lua).toContain("-- Comment added by beforeEmit plugin"); + } +}); + +test("beforeEmit plugin bundle", () => { + const { transpiledFiles } = util.testBundle` + console.log("Hello, World!"); + [].push(1,2,3); // Use lualib code + ` + .addExtraFile( + "extrafile.ts", + ` + console.log("Hello, Mars!"); + ` + ) + .setOptions({ luaPlugins: [{ name: path.join(__dirname, "beforeEmit.ts") }] }) + .getLuaResult(); + + // 1 lua bundle output + expect(transpiledFiles).toHaveLength(1); + for (const f of transpiledFiles) { + // Expect bundle to be affected by plugin + expect(f.lua).toContain("-- Comment added by beforeEmit plugin"); } }); From 2ab7c78152fbe57eb3624c568a7145971587e71b Mon Sep 17 00:00:00 2001 From: Perryvw Date: Sun, 20 Mar 2022 11:44:12 +0100 Subject: [PATCH 2/2] Updated verbose log snapshot --- src/transpilation/plugins.ts | 2 +- test/transpile/__snapshots__/project.spec.ts.snap | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/transpilation/plugins.ts b/src/transpilation/plugins.ts index 399caba5c..f425c5488 100644 --- a/src/transpilation/plugins.ts +++ b/src/transpilation/plugins.ts @@ -70,7 +70,7 @@ export function getPlugins(program: ts.Program): { diagnostics: ts.Diagnostic[]; } if (options.tstlVerbose) { - console.log(`Successfully loaded ${pluginsFromOptions.length} plugins`); + console.log(`Loaded ${pluginsFromOptions.length} plugins`); } return { diagnostics, plugins: pluginsFromOptions }; diff --git a/test/transpile/__snapshots__/project.spec.ts.snap b/test/transpile/__snapshots__/project.spec.ts.snap index ce03539da..c2f66a1e7 100644 --- a/test/transpile/__snapshots__/project.spec.ts.snap +++ b/test/transpile/__snapshots__/project.spec.ts.snap @@ -2,8 +2,8 @@ exports[`should give verbose output 1`] = ` Array [ + "Loaded 0 plugins", "Parsing project settings", - "Successfully loaded 0 plugins", "Transforming /test/transpile/project/otherFile.ts", "Printing /test/transpile/project/otherFile.ts", "Transforming /test/transpile/project/index.ts",