|
1 | 1 | import * as path from "path"; |
2 | 2 | import { Mapping, SourceMapGenerator, SourceNode } from "source-map"; |
| 3 | +import * as ts from "typescript"; |
3 | 4 | import { CompilerOptions, LuaLibImportKind } from "./CompilerOptions"; |
4 | 5 | import * as lua from "./LuaAST"; |
5 | 6 | import { loadLuaLibFeatures, LuaLibFeature } from "./LuaLib"; |
@@ -75,6 +76,25 @@ function isSimpleExpression(expression: lua.Expression): boolean { |
75 | 76 |
|
76 | 77 | type SourceChunk = string | SourceNode; |
77 | 78 |
|
| 79 | +export interface PrintResult { |
| 80 | + code: string; |
| 81 | + sourceMap: string; |
| 82 | +} |
| 83 | + |
| 84 | +export type PrinterFactory = (program: ts.Program, emitHost: EmitHost) => Printer; |
| 85 | +export type Printer = LuaPrinter["print"]; |
| 86 | + |
| 87 | +export function createPrinter(program: ts.Program, emitHost: EmitHost, factories: PrinterFactory[]): Printer { |
| 88 | + if (factories.length === 0) { |
| 89 | + const printer = new LuaPrinter(program.getCompilerOptions(), emitHost); |
| 90 | + return (...args) => printer.print(...args); |
| 91 | + } else if (factories.length === 1) { |
| 92 | + return factories[0](program, emitHost); |
| 93 | + } else { |
| 94 | + throw new Error("Only one plugin can specify 'createPrinter'"); |
| 95 | + } |
| 96 | +} |
| 97 | + |
78 | 98 | export class LuaPrinter { |
79 | 99 | private static operatorMap: { [key in lua.Operator]: string } = { |
80 | 100 | [lua.SyntaxKind.AdditionOperator]: "+", |
@@ -105,36 +125,35 @@ export class LuaPrinter { |
105 | 125 | }; |
106 | 126 |
|
107 | 127 | private currentIndent = ""; |
108 | | - private sourceFile = ""; |
| 128 | + private sourceFile!: string; |
109 | 129 |
|
110 | 130 | public constructor(private options: CompilerOptions, private emitHost: EmitHost) {} |
111 | 131 |
|
112 | | - public print(block: lua.Block, luaLibFeatures: Set<LuaLibFeature>, sourceFile = ""): [string, string] { |
| 132 | + public print(block: lua.Block, luaLibFeatures: Set<LuaLibFeature>, fileName: string): PrintResult { |
113 | 133 | // Add traceback lualib if sourcemap traceback option is enabled |
114 | 134 | if (this.options.sourceMapTraceback) { |
115 | 135 | luaLibFeatures.add(LuaLibFeature.SourceMapTraceBack); |
116 | 136 | } |
117 | 137 |
|
118 | | - const rootSourceNode = this.printImplementation(block, luaLibFeatures, sourceFile); |
119 | | - |
120 | 138 | const sourceRoot = |
121 | 139 | this.options.sourceRoot || |
122 | 140 | (this.options.outDir ? path.relative(this.options.outDir, this.options.rootDir || process.cwd()) : "."); |
123 | 141 |
|
124 | | - const sourceMap = this.buildSourceMap(sourceFile, sourceRoot, rootSourceNode); |
| 142 | + const rootSourceNode = this.printImplementation(block, luaLibFeatures, fileName); |
| 143 | + const sourceMap = this.buildSourceMap(fileName, sourceRoot, rootSourceNode); |
125 | 144 |
|
126 | | - let codeResult = rootSourceNode.toString(); |
| 145 | + let code = rootSourceNode.toString(); |
127 | 146 |
|
128 | 147 | if (this.options.inlineSourceMap) { |
129 | | - codeResult += "\n" + this.printInlineSourceMap(sourceMap); |
| 148 | + code += "\n" + this.printInlineSourceMap(sourceMap); |
130 | 149 | } |
131 | 150 |
|
132 | 151 | if (this.options.sourceMapTraceback) { |
133 | 152 | const stackTraceOverride = this.printStackTraceOverride(rootSourceNode); |
134 | | - codeResult = codeResult.replace("{#SourceMapTraceback}", stackTraceOverride); |
| 153 | + code = code.replace("{#SourceMapTraceback}", stackTraceOverride); |
135 | 154 | } |
136 | 155 |
|
137 | | - return [codeResult, sourceMap.toString()]; |
| 156 | + return { code, sourceMap: sourceMap.toString() }; |
138 | 157 | } |
139 | 158 |
|
140 | 159 | private printInlineSourceMap(sourceMap: SourceMapGenerator): string { |
@@ -168,27 +187,25 @@ export class LuaPrinter { |
168 | 187 | return `__TS__SourceMapTraceBack(debug.getinfo(1).short_src, ${mapString});`; |
169 | 188 | } |
170 | 189 |
|
171 | | - private printImplementation(block: lua.Block, luaLibFeatures?: Set<LuaLibFeature>, sourceFile = ""): SourceNode { |
| 190 | + private printImplementation(block: lua.Block, luaLibFeatures: Set<LuaLibFeature>, sourceFile: string): SourceNode { |
172 | 191 | let header = ""; |
173 | 192 |
|
174 | 193 | if (!this.options.noHeader) { |
175 | 194 | header += `--[[ Generated with https://github.com/TypeScriptToLua/TypeScriptToLua ]]\n`; |
176 | 195 | } |
177 | 196 |
|
178 | | - if (luaLibFeatures) { |
179 | | - const luaLibImport = this.options.luaLibImport || LuaLibImportKind.Inline; |
180 | | - // Require lualib bundle |
181 | | - if ( |
182 | | - (luaLibImport === LuaLibImportKind.Require && luaLibFeatures.size > 0) || |
183 | | - luaLibImport === LuaLibImportKind.Always |
184 | | - ) { |
185 | | - header += `require("lualib_bundle");\n`; |
186 | | - } |
187 | | - // Inline lualib features |
188 | | - else if (luaLibImport === LuaLibImportKind.Inline && luaLibFeatures.size > 0) { |
189 | | - header += "-- Lua Library inline imports\n"; |
190 | | - header += loadLuaLibFeatures(luaLibFeatures, this.emitHost); |
191 | | - } |
| 197 | + const luaLibImport = this.options.luaLibImport || LuaLibImportKind.Inline; |
| 198 | + // Require lualib bundle |
| 199 | + if ( |
| 200 | + (luaLibImport === LuaLibImportKind.Require && luaLibFeatures.size > 0) || |
| 201 | + luaLibImport === LuaLibImportKind.Always |
| 202 | + ) { |
| 203 | + header += `require("lualib_bundle");\n`; |
| 204 | + } |
| 205 | + // Inline lualib features |
| 206 | + else if (luaLibImport === LuaLibImportKind.Inline && luaLibFeatures.size > 0) { |
| 207 | + header += "-- Lua Library inline imports\n"; |
| 208 | + header += loadLuaLibFeatures(luaLibFeatures, this.emitHost); |
192 | 209 | } |
193 | 210 |
|
194 | 211 | this.sourceFile = path.basename(sourceFile); |
|
0 commit comments