11import * as path from "path" ;
2- import { EmitHost } from "./transpilation" ;
2+ import { EmitHost , transpileProject } from "./transpilation" ;
33import * as lua from "./LuaAST" ;
4- import { LuaTarget } from "./CompilerOptions" ;
4+ import { LuaTarget , type CompilerOptions } from "./CompilerOptions" ;
55import { getOrUpdate } from "./utils" ;
6+ import { createEmitOutputCollector , type TranspiledFile } from "./transpilation/output-collector" ;
7+ import { parseConfigFileWithSystem } from "./cli/tsconfig" ;
8+ import { createDiagnosticReporter } from "./cli/report" ;
69
710export enum LuaLibFeature {
811 ArrayAt = "ArrayAt" ,
@@ -139,12 +142,16 @@ export function resolveLuaLibDir(luaTarget: LuaTarget) {
139142export const luaLibModulesInfoFileName = "lualib_module_info.json" ;
140143const luaLibModulesInfo = new Map < LuaTarget , LuaLibModulesInfo > ( ) ;
141144
142- export function getLuaLibModulesInfo ( luaTarget : LuaTarget , emitHost : EmitHost ) : LuaLibModulesInfo {
143- if ( ! luaLibModulesInfo . has ( luaTarget ) ) {
145+ export function getLuaLibModulesInfo ( luaTarget : LuaTarget , emitHost : EmitHost , useCache = true ) : LuaLibModulesInfo {
146+ if ( ! useCache || ! luaLibModulesInfo . has ( luaTarget ) ) {
144147 const lualibPath = path . join ( resolveLuaLibDir ( luaTarget ) , luaLibModulesInfoFileName ) ;
145148 const result = emitHost . readFile ( lualibPath ) ;
146149 if ( result !== undefined ) {
147- luaLibModulesInfo . set ( luaTarget , JSON . parse ( result ) as LuaLibModulesInfo ) ;
150+ const info = JSON . parse ( result ) as LuaLibModulesInfo ;
151+ if ( ! useCache ) {
152+ return info ;
153+ }
154+ luaLibModulesInfo . set ( luaTarget , info ) ;
148155 } else {
149156 throw new Error ( `Could not load lualib dependencies from '${ lualibPath } '` ) ;
150157 }
@@ -175,7 +182,21 @@ export function getLuaLibExportToFeatureMap(
175182
176183const lualibFeatureCache = new Map < LuaTarget , Map < LuaLibFeature , string > > ( ) ;
177184
178- export function readLuaLibFeature ( feature : LuaLibFeature , luaTarget : LuaTarget , emitHost : EmitHost ) : string {
185+ export function readLuaLibFeature (
186+ feature : LuaLibFeature ,
187+ luaTarget : LuaTarget ,
188+ emitHost : EmitHost ,
189+ useCache = true
190+ ) : string {
191+ if ( ! useCache ) {
192+ const featurePath = path . join ( resolveLuaLibDir ( luaTarget ) , `${ feature } .lua` ) ;
193+ const luaLibFeature = emitHost . readFile ( featurePath ) ;
194+ if ( luaLibFeature === undefined ) {
195+ throw new Error ( `Could not load lualib feature from '${ featurePath } '` ) ;
196+ }
197+ return luaLibFeature ;
198+ }
199+
179200 const featureMap = getOrUpdate ( lualibFeatureCache , luaTarget , ( ) => new Map ( ) ) ;
180201 if ( ! featureMap . has ( feature ) ) {
181202 const featurePath = path . join ( resolveLuaLibDir ( luaTarget ) , `${ feature } .lua` ) ;
@@ -257,9 +278,68 @@ export function loadImportedLualibFeatures(
257278 return statements ;
258279}
259280
281+ const recompileLualibCache = new WeakMap < EmitHost , TranspiledFile [ ] > ( ) ;
282+
283+ function recompileLuaLibFiles ( sourceOptions : CompilerOptions , emitHost : EmitHost ) : TranspiledFile [ ] {
284+ let transpiledFiles = recompileLualibCache . get ( emitHost ) ;
285+ if ( ! transpiledFiles ) {
286+ const tsconfigPath =
287+ sourceOptions . luaTarget === LuaTarget . Lua50
288+ ? path . join ( __dirname , "./lualib/tsconfig.lua50.json" )
289+ : path . join ( __dirname , "./lualib/tsconfig.json" ) ;
290+ const config = parseConfigFileWithSystem ( tsconfigPath ) ;
291+ const options = config . options ;
292+ options . luaPlugins = [ ...( options . luaPlugins ?? [ ] ) , ...( sourceOptions . luaPlugins ?? [ ] ) ] ;
293+
294+ const collector = createEmitOutputCollector ( options . extension ) ;
295+ const reportDiagnostic = createDiagnosticReporter ( false ) ;
296+
297+ const { diagnostics } = transpileProject ( tsconfigPath , options , collector . writeFile ) ;
298+ diagnostics . forEach ( reportDiagnostic ) ;
299+
300+ transpiledFiles = collector . files ;
301+ recompileLualibCache . set ( emitHost , transpiledFiles ) ;
302+ }
303+
304+ return transpiledFiles ;
305+ }
306+
307+ function recompileLuaLibBundle ( sourceOptions : CompilerOptions , emitHost : EmitHost ) : string | undefined {
308+ const transpiledFiles = recompileLuaLibFiles ( sourceOptions , emitHost ) ;
309+ const lualibBundle = transpiledFiles . find ( f => f . outPath . endsWith ( "lualib_bundle.lua" ) ) ;
310+ return lualibBundle ?. lua ;
311+ }
312+
313+ export function recompileInlineLualibFeatures (
314+ features : Iterable < LuaLibFeature > ,
315+ options : CompilerOptions ,
316+ emitHost : EmitHost
317+ ) : string {
318+ const luaTarget = options . luaTarget ?? LuaTarget . Universal ;
319+ const transpiledFiles = recompileLuaLibFiles ( options , emitHost ) ;
320+ emitHost = {
321+ readFile ( filePath : string ) {
322+ const file = transpiledFiles . find ( f => f . outPath === filePath ) ;
323+ return file ? file . text : undefined ;
324+ } ,
325+ } as any as EmitHost ;
326+ const moduleInfo = getLuaLibModulesInfo ( luaTarget , emitHost , false ) ;
327+ return resolveRecursiveLualibFeatures ( features , luaTarget , emitHost , moduleInfo )
328+ . map ( feature => readLuaLibFeature ( feature , luaTarget , emitHost , false ) )
329+ . join ( "\n" ) ;
330+ }
331+
260332const luaLibBundleContent = new Map < string , string > ( ) ;
261333
262- export function getLuaLibBundle ( luaTarget : LuaTarget , emitHost : EmitHost ) : string {
334+ export function getLuaLibBundle ( luaTarget : LuaTarget , emitHost : EmitHost , options : CompilerOptions ) : string {
335+ if ( options . recompileLuaLib ) {
336+ const result = recompileLuaLibBundle ( options , emitHost ) ;
337+ if ( ! result ) {
338+ throw new Error ( `Failed to recompile lualib bundle` ) ;
339+ }
340+ return result ;
341+ }
342+
263343 const lualibPath = path . join ( resolveLuaLibDir ( luaTarget ) , "lualib_bundle.lua" ) ;
264344 if ( ! luaLibBundleContent . has ( lualibPath ) ) {
265345 const result = emitHost . readFile ( lualibPath ) ;
@@ -279,13 +359,26 @@ export function getLualibBundleReturn(exportedValues: string[]): string {
279359
280360export function buildMinimalLualibBundle (
281361 features : Iterable < LuaLibFeature > ,
282- luaTarget : LuaTarget ,
362+ options : CompilerOptions ,
283363 emitHost : EmitHost
284364) : string {
285- const code = loadInlineLualibFeatures ( features , luaTarget , emitHost ) ;
286- const moduleInfo = getLuaLibModulesInfo ( luaTarget , emitHost ) ;
287- const exports = Array . from ( features ) . flatMap ( feature => moduleInfo [ feature ] . exports ) ;
365+ const luaTarget = options . luaTarget ?? LuaTarget . Universal ;
366+ let code ;
367+ if ( options . recompileLuaLib ) {
368+ code = recompileInlineLualibFeatures ( features , options , emitHost ) ;
369+ const transpiledFiles = recompileLuaLibFiles ( options , emitHost ) ;
370+ emitHost = {
371+ readFile ( filePath : string ) {
372+ const file = transpiledFiles . find ( f => f . outPath === filePath ) ;
373+ return file ? file . text : undefined ;
374+ } ,
375+ } as any as EmitHost ;
376+ } else {
377+ code = loadInlineLualibFeatures ( features , luaTarget , emitHost ) ;
378+ }
288379
380+ const moduleInfo = getLuaLibModulesInfo ( luaTarget , emitHost , ! options . recompileLuaLib ) ;
381+ const exports = Array . from ( features ) . flatMap ( feature => moduleInfo [ feature ] . exports ) ;
289382 return code + getLualibBundleReturn ( exports ) ;
290383}
291384
0 commit comments