|
1 | | -import { Resolver, ResolverFactory } from "enhanced-resolve"; |
2 | | -import * as fs from "fs"; |
3 | | -import * as path from "path"; |
4 | 1 | import * as ts from "typescript"; |
5 | | -import { CompilerOptions, isBundleEnabled, LuaTarget } from "../CompilerOptions"; |
6 | | -import { getLuaLibBundle } from "../LuaLib"; |
7 | | -import { assert, cast, isNonNull, normalizeSlashes, trimExtension } from "../utils"; |
8 | | -import { Chunk, modulesToBundleChunks, modulesToChunks } from "./chunk"; |
9 | | -import { createResolutionErrorDiagnostic } from "./diagnostics"; |
10 | | -import { buildModule, Module } from "./module"; |
| 2 | +import { Transpilation } from "./transpilation"; |
11 | 3 | import { emitProgramModules, TranspileOptions } from "./transpile"; |
12 | 4 | import { EmitHost } from "./utils"; |
13 | 5 |
|
@@ -49,104 +41,3 @@ export class Transpiler { |
49 | 41 | return { diagnostics, emitSkipped: emitPlan.length === 0 }; |
50 | 42 | } |
51 | 43 | } |
52 | | - |
53 | | -export class Transpilation { |
54 | | - public readonly diagnostics: ts.Diagnostic[] = []; |
55 | | - private modules: Module[] = []; |
56 | | - |
57 | | - public options = this.program.getCompilerOptions() as CompilerOptions; |
58 | | - public rootDir: string; |
59 | | - public outDir: string; |
60 | | - public emitHost: EmitHost; |
61 | | - |
62 | | - private readonly implicitScriptExtensions = [".ts", ".tsx", ".js", ".jsx"] as const; |
63 | | - protected resolver: Resolver; |
64 | | - |
65 | | - constructor(public transpiler: Transpiler, public program: ts.Program) { |
66 | | - this.emitHost = transpiler.emitHost; |
67 | | - |
68 | | - const { rootDir } = program.getCompilerOptions(); |
69 | | - this.rootDir = |
70 | | - // getCommonSourceDirectory ignores provided rootDir when TS6059 is emitted |
71 | | - rootDir == null |
72 | | - ? program.getCommonSourceDirectory() |
73 | | - : ts.getNormalizedAbsolutePath(rootDir, this.emitHost.getCurrentDirectory()); |
74 | | - |
75 | | - this.outDir = this.options.outDir ?? this.rootDir; |
76 | | - |
77 | | - this.resolver = ResolverFactory.createResolver({ |
78 | | - extensions: [".lua", ...this.implicitScriptExtensions], |
79 | | - conditionNames: ["lua", `lua:${this.options.luaTarget ?? LuaTarget.Universal}`], |
80 | | - fileSystem: this.emitHost.resolutionFileSystem ?? fs, |
81 | | - useSyncFileSystemCalls: true, |
82 | | - }); |
83 | | - } |
84 | | - |
85 | | - public emit(programModules: Module[]): Chunk[] { |
86 | | - programModules.forEach(module => this.modules.push(module)); |
87 | | - programModules.forEach(module => this.buildModule(module)); |
88 | | - |
89 | | - const lualibRequired = this.modules.some(m => m.code.toString().includes('require("lualib_bundle")')); |
90 | | - if (lualibRequired) { |
91 | | - const fileName = normalizeSlashes(path.resolve(this.rootDir, "lualib_bundle.lua")); |
92 | | - this.modules.unshift({ request: fileName, code: getLuaLibBundle(this.emitHost), isBuilt: true }); |
93 | | - } |
94 | | - |
95 | | - return this.mapModulesToChunks(this.modules); |
96 | | - } |
97 | | - |
98 | | - private buildModule(module: Module) { |
99 | | - buildModule(module, request => { |
100 | | - let resolvedModule: Module; |
101 | | - try { |
102 | | - resolvedModule = this.resolveRequestToModule(module.request, request); |
103 | | - } catch (error) { |
104 | | - this.diagnostics.push(createResolutionErrorDiagnostic(error.message, request, module.request)); |
105 | | - return { error: error.message }; |
106 | | - } |
107 | | - |
108 | | - return this.getModuleId(resolvedModule); |
109 | | - }); |
110 | | - } |
111 | | - |
112 | | - private resolveRequestToModule(issuer: string, request: string) { |
113 | | - const resolvedPath = this.resolver.resolveSync({}, path.dirname(issuer), request); |
114 | | - assert(typeof resolvedPath === "string", `Invalid resolution result: ${resolvedPath}`); |
115 | | - |
116 | | - let module = this.modules.find(m => m.request === resolvedPath); |
117 | | - if (!module) { |
118 | | - if ( |
119 | | - this.implicitScriptExtensions.some(extension => resolvedPath.endsWith(extension)) || |
120 | | - resolvedPath.endsWith(".json") |
121 | | - ) { |
122 | | - throw new Error(`Resolved source file '${resolvedPath}' is not a part of the project.`); |
123 | | - } |
124 | | - |
125 | | - // TODO: Load source map files |
126 | | - module = { |
127 | | - request: resolvedPath, |
128 | | - code: cast(this.emitHost.readFile(resolvedPath), isNonNull), |
129 | | - isBuilt: false, |
130 | | - }; |
131 | | - |
132 | | - this.modules.push(module); |
133 | | - this.buildModule(module); |
134 | | - } |
135 | | - |
136 | | - return module; |
137 | | - } |
138 | | - |
139 | | - public getModuleId(module: Module) { |
140 | | - const result = path.relative(this.rootDir, trimExtension(module.request)); |
141 | | - // TODO: handle files on other drives |
142 | | - assert(!path.isAbsolute(result), `Invalid path: ${result}`); |
143 | | - return result |
144 | | - .replace(/\.\.[/\\]/g, "_/") |
145 | | - .replace(/\./g, "__") |
146 | | - .replace(/[/\\]/g, "."); |
147 | | - } |
148 | | - |
149 | | - private mapModulesToChunks(modules: Module[]): Chunk[] { |
150 | | - return isBundleEnabled(this.options) ? modulesToBundleChunks(this, modules) : modulesToChunks(this, modules); |
151 | | - } |
152 | | -} |
0 commit comments