Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/LuaAST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,7 @@ export function createMethodCallExpression(
export interface Identifier extends Expression {
kind: SyntaxKind.Identifier;
text: string;
originalName?: string;
symbolId?: SymbolId;
}

Expand All @@ -841,16 +842,18 @@ export function createIdentifier(
text: string | ts.__String,
tsOriginal?: ts.Node,
symbolId?: SymbolId,
originalName?: string,
parent?: Node
): Identifier {
const expression = createNode(SyntaxKind.Identifier, tsOriginal, parent) as Identifier;
expression.text = text as string;
expression.symbolId = symbolId;
expression.originalName = originalName;
return expression;
}

export function cloneIdentifier(identifier: Identifier, tsOriginal?: ts.Node): Identifier {
return createIdentifier(identifier.text, tsOriginal, identifier.symbolId);
return createIdentifier(identifier.text, tsOriginal, identifier.symbolId, identifier.originalName);
}

export function createAnonymousIdentifier(tsOriginal?: ts.Node, parent?: Node): Identifier {
Expand Down
28 changes: 18 additions & 10 deletions src/LuaPrinter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,12 @@ export class LuaPrinter {
return this.concatNodes(this.currentIndent, input);
}

protected createSourceNode(node: tstl.Node, chunks: SourceChunk | SourceChunk[]): SourceNode {
protected createSourceNode(node: tstl.Node, chunks: SourceChunk | SourceChunk[], name?: string): SourceNode {
const originalPos = tstl.getOriginalPos(node);

return originalPos !== undefined && originalPos.line !== undefined && originalPos.column !== undefined
? new SourceNode(originalPos.line + 1, originalPos.column, this.sourceFile, chunks)
: new SourceNode(null, null, this.sourceFile, chunks); // tslint:disable-line:no-null-keyword
? new SourceNode(originalPos.line + 1, originalPos.column, this.sourceFile, chunks, name)
: new SourceNode(null, null, this.sourceFile, chunks, name); // tslint:disable-line:no-null-keyword
}

protected concatNodes(...chunks: SourceChunk[]): SourceNode {
Expand Down Expand Up @@ -274,7 +274,7 @@ export class LuaPrinter {
}
}

return this.concatNodes(...chunks);
return this.createSourceNode(statement, chunks);
}

public printVariableAssignmentStatement(statement: tstl.AssignmentStatement): SourceNode {
Expand Down Expand Up @@ -516,13 +516,13 @@ export class LuaPrinter {
...this.joinChunks(", ", returnStatement.expressions.map(e => this.printExpression(e))),
];
chunks.push(this.createSourceNode(returnStatement, returnNode));
chunks.push(" end");
chunks.push(this.createSourceNode(expression, " end"));
} else {
chunks.push("\n");
this.pushIndent();
chunks.push(this.printBlock(expression.body));
this.popIndent();
chunks.push(this.indent("end"));
chunks.push(this.indent(this.createSourceNode(expression, "end")));
}

return this.createSourceNode(expression, chunks);
Expand All @@ -541,7 +541,7 @@ export class LuaPrinter {
this.pushIndent();
chunks.push(this.printBlock(expression.body));
this.popIndent();
chunks.push(this.indent("end"));
chunks.push(this.indent(this.createSourceNode(statement, "end")));

return this.createSourceNode(expression, chunks);
}
Expand Down Expand Up @@ -661,7 +661,11 @@ export class LuaPrinter {
}

public printIdentifier(expression: tstl.Identifier): SourceNode {
return this.createSourceNode(expression, expression.text);
return this.createSourceNode(
expression,
expression.text,
expression.originalName !== expression.text ? expression.originalName : undefined
);
}

public printTableIndexExpression(expression: tstl.TableIndexExpression): SourceNode {
Expand Down Expand Up @@ -734,12 +738,15 @@ export class LuaPrinter {
}
if (
currentMapping.generated.line === generatedLine &&
currentMapping.generated.column === generatedColumn
currentMapping.generated.column === generatedColumn &&
currentMapping.name === sourceNode.name
) {
return false;
}
return (
currentMapping.original.line !== sourceNode.line || currentMapping.original.column !== sourceNode.column
currentMapping.original.line !== sourceNode.line ||
currentMapping.original.column !== sourceNode.column ||
currentMapping.name !== sourceNode.name
);
};

Expand All @@ -749,6 +756,7 @@ export class LuaPrinter {
source: sourceNode.source,
original: { line: sourceNode.line, column: sourceNode.column },
generated: { line: generatedLine, column: generatedColumn },
name: sourceNode.name,
};
map.addMapping(currentMapping);
}
Expand Down
32 changes: 22 additions & 10 deletions src/LuaTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,12 @@ export class LuaTransformer {

let localClassName: tstl.Identifier;
if (this.isUnsafeName(className.text)) {
localClassName = tstl.createIdentifier(this.createSafeName(className.text), undefined, className.symbolId);
localClassName = tstl.createIdentifier(
this.createSafeName(className.text),
undefined,
className.symbolId,
className.text
);
tstl.setNodePosition(localClassName, className);
} else {
localClassName = className;
Expand Down Expand Up @@ -1060,20 +1065,22 @@ export class LuaTransformer {
tstl.createCallExpression(tstl.createIdentifier("setmetatable"), [
tstl.createTableExpression(),
createClassPrototype(),
])
]),
statement
);
newFuncStatements.push(assignSelf);

// self:____constructor(...)
const callConstructor = tstl.createExpressionStatement(
tstl.createMethodCallExpression(this.createSelfIdentifier(), tstl.createIdentifier("____constructor"), [
tstl.createDotsLiteral(),
])
]),
statement
);
newFuncStatements.push(callConstructor);

// return self
const returnSelf = tstl.createReturnStatement([this.createSelfIdentifier()]);
const returnSelf = tstl.createReturnStatement([this.createSelfIdentifier()], statement);
newFuncStatements.push(returnSelf);

// function localClassName.new(construct, ...) ... end
Expand All @@ -1086,7 +1093,8 @@ export class LuaTransformer {
tstl.createDotsLiteral(),
undefined,
tstl.FunctionExpressionFlags.Declaration
)
),
statement
);
result.push(newFunc);

Expand Down Expand Up @@ -1128,7 +1136,8 @@ export class LuaTransformer {
this.createSelfIdentifier(),
getterName,
tstl.createNilLiteral(),
])
]),
classDeclaration.members.find(ts.isConstructorDeclaration) || classDeclaration
);
statements.push(resetGetter);
}
Expand Down Expand Up @@ -1220,6 +1229,8 @@ export class LuaTransformer {

const block: tstl.Block = tstl.createBlock(bodyWithFieldInitializers);

const constructorWasGenerated = statement.pos === -1;

const result = tstl.createAssignmentStatement(
this.createConstructorName(className),
tstl.createFunctionExpression(
Expand All @@ -1229,7 +1240,7 @@ export class LuaTransformer {
restParamName,
tstl.FunctionExpressionFlags.Declaration
),
statement
constructorWasGenerated ? classDeclaration : statement
);

return result;
Expand Down Expand Up @@ -1550,7 +1561,8 @@ export class LuaTransformer {
return tstl.createIdentifier(
this.createSafeName(declaration.name.text),
declaration.name,
moduleSymbol && this.symbolIds.get(moduleSymbol)
moduleSymbol && this.symbolIds.get(moduleSymbol),
declaration.name.text
);
}
return this.transformIdentifier(declaration.name as ts.Identifier);
Expand Down Expand Up @@ -4688,7 +4700,7 @@ export class LuaTransformer {
: this.getIdentifierText(identifier);

const symbolId = this.getIdentifierSymbolId(identifier);
return tstl.createIdentifier(text, identifier, symbolId);
return tstl.createIdentifier(text, identifier, symbolId, this.getIdentifierText(identifier));
}

protected transformIdentifierExpression(expression: ts.Identifier): tstl.Expression {
Expand Down Expand Up @@ -4917,7 +4929,7 @@ export class LuaTransformer {
}

protected createSelfIdentifier(tsOriginal?: ts.Node): tstl.Identifier {
return tstl.createIdentifier("self", tsOriginal);
return tstl.createIdentifier("self", tsOriginal, undefined, "this");
}

protected createExportsIdentifier(): tstl.Identifier {
Expand Down
50 changes: 49 additions & 1 deletion test/unit/sourcemaps.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ test.each([
{ luaPattern: "function abc(", typeScriptPattern: "function abc() {" },
{ luaPattern: "function def(", typeScriptPattern: "function def() {" },
{ luaPattern: "return abc(", typeScriptPattern: "return abc(" },
{ luaPattern: "end", typeScriptPattern: "function def() {" },
],
},
{
Expand Down Expand Up @@ -69,7 +70,11 @@ test.each([
},
{
typeScriptSource: `
class Bar extends Foo {}
class Bar extends Foo {
constructor() {
super();
}
}
`,

assertPatterns: [
Expand All @@ -82,8 +87,27 @@ test.each([
{ luaPattern: "Bar.____super = Foo", typeScriptPattern: "Foo {" },
{ luaPattern: "setmetatable(Bar,", typeScriptPattern: "Foo {" },
{ luaPattern: "setmetatable(Bar.prototype,", typeScriptPattern: "Foo {" },
{ luaPattern: "function Bar.new", typeScriptPattern: "class Bar" },
{ luaPattern: "function Bar.prototype.____constructor", typeScriptPattern: "constructor" },
],
},
{
typeScriptSource: `
class Foo {
}
`,

assertPatterns: [{ luaPattern: "function Foo.prototype.____constructor", typeScriptPattern: "class Foo" }],
},
{
typeScriptSource: `
class Foo {
bar = "baz";
}
`,

assertPatterns: [{ luaPattern: "function Foo.prototype.____constructor", typeScriptPattern: "class Foo" }],
},
{
typeScriptSource: `
declare const arr: string[];
Expand Down Expand Up @@ -161,6 +185,30 @@ test("Source map has correct source root", async () => {
expect(sourceMap.sourceRoot).toBe(".");
});

test.each([
{ code: `const type = "foobar";`, name: "type" },
{ code: `const and = "foobar";`, name: "and" },
{ code: `const $$$ = "foobar";`, name: "$$$" },
{ code: `const foo = { bar() { console.log(this); } };`, name: "this" },
{ code: `function foo($$$: unknown) {}`, name: "$$$" },
{ code: `class $$$ {}`, name: "$$$" },
{ code: `namespace $$$ { const foo = "bar"; }`, name: "$$$" },
])("Source map has correct name mappings (%p)", async ({ code, name }) => {
const { file } = util.transpileStringResult(code);

if (!util.expectToBeDefined(file.lua) || !util.expectToBeDefined(file.sourceMap)) return;

const consumer = await new SourceMapConsumer(file.sourceMap);
const typescriptPosition = lineAndColumnOf(code, name);
let mappedName: string | undefined;
consumer.eachMapping(mapping => {
if (mapping.originalLine === typescriptPosition.line && mapping.originalColumn === typescriptPosition.column) {
mappedName = mapping.name;
}
});
expect(mappedName).toBe(name);
});

test("sourceMapTraceback saves sourcemap in _G", () => {
// Arrange
const typeScriptSource = `
Expand Down