From 69bf73f3a2465953ba32c20e9d77bc842e35de3e Mon Sep 17 00:00:00 2001
From: Ryan Cavanaugh <RyanCavanaugh@users.noreply.github.com>
Date: Mon, 2 Jul 2018 10:53:38 -0700
Subject: [PATCH 1/2] Handle multiple output .d.ts files changedness correctly

Fixes #25337
---
 src/compiler/tsbuild.ts                      | 32 ++++++++++++--------
 tests/projects/sample1/core/anotherModule.ts |  1 +
 2 files changed, 21 insertions(+), 12 deletions(-)
 create mode 100644 tests/projects/sample1/core/anotherModule.ts

diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts
index 498b9eb6432e1..0229e0885f717 100644
--- a/src/compiler/tsbuild.ts
+++ b/src/compiler/tsbuild.ts
@@ -126,12 +126,12 @@ namespace ts {
          */
         export interface UpToDate {
             type: UpToDateStatusType.UpToDate | UpToDateStatusType.UpToDateWithUpstreamTypes;
-            newestInputFileTime: Date;
-            newestInputFileName: string;
-            newestDeclarationFileContentChangedTime: Date;
-            newestOutputFileTime: Date;
-            newestOutputFileName: string;
-            oldestOutputFileName: string;
+            newestInputFileTime?: Date;
+            newestInputFileName?: string;
+            newestDeclarationFileContentChangedTime?: Date;
+            newestOutputFileTime?: Date;
+            newestOutputFileName?: string;
+            oldestOutputFileName?: string;
         }
 
         /**
@@ -801,15 +801,19 @@ namespace ts {
             }
 
             let newestDeclarationFileContentChangedTime = minimumDate;
+            let anyDtsChanged = false;
             program.emit(/*targetSourceFile*/ undefined, (fileName, content, writeBom, onError) => {
                 let priorChangeTime: Date | undefined;
 
-                if (isDeclarationFile(fileName) && compilerHost.fileExists(fileName)) {
+                if (!anyDtsChanged && isDeclarationFile(fileName) && compilerHost.fileExists(fileName)) {
                     if (compilerHost.readFile(fileName) === content) {
                         // Check for unchanged .d.ts files
                         resultFlags &= ~BuildResultFlags.DeclarationOutputUnchanged;
                         priorChangeTime = compilerHost.getModifiedTime && compilerHost.getModifiedTime(fileName);
                     }
+                    else {
+                        anyDtsChanged = true;
+                    }
                 }
 
                 compilerHost.writeFile(fileName, content, writeBom, onError, emptyArray);
@@ -819,7 +823,11 @@ namespace ts {
                 }
             });
 
-            context.projectStatus.setValue(proj, { type: UpToDateStatusType.UpToDate, newestDeclarationFileContentChangedTime } as UpToDateStatus);
+            const status: UpToDateStatus = {
+                type: UpToDateStatusType.UpToDate,
+                newestDeclarationFileContentChangedTime: anyDtsChanged ? maximumDate : newestDeclarationFileContentChangedTime
+            };
+            context.projectStatus.setValue(proj, status);
             return resultFlags;
         }
 
@@ -1134,13 +1142,13 @@ namespace ts {
 
                 // If the upstream project's newest file is older than our oldest output, we
                 // can't be out of date because of it
-                if (refStatus.newestInputFileTime <= oldestOutputFileTime) {
+                if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
                     continue;
                 }
 
                 // If the upstream project has only change .d.ts files, and we've built
                 // *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild
-                if (refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
+                if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
                     pseudoUpToDate = true;
                     upstreamChangedProject = ref.path;
                     continue;
@@ -1224,8 +1232,8 @@ namespace ts {
                 if (status.newestInputFileTime !== undefined) {
                     return formatMessage(Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2,
                         relName(configFileName),
-                        relName(status.newestInputFileName),
-                        relName(status.oldestOutputFileName));
+                        relName(status.newestInputFileName || ""),
+                        relName(status.oldestOutputFileName || ""));
                 }
                 // Don't report anything for "up to date because it was already built" -- too verbose
                 break;
diff --git a/tests/projects/sample1/core/anotherModule.ts b/tests/projects/sample1/core/anotherModule.ts
new file mode 100644
index 0000000000000..aaeaf200cc68d
--- /dev/null
+++ b/tests/projects/sample1/core/anotherModule.ts
@@ -0,0 +1 @@
+export const World = "hello";

From 3031f7b3e56712c8bce31c2320984c20dfe39ccf Mon Sep 17 00:00:00 2001
From: Ryan Cavanaugh <RyanCavanaugh@users.noreply.github.com>
Date: Mon, 2 Jul 2018 11:38:53 -0700
Subject: [PATCH 2/2] Baseline update

---
 tests/baselines/reference/api/tsserverlibrary.d.ts | 12 ++++++------
 tests/baselines/reference/api/typescript.d.ts      | 12 ++++++------
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts
index a58523852cb28..7923cf87450a5 100644
--- a/tests/baselines/reference/api/tsserverlibrary.d.ts
+++ b/tests/baselines/reference/api/tsserverlibrary.d.ts
@@ -9528,12 +9528,12 @@ declare namespace ts {
          */
         interface UpToDate {
             type: UpToDateStatusType.UpToDate | UpToDateStatusType.UpToDateWithUpstreamTypes;
-            newestInputFileTime: Date;
-            newestInputFileName: string;
-            newestDeclarationFileContentChangedTime: Date;
-            newestOutputFileTime: Date;
-            newestOutputFileName: string;
-            oldestOutputFileName: string;
+            newestInputFileTime?: Date;
+            newestInputFileName?: string;
+            newestDeclarationFileContentChangedTime?: Date;
+            newestOutputFileTime?: Date;
+            newestOutputFileName?: string;
+            oldestOutputFileName?: string;
         }
         /**
          * One or more of the outputs of the project does not exist.
diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts
index 99cc7989375c1..cbc10a2e91fd4 100644
--- a/tests/baselines/reference/api/typescript.d.ts
+++ b/tests/baselines/reference/api/typescript.d.ts
@@ -4476,12 +4476,12 @@ declare namespace ts {
          */
         interface UpToDate {
             type: UpToDateStatusType.UpToDate | UpToDateStatusType.UpToDateWithUpstreamTypes;
-            newestInputFileTime: Date;
-            newestInputFileName: string;
-            newestDeclarationFileContentChangedTime: Date;
-            newestOutputFileTime: Date;
-            newestOutputFileName: string;
-            oldestOutputFileName: string;
+            newestInputFileTime?: Date;
+            newestInputFileName?: string;
+            newestDeclarationFileContentChangedTime?: Date;
+            newestOutputFileTime?: Date;
+            newestOutputFileName?: string;
+            oldestOutputFileName?: string;
         }
         /**
          * One or more of the outputs of the project does not exist.