Skip to content

Commit 9a23ce3

Browse files
hazzard993Perryvw
authored andcommitted
Absolute import path slashes normalized (#390)
* Absolute import path slashes normalized * Added require spec tests * path logic no longer uses absolute paths * Added errors and path conversion * Added filename for compiler and more tests * Removed FocusTest * Added default root dir * Fixed test * Fixed paths for Linux and Windows machines * .json paths are chopped * json replacement first * json path before windows
1 parent 1691f23 commit 9a23ce3

File tree

4 files changed

+72
-16
lines changed

4 files changed

+72
-16
lines changed

src/LuaTransformer.ts

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3719,22 +3719,31 @@ export class LuaTransformer {
37193719
}
37203720

37213721
private getImportPath(relativePath: string): string {
3722-
// Calculate absolute path to import
3723-
const absolutePathToImport = this.getAbsoluteImportPath(relativePath);
3724-
if (this.options.rootDir) {
3725-
// Calculate path relative to project root
3726-
// and replace path.sep with dots (lua doesn't know paths)
3727-
const relativePathToRoot = this.pathToLuaRequirePath(
3728-
absolutePathToImport.replace(this.options.rootDir, "").slice(1)
3729-
);
3730-
return relativePathToRoot;
3722+
const rootDir = this.options.rootDir || path.resolve(".");
3723+
const absoluteImportPath = this.formatPathToLuaPath(this.getAbsoluteImportPath(relativePath));
3724+
const absoluteRootDirPath = this.formatPathToLuaPath(rootDir);
3725+
if (absoluteImportPath.includes(absoluteRootDirPath)) {
3726+
const relativePathToRoot = this.formatPathToLuaPath(
3727+
absoluteImportPath.replace(absoluteRootDirPath, "").slice(1));
3728+
return this.formatPathToLuaPath(relativePathToRoot);
3729+
} else {
3730+
throw TSTLErrors.UnresolvableRequirePath(undefined,
3731+
`Cannot create require path. Module does not exist within --rootDir`,
3732+
relativePath);
37313733
}
3732-
3733-
return this.pathToLuaRequirePath(relativePath);
37343734
}
37353735

3736-
private pathToLuaRequirePath(filePath: string): string {
3737-
return filePath.replace(/\.json$/, '').replace(new RegExp("\\\\|\/", "g"), ".");
3736+
private formatPathToLuaPath(filePath: string): string {
3737+
filePath = filePath.replace(/\.json$/, "");
3738+
if (process.platform === "win32") {
3739+
// Windows can use backslashes
3740+
filePath = filePath
3741+
.replace(/\.\\/g, "")
3742+
.replace(/\\/g, ".");
3743+
}
3744+
return filePath
3745+
.replace(/\.\//g, "")
3746+
.replace(/\//g, ".");
37383747
}
37393748

37403749
private shouldExportIdentifier(identifier: tstl.Identifier | tstl.Identifier[]): boolean {

src/TSTLErrors.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,13 @@ export class TSTLErrors {
134134
node);
135135
};
136136

137+
public static UnresolvableRequirePath = (node: ts.Node, reason: string, path?: string) => {
138+
return new TranspileError(
139+
`${reason}. ` +
140+
`TypeScript path: ${path}.`,
141+
node);
142+
};
143+
137144
public static ReferencedBeforeDeclaration = (node: ts.Identifier) => {
138145
return new TranspileError(
139146
`Identifier "${node.text}" was referenced before it was declared. The declaration ` +

test/src/util.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,16 @@ import {lauxlib, lua, lualib, to_jsstring, to_luastring } from "fengari";
1111
import * as fs from "fs";
1212
import { LuaTransformer } from "../../src/LuaTransformer";
1313

14-
export function transpileString(str: string, options?: CompilerOptions, ignoreDiagnostics = true): string {
14+
export function transpileString(
15+
str: string,
16+
options?: CompilerOptions,
17+
ignoreDiagnostics = true,
18+
filePath = "file.ts"): string {
1519
if (options) {
1620
if (options.noHeader === undefined) {
1721
options.noHeader = true;
1822
}
19-
return compilerTranspileString(str, options, ignoreDiagnostics);
23+
return compilerTranspileString(str, options, ignoreDiagnostics, filePath);
2024
} else {
2125
return compilerTranspileString(
2226
str,
@@ -26,7 +30,8 @@ export function transpileString(str: string, options?: CompilerOptions, ignoreDi
2630
target: ts.ScriptTarget.ES2015,
2731
noHeader: true,
2832
},
29-
ignoreDiagnostics
33+
ignoreDiagnostics,
34+
filePath
3035
);
3136
}
3237
}

test/unit/require.spec.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { Expect, FocusTest, Test, TestCase } from "alsatian";
2+
3+
import * as util from "../src/util";
4+
import * as path from "path";
5+
import { CompilerOptions } from "../../src/CompilerOptions";
6+
7+
export class RequireTests {
8+
9+
@TestCase("file.ts", "./folder/Module", "folder.Module", { rootDir: "." }, false)
10+
@TestCase("src/file.ts", "./folder/Module", "src.folder.Module", { rootDir: "." }, false)
11+
@TestCase("file.ts", "folder/Module", "folder.Module", { rootDir: ".", baseUrl: "." }, false)
12+
@TestCase("src/file.ts", "./folder/Module", "folder.Module", { rootDir: "src" }, false)
13+
@TestCase("src/file.ts", "./folder/Module", "folder.Module", { rootDir: "./src" }, false)
14+
@TestCase("file.ts", "../Module", "", { rootDir: "./src" }, true)
15+
@TestCase("src/dir/file.ts", "../Module", "Module", { rootDir: "./src" }, false)
16+
@TestCase("src/dir/dir/file.ts", "../../dir/Module", "dir.Module", { rootDir: "./src" }, false)
17+
@Test("require paths root from --baseUrl or --rootDir")
18+
public testRequirePath(
19+
filePath: string,
20+
usedPath: string,
21+
expectedPath: string,
22+
options: CompilerOptions,
23+
throwsError: boolean): void {
24+
const regex = /require\("(.*?)"\)/; // This regex extracts `hello` from require("hello")
25+
options.rootDir = path.resolve(options.rootDir); // This happens automatically from the command line
26+
if (throwsError) {
27+
Expect(() => util.transpileString(`import * from "${usedPath}";`, options, true, filePath)).toThrow();
28+
} else {
29+
const lua = util.transpileString(`import * from "${usedPath}";`, options, true, filePath);
30+
const match = regex.exec(lua);
31+
Expect(match[1]).toBe(expectedPath);
32+
}
33+
}
34+
35+
}

0 commit comments

Comments
 (0)