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
52 changes: 52 additions & 0 deletions src/transpilation/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,16 @@ class ResolutionContext {
const fileFromPath = this.getFileFromPath(resolvedPath);
if (fileFromPath) return fileFromPath;

if (this.options.paths && this.options.baseUrl) {
// If no file found yet and paths are present, try to find project file via paths mappings
const fileFromPaths = this.tryGetModuleNameFromPaths(
dependencyPath,
this.options.paths,
this.options.baseUrl
);
if (fileFromPaths) return fileFromPaths;
}

// Not a TS file in our project sources, use resolver to check if we can find dependency
try {
const resolveResult = resolver.resolveSync({}, fileDirectory, dependencyPath);
Expand Down Expand Up @@ -222,6 +232,40 @@ class ResolutionContext {
}
}
}

// Taken from TS and modified: https://github.com/microsoft/TypeScript/blob/88a1e3a1dd8d2d86e844ff1c16d5f041cebcfdb9/src/compiler/moduleSpecifiers.ts#L562
private tryGetModuleNameFromPaths(relativeToBaseUrl: string, paths: ts.MapLike<string[]>, baseUrl: string) {
const relativeImport = removeTrailingDirectorySeparator(normalizeSlashes(relativeToBaseUrl));
for (const [importPattern, targetPatterns] of Object.entries(paths)) {
const pattern = removeFileExtension(normalizeSlashes(importPattern));
const indexOfStar = pattern.indexOf("*");
if (indexOfStar !== -1) {
// Try to match <prefix>*<suffix> to relativeImport
const prefix = pattern.substring(0, indexOfStar);
const suffix = pattern.substring(indexOfStar + 1);
if (
(relativeImport.length >= prefix.length + suffix.length &&
relativeImport.startsWith(prefix) &&
relativeImport.endsWith(suffix)) ||
(!suffix && relativeImport === removeTrailingDirectorySeparator(prefix))
) {
// If import matches <prefix>*<suffix>, extract the matched * path
const matchedStar = relativeImport.substring(prefix.length, relativeImport.length - suffix.length);
// Try to resolve to the target patterns with filled in * pattern
for (const target of targetPatterns) {
const file = this.getFileFromPath(path.join(baseUrl, target.replace("*", matchedStar)));
if (file) return file;
}
}
} else if (pattern === relativeImport) {
// If there is no * pattern, check for exact matches and try those targets
for (const target of targetPatterns) {
const file = this.getFileFromPath(path.join(baseUrl, target));
if (file) return file;
}
}
}
}
}

export function resolveDependencies(program: ts.Program, files: ProcessedFile[], emitHost: EmitHost): ResolutionResult {
Expand Down Expand Up @@ -340,3 +384,11 @@ function fallbackResolve(required: string, sourceRootDir: string, fileDir: strin
function luaRequireToPath(requirePath: string): string {
return requirePath.replace(/\./g, path.sep);
}

function removeFileExtension(path: string) {
return path.includes(".") ? trimExtension(path) : path;
}

function removeTrailingDirectorySeparator(path: string) {
return path.endsWith("/") || path.endsWith("\\") ? path.substring(0, -1) : path;
}
17 changes: 17 additions & 0 deletions test/transpile/__snapshots__/module-resolution.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`supports complicated paths configuration 1`] = `
Array [
"/monorepo-complicated/dist/packages/tstl-program/packages/mypackage/src/bar.lua",
"/monorepo-complicated/dist/packages/tstl-program/packages/mypackage/src/index.lua",
"/monorepo-complicated/dist/packages/tstl-program/packages/myprogram/src/main.lua",
]
`;

exports[`supports paths configuration 1`] = `
Array [
"/monorepo-with-paths/myprogram/dist/mypackage/bar.lua",
"/monorepo-with-paths/myprogram/dist/mypackage/index.lua",
"/monorepo-with-paths/myprogram/dist/myprogram/main.lua",
]
`;
58 changes: 55 additions & 3 deletions test/transpile/module-resolution.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import * as path from "path";
import * as tstl from "../../src";
import * as util from "../util";
import * as ts from "typescript";
import { BuildMode, transpileProject } from "../../src";
import { BuildMode } from "../../src";
import { normalizeSlashes } from "../../src/utils";

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

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

const expectedResult = {
dependency1IndexResult: "function in dependency 1 index: dependency1OtherFileFunc in dependency1/d1otherfile",
Expand Down Expand Up @@ -538,3 +539,54 @@ test("lualib_module with parent directory import (#1307)", () => {
FEATURE_CONSTANT: 456,
});
});

test("supports paths configuration", () => {
// Package root
const baseProjectPath = path.resolve(__dirname, "module-resolution", "monorepo-with-paths");
// myprogram package
const projectPath = path.join(baseProjectPath, "myprogram");
const projectTsConfig = path.join(projectPath, "tsconfig.json");
const mainFile = path.join(projectPath, "main.ts");

const luaResult = util
.testProject(projectTsConfig)
.setMainFileName(mainFile)
.expectToHaveNoDiagnostics()
.getLuaResult();

expect(snapshotPaths(luaResult.transpiledFiles)).toMatchSnapshot();

// Bundle to have all files required to execute and check result
util.testProject(projectTsConfig)
.setMainFileName(mainFile)
.setOptions({ luaBundle: "bundle.lua", luaBundleEntry: mainFile })
.expectToEqual({ foo: 314, bar: 271 });
});

test("supports complicated paths configuration", () => {
// Package root
const baseProjectPath = path.resolve(__dirname, "module-resolution", "monorepo-complicated");
// myprogram package
const projectPath = path.join(baseProjectPath, "packages", "myprogram");
const projectTsConfig = path.join(projectPath, "tsconfig.json");
const mainFile = path.join(projectPath, "src", "main.ts");

const luaResult = util
.testProject(projectTsConfig)
.setMainFileName(mainFile)
.expectToHaveNoDiagnostics()
.getLuaResult();

expect(snapshotPaths(luaResult.transpiledFiles)).toMatchSnapshot();

// Bundle to have all files required to execute
util.testProject(projectTsConfig)
.setMainFileName(mainFile)
.setOptions({ luaBundle: "bundle.lua", luaBundleEntry: mainFile })
.debug()
.expectToEqual({ foo: 314, bar: 271 });
});

function snapshotPaths(files: tstl.TranspiledFile[]) {
return files.map(f => normalizeSlashes(f.outPath).split("module-resolution")[1]).sort();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const bar = 271;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const foo = 314;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "../../dist/packages/tstl-module"
},
"include": ["./src/**/*.ts"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { foo } from "mypackage";
import { bar } from "mypackage/bar";

export { foo, bar };
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "../../dist/packages/tstl-program"
},
"include": ["./src/**/*.ts"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"compilerOptions": {
"rootDir": ".",
"baseUrl": ".",
"paths": {
"mypackage": ["packages/mypackage/src/index.ts"],
"mypackage/*": ["packages/mypackage/src/*"]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const bar = 271;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const foo = 314;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { foo } from "mypackage";
import { bar } from "mypackage/bar";

export { foo, bar };
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"compilerOptions": {
"baseUrl": "..",
"outDir": "dist",
"paths": {
"mypackage": ["mypackage"]
}
}
}