@ttsc/unplugin 0.30.1 → 0.30.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,6 +6,7 @@ import path from 'node:path';
6
6
  import { TtscCompiler } from 'ttsc';
7
7
  import { createFilesystemPathIdentityContext, resolveFilesystemPath } from 'ttsc/path-identity';
8
8
  import { findNearestProjectTsconfig, isIgnoredProjectDirectory } from './projectDiscovery.mjs';
9
+ import { matchesProjectRootFile } from './projectRootFiles.mjs';
9
10
  import { mergeMembershipPolicyOverlay, PERMISSIVE_PROJECT_MEMBERSHIP_POLICY, readProjectMembershipPolicy, readEffectiveTsconfigPaths, readEffectiveTsconfigTemplateCompilerOptions, readEffectiveTsconfigTemplateFileSpecs, readTsconfigSourceSnapshot, CONFIG_DIR_TEMPLATE_SCALAR_OPTIONS, resolveConfigDirTemplatePath, CONFIG_DIR_TEMPLATE_LIST_OPTIONS, absolutizePathsTarget } from './tsconfigPaths.mjs';
10
11
 
11
12
  const TTSC_SEMANTIC_CONFIG_PATH = "TTSC_SEMANTIC_CONFIG_PATH";
@@ -1575,6 +1576,20 @@ function matchesCachedSource(cached, file, source, epoch) {
1575
1576
  const expected = cached.sourceHashes?.[identity] ??
1576
1577
  cached.inputHashes[currentKey] ??
1577
1578
  cached.externalInputHashes?.[identity];
1579
+ if (expected === undefined &&
1580
+ cached.result.type === "success" &&
1581
+ !matchesProjectRootFile(file, cached.membershipPolicy, false)) {
1582
+ const state = envelopeDerivation(cached);
1583
+ const outputs = (state.outputIndex ??= createEnvelopeKeyIndex(state, cached.projectRoot, cached.result.typescript));
1584
+ if (!outputs.has(identity)) {
1585
+ // Root discovery deliberately never hashed this unrelated module. Its
1586
+ // bytes cannot affect an output the compiler did not produce, but the
1587
+ // whole program must still be current before we reuse that absence: a
1588
+ // changed config or importer can bring this file into the next program.
1589
+ refreshFilesystemClockReference(TRANSFORM_CLOCK_REFERENCE_DIRECTORIES.get(cached), resultFilesystem(cached.result));
1590
+ return matchesCompleteInputSnapshot(cached, currentKey, source);
1591
+ }
1592
+ }
1578
1593
  if (expected !== hashText(source)) {
1579
1594
  return false;
1580
1595
  }
@@ -3010,7 +3025,8 @@ function walkProjectInputs(root, filesystem = DEFAULT_FILESYSTEM_OPERATIONS, pol
3010
3025
  continue;
3011
3026
  }
3012
3027
  const file = path.join(current, entry.name);
3013
- if (entry.isDirectory() && isExcludedProjectDirectory(file, policy)) {
3028
+ if ((entry.isDirectory() && isExcludedProjectDirectory(file, policy)) ||
3029
+ !matchesProjectRootFile(file, policy, entry.isDirectory())) {
3014
3030
  continue;
3015
3031
  }
3016
3032
  const possible = isPossibleProgramEntry(entry, policy);
@@ -3315,31 +3331,29 @@ function insideExcludedProjectDirectory(location, policy, strictly) {
3315
3331
  * name the host did not report is unattributable and always counts.
3316
3332
  */
3317
3333
  function reportsProgramMembership(location, filename, policy, filesystem) {
3318
- if (isPossibleProgramFileName(filename, policy)) {
3319
- // A name the program could admit. It still says nothing if it lies inside a
3320
- // directory the walk never descends into, because the digest cannot see
3321
- // there either and the tracker must not be the one side that reacts.
3322
- return !insideExcludedProjectDirectory(location, policy, true);
3334
+ if (!matchesProjectRootFile(location, policy, false) &&
3335
+ !matchesProjectRootFile(location, policy, true)) {
3336
+ return false;
3323
3337
  }
3324
- let directory;
3325
3338
  try {
3326
- directory = filesystem.lstat(location).isDirectory();
3339
+ if (filesystem.lstat(location).isDirectory()) {
3340
+ return (matchesProjectRootFile(location, policy, true) &&
3341
+ !insideExcludedProjectDirectory(location, policy, false));
3342
+ }
3327
3343
  }
3328
3344
  catch {
3329
- // Gone again, or unreadable. Its name could not have been a program input,
3330
- // and a directory removed under this one reports its own contents leaving
3331
- // through the watch that was opened on it.
3332
- return false;
3345
+ // Deleted file names still need classification below.
3333
3346
  }
3334
- if (!directory) {
3335
- return false;
3347
+ if (isPossibleProgramFileName(filename, policy)) {
3348
+ // A name the program could admit. It still says nothing if it lies inside a
3349
+ // directory the walk never descends into, because the digest cannot see
3350
+ // there either and the tracker must not be the one side that reacts.
3351
+ return (matchesProjectRootFile(location, policy, false) &&
3352
+ !insideExcludedProjectDirectory(location, policy, true));
3336
3353
  }
3337
- // A directory counts, because it can hold sources and the tracker is not
3338
- // watching it yet, unless the configuration says the program does not contain
3339
- // it. Emptying and recreating an `outDir`, which is what `emptyOutDir` and
3340
- // `output.clean` do on every build, would otherwise void the generation once
3341
- // per build on every host that has no build boundary.
3342
- return !insideExcludedProjectDirectory(location, policy, false);
3354
+ // Removed directories report their source removals through their own watch.
3355
+ // A non-source file name cannot introduce program membership.
3356
+ return false;
3343
3357
  }
3344
3358
  /** Record enough exact mutation evidence without retaining an event stream. */
3345
3359
  function recordProjectMutation(tracker, changed) {
@@ -3740,7 +3754,8 @@ function isProjectWalkPath(root, file, _identities = createHostPathIdentityConte
3740
3754
  // a graph input the compiler really read in neither snapshot: absent from
3741
3755
  // `inputHashes` because the walk skipped it, and absent from the out-of-walk
3742
3756
  // snapshot because this predicate claimed the walk covered it.
3743
- if (!isPossibleProgramFileName(path.basename(file), policy)) {
3757
+ if (!isPossibleProgramFileName(path.basename(file), policy) ||
3758
+ !matchesProjectRootFile(file, policy, false)) {
3744
3759
  return false;
3745
3760
  }
3746
3761
  let current = resolvedRoot;