@@ -2,6 +2,7 @@ package build
22
33import (
44 "fmt"
5+ "slices"
56 "strings"
67 "sync"
78 "sync/atomic"
@@ -63,6 +64,7 @@ type BuildTask struct {
6364
6465 buildInfoEntry * buildInfoEntry
6566 buildInfoEntryMu sync.Mutex
67+ packageJsons []string
6668
6769 errors []* ast.Diagnostic
6870 pending atomic.Bool
@@ -231,6 +233,7 @@ func (t *BuildTask) compileAndEmit(orchestrator *Orchestrator, path tspath.Path)
231233 })
232234 t .result .exitStatus = result .Status
233235 t .result .statistics = statistics
236+ t .packageJsons = t .result .program .PackageJsonLookupPaths ()
234237 if (! program .Options ().NoEmitOnError .IsTrue () || len (result .Diagnostics ) == 0 ) &&
235238 (len (result .EmitResult .EmittedFiles ) > 0 || t .status .kind != upToDateStatusTypeOutOfDateBuildInfoWithErrors ) {
236239 // Update time stamps for rest of the outputs
@@ -327,6 +330,9 @@ func (t *BuildTask) getUpToDateStatus(orchestrator *Orchestrator, configPath tsp
327330
328331 // Check the build info
329332 buildInfoPath := t .resolved .GetBuildInfoFileName ()
333+ getBuildInfoDirectory := core .Memoize (func () string {
334+ return tspath .GetDirectoryPath (tspath .GetNormalizedAbsolutePath (buildInfoPath , orchestrator .comparePathsOptions .CurrentDirectory ))
335+ })
330336 buildInfo , buildInfoTime := t .loadOrStoreBuildInfo (orchestrator , configPath , buildInfoPath )
331337 if buildInfo == nil {
332338 return & upToDateStatus {kind : upToDateStatusTypeOutputMissing , data : buildInfoPath }
@@ -363,15 +369,17 @@ func (t *BuildTask) getUpToDateStatus(orchestrator *Orchestrator, configPath tsp
363369 }
364370
365371 // Some of the emit files like source map or dts etc are not yet done
366- if buildInfo .IsEmitPending (t .resolved , tspath . GetDirectoryPath ( tspath . GetNormalizedAbsolutePath ( buildInfoPath , orchestrator . comparePathsOptions . CurrentDirectory ) )) {
372+ if buildInfo .IsEmitPending (t .resolved , getBuildInfoDirectory ( )) {
367373 return & upToDateStatus {kind : upToDateStatusTypeOutOfDateOptions , data : buildInfoPath }
368374 }
369375 }
370376 var inputTextUnchanged bool
371377 oldestOutputFileAndTime := fileAndTime {buildInfoPath , buildInfoTime }
372378 var newestInputFileAndTime fileAndTime
373379 var seenRoots collections.Set [tspath.Path ]
374- var buildInfoRootInfoReader * incremental.BuildInfoRootInfoReader
380+ getBuildInfoRootInfoReader := core .Memoize (func () * incremental.BuildInfoRootInfoReader {
381+ return buildInfo .GetBuildInfoRootInfoReader (getBuildInfoDirectory (), orchestrator .comparePathsOptions )
382+ })
375383 for _ , inputFile := range t .resolved .FileNames () {
376384 inputTime := orchestrator .host .GetMTime (inputFile )
377385 if inputTime .IsZero () {
@@ -382,10 +390,7 @@ func (t *BuildTask) getUpToDateStatus(orchestrator *Orchestrator, configPath tsp
382390 var version string
383391 var currentVersion string
384392 if buildInfo .IsIncremental () {
385- if buildInfoRootInfoReader == nil {
386- buildInfoRootInfoReader = buildInfo .GetBuildInfoRootInfoReader (tspath .GetDirectoryPath (tspath .GetNormalizedAbsolutePath (buildInfoPath , orchestrator .comparePathsOptions .CurrentDirectory )), orchestrator .comparePathsOptions )
387- }
388- buildInfoFileInfo , resolvedInputPath := buildInfoRootInfoReader .GetBuildInfoFileInfo (inputPath )
393+ buildInfoFileInfo , resolvedInputPath := getBuildInfoRootInfoReader ().GetBuildInfoFileInfo (inputPath )
389394 if fileInfo := buildInfoFileInfo .GetFileInfo (); fileInfo != nil && fileInfo .Version () != "" {
390395 version = fileInfo .Version ()
391396 if text , ok := orchestrator .host .FS ().ReadFile (string (resolvedInputPath )); ok {
@@ -407,16 +412,54 @@ func (t *BuildTask) getUpToDateStatus(orchestrator *Orchestrator, configPath tsp
407412 seenRoots .Add (inputPath )
408413 }
409414
410- if buildInfoRootInfoReader == nil {
411- buildInfoRootInfoReader = buildInfo .GetBuildInfoRootInfoReader (tspath .GetDirectoryPath (tspath .GetNormalizedAbsolutePath (buildInfoPath , orchestrator .comparePathsOptions .CurrentDirectory )), orchestrator .comparePathsOptions )
412- }
413- for root := range buildInfoRootInfoReader .Roots () {
415+ for root := range getBuildInfoRootInfoReader ().Roots () {
414416 if ! seenRoots .Has (root ) {
415417 // File was root file when project was built but its not any more
416418 return & upToDateStatus {kind : upToDateStatusTypeOutOfDateRoots , data : & inputOutputName {string (root ), buildInfoPath }}
417419 }
418420 }
419421
422+ if buildInfo .IsIncremental () {
423+ var resolvedRoots collections.Set [tspath.Path ]
424+ for root := range getBuildInfoRootInfoReader ().Roots () {
425+ if _ , resolved := getBuildInfoRootInfoReader ().GetBuildInfoFileInfo (root ); resolved != "" {
426+ resolvedRoots .Add (resolved )
427+ }
428+ }
429+ for index , buildInfoFileInfo := range buildInfo .FileInfos {
430+ buildInfoFileName := buildInfo .FileNames [index ]
431+ // Lib files bundled with the compiler can change only with the version of the compiler,
432+ // which is already verified with buildInfo.Version
433+ if incremental .IsBuildInfoFileNameDefaultLibrary (buildInfoFileName ) {
434+ continue
435+ }
436+ inputFile := tspath .GetNormalizedAbsolutePath (buildInfoFileName , getBuildInfoDirectory ())
437+ inputPath := orchestrator .toPath (inputFile )
438+ // Root files are already checked
439+ if seenRoots .Has (inputPath ) || resolvedRoots .Has (inputPath ) {
440+ continue
441+ }
442+ inputTime := orchestrator .host .GetMTime (inputFile )
443+ if inputTime .IsZero () {
444+ // Input file that was part of the program is missing (eg: dependency was removed)
445+ return & upToDateStatus {kind : upToDateStatusTypeInputFileMissing , data : inputFile }
446+ }
447+ if inputTime .After (oldestOutputFileAndTime .time ) {
448+ var currentVersion string
449+ version := buildInfoFileInfo .GetFileInfo ().Version ()
450+ if version != "" {
451+ if text , ok := orchestrator .host .FS ().ReadFile (inputFile ); ok {
452+ currentVersion = incremental .ComputeHash (text , orchestrator .opts .Testing != nil )
453+ }
454+ }
455+ if version == "" || version != currentVersion {
456+ return & upToDateStatus {kind : upToDateStatusTypeInputFileNewer , data : & inputOutputName {inputFile , buildInfoPath }}
457+ }
458+ inputTextUnchanged = true
459+ }
460+ }
461+ }
462+
420463 if ! t .resolved .CompilerOptions ().IsIncremental () {
421464 // Check output file stamps
422465 for outputFile := range t .resolved .GetOutputFileNames () {
@@ -493,14 +536,22 @@ func (t *BuildTask) getUpToDateStatus(orchestrator *Orchestrator, configPath tsp
493536 }
494537 }
495538
496- // !!! sheetal TODO : watch??
497- // // Check package file time
498- // const packageJsonLookups = state.lastCachedPackageJsonLookups.get(resolvedPath);
499- // const dependentPackageFileStatus = packageJsonLookups && forEachKey(
500- // packageJsonLookups,
501- // path => checkConfigFileUpToDateStatus(state, path, oldestOutputFileTime, oldestOutputFileName),
502- // );
503- // if (dependentPackageFileStatus) return dependentPackageFileStatus;
539+ for packageJson := range buildInfo .GetPackageJsons (getBuildInfoDirectory ()) {
540+ packageJsonTime := orchestrator .host .GetMTime (packageJson )
541+ if packageJsonTime .IsZero () {
542+ return & upToDateStatus {kind : upToDateStatusTypeInputFileMissing , data : packageJson }
543+ }
544+ if packageJsonTime .After (oldestOutputFileAndTime .time ) {
545+ return & upToDateStatus {kind : upToDateStatusTypeInputFileNewer , data : & inputOutputName {packageJson , oldestOutputFileAndTime .file }}
546+ }
547+ }
548+ for packageJson := range buildInfo .GetMissingPackageJsons (getBuildInfoDirectory ()) {
549+ if ! orchestrator .host .GetMTime (packageJson ).IsZero () {
550+ return & upToDateStatus {kind : upToDateStatusTypeInputFileNewer , data : & inputOutputName {packageJson , oldestOutputFileAndTime .file }}
551+ }
552+ }
553+ t .packageJsons = slices .Collect (buildInfo .GetPackageJsons (getBuildInfoDirectory ()))
554+ t .packageJsons = append (t .packageJsons , slices .Collect (buildInfo .GetMissingPackageJsons (getBuildInfoDirectory ()))... )
504555
505556 return & upToDateStatus {
506557 kind : core .IfElse (
0 commit comments