Skip to content

Commit d72287e

Browse files
authored
Fix issue when building dependency graph for files with circular refs (microsoft#10514)
* Fix issue when building dependency graph for files with circular refs * Make "emitOnlyDtsFiles" parameter non-optional in most cases
1 parent 8fe0d2d commit d72287e

File tree

5 files changed

+35
-13
lines changed

5 files changed

+35
-13
lines changed

src/compiler/declarationEmitter.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ namespace ts {
3636
return declarationDiagnostics.getDiagnostics(targetSourceFile ? targetSourceFile.fileName : undefined);
3737

3838
function getDeclarationDiagnosticsFromFile({ declarationFilePath }: EmitFileNames, sources: SourceFile[], isBundledEmit: boolean) {
39-
emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath, sources, isBundledEmit);
39+
emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath, sources, isBundledEmit, /*emitOnlyDtsFiles*/ false);
4040
}
4141
}
4242

4343
function emitDeclarations(host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, declarationFilePath: string,
44-
sourceFiles: SourceFile[], isBundledEmit: boolean): DeclarationEmit {
44+
sourceFiles: SourceFile[], isBundledEmit: boolean, emitOnlyDtsFiles: boolean): DeclarationEmit {
4545
const newLine = host.getNewLine();
4646
const compilerOptions = host.getCompilerOptions();
4747

@@ -98,7 +98,7 @@ namespace ts {
9898
// global file reference is added only
9999
// - if it is not bundled emit (because otherwise it would be self reference)
100100
// - and it is not already added
101-
if (writeReferencePath(referencedFile, !isBundledEmit && !addedGlobalFileReference)) {
101+
if (writeReferencePath(referencedFile, !isBundledEmit && !addedGlobalFileReference, emitOnlyDtsFiles)) {
102102
addedGlobalFileReference = true;
103103
}
104104
emittedReferencedFiles.push(referencedFile);
@@ -1713,7 +1713,7 @@ namespace ts {
17131713
* @param referencedFile
17141714
* @param addBundledFileReference Determines if global file reference corresponding to bundled file should be emitted or not
17151715
*/
1716-
function writeReferencePath(referencedFile: SourceFile, addBundledFileReference: boolean): boolean {
1716+
function writeReferencePath(referencedFile: SourceFile, addBundledFileReference: boolean, emitOnlyDtsFiles: boolean): boolean {
17171717
let declFileName: string;
17181718
let addedBundledEmitReference = false;
17191719
if (isDeclarationFile(referencedFile)) {
@@ -1722,7 +1722,7 @@ namespace ts {
17221722
}
17231723
else {
17241724
// Get the declaration file path
1725-
forEachExpectedEmitFile(host, getDeclFileName, referencedFile);
1725+
forEachExpectedEmitFile(host, getDeclFileName, referencedFile, emitOnlyDtsFiles);
17261726
}
17271727

17281728
if (declFileName) {
@@ -1751,8 +1751,8 @@ namespace ts {
17511751
}
17521752

17531753
/* @internal */
1754-
export function writeDeclarationFile(declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection) {
1755-
const emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFiles, isBundledEmit);
1754+
export function writeDeclarationFile(declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, emitOnlyDtsFiles: boolean) {
1755+
const emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFiles, isBundledEmit, emitOnlyDtsFiles);
17561756
const emitSkipped = emitDeclarationResult.reportedDeclarationError || host.isEmitBlocked(declarationFilePath) || host.getCompilerOptions().noEmit;
17571757
if (!emitSkipped) {
17581758
const declarationOutput = emitDeclarationResult.referencesOutput

src/compiler/emitter.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -8365,7 +8365,7 @@ const _super = (function (geti, seti) {
83658365
}
83668366

83678367
function emitFile({ jsFilePath, sourceMapFilePath, declarationFilePath }: EmitFileNames,
8368-
sourceFiles: SourceFile[], isBundledEmit: boolean) {
8368+
sourceFiles: SourceFile[], isBundledEmit: boolean, emitOnlyDtsFiles: boolean) {
83698369
if (!emitOnlyDtsFiles) {
83708370
// Make sure not to write js File and source map file if any of them cannot be written
83718371
if (!host.isEmitBlocked(jsFilePath) && !compilerOptions.noEmit) {
@@ -8377,7 +8377,7 @@ const _super = (function (geti, seti) {
83778377
}
83788378

83798379
if (declarationFilePath) {
8380-
emitSkipped = writeDeclarationFile(declarationFilePath, sourceFiles, isBundledEmit, host, resolver, emitterDiagnostics) || emitSkipped;
8380+
emitSkipped = writeDeclarationFile(declarationFilePath, sourceFiles, isBundledEmit, host, resolver, emitterDiagnostics, emitOnlyDtsFiles) || emitSkipped;
83818381
}
83828382

83838383
if (!emitSkipped && emittedFilesList) {

src/compiler/utilities.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -2231,7 +2231,7 @@ namespace ts {
22312231
}
22322232

22332233
export function forEachExpectedEmitFile(host: EmitHost,
2234-
action: (emitFileNames: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean) => void,
2234+
action: (emitFileNames: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean, emitOnlyDtsFiles: boolean) => void,
22352235
targetSourceFile?: SourceFile,
22362236
emitOnlyDtsFiles?: boolean) {
22372237
const options = host.getCompilerOptions();
@@ -2272,7 +2272,7 @@ namespace ts {
22722272
sourceMapFilePath: getSourceMapFilePath(jsFilePath, options),
22732273
declarationFilePath
22742274
};
2275-
action(emitFileNames, [sourceFile], /*isBundledEmit*/false);
2275+
action(emitFileNames, [sourceFile], /*isBundledEmit*/false, emitOnlyDtsFiles);
22762276
}
22772277

22782278
function onBundledEmit(host: EmitHost) {
@@ -2290,7 +2290,7 @@ namespace ts {
22902290
sourceMapFilePath: getSourceMapFilePath(jsFilePath, options),
22912291
declarationFilePath: options.declaration ? removeFileExtension(jsFilePath) + ".d.ts" : undefined
22922292
};
2293-
action(emitFileNames, bundledSources, /*isBundledEmit*/true);
2293+
action(emitFileNames, bundledSources, /*isBundledEmit*/true, emitOnlyDtsFiles);
22942294
}
22952295
}
22962296

src/harness/unittests/tsserverProjectSystem.ts

+22
Original file line numberDiff line numberDiff line change
@@ -1844,6 +1844,28 @@ namespace ts {
18441844
session.executeCommand(changeFile1Consumer1ShapeRequest);
18451845
sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [moduleFile1, file1Consumer1, file1Consumer1Consumer1]);
18461846
});
1847+
1848+
it("should work fine for files with circular references", () => {
1849+
const file1: FileOrFolder = {
1850+
path: "/a/b/file1.ts",
1851+
content: `
1852+
/// <reference path="./file2.ts" />
1853+
export var t1 = 10;`
1854+
};
1855+
const file2: FileOrFolder = {
1856+
path: "/a/b/file2.ts",
1857+
content: `
1858+
/// <reference path="./file1.ts" />
1859+
export var t2 = 10;`
1860+
};
1861+
host = createServerHost([file1, file2, configFile]);
1862+
typingsInstaller = new TestTypingsInstaller("/a/data/", host);
1863+
session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
1864+
1865+
openFilesForSession([file1, file2], session);
1866+
const file1AffectedListRequest = makeSessionRequest<server.protocol.FileRequestArgs>(server.CommandNames.CompileOnSaveAffectedFileList, { file: file1.path });
1867+
sendAffectedFileRequestAndCheckResult(session, file1AffectedListRequest, [file1, file2]);
1868+
});
18471869
});
18481870
});
18491871

src/server/builder.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ namespace ts.server {
243243

244244
const referencedFilePaths = this.project.getReferencedFiles(fileInfo.scriptInfo.path);
245245
if (referencedFilePaths.length > 0) {
246-
return map(referencedFilePaths, f => this.getFileInfo(f)).sort(ModuleBuilderFileInfo.compareFileInfos);
246+
return map(referencedFilePaths, f => this.getOrCreateFileInfo(f)).sort(ModuleBuilderFileInfo.compareFileInfos);
247247
}
248248
return [];
249249
}

0 commit comments

Comments
 (0)