diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 4f1210793bf..ac2b88fbe93 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -752,7 +752,7 @@ namespace ts { } } - export function parseCommandLine(commandLine: string[], readFile?: (path: string) => string): ParsedCommandLine { + export function parseCommandLine(commandLine: string[], readFile?: (path: string) => string | undefined): ParsedCommandLine { const options: CompilerOptions = {}; const fileNames: string[] = []; const errors: Diagnostic[] = []; @@ -878,15 +878,9 @@ namespace ts { * Read tsconfig.json file * @param fileName The path to the config file */ - export function readConfigFile(fileName: string, readFile: (path: string) => string): { config?: any; error?: Diagnostic } { - let text = ""; - try { - text = readFile(fileName); - } - catch (e) { - return { config: {}, error: createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message) }; - } - return parseConfigFileTextToJson(fileName, text); + export function readConfigFile(fileName: string, readFile: (path: string) => string | undefined): { config?: any; error?: Diagnostic } { + const textOrDiagnostic = tryReadFile(fileName, readFile); + return typeof textOrDiagnostic === "string" ? parseConfigFileTextToJson(fileName, textOrDiagnostic) : { config: {}, error: textOrDiagnostic }; } /** @@ -906,15 +900,20 @@ namespace ts { * Read tsconfig.json file * @param fileName The path to the config file */ - export function readJsonConfigFile(fileName: string, readFile: (path: string) => string): JsonSourceFile { - let text = ""; + export function readJsonConfigFile(fileName: string, readFile: (path: string) => string | undefined): JsonSourceFile { + const textOrDiagnostic = tryReadFile(fileName, readFile); + return typeof textOrDiagnostic === "string" ? parseJsonText(fileName, textOrDiagnostic) : { parseDiagnostics: [textOrDiagnostic] }; + } + + function tryReadFile(fileName: string, readFile: (path: string) => string | undefined): string | Diagnostic { + let text: string | undefined; try { text = readFile(fileName); } catch (e) { - return { parseDiagnostics: [createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message)] }; + return createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message); } - return parseJsonText(fileName, text); + return text === undefined ? createCompilerDiagnostic(Diagnostics.The_specified_path_does_not_exist_Colon_0, fileName) : text; } function commandLineOptionsToMap(options: CommandLineOption[]) { diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 3e3ff90c00c..62ce272e96c 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -23,7 +23,7 @@ namespace ts { newLine: string; useCaseSensitiveFileNames: boolean; write(s: string): void; - readFile(path: string, encoding?: string): string; + readFile(path: string, encoding?: string): string | undefined; getFileSize?(path: string): number; writeFile(path: string, data: string, writeByteOrderMark?: boolean): void; /** @@ -97,7 +97,7 @@ namespace ts { directoryExists(path: string): boolean; createDirectory(path: string): void; resolvePath(path: string): string; - readFile(path: string): string; + readFile(path: string): string | undefined; writeFile(path: string, contents: string): void; getDirectories(path: string): string[]; readDirectory(path: string, extensions?: ReadonlyArray, basePaths?: ReadonlyArray, excludeEx?: string, includeFileEx?: string, includeDirEx?: string): string[]; @@ -204,7 +204,7 @@ namespace ts { const platform: string = _os.platform(); const useCaseSensitiveFileNames = isFileSystemCaseSensitive(); - function readFile(fileName: string, _encoding?: string): string { + function readFile(fileName: string, _encoding?: string): string | undefined { if (!fileExists(fileName)) { return undefined; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 6ba1591d54f..e252f9c3207 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2349,7 +2349,7 @@ namespace ts { */ fileExists(path: string): boolean; - readFile(path: string): string; + readFile(path: string): string | undefined; } export interface WriteFileCallback { @@ -3856,7 +3856,7 @@ namespace ts { fileExists(fileName: string): boolean; // readFile function is used to read arbitrary text files on disk, i.e. when resolution procedure needs the content of 'package.json' // to determine location of bundled typings for node module - readFile(fileName: string): string; + readFile(fileName: string): string | undefined; trace?(s: string): void; directoryExists?(directoryName: string): boolean; realpath?(path: string): string; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 591baaab706..b7fabdda381 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3925,7 +3925,7 @@ namespace ts { */ export function validateLocaleAndSetLanguage( locale: string, - sys: { getExecutingFilePath(): string, resolvePath(path: string): string, fileExists(fileName: string): boolean, readFile(fileName: string): string }, + sys: { getExecutingFilePath(): string, resolvePath(path: string): string, fileExists(fileName: string): boolean, readFile(fileName: string): string | undefined }, errors?: Diagnostic[]) { const matchResult = /^([a-z]+)([_\-]([a-z]+))?$/.exec(locale.toLowerCase()); diff --git a/src/harness/harness.ts b/src/harness/harness.ts index d5218695f09..55a8f3ebb4d 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -479,7 +479,7 @@ namespace Harness { getCurrentDirectory(): string; useCaseSensitiveFileNames(): boolean; resolvePath(path: string): string; - readFile(path: string): string; + readFile(path: string): string | undefined; writeFile(path: string, contents: string): void; directoryName(path: string): string; getDirectories(path: string): string[]; @@ -719,7 +719,7 @@ namespace Harness { } }); - export function readFile(file: string) { + export function readFile(file: string): string | undefined { const response = Http.getFileFromServerSync(serverRoot + file); if (response.status === 200) { return response.responseText; @@ -976,7 +976,7 @@ namespace Harness { useCaseSensitiveFileNames: () => useCaseSensitiveFileNames, getNewLine: () => newLine, fileExists: fileName => fileMap.has(toPath(fileName)), - readFile: (fileName: string): string => { + readFile(fileName: string): string | undefined { const file = fileMap.get(toPath(fileName)); if (ts.endsWith(fileName, "json")) { // strip comments diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 339138ba30f..156a9e08dce 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -215,7 +215,7 @@ namespace Harness.LanguageService { depth, (p) => this.virtualFileSystem.getAccessibleFileSystemEntries(p)); } - readFile(path: string): string { + readFile(path: string): string | undefined { const snapshot = this.getScriptSnapshot(path); return snapshot.getText(0, snapshot.getLength()); } @@ -619,7 +619,7 @@ namespace Harness.LanguageService { this.writeMessage(message); } - readFile(fileName: string): string { + readFile(fileName: string): string | undefined { if (fileName.indexOf(Harness.Compiler.defaultLibFileName) >= 0) { fileName = Harness.Compiler.defaultLibFileName; } diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index 46c2b42f6a0..7344c432b97 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -289,7 +289,7 @@ class ProjectRunner extends RunnerBase { return Harness.IO.fileExists(getFileNameInTheProjectTest(fileName)); } - function readFile(fileName: string): string { + function readFile(fileName: string): string | undefined { return Harness.IO.readFile(getFileNameInTheProjectTest(fileName)); } diff --git a/src/harness/unittests/moduleResolution.ts b/src/harness/unittests/moduleResolution.ts index 3923e4b2755..ffae1b5f4a9 100644 --- a/src/harness/unittests/moduleResolution.ts +++ b/src/harness/unittests/moduleResolution.ts @@ -56,7 +56,7 @@ namespace ts { else { return { readFile, fileExists: path => map.has(path) }; } - function readFile(path: string): string { + function readFile(path: string): string | undefined { const file = map.get(path); return file && file.content; } diff --git a/src/harness/unittests/session.ts b/src/harness/unittests/session.ts index c6ec2042fae..862ebee4b03 100644 --- a/src/harness/unittests/session.ts +++ b/src/harness/unittests/session.ts @@ -9,7 +9,7 @@ namespace ts.server { newLine: "\n", useCaseSensitiveFileNames: true, write(s): void { lastWrittenToHost = s; }, - readFile(): string { return void 0; }, + readFile: () => undefined, writeFile: noop, resolvePath(): string { return void 0; }, fileExists: () => false, diff --git a/src/harness/virtualFileSystem.ts b/src/harness/virtualFileSystem.ts index da7784770df..8accd6f621e 100644 --- a/src/harness/virtualFileSystem.ts +++ b/src/harness/virtualFileSystem.ts @@ -209,7 +209,7 @@ namespace Utils { } } - readFile(path: string): string { + readFile(path: string): string | undefined { const value = this.traversePath(path); if (value && value.isFile()) { return value.content.content; diff --git a/src/server/lsHost.ts b/src/server/lsHost.ts index 3f1a4e054a8..13b9505a658 100644 --- a/src/server/lsHost.ts +++ b/src/server/lsHost.ts @@ -217,7 +217,7 @@ namespace ts.server { return !this.project.isWatchedMissingFile(path) && this.host.fileExists(file); } - readFile(fileName: string): string { + readFile(fileName: string): string | undefined { return this.host.readFile(fileName); } diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index 730257d2ccc..b1fddfb4129 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -93,10 +93,10 @@ namespace ts.server.typingsInstaller { abstract readonly typesRegistry: Map; constructor( - readonly installTypingHost: InstallTypingHost, - readonly globalCachePath: string, - readonly safeListPath: Path, - readonly throttleLimit: number, + protected readonly installTypingHost: InstallTypingHost, + private readonly globalCachePath: string, + private readonly safeListPath: Path, + private readonly throttleLimit: number, protected readonly log = nullLog) { if (this.log.isEnabled()) { this.log.writeLine(`Global cache location '${globalCachePath}', safe file path '${safeListPath}'`); diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index f31276b6498..670633eb44b 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -9,10 +9,10 @@ namespace ts.JsTyping { export interface TypingResolutionHost { - directoryExists: (path: string) => boolean; - fileExists: (fileName: string) => boolean; - readFile: (path: string, encoding?: string) => string; - readDirectory: (rootDir: string, extensions: ReadonlyArray, excludes: ReadonlyArray, includes: ReadonlyArray, depth?: number) => string[]; + directoryExists(path: string): boolean; + fileExists(fileName: string): boolean; + readFile(path: string, encoding?: string): string | undefined; + readDirectory(rootDir: string, extensions: ReadonlyArray, excludes: ReadonlyArray, includes: ReadonlyArray, depth?: number): string[]; } interface PackageJson { diff --git a/src/services/services.ts b/src/services/services.ts index 5b2cf949d2a..30c6b88b1e2 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1149,7 +1149,7 @@ namespace ts { !!hostCache.getEntryByPath(path) : (host.fileExists && host.fileExists(fileName)); }, - readFile: (fileName): string => { + readFile(fileName) { // stub missing host functionality const path = toPath(fileName, currentDirectory, getCanonicalFileName); if (hostCache.containsEntryByPath(path)) { diff --git a/src/services/shims.ts b/src/services/shims.ts index 2ee1853f18f..03965cb5d48 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -69,7 +69,7 @@ namespace ts { getTypeRootsVersion?(): number; readDirectory(rootDir: string, extension: string, basePaths?: string, excludeEx?: string, includeFileEx?: string, includeDirEx?: string, depth?: number): string; - readFile(path: string, encoding?: string): string; + readFile(path: string, encoding?: string): string | undefined; fileExists(path: string): boolean; getModuleResolutionsForFile?(fileName: string): string; @@ -95,7 +95,7 @@ namespace ts { /** * Read arbitary text files on disk, i.e. when resolution procedure needs the content of 'package.json' to determine location of bundled typings for node modules */ - readFile(fileName: string): string; + readFile(fileName: string): string | undefined; realpath?(path: string): string; trace(s: string): void; useCaseSensitiveFileNames?(): boolean; @@ -458,7 +458,7 @@ namespace ts { )); } - public readFile(path: string, encoding?: string): string { + public readFile(path: string, encoding?: string): string | undefined { return this.shimHost.readFile(path, encoding); } @@ -501,7 +501,7 @@ namespace ts { return this.shimHost.fileExists(fileName); } - public readFile(fileName: string): string { + public readFile(fileName: string): string | undefined { return this.shimHost.readFile(fileName); } @@ -1006,7 +1006,7 @@ namespace ts { class CoreServicesShimObject extends ShimBase implements CoreServicesShim { private logPerformance = false; - constructor(factory: ShimFactory, public logger: Logger, private host: CoreServicesShimHostAdapter) { + constructor(factory: ShimFactory, public readonly logger: Logger, private readonly host: CoreServicesShimHostAdapter) { super(factory); } diff --git a/src/services/types.ts b/src/services/types.ts index bfb8a80b769..19d2345d968 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -165,7 +165,7 @@ namespace ts { * Without these methods, only completions for ambient modules will be provided. */ readDirectory?(path: string, extensions?: ReadonlyArray, exclude?: ReadonlyArray, include?: ReadonlyArray, depth?: number): string[]; - readFile?(path: string, encoding?: string): string; + readFile?(path: string, encoding?: string): string | undefined; fileExists?(path: string): boolean; /*