Skip to content

Commit 751cb9e

Browse files
committed
Update source and declaration projects on update to declaration file or map file
TODO: add tests
1 parent 56a39b7 commit 751cb9e

File tree

3 files changed

+86
-23
lines changed

3 files changed

+86
-23
lines changed

src/server/editorServices.ts

Lines changed: 71 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -945,10 +945,39 @@ namespace ts.server {
945945
// this file and set of inferred projects
946946
info.delayReloadNonMixedContentFile();
947947
this.delayUpdateProjectGraphs(info.containingProjects);
948+
this.handleSourceMapProjects(info);
948949
}
949950
}
950951
}
951952

953+
private handleSourceMapProjects(info: ScriptInfo) {
954+
// Change in d.ts, update source projects as well
955+
if (info.sourceMapFilePath) {
956+
const sourceMapFileInfo = this.getScriptInfoForPath(info.sourceMapFilePath);
957+
if (sourceMapFileInfo && sourceMapFileInfo.sourceInfos) {
958+
this.delayUpdateSourceInfoProjects(sourceMapFileInfo.sourceInfos);
959+
}
960+
}
961+
// Change in mapInfo, update declarationProjects and source projects
962+
if (info.sourceInfos) {
963+
this.delayUpdateSourceInfoProjects(info.sourceInfos);
964+
}
965+
if (info.declarationInfoPath) {
966+
this.delayUpdateProjectsOfScriptInfoPath(info.declarationInfoPath);
967+
}
968+
}
969+
970+
private delayUpdateSourceInfoProjects(sourceInfos: Map<true>) {
971+
sourceInfos.forEach((_value, path) => this.delayUpdateProjectsOfScriptInfoPath(path as Path));
972+
}
973+
974+
private delayUpdateProjectsOfScriptInfoPath(path: Path) {
975+
const info = this.getScriptInfoForPath(path);
976+
if (info) {
977+
this.delayUpdateProjectGraphs(info.containingProjects);
978+
}
979+
}
980+
952981
private handleDeletedFile(info: ScriptInfo) {
953982
this.stopWatchingScriptInfo(info);
954983

@@ -962,6 +991,7 @@ namespace ts.server {
962991

963992
// update projects to make sure that set of referenced files is correct
964993
this.delayUpdateProjectGraphs(containingProjects);
994+
this.handleSourceMapProjects(info);
965995
}
966996
}
967997

@@ -2201,19 +2231,30 @@ namespace ts.server {
22012231
const declarationInfo = this.getOrCreateScriptInfoNotOpenedByClient(generatedFileName, project.currentDirectory, project.directoryStructureHost);
22022232
if (!declarationInfo) return undefined;
22032233

2234+
// Try to get from cache
22042235
declarationInfo.getSnapshot(); // Ensure synchronized
2205-
const existingMapper = declarationInfo.mapper;
2206-
if (existingMapper !== undefined) {
2207-
return existingMapper ? existingMapper : undefined;
2236+
if (declarationInfo.sourceMapFilePath !== undefined) {
2237+
// Doesnt have sourceMap
2238+
if (!declarationInfo.sourceMapFilePath) return undefined;
2239+
2240+
// Ensure mapper is synchronized
2241+
const mapFileInfo = this.getScriptInfoForPath(declarationInfo.sourceMapFilePath);
2242+
if (mapFileInfo) {
2243+
mapFileInfo.getSnapshot();
2244+
if (mapFileInfo.mapper !== undefined) {
2245+
return mapFileInfo.mapper ? mapFileInfo.mapper : undefined;
2246+
}
2247+
}
22082248
}
22092249

22102250
// Create the mapper
2211-
declarationInfo.mapInfo = undefined;
2251+
declarationInfo.sourceMapFilePath = undefined;
2252+
let sourceMapFileInfo: ScriptInfo | undefined;
22122253

22132254
let readMapFile: ((fileName: string) => string | undefined) | undefined = fileName => {
22142255
const mapInfo = this.getOrCreateScriptInfoNotOpenedByClient(fileName, project.currentDirectory, project.directoryStructureHost);
22152256
if (!mapInfo) return undefined;
2216-
declarationInfo.mapInfo = mapInfo;
2257+
sourceMapFileInfo = mapInfo;
22172258
const snap = mapInfo.getSnapshot();
22182259
return snap.getText(0, snap.getLength());
22192260
};
@@ -2225,11 +2266,17 @@ namespace ts.server {
22252266
readMapFile
22262267
);
22272268
readMapFile = undefined; // Remove ref to project
2228-
declarationInfo.mapper = mapper || false;
2229-
if (sourceFileName && mapper) {
2230-
// Attach as source
2231-
const sourceInfo = this.getOrCreateScriptInfoNotOpenedByClient(sourceFileName, project.currentDirectory, project.directoryStructureHost)!;
2232-
(declarationInfo.mapInfo!.sourceInfos || (declarationInfo.mapInfo!.sourceInfos = createMap())).set(sourceInfo.path, true);
2269+
if (sourceMapFileInfo) {
2270+
declarationInfo.sourceMapFilePath = sourceMapFileInfo.path;
2271+
sourceMapFileInfo.mapper = mapper || false;
2272+
if (sourceFileName && mapper) {
2273+
// Attach as source
2274+
const sourceInfo = this.getOrCreateScriptInfoNotOpenedByClient(sourceFileName, project.currentDirectory, project.directoryStructureHost)!;
2275+
(sourceMapFileInfo.sourceInfos || (sourceMapFileInfo.sourceInfos = createMap())).set(sourceInfo.path, true);
2276+
}
2277+
}
2278+
else {
2279+
declarationInfo.sourceMapFilePath = false;
22332280
}
22342281
return mapper;
22352282
}
@@ -2248,8 +2295,11 @@ namespace ts.server {
22482295
if (!info) return undefined;
22492296

22502297
// Attach as source
2251-
if (declarationInfo && declarationInfo.mapInfo && info !== declarationInfo) {
2252-
(declarationInfo.mapInfo.sourceInfos || (declarationInfo.mapInfo.sourceInfos = createMap())).set(info.path, true);
2298+
if (declarationInfo && declarationInfo.sourceMapFilePath && info !== declarationInfo) {
2299+
const sourceMapInfo = this.getScriptInfoForPath(declarationInfo.sourceMapFilePath);
2300+
if (sourceMapInfo) {
2301+
(sourceMapInfo.sourceInfos || (sourceMapInfo.sourceInfos = createMap())).set(info.path, true);
2302+
}
22532303
}
22542304

22552305
// Key doesnt matter since its only for text and lines
@@ -2616,8 +2666,10 @@ namespace ts.server {
26162666
// If script info is open or orphan, retain it and its dependencies
26172667
if (!info.isScriptOpen() && info.isOrphan()) {
26182668
// Otherwise if there is any source info that is alive, this alive too
2619-
if (!info.mapInfo || !info.mapInfo.sourceInfos) return;
2620-
if (!forEachKey(info.mapInfo.sourceInfos, path => {
2669+
if (!info.sourceMapFilePath) return;
2670+
const sourceMapInfo = this.getScriptInfoForPath(info.sourceMapFilePath);
2671+
if (!sourceMapInfo || !sourceMapInfo.sourceInfos) return;
2672+
if (!forEachKey(sourceMapInfo.sourceInfos, path => {
26212673
const info = this.getScriptInfoForPath(path as Path)!;
26222674
return info.isScriptOpen() || !info.isOrphan();
26232675
})) {
@@ -2627,11 +2679,12 @@ namespace ts.server {
26272679

26282680
// Retain this script info
26292681
toRemoveScriptInfos.delete(info.path);
2630-
if (info.mapInfo) {
2682+
if (info.sourceMapFilePath) {
26312683
// And map file info and source infos
2632-
toRemoveScriptInfos.delete(info.mapInfo.path);
2633-
if (info.mapInfo.sourceInfos) {
2634-
info.mapInfo.sourceInfos.forEach((_value, path) => toRemoveScriptInfos.delete(path));
2684+
toRemoveScriptInfos.delete(info.sourceMapFilePath);
2685+
const sourceMapInfo = this.getScriptInfoForPath(info.sourceMapFilePath);
2686+
if (sourceMapInfo && sourceMapInfo.sourceInfos) {
2687+
sourceMapInfo.sourceInfos.forEach((_value, path) => toRemoveScriptInfos.delete(path));
26352688
}
26362689
}
26372690
});

src/server/scriptInfo.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,11 @@ namespace ts.server {
6565
}
6666

6767
private resetSourceMapInfo() {
68-
this.info.mapper = undefined;
6968
this.info.sourceFileLike = undefined;
70-
this.info.mapInfo = undefined;
69+
this.info.sourceMapFilePath = undefined;
70+
this.info.declarationInfoPath = undefined;
7171
this.info.sourceInfos = undefined;
72+
this.info.mapper = undefined;
7273
}
7374

7475
/** Public for testing */
@@ -305,13 +306,18 @@ namespace ts.server {
305306
mTime?: number;
306307

307308
/*@internal*/
308-
mapInfo?: ScriptInfo;
309+
sourceFileLike?: SourceFileLike;
310+
311+
/*@internal*/
312+
sourceMapFilePath?: Path | false;
313+
314+
// Present on sourceMapFile info
315+
/*@internal*/
316+
declarationInfoPath?: Path;
309317
/*@internal*/
310318
sourceInfos?: Map<true>;
311319
/*@internal*/
312320
mapper?: DocumentPositionMapper | false;
313-
/*@internal*/
314-
sourceFileLike: SourceFileLike | undefined;
315321

316322
constructor(
317323
private readonly host: ServerHost,

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8595,6 +8595,9 @@ declare namespace ts.server {
85958595
getHostFormatCodeOptions(): FormatCodeSettings;
85968596
getHostPreferences(): protocol.UserPreferences;
85978597
private onSourceFileChanged;
8598+
private handleSourceMapProjects;
8599+
private delayUpdateSourceInfoProjects;
8600+
private delayUpdateProjectsOfScriptInfoPath;
85988601
private handleDeletedFile;
85998602
private onConfigChangedForConfiguredProject;
86008603
/**
@@ -8722,6 +8725,7 @@ declare namespace ts.server {
87228725
private findExternalProjectContainingOpenScriptInfo;
87238726
openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult;
87248727
private removeOrphanConfiguredProjects;
8728+
private removeOrphanScriptInfos;
87258729
private telemetryOnOpenFile;
87268730
/**
87278731
* Close file whose contents is managed by the client

0 commit comments

Comments
 (0)