Skip to content

Commit 82f4f8b

Browse files
authored
Support for tsconfig.json paths (#1319)
* module resolution with paths tests * paths support
1 parent a4f2666 commit 82f4f8b

File tree

14 files changed

+170
-3
lines changed

14 files changed

+170
-3
lines changed

src/transpilation/resolve.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,16 @@ class ResolutionContext {
147147
const fileFromPath = this.getFileFromPath(resolvedPath);
148148
if (fileFromPath) return fileFromPath;
149149

150+
if (this.options.paths && this.options.baseUrl) {
151+
// If no file found yet and paths are present, try to find project file via paths mappings
152+
const fileFromPaths = this.tryGetModuleNameFromPaths(
153+
dependencyPath,
154+
this.options.paths,
155+
this.options.baseUrl
156+
);
157+
if (fileFromPaths) return fileFromPaths;
158+
}
159+
150160
// Not a TS file in our project sources, use resolver to check if we can find dependency
151161
try {
152162
const resolveResult = resolver.resolveSync({}, fileDirectory, dependencyPath);
@@ -222,6 +232,40 @@ class ResolutionContext {
222232
}
223233
}
224234
}
235+
236+
// Taken from TS and modified: https://github.com/microsoft/TypeScript/blob/88a1e3a1dd8d2d86e844ff1c16d5f041cebcfdb9/src/compiler/moduleSpecifiers.ts#L562
237+
private tryGetModuleNameFromPaths(relativeToBaseUrl: string, paths: ts.MapLike<string[]>, baseUrl: string) {
238+
const relativeImport = removeTrailingDirectorySeparator(normalizeSlashes(relativeToBaseUrl));
239+
for (const [importPattern, targetPatterns] of Object.entries(paths)) {
240+
const pattern = removeFileExtension(normalizeSlashes(importPattern));
241+
const indexOfStar = pattern.indexOf("*");
242+
if (indexOfStar !== -1) {
243+
// Try to match <prefix>*<suffix> to relativeImport
244+
const prefix = pattern.substring(0, indexOfStar);
245+
const suffix = pattern.substring(indexOfStar + 1);
246+
if (
247+
(relativeImport.length >= prefix.length + suffix.length &&
248+
relativeImport.startsWith(prefix) &&
249+
relativeImport.endsWith(suffix)) ||
250+
(!suffix && relativeImport === removeTrailingDirectorySeparator(prefix))
251+
) {
252+
// If import matches <prefix>*<suffix>, extract the matched * path
253+
const matchedStar = relativeImport.substring(prefix.length, relativeImport.length - suffix.length);
254+
// Try to resolve to the target patterns with filled in * pattern
255+
for (const target of targetPatterns) {
256+
const file = this.getFileFromPath(path.join(baseUrl, target.replace("*", matchedStar)));
257+
if (file) return file;
258+
}
259+
}
260+
} else if (pattern === relativeImport) {
261+
// If there is no * pattern, check for exact matches and try those targets
262+
for (const target of targetPatterns) {
263+
const file = this.getFileFromPath(path.join(baseUrl, target));
264+
if (file) return file;
265+
}
266+
}
267+
}
268+
}
225269
}
226270

227271
export function resolveDependencies(program: ts.Program, files: ProcessedFile[], emitHost: EmitHost): ResolutionResult {
@@ -340,3 +384,11 @@ function fallbackResolve(required: string, sourceRootDir: string, fileDir: strin
340384
function luaRequireToPath(requirePath: string): string {
341385
return requirePath.replace(/\./g, path.sep);
342386
}
387+
388+
function removeFileExtension(path: string) {
389+
return path.includes(".") ? trimExtension(path) : path;
390+
}
391+
392+
function removeTrailingDirectorySeparator(path: string) {
393+
return path.endsWith("/") || path.endsWith("\\") ? path.substring(0, -1) : path;
394+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`supports complicated paths configuration 1`] = `
4+
Array [
5+
"/monorepo-complicated/dist/packages/tstl-program/packages/mypackage/src/bar.lua",
6+
"/monorepo-complicated/dist/packages/tstl-program/packages/mypackage/src/index.lua",
7+
"/monorepo-complicated/dist/packages/tstl-program/packages/myprogram/src/main.lua",
8+
]
9+
`;
10+
11+
exports[`supports paths configuration 1`] = `
12+
Array [
13+
"/monorepo-with-paths/myprogram/dist/mypackage/bar.lua",
14+
"/monorepo-with-paths/myprogram/dist/mypackage/index.lua",
15+
"/monorepo-with-paths/myprogram/dist/myprogram/main.lua",
16+
]
17+
`;

test/transpile/module-resolution.spec.ts

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import * as path from "path";
22
import * as tstl from "../../src";
33
import * as util from "../util";
44
import * as ts from "typescript";
5-
import { BuildMode, transpileProject } from "../../src";
5+
import { BuildMode } from "../../src";
6+
import { normalizeSlashes } from "../../src/utils";
67

78
describe("basic module resolution", () => {
89
const projectPath = path.resolve(__dirname, "module-resolution", "project-with-node-modules");
@@ -236,8 +237,8 @@ describe("module resolution project with dependencies built by tstl library mode
236237
const projectPath = path.resolve(__dirname, "module-resolution", "project-with-tstl-library-modules");
237238

238239
// First compile dependencies into node_modules. NOTE: Actually writing to disk, very slow
239-
transpileProject(path.join(projectPath, "dependency1-ts", "tsconfig.json"));
240-
transpileProject(path.join(projectPath, "dependency2-ts", "tsconfig.json"));
240+
tstl.transpileProject(path.join(projectPath, "dependency1-ts", "tsconfig.json"));
241+
tstl.transpileProject(path.join(projectPath, "dependency2-ts", "tsconfig.json"));
241242

242243
const expectedResult = {
243244
dependency1IndexResult: "function in dependency 1 index: dependency1OtherFileFunc in dependency1/d1otherfile",
@@ -538,3 +539,54 @@ test("lualib_module with parent directory import (#1307)", () => {
538539
FEATURE_CONSTANT: 456,
539540
});
540541
});
542+
543+
test("supports paths configuration", () => {
544+
// Package root
545+
const baseProjectPath = path.resolve(__dirname, "module-resolution", "monorepo-with-paths");
546+
// myprogram package
547+
const projectPath = path.join(baseProjectPath, "myprogram");
548+
const projectTsConfig = path.join(projectPath, "tsconfig.json");
549+
const mainFile = path.join(projectPath, "main.ts");
550+
551+
const luaResult = util
552+
.testProject(projectTsConfig)
553+
.setMainFileName(mainFile)
554+
.expectToHaveNoDiagnostics()
555+
.getLuaResult();
556+
557+
expect(snapshotPaths(luaResult.transpiledFiles)).toMatchSnapshot();
558+
559+
// Bundle to have all files required to execute and check result
560+
util.testProject(projectTsConfig)
561+
.setMainFileName(mainFile)
562+
.setOptions({ luaBundle: "bundle.lua", luaBundleEntry: mainFile })
563+
.expectToEqual({ foo: 314, bar: 271 });
564+
});
565+
566+
test("supports complicated paths configuration", () => {
567+
// Package root
568+
const baseProjectPath = path.resolve(__dirname, "module-resolution", "monorepo-complicated");
569+
// myprogram package
570+
const projectPath = path.join(baseProjectPath, "packages", "myprogram");
571+
const projectTsConfig = path.join(projectPath, "tsconfig.json");
572+
const mainFile = path.join(projectPath, "src", "main.ts");
573+
574+
const luaResult = util
575+
.testProject(projectTsConfig)
576+
.setMainFileName(mainFile)
577+
.expectToHaveNoDiagnostics()
578+
.getLuaResult();
579+
580+
expect(snapshotPaths(luaResult.transpiledFiles)).toMatchSnapshot();
581+
582+
// Bundle to have all files required to execute
583+
util.testProject(projectTsConfig)
584+
.setMainFileName(mainFile)
585+
.setOptions({ luaBundle: "bundle.lua", luaBundleEntry: mainFile })
586+
.debug()
587+
.expectToEqual({ foo: 314, bar: 271 });
588+
});
589+
590+
function snapshotPaths(files: tstl.TranspiledFile[]) {
591+
return files.map(f => normalizeSlashes(f.outPath).split("module-resolution")[1]).sort();
592+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const bar = 271;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const foo = 314;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"extends": "../../tsconfig.base.json",
3+
"compilerOptions": {
4+
"outDir": "../../dist/packages/tstl-module"
5+
},
6+
"include": ["./src/**/*.ts"]
7+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { foo } from "mypackage";
2+
import { bar } from "mypackage/bar";
3+
4+
export { foo, bar };
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"extends": "../../tsconfig.base.json",
3+
"compilerOptions": {
4+
"outDir": "../../dist/packages/tstl-program"
5+
},
6+
"include": ["./src/**/*.ts"]
7+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"compilerOptions": {
3+
"rootDir": ".",
4+
"baseUrl": ".",
5+
"paths": {
6+
"mypackage": ["packages/mypackage/src/index.ts"],
7+
"mypackage/*": ["packages/mypackage/src/*"]
8+
}
9+
}
10+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const bar = 271;

0 commit comments

Comments
 (0)