mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-17 00:34:47 -05:00
Watch generated file if it doesnt exist when trying to translate it to to source generated position
This commit is contained in:
@@ -2240,7 +2240,13 @@ namespace ts.server {
|
||||
getDocumentPositionMapper(project: Project, generatedFileName: string, sourceFileName?: string): DocumentPositionMapper | undefined {
|
||||
// Since declaration info and map file watches arent updating project's directory structure host (which can cache file structure) use host
|
||||
const declarationInfo = this.getOrCreateScriptInfoNotOpenedByClient(generatedFileName, project.currentDirectory, this.host);
|
||||
if (!declarationInfo) return undefined;
|
||||
if (!declarationInfo) {
|
||||
if (sourceFileName) {
|
||||
// Project contains source file and it generates the generated file name
|
||||
project.addGeneratedFileWatch(generatedFileName, sourceFileName);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Try to get from cache
|
||||
declarationInfo.getSnapshot(); // Ensure synchronized
|
||||
|
||||
@@ -109,12 +109,22 @@ namespace ts.server {
|
||||
return value instanceof ScriptInfo;
|
||||
}
|
||||
|
||||
interface GeneratedFileWatcher {
|
||||
generatedFilePath: Path;
|
||||
watcher: FileWatcher;
|
||||
}
|
||||
type GeneratedFileWatcherMap = GeneratedFileWatcher | Map<GeneratedFileWatcher>;
|
||||
function isGeneratedFileWatcher(watch: GeneratedFileWatcherMap): watch is GeneratedFileWatcher {
|
||||
return (watch as GeneratedFileWatcher).generatedFilePath !== undefined;
|
||||
}
|
||||
|
||||
export abstract class Project implements LanguageServiceHost, ModuleResolutionHost {
|
||||
private rootFiles: ScriptInfo[] = [];
|
||||
private rootFilesMap: Map<ProjectRoot> = createMap<ProjectRoot>();
|
||||
private program: Program | undefined;
|
||||
private externalFiles: SortedReadonlyArray<string> | undefined;
|
||||
private missingFilesMap: Map<FileWatcher> | undefined;
|
||||
private generatedFilesMap: GeneratedFileWatcherMap | undefined;
|
||||
private plugins: PluginModuleWithName[] = [];
|
||||
|
||||
/*@internal*/
|
||||
@@ -573,6 +583,7 @@ namespace ts.server {
|
||||
this.lastFileExceededProgramSize = lastFileExceededProgramSize;
|
||||
this.builderState = undefined;
|
||||
this.resolutionCache.closeTypeRootsWatch();
|
||||
this.clearGeneratedFileWatch();
|
||||
this.projectService.onUpdateLanguageServiceStateForProject(this, /*languageServiceEnabled*/ false);
|
||||
}
|
||||
|
||||
@@ -654,6 +665,7 @@ namespace ts.server {
|
||||
clearMap(this.missingFilesMap, closeFileWatcher);
|
||||
this.missingFilesMap = undefined!;
|
||||
}
|
||||
this.clearGeneratedFileWatch();
|
||||
|
||||
// signal language service to release source files acquired from document registry
|
||||
this.languageService.dispose();
|
||||
@@ -947,6 +959,39 @@ namespace ts.server {
|
||||
missingFilePath => this.addMissingFileWatcher(missingFilePath)
|
||||
);
|
||||
|
||||
if (this.generatedFilesMap) {
|
||||
const outPath = this.compilerOptions.outFile && this.compilerOptions.out;
|
||||
if (isGeneratedFileWatcher(this.generatedFilesMap)) {
|
||||
// --out
|
||||
if (!outPath || !this.isValidGeneratedFileWatcher(
|
||||
removeFileExtension(outPath) + Extension.Dts,
|
||||
this.generatedFilesMap,
|
||||
)) {
|
||||
this.clearGeneratedFileWatch();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// MultiFile
|
||||
if (outPath) {
|
||||
this.clearGeneratedFileWatch();
|
||||
}
|
||||
else {
|
||||
this.generatedFilesMap.forEach((watcher, source) => {
|
||||
const sourceFile = this.program!.getSourceFileByPath(source as Path);
|
||||
if (!sourceFile ||
|
||||
sourceFile.resolvedPath !== source ||
|
||||
!this.isValidGeneratedFileWatcher(
|
||||
getDeclarationEmitOutputFilePathWorker(sourceFile.fileName, this.compilerOptions, this.currentDirectory, this.program!.getCommonSourceDirectory(), this.getCanonicalFileName),
|
||||
watcher
|
||||
)) {
|
||||
closeFileWatcherOf(watcher);
|
||||
(this.generatedFilesMap as Map<GeneratedFileWatcher>).delete(source);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Watch the type locations that would be added to program as part of automatic type resolutions
|
||||
if (this.languageServiceEnabled) {
|
||||
this.resolutionCache.updateTypeRootsWatch();
|
||||
@@ -1011,6 +1056,61 @@ namespace ts.server {
|
||||
return !!this.missingFilesMap && this.missingFilesMap.has(path);
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
addGeneratedFileWatch(generatedFile: string, sourceFile: string) {
|
||||
if (this.compilerOptions.outFile || this.compilerOptions.out) {
|
||||
// Single watcher
|
||||
if (!this.generatedFilesMap) {
|
||||
this.generatedFilesMap = this.createGeneratedFileWatcher(generatedFile);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Map
|
||||
const path = this.toPath(sourceFile);
|
||||
if (this.generatedFilesMap) {
|
||||
if (isGeneratedFileWatcher(this.generatedFilesMap)) {
|
||||
Debug.fail(`${this.projectName} Expected not to have --out watcher for generated file with options: ${JSON.stringify(this.compilerOptions)}`);
|
||||
return;
|
||||
}
|
||||
if (this.generatedFilesMap.has(path)) return;
|
||||
}
|
||||
else {
|
||||
this.generatedFilesMap = createMap();
|
||||
}
|
||||
this.generatedFilesMap.set(path, this.createGeneratedFileWatcher(generatedFile));
|
||||
}
|
||||
}
|
||||
|
||||
private createGeneratedFileWatcher(generatedFile: string): GeneratedFileWatcher {
|
||||
return {
|
||||
generatedFilePath: this.toPath(generatedFile),
|
||||
watcher: this.projectService.watchFactory.watchFile(
|
||||
this.projectService.host,
|
||||
generatedFile,
|
||||
() => this.projectService.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(this),
|
||||
PollingInterval.High,
|
||||
WatchType.MissingGeneratedFile,
|
||||
this
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
private isValidGeneratedFileWatcher(generateFile: string, watcher: GeneratedFileWatcher) {
|
||||
return this.toPath(generateFile) === watcher.generatedFilePath;
|
||||
}
|
||||
|
||||
private clearGeneratedFileWatch() {
|
||||
if (this.generatedFilesMap) {
|
||||
if (isGeneratedFileWatcher(this.generatedFilesMap)) {
|
||||
closeFileWatcherOf(this.generatedFilesMap);
|
||||
}
|
||||
else {
|
||||
clearMap(this.generatedFilesMap, closeFileWatcherOf);
|
||||
}
|
||||
this.generatedFilesMap = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
getScriptInfoForNormalizedPath(fileName: NormalizedPath): ScriptInfo | undefined {
|
||||
const scriptInfo = this.projectService.getScriptInfoForPath(this.toPath(fileName));
|
||||
if (scriptInfo && !scriptInfo.isAttached(this)) {
|
||||
|
||||
@@ -227,5 +227,6 @@ namespace ts {
|
||||
NodeModulesForClosedScriptInfo = "node_modules for closed script infos in them",
|
||||
MissingSourceMapFile = "Missing source map file",
|
||||
NoopConfigFileForInferredRoot = "Noop Config file for the inferred project root",
|
||||
MissingGeneratedFile = "Missing generated file"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user