From f9c901ada7148cbaf697c4b8bdd8905ba2cc219f Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 17 Oct 2017 21:18:27 -0700 Subject: [PATCH] Use get files affected by internally and hence use file paths as input --- src/compiler/builder.ts | 132 +++++++++++++++++----------------------- src/server/project.ts | 9 ++- 2 files changed, 64 insertions(+), 77 deletions(-) diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 192f1e43027..93b265f12ca 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -47,11 +47,11 @@ namespace ts { /* @internal */ namespace ts { export interface Builder { - /** - * Call this to feed new program - */ + /** Called to inform builder about new program */ updateProgram(newProgram: Program): void; - getFilesAffectedBy(program: Program, path: Path): string[]; + /** Gets the files affected by the file path */ + getFilesAffectedBy(program: Program, path: Path): ReadonlyArray; + /** Emits the given file */ emitFile(program: Program, path: Path): EmitOutput; /** Emit the changed files and clear the cache of the changed files */ @@ -88,11 +88,10 @@ namespace ts { /** * Gets the files affected by the script info which has updated shape from the known one */ - getFilesAffectedByUpdatedShape(program: Program, sourceFile: SourceFile, singleFileResult: string[]): string[]; + getFilesAffectedByUpdatedShape(program: Program, sourceFile: SourceFile): ReadonlyArray; } interface FileInfo { - fileName: string; version: string; signature: string; } @@ -109,7 +108,7 @@ namespace ts { const fileInfos = createMap(); const semanticDiagnosticsPerFile = createMap>(); /** The map has key by source file's path that has been changed */ - const changedFileNames = createMap(); + const changedFileNames = createMap(); let emitHandler: EmitHandler; return { updateProgram, @@ -142,31 +141,31 @@ namespace ts { ); } - function registerChangedFile(path: Path, fileName: string) { - changedFileNames.set(path, fileName); + function registerChangedFile(path: Path) { + changedFileNames.set(path, true); // All changed files need to re-evaluate its semantic diagnostics semanticDiagnosticsPerFile.delete(path); } function addNewFileInfo(program: Program, sourceFile: SourceFile): FileInfo { - registerChangedFile(sourceFile.path, sourceFile.fileName); + registerChangedFile(sourceFile.path); emitHandler.onAddSourceFile(program, sourceFile); - return { fileName: sourceFile.fileName, version: sourceFile.version, signature: undefined }; + return { version: sourceFile.version, signature: undefined }; } - function removeExistingFileInfo(existingFileInfo: FileInfo, path: Path) { - registerChangedFile(path, existingFileInfo.fileName); + function removeExistingFileInfo(_existingFileInfo: FileInfo, path: Path) { + registerChangedFile(path); emitHandler.onRemoveSourceFile(path); } function updateExistingFileInfo(program: Program, existingInfo: FileInfo, sourceFile: SourceFile) { if (existingInfo.version !== sourceFile.version) { - registerChangedFile(sourceFile.path, sourceFile.fileName); + registerChangedFile(sourceFile.path); existingInfo.version = sourceFile.version; emitHandler.onUpdateSourceFile(program, sourceFile); } else if (emitHandler.onUpdateSourceFileWithSameVersion(program, sourceFile)) { - registerChangedFile(sourceFile.path, sourceFile.fileName); + registerChangedFile(sourceFile.path); } } @@ -182,23 +181,23 @@ namespace ts { } } - function getFilesAffectedBy(program: Program, path: Path): string[] { + function getFilesAffectedBy(program: Program, path: Path): ReadonlyArray { ensureProgramGraph(program); - const sourceFile = program.getSourceFile(path); - const singleFileResult = sourceFile && options.shouldEmitFile(sourceFile) ? [sourceFile.fileName] : []; + const sourceFile = program.getSourceFileByPath(path); const info = fileInfos.get(path); if (!info || !updateShapeSignature(program, sourceFile, info)) { - return singleFileResult; + return sourceFile && [sourceFile] || emptyArray; } Debug.assert(!!sourceFile); - return emitHandler.getFilesAffectedByUpdatedShape(program, sourceFile, singleFileResult); + return emitHandler.getFilesAffectedByUpdatedShape(program, sourceFile); } function emitFile(program: Program, path: Path) { ensureProgramGraph(program); - if (!fileInfos.has(path)) { + const sourceFile = program.getSourceFileByPath(path); + if (!fileInfos.has(path) || options.shouldEmitFile(sourceFile)) { return { outputFiles: [], emitSkipped: true }; } @@ -207,14 +206,12 @@ namespace ts { function enumerateChangedFilesSet( program: Program, - onChangedFile: (fileName: string, path: Path) => void, - onAffectedFile: (fileName: string, sourceFile: SourceFile) => void + onAffectedFile: (sourceFile: SourceFile) => void ) { - changedFileNames.forEach((fileName, path) => { - onChangedFile(fileName, path as Path); + changedFileNames.forEach((_true, path) => { const affectedFiles = getFilesAffectedBy(program, path as Path); for (const file of affectedFiles) { - onAffectedFile(file, program.getSourceFile(file)); + onAffectedFile(file); } }); } @@ -222,27 +219,25 @@ namespace ts { function enumerateChangedFilesEmitOutput( program: Program, emitOnlyDtsFiles: boolean, - onChangedFile: (fileName: string, path: Path) => void, - onEmitOutput: (emitOutput: EmitOutputDetailed, sourceFile: SourceFile) => void + onEmitOutput: (emitOutput: EmitOutputDetailed) => void ) { const seenFiles = createMap(); - enumerateChangedFilesSet(program, onChangedFile, (fileName, sourceFile) => { - if (!seenFiles.has(fileName)) { - seenFiles.set(fileName, true); - if (sourceFile) { - // Any affected file shouldnt have the cached diagnostics - semanticDiagnosticsPerFile.delete(sourceFile.path); + enumerateChangedFilesSet(program, sourceFile => { + if (!seenFiles.has(sourceFile.path)) { + seenFiles.set(sourceFile.path, true); + // Any affected file shouldnt have the cached diagnostics + semanticDiagnosticsPerFile.delete(sourceFile.path); - const emitOutput = options.getEmitOutput(program, sourceFile, emitOnlyDtsFiles, /*isDetailed*/ true) as EmitOutputDetailed; - onEmitOutput(emitOutput, sourceFile); + const emitOutput = options.getEmitOutput(program, sourceFile, emitOnlyDtsFiles, /*isDetailed*/ true) as EmitOutputDetailed; - // mark all the emitted source files as seen - if (emitOutput.emittedSourceFiles) { - for (const file of emitOutput.emittedSourceFiles) { - seenFiles.set(file.fileName, true); - } + // mark all the emitted source files as seen + if (emitOutput.emittedSourceFiles) { + for (const file of emitOutput.emittedSourceFiles) { + seenFiles.set(file.path, true); } } + + onEmitOutput(emitOutput); } }); } @@ -250,8 +245,7 @@ namespace ts { function emitChangedFiles(program: Program): EmitOutputDetailed[] { ensureProgramGraph(program); const result: EmitOutputDetailed[] = []; - enumerateChangedFilesEmitOutput(program, /*emitOnlyDtsFiles*/ false, - /*onChangedFile*/ noop, emitOutput => result.push(emitOutput)); + enumerateChangedFilesEmitOutput(program, /*emitOnlyDtsFiles*/ false, emitOutput => result.push(emitOutput)); changedFileNames.clear(); return result; } @@ -260,11 +254,7 @@ namespace ts { ensureProgramGraph(program); // Ensure that changed files have cleared their respective - enumerateChangedFilesSet(program, /*onChangedFile*/ noop, (_affectedFileName, sourceFile) => { - if (sourceFile) { - semanticDiagnosticsPerFile.delete(sourceFile.path); - } - }); + enumerateChangedFilesSet(program, sourceFile => semanticDiagnosticsPerFile.delete(sourceFile.path)); let diagnostics: Diagnostic[]; for (const sourceFile of program.getSourceFiles()) { @@ -386,24 +376,20 @@ namespace ts { } /** - * Gets all the emittable files from the program. - * @param firstSourceFile This one will be emitted first. See https://github.com/Microsoft/TypeScript/issues/16888 + * Gets all files of the program excluding the default library file */ - function getAllEmittableFiles(program: Program, firstSourceFile: SourceFile): string[] { - const defaultLibraryFileName = getDefaultLibFileName(program.getCompilerOptions()); - const sourceFiles = program.getSourceFiles(); - const result: string[] = []; - add(firstSourceFile); - for (const sourceFile of sourceFiles) { + function getAllFilesExcludingDefaultLibraryFile(program: Program, firstSourceFile: SourceFile): ReadonlyArray { + let result: SourceFile[]; + for (const sourceFile of program.getSourceFiles()) { if (sourceFile !== firstSourceFile) { - add(sourceFile); + addSourceFile(sourceFile); } } - return result; + return result || emptyArray; - function add(sourceFile: SourceFile): void { - if (getBaseFileName(sourceFile.fileName) !== defaultLibraryFileName && options.shouldEmitFile(sourceFile)) { - result.push(sourceFile.fileName); + function addSourceFile(sourceFile: SourceFile) { + if (!program.isSourceFileDefaultLibrary(sourceFile)) { + (result || (result = [])).push(sourceFile); } } } @@ -417,14 +403,14 @@ namespace ts { getFilesAffectedByUpdatedShape }; - function getFilesAffectedByUpdatedShape(program: Program, sourceFile: SourceFile, singleFileResult: string[]): string[] { + function getFilesAffectedByUpdatedShape(program: Program, sourceFile: SourceFile): ReadonlyArray { const options = program.getCompilerOptions(); // If `--out` or `--outFile` is specified, any new emit will result in re-emitting the entire project, // so returning the file itself is good enough. if (options && (options.out || options.outFile)) { - return singleFileResult; + return [sourceFile]; } - return getAllEmittableFiles(program, sourceFile); + return getAllFilesExcludingDefaultLibraryFile(program, sourceFile); } } @@ -481,7 +467,7 @@ namespace ts { // add files referencing the removedFilePath, as changed files too const referencedByInfo = fileInfos.get(filePath); if (referencedByInfo) { - registerChangedFile(filePath as Path, referencedByInfo.fileName); + registerChangedFile(filePath as Path); } } }); @@ -495,37 +481,33 @@ namespace ts { ); } - function getFilesAffectedByUpdatedShape(program: Program, sourceFile: SourceFile, singleFileResult: string[]): string[] { + function getFilesAffectedByUpdatedShape(program: Program, sourceFile: SourceFile): ReadonlyArray { if (!isExternalModule(sourceFile) && !containsOnlyAmbientModules(sourceFile)) { - return getAllEmittableFiles(program, sourceFile); + return getAllFilesExcludingDefaultLibraryFile(program, sourceFile); } const compilerOptions = program.getCompilerOptions(); if (compilerOptions && (compilerOptions.isolatedModules || compilerOptions.out || compilerOptions.outFile)) { - return singleFileResult; + return [sourceFile]; } // Now we need to if each file in the referencedBy list has a shape change as well. // Because if so, its own referencedBy files need to be saved as well to make the // emitting result consistent with files on disk. - - const seenFileNamesMap = createMap(); - const setSeenFileName = (path: Path, sourceFile: SourceFile) => { - seenFileNamesMap.set(path, sourceFile && options.shouldEmitFile(sourceFile) ? sourceFile.fileName : undefined); - }; + const seenFileNamesMap = createMap(); // Start with the paths this file was referenced by const path = sourceFile.path; - setSeenFileName(path, sourceFile); + seenFileNamesMap.set(path, sourceFile); const queue = getReferencedByPaths(path); while (queue.length > 0) { const currentPath = queue.pop(); if (!seenFileNamesMap.has(currentPath)) { const currentSourceFile = program.getSourceFileByPath(currentPath); + seenFileNamesMap.set(currentPath, currentSourceFile); if (currentSourceFile && updateShapeSignature(program, currentSourceFile, fileInfos.get(currentPath))) { queue.push(...getReferencedByPaths(currentPath)); } - setSeenFileName(currentPath, currentSourceFile); } } diff --git a/src/server/project.ts b/src/server/project.ts index 725ce725c38..5e6e76db986 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -448,18 +448,23 @@ namespace ts.server { computeHash: data => this.projectService.host.createHash(data), shouldEmitFile: sourceFile => - !this.projectService.getScriptInfoForPath(sourceFile.path).isDynamicOrHasMixedContent() + !this.shouldEmitFile(sourceFile) }); } } + private shouldEmitFile(sourceFile: SourceFile) { + return !this.projectService.getScriptInfoForPath(sourceFile.path).isDynamicOrHasMixedContent(); + } + getCompileOnSaveAffectedFileList(scriptInfo: ScriptInfo): string[] { if (!this.languageServiceEnabled) { return []; } this.updateGraph(); this.ensureBuilder(); - return this.builder.getFilesAffectedBy(this.program, scriptInfo.path); + return mapDefined(this.builder.getFilesAffectedBy(this.program, scriptInfo.path), + sourceFile => this.shouldEmitFile(sourceFile) ? sourceFile.fileName : undefined); } /**