Refactoring to createSourceMapperHost

This commit is contained in:
Sheetal Nandi
2018-11-15 11:29:04 -08:00
parent 86857d5b09
commit 0a8c47bd45
4 changed files with 72 additions and 70 deletions

View File

@@ -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;
}
/**

View File

@@ -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) {

View File

@@ -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<SourceFileLike | false>();
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<SourceFileLike>();
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;
}
};
}
}

View File

@@ -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));
}