From 0a8c47bd45fb4265c9d783a5492bdf86d91e5ddd Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 15 Nov 2018 11:29:04 -0800 Subject: [PATCH] Refactoring to createSourceMapperHost --- src/compiler/types.ts | 2 +- src/services/services.ts | 29 ++++++---- src/services/sourcemaps.ts | 107 +++++++++++++++++-------------------- src/services/utilities.ts | 4 +- 4 files changed, 72 insertions(+), 70 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 495465f7032..f52d82a8a2f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5530,7 +5530,7 @@ namespace ts { export interface DocumentPositionMapperHost { getSourceFileLike(path: Path): SourceFileLike | undefined; getCanonicalFileName(path: string): string; - log?(text: string): void; + log(text: string): void; } /** diff --git a/src/services/services.ts b/src/services/services.ts index 20400a3ec47..67f9e537574 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1139,7 +1139,14 @@ namespace ts { const useCaseSensitiveFileNames = hostUsesCaseSensitiveFileNames(host); const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames); - const sourceMapper = getSourceMapper(useCaseSensitiveFileNames, currentDirectory, log, host, () => program); + const sourceMapper = getSourceMapper({ + useCaseSensitiveFileNames: () => useCaseSensitiveFileNames, + getCurrentDirectory: () => currentDirectory, + getProgram, + fileExists: host.fileExists ? f => host.fileExists!(f) : returnFalse, + readFile: host.readFile ? (f, encoding) => host.readFile!(f, encoding) : () => undefined, + log + }); function getValidSourceFile(fileName: string): SourceFile { const sourceFile = program.getSourceFile(fileName); @@ -1203,15 +1210,7 @@ namespace ts { writeFile: noop, getCurrentDirectory: () => currentDirectory, fileExists, - readFile(fileName) { - // stub missing host functionality - const path = toPath(fileName, currentDirectory, getCanonicalFileName); - const entry = hostCache && hostCache.getEntryByPath(path); - if (entry) { - return isString(entry) ? undefined : getSnapshotText(entry.scriptSnapshot); - } - return host.readFile && host.readFile(fileName); - }, + readFile, realpath: host.realpath && (path => host.realpath!(path)), directoryExists: directoryName => { return directoryProbablyExists(directoryName, host); @@ -1272,6 +1271,16 @@ namespace ts { (!!host.fileExists && host.fileExists(fileName)); } + function readFile(fileName: string) { + // stub missing host functionality + const path = toPath(fileName, currentDirectory, getCanonicalFileName); + const entry = hostCache && hostCache.getEntryByPath(path); + if (entry) { + return isString(entry) ? undefined : getSnapshotText(entry.scriptSnapshot); + } + return host.readFile && host.readFile(fileName); + } + // Release any files we have acquired in the old program but are // not part of the new program. function onReleaseOldSourceFile(oldSourceFile: SourceFile, oldOptions: CompilerOptions) { diff --git a/src/services/sourcemaps.ts b/src/services/sourcemaps.ts index 9b8f97a6640..c2b9dbfb46a 100644 --- a/src/services/sourcemaps.ts +++ b/src/services/sourcemaps.ts @@ -9,15 +9,21 @@ namespace ts { clearCache(): void; } + export interface SourceMapperHost { + useCaseSensitiveFileNames(): boolean; + getCurrentDirectory(): string; + getProgram(): Program | undefined; + fileExists(path: string): boolean; + readFile(path: string, encoding?: string): string | undefined; + log(s: string): void; + } + export function getSourceMapper( - useCaseSensitiveFileNames: boolean, - currentDirectory: string, - log: (message: string) => void, - host: LanguageServiceHost, - getProgram: () => Program, + host: SourceMapperHost ): SourceMapper { - const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames); - let sourcemappedFileCache: SourceFileLikeCache; + const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames()); + const currentDirectory = host.getCurrentDirectory(); + const generatedFileCache = createMap(); return { tryGetSourcePosition, tryGetGeneratedPosition, toLineColumnOffset, clearCache }; function toPath(fileName: string) { @@ -25,7 +31,7 @@ namespace ts { } function scanForSourcemapURL(fileName: string) { - const mappedFile = sourcemappedFileCache.get(toPath(fileName)); + const mappedFile = generatedFileCache.get(toPath(fileName)); if (!mappedFile) { return; } @@ -41,26 +47,13 @@ namespace ts { } return file.sourceMapper = createDocumentPositionMapper({ - getSourceFileLike: s => { - const program = getProgram(); - // Lookup file in program, if provided - const file = program && program.getSourceFileByPath(s); - // file returned here could be .d.ts when asked for .ts file if projectReferences and module resolution created this source file - if (file === undefined || file.resolvedPath !== s) { - // Otherwise check the cache (which may hit disk) - return sourcemappedFileCache.get(s); - } - return file; - }, + getSourceFileLike, getCanonicalFileName, - log, + log: s => host.log(s), }, map, mapFileName); } function getSourceMapper(fileName: string, file: SourceFileLike): DocumentPositionMapper { - if (!host.readFile || !host.fileExists) { - return file.sourceMapper = identitySourceMapConsumer; - } if (file.sourceMapper) { return file.sourceMapper; } @@ -101,7 +94,9 @@ namespace ts { } function tryGetGeneratedPosition(info: DocumentPosition): DocumentPosition | undefined { - const program = getProgram(); + const program = host.getProgram(); + if (!program) return undefined; + const options = program.getCompilerOptions(); const outPath = options.outFile || options.out; @@ -118,49 +113,47 @@ namespace ts { } function getSourceFile(fileName: string) { - const program = getProgram(); + const program = host.getProgram(); return program && program.getSourceFileByPath(toPath(fileName)); } - function getGeneratedFile(fileName: string) { - return sourcemappedFileCache.get(toPath(fileName)); // TODO: should ask host instead? + function getGeneratedFile(fileName: string): SourceFileLike | undefined { + const path = toPath(fileName); + const fileFromCache = generatedFileCache.get(path); + if (fileFromCache !== undefined) return fileFromCache ? fileFromCache : undefined; + + // TODO: should ask host instead? + if (!host.fileExists(path)) { + generatedFileCache.set(path, false); + return undefined; + } + + // And failing that, check the disk + const text = host.readFile(path); + const file: SourceFileLike | false = text ? { + text, + lineMap: undefined, + getLineAndCharacterOfPosition(pos: number) { + return computeLineAndCharacterOfPosition(getLineStarts(this as SourceFileLike), pos); + } + } : false; + generatedFileCache.set(path, file); + return file ? file : undefined; + } + + function getSourceFileLike(fileName: string) { + const sourceFile = getSourceFile(fileName); + // file returned here could be .d.ts when asked for .ts file if projectReferences and module resolution created this source file + return sourceFile && sourceFile.resolvedPath === toPath(fileName) ? sourceFile : getGeneratedFile(fileName); } function toLineColumnOffset(fileName: string, position: number): LineAndCharacter { - const sourceFile = getSourceFile(fileName); - const file = sourceFile && sourceFile.resolvedPath === toPath(fileName) ? sourceFile : getGeneratedFile(fileName)!; // TODO: GH#18217 + const file = getSourceFileLike(fileName)!; // TODO: GH#18217 return file.getLineAndCharacterOfPosition(position); } function clearCache(): void { - sourcemappedFileCache = createSourceFileLikeCache(host); + generatedFileCache.clear(); } } - - interface SourceFileLikeCache { - get(path: Path): SourceFileLike | undefined; - } - - function createSourceFileLikeCache(host: { readFile?: (path: string) => string | undefined, fileExists?: (path: string) => boolean }): SourceFileLikeCache { - const cached = createMap(); - return { - get(path: Path) { - if (cached.has(path)) { - return cached.get(path); - } - if (!host.fileExists || !host.readFile || !host.fileExists(path)) return; - // And failing that, check the disk - const text = host.readFile(path)!; // TODO: GH#18217 - const file = { - text, - lineMap: undefined, - getLineAndCharacterOfPosition(pos: number) { - return computeLineAndCharacterOfPosition(getLineStarts(this), pos); - } - } as SourceFileLike; - cached.set(path, file); - return file; - } - }; - } } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 22e6b31b55c..2f78ef2324b 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1282,11 +1282,11 @@ namespace ts { return !!compilerOptions.module || compilerOptions.target! >= ScriptTarget.ES2015 || !!compilerOptions.noEmit; } - export function hostUsesCaseSensitiveFileNames(host: LanguageServiceHost): boolean { + export function hostUsesCaseSensitiveFileNames(host: { useCaseSensitiveFileNames?(): boolean; }): boolean { return host.useCaseSensitiveFileNames ? host.useCaseSensitiveFileNames() : false; } - export function hostGetCanonicalFileName(host: LanguageServiceHost): GetCanonicalFileName { + export function hostGetCanonicalFileName(host: { useCaseSensitiveFileNames?(): boolean; }): GetCanonicalFileName { return createGetCanonicalFileName(hostUsesCaseSensitiveFileNames(host)); }