use CompilerHost.realpath to resolve actual location for symlinks

This commit is contained in:
Vladimir Matveev
2016-05-05 13:38:09 -07:00
parent 166f95c677
commit 2b5bbfee60
12 changed files with 230 additions and 28 deletions
+4
View File
@@ -2752,6 +2752,10 @@
"category": "Error",
"code": 6129
},
"Resolving real path for '{0}', result '{1}'": {
"category": "Message",
"code": 6130
},
"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",
"code": 7005
+21 -12
View File
@@ -570,22 +570,29 @@ namespace ts {
let resolvedFileName = tryLoadModuleUsingOptionalResolutionSettings(moduleName, containingDirectory, nodeLoadModuleByRelativeName,
failedLookupLocations, supportedExtensions, state);
if (resolvedFileName) {
return createResolvedModule(resolvedFileName, /*isExternalLibraryImport*/false, failedLookupLocations);
let isExternalLibraryImport = false;
if (!resolvedFileName) {
if (moduleHasNonRelativeName(moduleName)) {
if (traceEnabled) {
trace(host, Diagnostics.Loading_module_0_from_node_modules_folder, moduleName);
}
resolvedFileName = loadModuleFromNodeModules(moduleName, containingDirectory, failedLookupLocations, state);
isExternalLibraryImport = resolvedFileName !== undefined;
}
else {
const candidate = normalizePath(combinePaths(containingDirectory, moduleName));
resolvedFileName = nodeLoadModuleByRelativeName(candidate, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state);
}
}
let isExternalLibraryImport = false;
if (moduleHasNonRelativeName(moduleName)) {
if (resolvedFileName && host.realpath) {
const originalFileName = resolvedFileName;
resolvedFileName = normalizePath(host.realpath(resolvedFileName));
if (traceEnabled) {
trace(host, Diagnostics.Loading_module_0_from_node_modules_folder, moduleName);
trace(host, Diagnostics.Resolving_real_path_for_0_result_1, originalFileName, resolvedFileName);
}
resolvedFileName = loadModuleFromNodeModules(moduleName, containingDirectory, failedLookupLocations, state);
isExternalLibraryImport = resolvedFileName !== undefined;
}
else {
const candidate = normalizePath(combinePaths(containingDirectory, moduleName));
resolvedFileName = nodeLoadModuleByRelativeName(candidate, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state);
}
return createResolvedModule(resolvedFileName, isExternalLibraryImport, failedLookupLocations);
}
@@ -873,6 +880,7 @@ namespace ts {
}
const newLine = getNewLineCharacter(options);
const realpath = sys.realpath && ((path: string) => sys.realpath(path));
return {
getSourceFile,
@@ -886,7 +894,8 @@ namespace ts {
fileExists: fileName => sys.fileExists(fileName),
readFile: fileName => sys.readFile(fileName),
trace: (s: string) => sys.write(s + newLine),
directoryExists: directoryName => sys.directoryExists(directoryName)
directoryExists: directoryName => sys.directoryExists(directoryName),
realpath
};
}
+7 -1
View File
@@ -29,6 +29,7 @@ namespace ts {
createHash?(data: string): string;
getMemoryUsage?(): number;
exit(exitCode?: number): void;
realpath?(path: string): string;
}
export interface FileWatcher {
@@ -73,6 +74,7 @@ namespace ts {
readDirectory(path: string, extension?: string, exclude?: string[]): string[];
watchFile?(path: string, callback: FileWatcherCallback): FileWatcher;
watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
realpath(path: string): string;
};
export var sys: System = (function () {
@@ -527,12 +529,15 @@ namespace ts {
},
exit(exitCode?: number): void {
process.exit(exitCode);
},
realpath(path: string): string {
return _fs.realpathSync(path);
}
};
}
function getChakraSystem(): System {
const realpath = ChakraHost.realpath && ((path: string) => ChakraHost.realpath(path));
return {
newLine: ChakraHost.newLine || "\r\n",
args: ChakraHost.args,
@@ -558,6 +563,7 @@ namespace ts {
getCurrentDirectory: () => ChakraHost.currentDirectory,
readDirectory: ChakraHost.readDirectory,
exit: ChakraHost.quit,
realpath
};
}
+1
View File
@@ -2779,6 +2779,7 @@ namespace ts {
readFile(fileName: string): string;
trace?(s: string): void;
directoryExists?(directoryName: string): boolean;
realpath?(path: string): string;
}
export interface ResolvedModule {
+3 -3
View File
@@ -89,16 +89,16 @@ class CompilerBaselineRunner extends RunnerBase {
otherFiles = [];
if (testCaseContent.settings["noImplicitReferences"] || /require\(/.test(lastUnit.content) || /reference\spath/.test(lastUnit.content)) {
toBeCompiled.push({ unitName: this.makeUnitName(lastUnit.name, rootDir), content: lastUnit.content });
toBeCompiled.push({ unitName: this.makeUnitName(lastUnit.name, rootDir), content: lastUnit.content, fileOptions: lastUnit.fileOptions });
units.forEach(unit => {
if (unit.name !== lastUnit.name) {
otherFiles.push({ unitName: this.makeUnitName(unit.name, rootDir), content: unit.content });
otherFiles.push({ unitName: this.makeUnitName(unit.name, rootDir), content: unit.content, fileOptions: unit.fileOptions });
}
});
}
else {
toBeCompiled = units.map(unit => {
return { unitName: this.makeUnitName(unit.name, rootDir), content: unit.content };
return { unitName: this.makeUnitName(unit.name, rootDir), content: unit.content, fileOptions: unit.fileOptions };
});
}
+27 -12
View File
@@ -855,13 +855,23 @@ namespace Harness {
// Local get canonical file name function, that depends on passed in parameter for useCaseSensitiveFileNames
const getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames);
const fileMap: ts.FileMap<ts.SourceFile> = ts.createFileMap<ts.SourceFile>();
let realPathMap: ts.FileMap<string>;
const fileMap: ts.FileMap<() => ts.SourceFile> = ts.createFileMap<() => ts.SourceFile>();
for (const file of inputFiles) {
if (file.content !== undefined) {
const fileName = ts.normalizePath(file.unitName);
const sourceFile = createSourceFileAndAssertInvariants(fileName, file.content, scriptTarget);
const path = ts.toPath(file.unitName, currentDirectory, getCanonicalFileName);
fileMap.set(path, sourceFile);
if (file.fileOptions && file.fileOptions["symlink"]) {
const link = file.fileOptions["symlink"];
const linkPath = ts.toPath(link, currentDirectory, getCanonicalFileName);
if (!realPathMap) {
realPathMap = ts.createFileMap<string>();
}
realPathMap.set(linkPath, fileName);
fileMap.set(path, (): ts.SourceFile => { throw new Error("Symlinks should always be resolved to a realpath first"); });
}
const sourceFile = createSourceFileAndAssertInvariants(fileName, file.content, scriptTarget);
fileMap.set(path, ts.memoize(() => sourceFile));
}
}
@@ -869,7 +879,7 @@ namespace Harness {
fileName = ts.normalizePath(fileName);
const path = ts.toPath(fileName, currentDirectory, getCanonicalFileName);
if (fileMap.contains(path)) {
return fileMap.get(path);
return fileMap.get(path)();
}
else if (fileName === fourslashFileName) {
const tsFn = "tests/cases/fourslash/" + fourslashFileName;
@@ -898,11 +908,16 @@ namespace Harness {
useCaseSensitiveFileNames: () => useCaseSensitiveFileNames,
getNewLine: () => newLine,
fileExists: fileName => {
return fileMap.contains(ts.toPath(fileName, currentDirectory, getCanonicalFileName));
const path = ts.toPath(fileName, currentDirectory, getCanonicalFileName);
return fileMap.contains(path) || (realPathMap && realPathMap.contains(path));
},
readFile: (fileName: string): string => {
return fileMap.get(ts.toPath(fileName, currentDirectory, getCanonicalFileName)).getText();
}
return fileMap.get(ts.toPath(fileName, currentDirectory, getCanonicalFileName))().getText();
},
realpath: realPathMap && ((f: string) => {
const path = ts.toPath(f, currentDirectory, getCanonicalFileName);
return realPathMap.contains(path) ? realPathMap.get(path) : path;
})
};
}
@@ -923,7 +938,8 @@ namespace Harness {
{ name: "libFiles", type: "string" },
{ name: "noErrorTruncation", type: "boolean" },
{ name: "suppressOutputPathCheck", type: "boolean" },
{ name: "noImplicitReferences", type: "boolean" }
{ name: "noImplicitReferences", type: "boolean" },
{ name: "symlink", type: "string" }
];
let optionsIndex: ts.Map<ts.CommandLineOption>;
@@ -978,6 +994,7 @@ namespace Harness {
export interface TestFile {
unitName: string;
content: string;
fileOptions?: any;
}
export interface CompilationOutput {
@@ -1415,10 +1432,8 @@ namespace Harness {
// Comment line, check for global/file @options and record them
optionRegex.lastIndex = 0;
const metaDataName = testMetaData[1].toLowerCase();
if (metaDataName === "filename") {
currentFileOptions[testMetaData[1]] = testMetaData[2];
}
else {
currentFileOptions[testMetaData[1]] = testMetaData[2];
if (metaDataName !== "filename") {
continue;
}
+4
View File
@@ -431,11 +431,15 @@ namespace ts {
export class CoreServicesShimHostAdapter implements ParseConfigHost, ModuleResolutionHost {
public directoryExists: (directoryName: string) => boolean;
public realpath: (path: string) => string;
constructor(private shimHost: CoreServicesShimHost) {
if ("directoryExists" in this.shimHost) {
this.directoryExists = directoryName => this.shimHost.directoryExists(directoryName);
}
if ("realpath" in this.shimHost) {
this.realpath = path => this.shimHost.realpath(path);
}
}
public readDirectory(rootDir: string, extension: string, exclude: string[], depth?: number): string[] {