Skip to content

Commit 267803d

Browse files
committed
Merge remote-tracking branch 'upstream/master' into small-improvements
2 parents 4cef77b + 26cf33c commit 267803d

File tree

10 files changed

+327
-78
lines changed

10 files changed

+327
-78
lines changed

src/LuaAST.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,6 @@ function getSourcePosition(sourceNode: ts.Node): TextRange | undefined {
173173
}
174174

175175
export function getOriginalPos(node: Node): TextRange {
176-
while (node.line === undefined && node.parent !== undefined) {
177-
node = node.parent;
178-
}
179-
180176
return { line: node.line, column: node.column };
181177
}
182178

src/LuaLib.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ export enum LuaLibFeature {
4747
Spread = "Spread",
4848
StringConcat = "StringConcat",
4949
StringEndsWith = "StringEndsWith",
50+
StringPadEnd = "StringPadEnd",
51+
StringPadStart = "StringPadStart",
5052
StringReplace = "StringReplace",
5153
StringSplit = "StringSplit",
5254
StringStartsWith = "StringStartsWith",

src/LuaPrinter.ts

Lines changed: 74 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as path from "path";
22

3-
import {SourceNode, SourceMapGenerator} from "source-map";
3+
import { Mapping, SourceNode, SourceMapGenerator } from "source-map";
44

55
import * as tstl from "./LuaAST";
66
import { CompilerOptions, LuaLibImportKind } from "./CompilerOptions";
@@ -59,22 +59,23 @@ export class LuaPrinter {
5959

6060
const rootSourceNode = this.printImplementation(block, luaLibFeatures, sourceFile);
6161

62-
const codeWithSourceMap = rootSourceNode
63-
// TODO is the file: part really required? and should this be handled in the printer?
64-
.toStringWithSourceMap({file: path.basename(sourceFile, path.extname(sourceFile)) + ".lua"});
62+
const sourceRoot = this.options.sourceRoot
63+
|| (this.options.outDir ? path.relative(this.options.outDir, this.options.rootDir || process.cwd()) : ".");
6564

66-
let codeResult = codeWithSourceMap.code;
65+
const sourceMap = this.buildSourceMap(sourceFile, sourceRoot, rootSourceNode);
66+
67+
let codeResult = rootSourceNode.toString();
6768

6869
if (this.options.inlineSourceMap) {
69-
codeResult += "\n" + this.printInlineSourceMap(codeWithSourceMap.map);
70+
codeResult += "\n" + this.printInlineSourceMap(sourceMap);
7071
}
7172

7273
if (this.options.sourceMapTraceback) {
7374
const stackTraceOverride = this.printStackTraceOverride(rootSourceNode);
7475
codeResult = codeResult.replace("{#SourceMapTraceback}", stackTraceOverride);
7576
}
7677

77-
return [codeResult, codeWithSourceMap.map.toString()];
78+
return [codeResult, sourceMap.toString()];
7879
}
7980

8081
private printInlineSourceMap(sourceMap: SourceMapGenerator): string {
@@ -140,7 +141,7 @@ export class LuaPrinter {
140141
header += "{#SourceMapTraceback}\n";
141142
}
142143

143-
const fileBlockNode = this.createSourceNode(block, this.printBlock(block));
144+
const fileBlockNode = this.printBlock(block);
144145

145146
return this.concatNodes(header, fileBlockNode);
146147
}
@@ -172,7 +173,7 @@ export class LuaPrinter {
172173
}
173174

174175
protected printBlock(block: tstl.Block): SourceNode {
175-
return this.createSourceNode(block, this.printStatementArray(block.statements));
176+
return this.concatNodes(...this.printStatementArray(block.statements));
176177
}
177178

178179
private statementMayRequireSemiColon(statement: tstl.Statement): boolean {
@@ -428,7 +429,7 @@ export class LuaPrinter {
428429
}
429430

430431
public printExpressionStatement(statement: tstl.ExpressionStatement): SourceNode {
431-
return this.concatNodes(this.indent(), this.printExpression(statement.expression));
432+
return this.createSourceNode(statement, [this.indent(), this.printExpression(statement.expression)]);
432433
}
433434

434435
// Expressions
@@ -626,7 +627,7 @@ export class LuaPrinter {
626627

627628
chunks.push(this.printExpression(expression.expression), "(", ...this.joinChunks(", ", parameterChunks), ")");
628629

629-
return this.concatNodes(...chunks);
630+
return this.createSourceNode(expression, chunks);
630631
}
631632

632633
public printMethodCallExpression(expression: tstl.MethodCallExpression): SourceNode {
@@ -638,7 +639,10 @@ export class LuaPrinter {
638639

639640
const name = this.printIdentifier(expression.name);
640641

641-
return this.concatNodes(prefix, ":", name, "(", ...this.joinChunks(", ", parameterChunks), ")");
642+
return this.createSourceNode(
643+
expression,
644+
[prefix, ":", name, "(", ...this.joinChunks(", ", parameterChunks), ")"]
645+
);
642646
}
643647

644648
public printIdentifier(expression: tstl.Identifier): SourceNode {
@@ -689,4 +693,62 @@ export class LuaPrinter {
689693
}
690694
return result;
691695
}
696+
697+
// The key difference between this and SourceNode.toStringWithSourceMap() is that SourceNodes with null line/column
698+
// will not generate 'empty' mappings in the source map that point to nothing in the original TS.
699+
private buildSourceMap(sourceFile: string, sourceRoot: string, rootSourceNode: SourceNode): SourceMapGenerator {
700+
const map = new SourceMapGenerator({
701+
file: path.basename(sourceFile, path.extname(sourceFile)) + ".lua",
702+
sourceRoot,
703+
});
704+
705+
let generatedLine = 1;
706+
let generatedColumn = 0;
707+
let currentMapping: Mapping | undefined;
708+
709+
const isNewMapping = (sourceNode: SourceNode) => {
710+
if (sourceNode.line === null) {
711+
return false;
712+
}
713+
if (currentMapping === undefined) {
714+
return true;
715+
}
716+
if (currentMapping.generated.line === generatedLine
717+
&& currentMapping.generated.column === generatedColumn)
718+
{
719+
return false;
720+
}
721+
return (currentMapping.original.line !== sourceNode.line
722+
|| currentMapping.original.column !== sourceNode.column);
723+
};
724+
725+
const build = (sourceNode: SourceNode) => {
726+
if (isNewMapping(sourceNode)) {
727+
currentMapping = {
728+
source: sourceNode.source,
729+
original: { line: sourceNode.line, column: sourceNode.column },
730+
generated: { line: generatedLine, column: generatedColumn },
731+
};
732+
map.addMapping(currentMapping);
733+
}
734+
735+
for (const chunk of sourceNode.children) {
736+
if (typeof chunk === "string") {
737+
const lines = (chunk as string).split("\n");
738+
if (lines.length > 1) {
739+
generatedLine += lines.length - 1;
740+
generatedColumn = 0;
741+
currentMapping = undefined; // Mappings end at newlines
742+
}
743+
generatedColumn += lines[lines.length - 1].length;
744+
745+
} else {
746+
build(chunk);
747+
}
748+
}
749+
};
750+
build(rootSourceNode);
751+
752+
return map;
753+
}
692754
}

0 commit comments

Comments
 (0)