Skip to content

Commit dbe2ed2

Browse files
committed
feat(node_modules) add fileExists and readFile to CompilerHost
1 parent a781916 commit dbe2ed2

File tree

6 files changed

+79
-23
lines changed

6 files changed

+79
-23
lines changed

src/compiler/program.ts

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,9 @@ module ts {
106106
getCurrentDirectory: () => currentDirectory || (currentDirectory = sys.getCurrentDirectory()),
107107
useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames,
108108
getCanonicalFileName,
109-
getNewLine: () => newLine
109+
getNewLine: () => newLine,
110+
readFile: sys.readFile,
111+
fileExists: sys.fileExists
110112
};
111113
}
112114

@@ -239,37 +241,34 @@ module ts {
239241
return emitResult;
240242
}
241243

242-
function resolveExternalModule(moduleName: string, searchPath: string): string {
243-
let cacheLookupName = moduleName + searchPath;
244+
function resolveExternalModule(moduleName: string, containingFile: string): string {
245+
let cacheLookupName = moduleName + containingFile;
244246
if (resolvedExternalModuleCache[cacheLookupName]) {
245247
return resolvedExternalModuleCache[cacheLookupName];
246248
}
247249
if (resolvedExternalModuleCache[cacheLookupName] === '') {
248250
return undefined;
249251
}
250252
function getNameIfExists(fileName: string): string {
251-
// To detect if file exists.
252-
// Using this is to demonstrate that sys.fileExists is what is causing module resolution to fail in test driver
253-
// This is just for code review
254-
if (host.getSourceFile(fileName, ScriptTarget.Latest)) {
253+
if (host.fileExists(fileName)) {
255254
return fileName;
256255
}
257256
}
258257
while (true) {
259258
// Look at files by all extensions
260259
let found = forEach(supportedExtensions,
261-
extension => getNameIfExists(normalizePath(combinePaths(searchPath, moduleName)) + extension));
260+
extension => getNameIfExists(normalizePath(combinePaths(containingFile, moduleName)) + extension));
262261
// Also look at all files by node_modules
263262
if (!found) {
264263
found = forEach(supportedExtensions,
265-
extension => getNameIfExists(normalizePath(combinePaths(combinePaths(searchPath, "node_modules"), moduleName)) + extension));
264+
extension => getNameIfExists(normalizePath(combinePaths(combinePaths(containingFile, "node_modules"), moduleName)) + extension));
266265
}
267266
// Also look at package.json's main in node_modules
268267
if (!found) {
269268
// If we found a package.json then look at its main field
270-
let pkgJson = getNameIfExists(normalizePath(combinePaths(combinePaths(combinePaths(searchPath, "node_modules"), moduleName), "package.json")));
269+
let pkgJson = getNameIfExists(normalizePath(combinePaths(combinePaths(combinePaths(containingFile, "node_modules"), moduleName), "package.json")));
271270
if (pkgJson) {
272-
let pkgFile = JSON.parse(sys.readFile(pkgJson));
271+
let pkgFile = JSON.parse(host.readFile(pkgJson));
273272
if (pkgFile.main) {
274273
var indexFileName = removeFileExtension(combinePaths(getDirectoryPath(pkgJson), pkgFile.main));
275274
found = forEach(supportedExtensions,
@@ -280,19 +279,19 @@ module ts {
280279
// look at node_modules index
281280
if (!found) {
282281
found = forEach(supportedExtensions,
283-
extension => getNameIfExists(normalizePath(combinePaths(combinePaths(combinePaths(searchPath, "node_modules"), moduleName), "index")) + extension));
282+
extension => getNameIfExists(normalizePath(combinePaths(combinePaths(combinePaths(containingFile, "node_modules"), moduleName), "index")) + extension));
284283
}
285284

286285
// Finally cache and return or continue up the directory tree
287286
if (found) {
288287
return resolvedExternalModuleCache[cacheLookupName] = found;
289288
}
290-
let parentPath = getDirectoryPath(searchPath);
291-
if (parentPath === searchPath) {
289+
let parentPath = getDirectoryPath(containingFile);
290+
if (parentPath === containingFile) {
292291
resolvedExternalModuleCache[cacheLookupName] = '';
293292
return undefined;
294293
}
295-
searchPath = parentPath;
294+
containingFile = parentPath;
296295
}
297296
}
298297

@@ -487,8 +486,8 @@ module ts {
487486
if (moduleNameExpr && moduleNameExpr.kind === SyntaxKind.StringLiteral) {
488487
let moduleNameText = (<LiteralExpression>moduleNameExpr).text;
489488
if (moduleNameText) {
490-
let resolvedName = resolveExternalModule(moduleNameText, getDirectoryPath(file.fileName));
491-
if (resolvedName) {
489+
let resolvedName = resolveExternalModule(moduleNameText, basePath);
490+
if (resolvedName) {
492491
findModuleSourceFile(resolvedName, moduleNameExpr);
493492
}
494493
}

src/compiler/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1881,6 +1881,8 @@ module ts {
18811881
getCanonicalFileName(fileName: string): string;
18821882
useCaseSensitiveFileNames(): boolean;
18831883
getNewLine(): string;
1884+
readFile(path: string): string;
1885+
fileExists(path: string): boolean;
18841886
}
18851887

18861888
export interface TextSpan {

src/harness/fourslash.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2230,6 +2230,8 @@ module FourSlash {
22302230
{
22312231
let host = Harness.Compiler.createCompilerHost([{ unitName: Harness.Compiler.fourslashFileName, content: undefined }],
22322232
(fn, contents) => fourslashJsOutput = contents,
2233+
(fn) => undefined,
2234+
(fn) => true,
22332235
ts.ScriptTarget.Latest,
22342236
ts.sys.useCaseSensitiveFileNames);
22352237

@@ -2252,6 +2254,8 @@ module FourSlash {
22522254
{ unitName: fileName, content: content }
22532255
],
22542256
(fn, contents) => result = contents,
2257+
(fn) => result,
2258+
(fn) => true,
22552259
ts.ScriptTarget.Latest,
22562260
ts.sys.useCaseSensitiveFileNames);
22572261

src/harness/harness.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,8 @@ module Harness {
822822

823823
export function createCompilerHost(inputFiles: { unitName: string; content: string; }[],
824824
writeFile: (fn: string, contents: string, writeByteOrderMark: boolean) => void,
825+
readFile: (fn: string) => string,
826+
fileExists: (fn: string) => boolean,
825827
scriptTarget: ts.ScriptTarget,
826828
useCaseSensitiveFileNames: boolean,
827829
// the currentDirectory is needed for rwcRunner to passed in specified current directory to compiler host
@@ -876,6 +878,8 @@ module Harness {
876878
},
877879
getDefaultLibFileName: options => defaultLibFileName,
878880
writeFile,
881+
readFile,
882+
fileExists,
879883
getCanonicalFileName,
880884
useCaseSensitiveFileNames: () => useCaseSensitiveFileNames,
881885
getNewLine: () => newLine
@@ -1121,8 +1125,16 @@ module Harness {
11211125
var fileOutputs: GeneratedFile[] = [];
11221126

11231127
var programFiles = inputFiles.concat(includeBuiltFiles).map(file => file.unitName);
1124-
var program = ts.createProgram(programFiles, options, createCompilerHost(inputFiles.concat(includeBuiltFiles).concat(otherFiles),
1128+
var compilerHostInputFiles = inputFiles.concat(includeBuiltFiles).concat(otherFiles);
1129+
var program = ts.createProgram(programFiles, options, createCompilerHost(compilerHostInputFiles,
11251130
(fn, contents, writeByteOrderMark) => fileOutputs.push({ fileName: fn, code: contents, writeByteOrderMark: writeByteOrderMark }),
1131+
(fn) => {
1132+
var found = compilerHostInputFiles.filter(f=>f.unitName === fn)[0];
1133+
return found ? found.content : undefined;
1134+
},
1135+
(fn) => {
1136+
return !!compilerHostInputFiles.some(f=> f.unitName === fn)
1137+
},
11261138
options.target, useCaseSensitiveFileNames, currentDirectory, options.newLine));
11271139

11281140
var emitResult = program.emit();

src/harness/projectsRunner.ts

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,10 @@ class ProjectRunner extends RunnerBase {
125125

126126
function compileProjectFiles(moduleKind: ts.ModuleKind, getInputFiles: ()=> string[],
127127
getSourceFileText: (fileName: string) => string,
128-
writeFile: (fileName: string, data: string, writeByteOrderMark: boolean) => void): CompileProjectFilesResult {
128+
writeFile: (fileName: string, data: string, writeByteOrderMark: boolean) => void,
129+
readFile: (fn: string) => string,
130+
fileExists: (fn: string) => boolean
131+
): CompileProjectFilesResult {
129132

130133
var program = ts.createProgram(getInputFiles(), createCompilerOptions(), createCompilerHost());
131134
var errors = ts.getPreEmitDiagnostics(program);
@@ -186,6 +189,8 @@ class ProjectRunner extends RunnerBase {
186189
getSourceFile,
187190
getDefaultLibFileName: options => Harness.Compiler.defaultLibFileName,
188191
writeFile,
192+
readFile,
193+
fileExists,
189194
getCurrentDirectory,
190195
getCanonicalFileName: Harness.Compiler.getCanonicalFileName,
191196
useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,
@@ -199,7 +204,7 @@ class ProjectRunner extends RunnerBase {
199204

200205
var outputFiles: BatchCompileProjectTestCaseEmittedFile[] = [];
201206

202-
var projectCompilerResult = compileProjectFiles(moduleKind, () => testCase.inputFiles, getSourceFileText, writeFile);
207+
var projectCompilerResult = compileProjectFiles(moduleKind, () => testCase.inputFiles, getSourceFileText, writeFile, readFile, fileExists);
203208
return {
204209
moduleKind,
205210
program: projectCompilerResult.program,
@@ -269,6 +274,22 @@ class ProjectRunner extends RunnerBase {
269274

270275
outputFiles.push({ emittedFileName: fileName, code: data, fileName: diskRelativeName, writeByteOrderMark: writeByteOrderMark });
271276
}
277+
278+
function getFullDiskFileName(fileName: string): string {
279+
return ts.isRootedDiskPath(fileName)
280+
? fileName
281+
: ts.normalizeSlashes(testCase.projectRoot) + "/" + ts.normalizeSlashes(fileName);
282+
}
283+
284+
function readFile(fileName: string) {
285+
fileName = getFullDiskFileName(fileName);
286+
return ts.sys.readFile(fileName);
287+
}
288+
289+
function fileExists(fileName: string) {
290+
fileName = getFullDiskFileName(fileName);
291+
return ts.sys.fileExists(fileName);
292+
}
272293
}
273294

274295
function compileCompileDTsFiles(compilerResult: BatchCompileProjectTestCaseResult) {
@@ -301,7 +322,7 @@ class ProjectRunner extends RunnerBase {
301322
}
302323
});
303324

304-
return compileProjectFiles(compilerResult.moduleKind,getInputFiles, getSourceFileText, writeFile);
325+
return compileProjectFiles(compilerResult.moduleKind,getInputFiles, getSourceFileText, writeFile, readFile, fileExists);
305326

306327
function findOutpuDtsFile(fileName: string) {
307328
return ts.forEach(compilerResult.outputFiles, outputFile => outputFile.emittedFileName === fileName ? outputFile : undefined);
@@ -315,6 +336,20 @@ class ProjectRunner extends RunnerBase {
315336

316337
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean) {
317338
}
339+
340+
function getFullDiskFileName(fileName: string): string {
341+
return ts.isRootedDiskPath(fileName)
342+
? fileName
343+
: ts.normalizeSlashes(getCurrentDirectory()) + "/" + ts.normalizeSlashes(fileName);
344+
}
345+
346+
function readFile(fileName: string) {
347+
return ts.sys.readFile(getFullDiskFileName(fileName));
348+
}
349+
350+
function fileExists(fileName: string) {
351+
return ts.forEach(allInputFiles, inputFile => inputFile.emittedFileName === fileName ? true : false);
352+
}
318353
}
319354

320355
function getErrorsBaseline(compilerResult: CompileProjectFilesResult) {

src/services/services.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1795,7 +1795,9 @@ module ts {
17951795
useCaseSensitiveFileNames: () => false,
17961796
getCanonicalFileName: fileName => fileName,
17971797
getCurrentDirectory: () => "",
1798-
getNewLine: () => (sys && sys.newLine) || "\r\n"
1798+
getNewLine: () => (sys && sys.newLine) || "\r\n",
1799+
readFile: sys.readFile,
1800+
fileExists: sys.fileExists
17991801
};
18001802

18011803
var program = createProgram([inputFileName], options, compilerHost);
@@ -2433,7 +2435,9 @@ module ts {
24332435
getNewLine: () => host.getNewLine ? host.getNewLine() : "\r\n",
24342436
getDefaultLibFileName: (options) => host.getDefaultLibFileName(options),
24352437
writeFile: (fileName, data, writeByteOrderMark) => { },
2436-
getCurrentDirectory: () => host.getCurrentDirectory()
2438+
readFile: (fileName) => sys.readFile(fileName),
2439+
fileExists: (fileName) => !!hostCache.getOrCreateEntry(fileName),
2440+
getCurrentDirectory: () => host.getCurrentDirectory(),
24372441
});
24382442

24392443
// Release any files we have acquired in the old program but are

0 commit comments

Comments
 (0)