Skip to content

Commit e124f1d

Browse files
authored
Initial Transformer Setup (#279)
* Initial Transformer Setup Added Transformer setup that allows us to incrementally port our transpile functions to transform functions. We have to prot all transpile functions that transpile Nodes that are not allowed in the 2nd AST. Once thats done we should restrucutre the whole project, because right now the transform process is just hacked before the transpilation. * Moved import path resolving from the transpiler to the transformer
1 parent 26fe357 commit e124f1d

File tree

10 files changed

+472
-94
lines changed

10 files changed

+472
-94
lines changed

.clang-format

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Language: JavaScript
2+
BasedOnStyle: Google
3+
IndentWidth: 4
4+
JavaScriptQuotes: Double
5+
ColumnLimit: 120
6+
AlignAfterOpenBracket: Align
7+
AllowAllParametersOfDeclarationOnNextLine: false
8+
BinPackParameters: false
9+
BinPackArguments: false
10+
ExperimentalAutoDetectBinPacking: false

.codecov.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ coverage:
44
status:
55
project:
66
default:
7-
target: 90
7+
target: 80
88
threshold: null
99
base: auto
1010
changes: off

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
node_modules/
33
yarn.lock
44

5+
.vscode/
6+
57
coverage/
68
.nyc*
79
*.js.map

src/TransformHelper.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import * as ts from "typescript";
2+
3+
export class TransformHelper {
4+
// Helper to create simple lua variable statement;
5+
public static createLuaVariableStatement(
6+
identifier: ts.Identifier,
7+
expression: ts.Expression,
8+
typeNode?: ts.TypeNode
9+
): ts.VariableStatement {
10+
const declaration = ts.createVariableDeclaration(identifier, typeNode, expression);
11+
const statement = ts.createVariableStatement([], ts.createVariableDeclarationList([declaration]));
12+
return statement;
13+
}
14+
15+
public static createLuaImport(identifier: ts.Identifier, moduleSpecifier: ts.StringLiteral): ts.VariableStatement {
16+
const requireIdentifier = ts.createIdentifier("require");
17+
const requireCall =
18+
ts.createCall(requireIdentifier, [ts.createLiteralTypeNode(moduleSpecifier)], [moduleSpecifier]);
19+
return this.createLuaVariableStatement(identifier, requireCall);
20+
}
21+
}

src/Transformer.ts

Lines changed: 428 additions & 0 deletions
Large diffs are not rendered by default.

src/Transpiler.ts

Lines changed: 5 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { DecoratorKind } from "./Decorator";
77
import { TSTLErrors } from "./Errors";
88
import { TSHelper as tsHelper } from "./TSHelper";
99

10+
import { LuaTransformer } from "./Transformer";
11+
1012
/* tslint:disable */
1113
const packageJSON = require("../package.json");
1214
/* tslint:enable */
@@ -159,31 +161,6 @@ export abstract class LuaTranspiler {
159161
this.luaLibFeatureSet.add(feature);
160162
}
161163

162-
public getAbsoluteImportPath(relativePath: string): string {
163-
if (relativePath.charAt(0) !== "." && this.options.baseUrl) {
164-
return path.resolve(this.options.baseUrl, relativePath);
165-
}
166-
return path.resolve(path.dirname(this.sourceFile.fileName), relativePath);
167-
}
168-
169-
public getImportPath(relativePath: string): string {
170-
// Calculate absolute path to import
171-
const absolutePathToImport = this.getAbsoluteImportPath(relativePath);
172-
if (this.options.rootDir) {
173-
// Calculate path relative to project root
174-
// and replace path.sep with dots (lua doesn't know paths)
175-
const relativePathToRoot =
176-
this.pathToLuaRequirePath(absolutePathToImport.replace(this.options.rootDir, "").slice(1));
177-
return `"${relativePathToRoot}"`;
178-
}
179-
180-
return `"${this.pathToLuaRequirePath(relativePath)}"`;
181-
}
182-
183-
public pathToLuaRequirePath(filePath: string): string {
184-
return filePath.replace(new RegExp("\\\\|\/", "g"), ".");
185-
}
186-
187164
public computeEnumMembers(node: ts.EnumDeclaration): Array<{ name: string, value: string | number }> {
188165
let val: number | string = 0;
189166
let hasStringInitializers = false;
@@ -221,6 +198,9 @@ export abstract class LuaTranspiler {
221198
}
222199
let result = header;
223200

201+
const transformer = new LuaTransformer(this.checker, this.options);
202+
this. sourceFile = transformer.transform(this.sourceFile);
203+
224204
// Transpile content first to gather some info on dependencies
225205
let fileStatements = "";
226206
this.exportStack.push([]);
@@ -285,8 +265,6 @@ export abstract class LuaTranspiler {
285265
}
286266

287267
switch (node.kind) {
288-
case ts.SyntaxKind.ImportDeclaration:
289-
return this.transpileImport(node as ts.ImportDeclaration);
290268
case ts.SyntaxKind.ClassDeclaration:
291269
return this.transpileClass(node as ts.ClassDeclaration);
292270
case ts.SyntaxKind.ModuleDeclaration:
@@ -341,53 +319,6 @@ export abstract class LuaTranspiler {
341319
return `__TS__${func}(${params.join(", ")})`;
342320
}
343321

344-
public transpileImport(node: ts.ImportDeclaration): string {
345-
const importPath = this.transpileExpression(node.moduleSpecifier);
346-
const importPathWithoutQuotes = importPath.replace(new RegExp("\"", "g"), "");
347-
348-
if (!node.importClause || !node.importClause.namedBindings) {
349-
throw TSTLErrors.DefaultImportsNotSupported(node);
350-
}
351-
352-
const imports = node.importClause.namedBindings;
353-
354-
const requireKeyword = "require";
355-
356-
if (ts.isNamedImports(imports)) {
357-
const fileImportTable = path.basename(importPathWithoutQuotes) + this.importCount;
358-
const resolvedImportPath = this.getImportPath(importPathWithoutQuotes);
359-
360-
let result = `local ${fileImportTable} = ${requireKeyword}(${resolvedImportPath})\n`;
361-
this.importCount++;
362-
363-
const filteredElements = imports.elements.filter(e => {
364-
const decorators = tsHelper.getCustomDecorators(this.checker.getTypeAtLocation(e), this.checker);
365-
return !decorators.has(DecoratorKind.Extension) && !decorators.has(DecoratorKind.MetaExtension);
366-
});
367-
368-
if (filteredElements.length === 0) {
369-
return "";
370-
}
371-
372-
filteredElements.forEach(element => {
373-
const nameText = this.transpileIdentifier(element.name);
374-
if (element.propertyName) {
375-
const propertyText = this.transpileIdentifier(element.propertyName);
376-
result += `local ${nameText} = ${fileImportTable}.${propertyText}\n`;
377-
} else {
378-
result += `local ${nameText} = ${fileImportTable}.${nameText}\n`;
379-
}
380-
});
381-
382-
return result;
383-
} else if (ts.isNamespaceImport(imports)) {
384-
const resolvedImportPath = this.getImportPath(importPathWithoutQuotes);
385-
return `local ${this.transpileIdentifier(imports.name)} = ${requireKeyword}(${resolvedImportPath})\n`;
386-
} else {
387-
throw TSTLErrors.UnsupportedImportType(imports);
388-
}
389-
}
390-
391322
public transpileNamespace(node: ts.ModuleDeclaration): string {
392323
const decorators = tsHelper.getCustomDecorators(this.checker.getTypeAtLocation(node), this.checker);
393324
// If phantom namespace just transpile the body as normal
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
local Test = require("test")
1+
local Test = require("test");
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
local test0 = require("test")
2-
local TestClass = test0.TestClass
1+
local test = require("test");
2+
local TestClass = test.TestClass;
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
local test0 = require("test")
2-
local RenamedClass = test0.TestClass
1+
local test = require("test");
2+
local RenamedClass = test.TestClass;

test/unit/modules.spec.ts

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,20 +41,6 @@ export class LuaModuleTests {
4141
Expect(lua).toBe(`require("lualib_bundle")`);
4242
}
4343

44-
@Test("Import named bindings exception")
45-
public namedBindigsException(): void {
46-
const transpiler = util.makeTestTranspiler();
47-
48-
const mockDeclaration: any = {
49-
importClause: {namedBindings: {}},
50-
kind: ts.SyntaxKind.ImportDeclaration,
51-
moduleSpecifier: ts.createLiteral("test"),
52-
};
53-
54-
Expect(() => transpiler.transpileImport(mockDeclaration as ts.ImportDeclaration))
55-
.toThrowError(Error, "Unsupported import type.");
56-
}
57-
5844
@Test("Non-exported module")
5945
public nonExportedModule(): void {
6046
const lua = util.transpileString("module g { export function test() { return 3; } } return g.test();");

0 commit comments

Comments
 (0)