Skip to content

Commit 5665c09

Browse files
author
Paul van Brenk
committed
Introduce the concept of a Dynamic File
Dynamic files are generally created by the debugger when while debugging it can't find a matching file on disk. Since these files don't exist on disk, we shouldn't check if the file exists on disk, and allow the content to be controlled by the host.
1 parent 80a7ed9 commit 5665c09

File tree

4 files changed

+30
-23
lines changed

4 files changed

+30
-23
lines changed

src/server/builder.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
namespace ts.server {
66

77
export function shouldEmitFile(scriptInfo: ScriptInfo) {
8-
return !scriptInfo.hasMixedContent;
8+
return !scriptInfo.hasMixedContent && !scriptInfo.isDynamic;
99
}
1010

1111
/**
@@ -188,7 +188,7 @@ namespace ts.server {
188188
*/
189189
getFilesAffectedBy(scriptInfo: ScriptInfo): string[] {
190190
const info = this.getOrCreateFileInfo(scriptInfo.path);
191-
const singleFileResult = scriptInfo.hasMixedContent ? [] : [scriptInfo.fileName];
191+
const singleFileResult = scriptInfo.hasMixedContent || scriptInfo.isDynamic ? [] : [scriptInfo.fileName];
192192
if (info.updateShapeSignature()) {
193193
const options = this.project.getCompilerOptions();
194194
// If `--out` or `--outFile` is specified, any new emit will result in re-emitting the entire project,
@@ -303,7 +303,7 @@ namespace ts.server {
303303
getFilesAffectedBy(scriptInfo: ScriptInfo): string[] {
304304
this.ensureProjectDependencyGraphUpToDate();
305305

306-
const singleFileResult = scriptInfo.hasMixedContent ? [] : [scriptInfo.fileName];
306+
const singleFileResult = scriptInfo.hasMixedContent || scriptInfo.isDynamic ? [] : [scriptInfo.fileName];
307307
const fileInfo = this.getFileInfo(scriptInfo.path);
308308
if (!fileInfo || !fileInfo.updateShapeSignature()) {
309309
return singleFileResult;

src/server/editorServices.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -234,18 +234,21 @@ namespace ts.server {
234234
getFileName(f: T): string;
235235
getScriptKind(f: T): ScriptKind;
236236
hasMixedContent(f: T, extraFileExtensions: JsFileExtensionInfo[]): boolean;
237+
isDynamicFile(f: T): boolean;
237238
}
238239

239240
const fileNamePropertyReader: FilePropertyReader<string> = {
240241
getFileName: x => x,
241242
getScriptKind: _ => undefined,
242243
hasMixedContent: (fileName, extraFileExtensions) => some(extraFileExtensions, ext => ext.isMixedContent && fileExtensionIs(fileName, ext.extension)),
244+
isDynamicFile: x => x[0] == '^',
243245
};
244246

245247
const externalFilePropertyReader: FilePropertyReader<protocol.ExternalFile> = {
246248
getFileName: x => x.fileName,
247249
getScriptKind: x => tryConvertScriptKindName(x.scriptKind),
248-
hasMixedContent: x => x.hasMixedContent
250+
hasMixedContent: x => x.hasMixedContent,
251+
isDynamicFile: x => x.fileName[0] == '^',
249252
};
250253

251254
function findProjectByName<T extends Project>(projectName: string, projects: T[]): T {
@@ -1177,15 +1180,16 @@ namespace ts.server {
11771180
private addFilesToProjectAndUpdateGraph<T>(project: ConfiguredProject | ExternalProject, files: T[], propertyReader: FilePropertyReader<T>, clientFileName: string, typeAcquisition: TypeAcquisition, configFileErrors: ReadonlyArray<Diagnostic>): void {
11781181
let errors: Diagnostic[];
11791182
for (const f of files) {
1180-
const rootFilename = propertyReader.getFileName(f);
1183+
const rootFileName = propertyReader.getFileName(f);
11811184
const scriptKind = propertyReader.getScriptKind(f);
11821185
const hasMixedContent = propertyReader.hasMixedContent(f, this.hostConfiguration.extraFileExtensions);
1183-
if (this.host.fileExists(rootFilename)) {
1184-
const info = this.getOrCreateScriptInfoForNormalizedPath(toNormalizedPath(rootFilename), /*openedByClient*/ clientFileName === rootFilename, /*fileContent*/ undefined, scriptKind, hasMixedContent);
1186+
const isDynamicFile = propertyReader.isDynamicFile(f);
1187+
if (isDynamicFile || this.host.fileExists(rootFileName)) {
1188+
const info = this.getOrCreateScriptInfoForNormalizedPath(toNormalizedPath(rootFileName), /*openedByClient*/ clientFileName === rootFileName, /*fileContent*/ undefined, scriptKind, hasMixedContent, isDynamicFile);
11851189
project.addRoot(info);
11861190
}
11871191
else {
1188-
(errors || (errors = [])).push(createFileNotFoundDiagnostic(rootFilename));
1192+
(errors || (errors = [])).push(createFileNotFoundDiagnostic(rootFileName));
11891193
}
11901194
}
11911195
project.setProjectErrors(concatenate(configFileErrors, errors));
@@ -1215,7 +1219,8 @@ namespace ts.server {
12151219
let rootFilesChanged = false;
12161220
for (const f of newUncheckedFiles) {
12171221
const newRootFile = propertyReader.getFileName(f);
1218-
if (!this.host.fileExists(newRootFile)) {
1222+
const isDynamic = propertyReader.isDynamicFile(f);
1223+
if (!isDynamic && !this.host.fileExists(newRootFile)) {
12191224
(projectErrors || (projectErrors = [])).push(createFileNotFoundDiagnostic(newRootFile));
12201225
continue;
12211226
}
@@ -1226,7 +1231,7 @@ namespace ts.server {
12261231
if (!scriptInfo) {
12271232
const scriptKind = propertyReader.getScriptKind(f);
12281233
const hasMixedContent = propertyReader.hasMixedContent(f, this.hostConfiguration.extraFileExtensions);
1229-
scriptInfo = this.getOrCreateScriptInfoForNormalizedPath(normalizedPath, /*openedByClient*/ false, /*fileContent*/ undefined, scriptKind, hasMixedContent);
1234+
scriptInfo = this.getOrCreateScriptInfoForNormalizedPath(normalizedPath, /*openedByClient*/ false, /*fileContent*/ undefined, scriptKind, hasMixedContent, isDynamic);
12301235
}
12311236
}
12321237
newRootScriptInfos.push(scriptInfo);
@@ -1410,17 +1415,17 @@ namespace ts.server {
14101415

14111416
watchClosedScriptInfo(info: ScriptInfo) {
14121417
// do not watch files with mixed content - server doesn't know how to interpret it
1413-
if (!info.hasMixedContent) {
1418+
if (!info.hasMixedContent && !info.isDynamic) {
14141419
const { fileName } = info;
14151420
info.setWatcher(this.host.watchFile(fileName, _ => this.onSourceFileChanged(fileName)));
14161421
}
14171422
}
14181423

1419-
getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean) {
1424+
getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, isDynamic?: boolean) {
14201425
let info = this.getScriptInfoForNormalizedPath(fileName);
14211426
if (!info) {
1422-
if (openedByClient || this.host.fileExists(fileName)) {
1423-
info = new ScriptInfo(this.host, fileName, scriptKind, hasMixedContent);
1427+
if (openedByClient || isDynamic || this.host.fileExists(fileName)) {
1428+
info = new ScriptInfo(this.host, fileName, scriptKind, hasMixedContent, isDynamic);
14241429

14251430
this.filenameToScriptInfo.set(info.path, info);
14261431

@@ -1430,6 +1435,7 @@ namespace ts.server {
14301435
fileContent = this.host.readFile(fileName) || "";
14311436
}
14321437
}
1438+
14331439
else {
14341440
this.watchClosedScriptInfo(info);
14351441
}

src/server/scriptInfo.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,12 @@ namespace ts.server {
156156
private readonly host: ServerHost,
157157
readonly fileName: NormalizedPath,
158158
readonly scriptKind: ScriptKind,
159-
public hasMixedContent = false) {
159+
public hasMixedContent = false,
160+
public isDynamic = false) {
160161

161162
this.path = toPath(fileName, host.getCurrentDirectory(), createGetCanonicalFileName(host.useCaseSensitiveFileNames));
162163
this.textStorage = new TextStorage(host, fileName);
163-
if (hasMixedContent) {
164+
if (hasMixedContent || isDynamic) {
164165
this.textStorage.reload("");
165166
}
166167
this.scriptKind = scriptKind
@@ -180,7 +181,7 @@ namespace ts.server {
180181

181182
public close() {
182183
this.isOpen = false;
183-
this.textStorage.useText(this.hasMixedContent ? "" : undefined);
184+
this.textStorage.useText(this.hasMixedContent || this.isDynamic ? "" : undefined);
184185
this.markContainingProjectsAsDirty();
185186
}
186187

@@ -307,7 +308,7 @@ namespace ts.server {
307308
}
308309

309310
reloadFromFile(tempFileName?: NormalizedPath) {
310-
if (this.hasMixedContent) {
311+
if (this.hasMixedContent || this.isDynamic) {
311312
this.reload("");
312313
}
313314
else {
@@ -354,4 +355,4 @@ namespace ts.server {
354355
return this.scriptKind === ScriptKind.JS || this.scriptKind === ScriptKind.JSX;
355356
}
356357
}
357-
}
358+
}

src/server/utilities.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ namespace ts.server {
8484
};
8585
}
8686

87-
export function mergeMapLikes(target: MapLike<any>, source: MapLike <any>): void {
87+
export function mergeMapLikes(target: MapLike<any>, source: MapLike<any>): void {
8888
for (const key in source) {
8989
if (hasProperty(source, key)) {
9090
target[key] = source[key];
@@ -115,9 +115,9 @@ namespace ts.server {
115115
}
116116

117117
export function createNormalizedPathMap<T>(): NormalizedPathMap<T> {
118-
/* tslint:disable:no-null-keyword */
118+
/* tslint:disable:no-null-keyword */
119119
const map = createMap<T>();
120-
/* tslint:enable:no-null-keyword */
120+
/* tslint:enable:no-null-keyword */
121121
return {
122122
get(path) {
123123
return map.get(path);
@@ -290,4 +290,4 @@ namespace ts.server {
290290
deleted(oldItems[oldIndex++]);
291291
}
292292
}
293-
}
293+
}

0 commit comments

Comments
 (0)