diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts
index 3642ee7f10a..648df9a702d 100644
--- a/src/compiler/declarationEmitter.ts
+++ b/src/compiler/declarationEmitter.ts
@@ -36,12 +36,12 @@ namespace ts {
return declarationDiagnostics.getDiagnostics(targetSourceFile ? targetSourceFile.fileName : undefined);
function getDeclarationDiagnosticsFromFile({ declarationFilePath }: EmitFileNames, sources: SourceFile[], isBundledEmit: boolean) {
- emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath, sources, isBundledEmit);
+ emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath, sources, isBundledEmit, /*emitOnlyDtsFiles*/ false);
}
}
function emitDeclarations(host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, declarationFilePath: string,
- sourceFiles: SourceFile[], isBundledEmit: boolean): DeclarationEmit {
+ sourceFiles: SourceFile[], isBundledEmit: boolean, emitOnlyDtsFiles: boolean): DeclarationEmit {
const newLine = host.getNewLine();
const compilerOptions = host.getCompilerOptions();
@@ -98,7 +98,7 @@ namespace ts {
// global file reference is added only
// - if it is not bundled emit (because otherwise it would be self reference)
// - and it is not already added
- if (writeReferencePath(referencedFile, !isBundledEmit && !addedGlobalFileReference)) {
+ if (writeReferencePath(referencedFile, !isBundledEmit && !addedGlobalFileReference, emitOnlyDtsFiles)) {
addedGlobalFileReference = true;
}
emittedReferencedFiles.push(referencedFile);
@@ -1713,7 +1713,7 @@ namespace ts {
* @param referencedFile
* @param addBundledFileReference Determines if global file reference corresponding to bundled file should be emitted or not
*/
- function writeReferencePath(referencedFile: SourceFile, addBundledFileReference: boolean): boolean {
+ function writeReferencePath(referencedFile: SourceFile, addBundledFileReference: boolean, emitOnlyDtsFiles: boolean): boolean {
let declFileName: string;
let addedBundledEmitReference = false;
if (isDeclarationFile(referencedFile)) {
@@ -1722,7 +1722,7 @@ namespace ts {
}
else {
// Get the declaration file path
- forEachExpectedEmitFile(host, getDeclFileName, referencedFile);
+ forEachExpectedEmitFile(host, getDeclFileName, referencedFile, emitOnlyDtsFiles);
}
if (declFileName) {
@@ -1751,8 +1751,8 @@ namespace ts {
}
/* @internal */
- export function writeDeclarationFile(declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection) {
- const emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFiles, isBundledEmit);
+ export function writeDeclarationFile(declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, emitOnlyDtsFiles: boolean) {
+ const emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFiles, isBundledEmit, emitOnlyDtsFiles);
const emitSkipped = emitDeclarationResult.reportedDeclarationError || host.isEmitBlocked(declarationFilePath) || host.getCompilerOptions().noEmit;
if (!emitSkipped) {
const declarationOutput = emitDeclarationResult.referencesOutput
diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts
index ca015edc73e..c3fac679048 100644
--- a/src/compiler/emitter.ts
+++ b/src/compiler/emitter.ts
@@ -8365,7 +8365,7 @@ const _super = (function (geti, seti) {
}
function emitFile({ jsFilePath, sourceMapFilePath, declarationFilePath }: EmitFileNames,
- sourceFiles: SourceFile[], isBundledEmit: boolean) {
+ sourceFiles: SourceFile[], isBundledEmit: boolean, emitOnlyDtsFiles: boolean) {
if (!emitOnlyDtsFiles) {
// Make sure not to write js File and source map file if any of them cannot be written
if (!host.isEmitBlocked(jsFilePath) && !compilerOptions.noEmit) {
@@ -8377,7 +8377,7 @@ const _super = (function (geti, seti) {
}
if (declarationFilePath) {
- emitSkipped = writeDeclarationFile(declarationFilePath, sourceFiles, isBundledEmit, host, resolver, emitterDiagnostics) || emitSkipped;
+ emitSkipped = writeDeclarationFile(declarationFilePath, sourceFiles, isBundledEmit, host, resolver, emitterDiagnostics, emitOnlyDtsFiles) || emitSkipped;
}
if (!emitSkipped && emittedFilesList) {
diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts
index 9d60521d76b..b4e4418dac2 100644
--- a/src/compiler/utilities.ts
+++ b/src/compiler/utilities.ts
@@ -2231,7 +2231,7 @@ namespace ts {
}
export function forEachExpectedEmitFile(host: EmitHost,
- action: (emitFileNames: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean) => void,
+ action: (emitFileNames: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean, emitOnlyDtsFiles: boolean) => void,
targetSourceFile?: SourceFile,
emitOnlyDtsFiles?: boolean) {
const options = host.getCompilerOptions();
@@ -2272,7 +2272,7 @@ namespace ts {
sourceMapFilePath: getSourceMapFilePath(jsFilePath, options),
declarationFilePath
};
- action(emitFileNames, [sourceFile], /*isBundledEmit*/false);
+ action(emitFileNames, [sourceFile], /*isBundledEmit*/false, emitOnlyDtsFiles);
}
function onBundledEmit(host: EmitHost) {
@@ -2290,7 +2290,7 @@ namespace ts {
sourceMapFilePath: getSourceMapFilePath(jsFilePath, options),
declarationFilePath: options.declaration ? removeFileExtension(jsFilePath) + ".d.ts" : undefined
};
- action(emitFileNames, bundledSources, /*isBundledEmit*/true);
+ action(emitFileNames, bundledSources, /*isBundledEmit*/true, emitOnlyDtsFiles);
}
}
diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts
index 8916c2d4189..736c087ec6a 100644
--- a/src/harness/unittests/tsserverProjectSystem.ts
+++ b/src/harness/unittests/tsserverProjectSystem.ts
@@ -1869,6 +1869,28 @@ namespace ts {
session.executeCommand(changeFile1Consumer1ShapeRequest);
sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [moduleFile1, file1Consumer1, file1Consumer1Consumer1]);
});
+
+ it("should work fine for files with circular references", () => {
+ const file1: FileOrFolder = {
+ path: "/a/b/file1.ts",
+ content: `
+ ///
+ export var t1 = 10;`
+ };
+ const file2: FileOrFolder = {
+ path: "/a/b/file2.ts",
+ content: `
+ ///
+ export var t2 = 10;`
+ };
+ host = createServerHost([file1, file2, configFile]);
+ typingsInstaller = new TestTypingsInstaller("/a/data/", host);
+ session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
+
+ openFilesForSession([file1, file2], session);
+ const file1AffectedListRequest = makeSessionRequest(server.CommandNames.CompileOnSaveAffectedFileList, { file: file1.path });
+ sendAffectedFileRequestAndCheckResult(session, file1AffectedListRequest, [file1, file2]);
+ });
});
});
diff --git a/src/server/builder.ts b/src/server/builder.ts
index 19e515c4459..9310976ddc0 100644
--- a/src/server/builder.ts
+++ b/src/server/builder.ts
@@ -243,7 +243,7 @@ namespace ts.server {
const referencedFilePaths = this.project.getReferencedFiles(fileInfo.scriptInfo.path);
if (referencedFilePaths.length > 0) {
- return map(referencedFilePaths, f => this.getFileInfo(f)).sort(ModuleBuilderFileInfo.compareFileInfos);
+ return map(referencedFilePaths, f => this.getOrCreateFileInfo(f)).sort(ModuleBuilderFileInfo.compareFileInfos);
}
return [];
}