JS: Resolve relative imports across real and virtual source roots

This commit is contained in:
Asger Feldthaus
2020-06-26 22:54:44 +01:00
parent d3b9ebe1d2
commit da58fb5e62
2 changed files with 25 additions and 13 deletions

View File

@@ -71,10 +71,19 @@ export class Project {
redirectedReference: ts.ResolvedProjectReference,
options: ts.CompilerOptions) {
let oppositePath =
this.virtualSourceRoot.toVirtualPath(containingFile) ||
this.virtualSourceRoot.fromVirtualPath(containingFile);
const { host, resolutionCache } = this;
return moduleNames.map((moduleName) => {
let redirected = this.redirectModuleName(moduleName, containingFile, options);
if (redirected != null) return redirected;
if (oppositePath != null) {
// If the containing file is in the virtual source root, try resolving from the real source root, and vice versa.
redirected = ts.resolveModuleName(moduleName, oppositePath, options, host, resolutionCache).resolvedModule;
if (redirected != null) return redirected;
}
return ts.resolveModuleName(moduleName, containingFile, options, host, resolutionCache).resolvedModule;
});
}
@@ -90,15 +99,7 @@ export class Project {
// Get the overridden location of this package, if one exists.
let packageEntryPoint = this.packageEntryPoints.get(packageName);
if (packageEntryPoint == null) {
// The package is not overridden, but we have established that it begins with a valid package name.
// Do a lookup in the virtual source root (where dependencies are installed) by changing the 'containing file'.
let virtualContainingFile = this.virtualSourceRoot.toVirtualPath(containingFile);
if (virtualContainingFile != null) {
return ts.resolveModuleName(moduleName, virtualContainingFile, options, this.host, this.resolutionCache).resolvedModule;
}
return null;
}
if (packageEntryPoint == null) return null;
// If the requested module name is exactly the overridden package name,
// return the entry point file (it is not necessarily called `index.ts`).

View File

@@ -16,14 +16,25 @@ export class VirtualSourceRoot {
private virtualSourceRoot: string | null,
) {}
private static translate(oldRoot: string, newRoot: string, path: string) {
if (!oldRoot || !newRoot) return null;
let relative = pathlib.relative(oldRoot, path);
if (relative.startsWith('..') || pathlib.isAbsolute(relative)) return null;
return pathlib.join(newRoot, relative);
}
/**
* Maps a path under the real source root to the corresponding path in the virtual source root.
*/
public toVirtualPath(path: string) {
if (!this.virtualSourceRoot || !this.sourceRoot) return null;
let relative = pathlib.relative(this.sourceRoot, path);
if (relative.startsWith('..') || pathlib.isAbsolute(relative)) return null;
return pathlib.join(this.virtualSourceRoot, relative);
return VirtualSourceRoot.translate(this.sourceRoot, this.virtualSourceRoot, path);
}
/**
* Maps a path under the virtual source root to the corresponding path in the real source root.
*/
public fromVirtualPath(path: string) {
return VirtualSourceRoot.translate(this.virtualSourceRoot, this.sourceRoot, path);
}
/**