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
23 changes: 14 additions & 9 deletions src/LuaPrinter.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import * as path from "path";
import { Mapping, SourceMapGenerator, SourceNode } from "source-map";
import { getEmitPath } from ".";
import * as ts from "typescript";
import { CompilerOptions, isBundleEnabled, LuaLibImportKind } from "./CompilerOptions";
import * as lua from "./LuaAST";
import { loadLuaLibFeatures, LuaLibFeature } from "./LuaLib";
import { isValidLuaIdentifier } from "./transformation/utils/safe-names";
import { EmitHost } from "./transpilation";
import { intersperse, trimExtension } from "./utils";
import { intersperse, normalizeSlashes } from "./utils";

// https://www.lua.org/pil/2.4.html
// https://www.ecma-international.org/ecma-262/10.0/index.html#table-34
Expand Down Expand Up @@ -120,14 +122,17 @@ export class LuaPrinter {
};

private currentIndent = "";
private sourceFile: string;
private luaFile: string;
private relativeSourcePath: string;
private options: CompilerOptions;

public static readonly sourceMapTracebackPlaceholder = "{#SourceMapTraceback}";

constructor(private emitHost: EmitHost, program: ts.Program, fileName: string) {
constructor(private emitHost: EmitHost, private program: ts.Program, private sourceFile: string) {
this.options = program.getCompilerOptions();
this.sourceFile = fileName;
this.luaFile = normalizeSlashes(getEmitPath(this.sourceFile, this.program));
// Source nodes contain relative path from mapped lua file to original TS source file
this.relativeSourcePath = normalizeSlashes(path.relative(path.dirname(this.luaFile), this.sourceFile));
}

public print(file: lua.File): PrintResult {
Expand Down Expand Up @@ -230,12 +235,12 @@ export class LuaPrinter {
const { line, column } = lua.getOriginalPos(node);

return line !== undefined && column !== undefined
? new SourceNode(line + 1, column, this.sourceFile, chunks, name)
: new SourceNode(null, null, this.sourceFile, chunks, name);
? new SourceNode(line + 1, column, this.relativeSourcePath, chunks, name)
: new SourceNode(null, null, this.relativeSourcePath, chunks, name);
}

protected concatNodes(...chunks: SourceChunk[]): SourceNode {
return new SourceNode(null, null, this.sourceFile, chunks);
return new SourceNode(null, null, this.relativeSourcePath, chunks);
}

protected printBlock(block: lua.Block): SourceNode {
Expand Down Expand Up @@ -757,7 +762,7 @@ export class LuaPrinter {
}

public printOperator(kind: lua.Operator): SourceNode {
return new SourceNode(null, null, this.sourceFile, LuaPrinter.operatorMap[kind]);
return new SourceNode(null, null, this.relativeSourcePath, LuaPrinter.operatorMap[kind]);
}

protected joinChunksWithComma(chunks: SourceChunk[]): SourceChunk[] {
Expand Down Expand Up @@ -787,7 +792,7 @@ export class LuaPrinter {
// will not generate 'empty' mappings in the source map that point to nothing in the original TS.
private buildSourceMap(sourceRoot: string, rootSourceNode: SourceNode): SourceMapGenerator {
const map = new SourceMapGenerator({
file: trimExtension(this.sourceFile) + ".lua",
file: path.basename(this.luaFile),
sourceRoot,
});

Expand Down
2 changes: 1 addition & 1 deletion src/transpilation/diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const createDiagnosticFactory = <TArgs extends any[]>(

export const couldNotResolveRequire = createDiagnosticFactory(
(requirePath: string, containingFile: string) =>
`Could not resolve require path '${requirePath}' in file ${containingFile}.`
`Could not resolve lua source files for require path '${requirePath}' in file ${containingFile}.`
);

export const couldNotReadDependency = createDiagnosticFactory(
Expand Down
2 changes: 1 addition & 1 deletion test/unit/modules/__snapshots__/resolution.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ local ____ = module
return ____exports"
`;

exports[`doesn't resolve paths out of root dir: diagnostics 1`] = `"error TSTL: Could not resolve require path '../module' in file main.ts."`;
exports[`doesn't resolve paths out of root dir: diagnostics 1`] = `"error TSTL: Could not resolve lua source files for require path '../module' in file main.ts."`;
24 changes: 17 additions & 7 deletions test/unit/printer/sourcemaps.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,25 +163,35 @@ test.each([
});

test.each([
{ fileName: "/proj/foo.ts", config: {} },
{
fileName: "/proj/foo.ts",
config: {},
expectedSourcePath: "foo.ts", // ts and lua will be emitted to same directory
},
{
fileName: "/proj/src/foo.ts",
config: { outDir: "/proj/dst" },
config: {
outDir: "/proj/dst",
},
expectedSourcePath: "../src/foo.ts", // path from proj/dst outDir to proj/src/foo.ts
},
{
fileName: "/proj/src/foo.ts",
config: { rootDir: "/proj/src", outDir: "/proj/dst" },
expectedSourcePath: "../src/foo.ts", // path from proj/dst outDir to proj/src/foo.ts
},
{
fileName: "/proj/src/sub/foo.ts",
config: { rootDir: "/proj/src", outDir: "/proj/dst" },
expectedSourcePath: "../../src/sub/foo.ts", // path from proj/dst/sub outDir to proj/src/sub/foo.ts
},
{
fileName: "/proj/src/sub/main.ts",
config: { rootDir: "/proj/src", outDir: "/proj/dst", sourceRoot: "bin" },
fullSource: "bin/proj/src/sub/main.ts",
config: { rootDir: "/proj/src", outDir: "/proj/dst", sourceRoot: "bin/binsub/binsubsub" },
expectedSourcePath: "../../src/sub/main.ts", // path from proj/dst/sub outDir to proj/src/sub/foo.ts
fullSource: "bin/src/sub/main.ts",
},
])("Source map has correct sources (%p)", async ({ fileName, config, fullSource }) => {
])("Source map has correct sources (%p)", async ({ fileName, config, fullSource, expectedSourcePath }) => {
const file = util.testModule`
const foo = "foo"
`
Expand All @@ -191,11 +201,11 @@ test.each([

const sourceMap = JSON.parse(file.luaSourceMap);
expect(sourceMap.sources).toHaveLength(1);
expect(sourceMap.sources[0]).toBe(fileName);
expect(sourceMap.sources[0]).toBe(expectedSourcePath);

const consumer = await new SourceMapConsumer(file.luaSourceMap);
expect(consumer.sources).toHaveLength(1);
expect(consumer.sources[0]).toBe(fullSource ?? fileName);
expect(consumer.sources[0]).toBe(fullSource ?? expectedSourcePath);
});

test.each([
Expand Down