@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.
- package/lib/core/projectRootFiles.d.cts +11 -0
- package/lib/core/projectRootFiles.d.mts +11 -0
- package/lib/core/projectRootFiles.d.ts +11 -0
- package/lib/core/projectRootFiles.js +136 -0
- package/lib/core/projectRootFiles.js.map +1 -0
- package/lib/core/projectRootFiles.mjs +134 -0
- package/lib/core/projectRootFiles.mjs.map +1 -0
- package/lib/core/transform.js +36 -21
- package/lib/core/transform.js.map +1 -1
- package/lib/core/transform.mjs +36 -21
- package/lib/core/transform.mjs.map +1 -1
- package/lib/core/tsconfigPaths.d.cts +14 -0
- package/lib/core/tsconfigPaths.d.mts +14 -0
- package/lib/core/tsconfigPaths.d.ts +14 -0
- package/lib/core/tsconfigPaths.js +41 -4
- package/lib/core/tsconfigPaths.js.map +1 -1
- package/lib/core/tsconfigPaths.mjs +41 -4
- package/lib/core/tsconfigPaths.mjs.map +1 -1
- package/package.json +3 -3
- package/src/core/projectRootFiles.ts +151 -0
- package/src/core/transform.ts +55 -21
- package/src/core/tsconfigPaths.ts +64 -4
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ITtscProjectMembershipPolicy } from "./tsconfigPaths.cjs";
|
|
2
|
+
/**
|
|
3
|
+
* Match configured root files or a directory that can contain one.
|
|
4
|
+
*
|
|
5
|
+
* This is discovery, not dependency membership: imports outside these specs
|
|
6
|
+
* remain compiler inputs and are proven by the external-input snapshot.
|
|
7
|
+
* TypeScript's include grammar has only *, ?, ** and implicit directory globs.
|
|
8
|
+
* Unknown policies stay permissive; no filesystem existence probe is needed, so
|
|
9
|
+
* a newly created directory receives the same answer as an existing one.
|
|
10
|
+
*/
|
|
11
|
+
export declare function matchesProjectRootFile(location: string, policy: ITtscProjectMembershipPolicy, directory: boolean): boolean;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ITtscProjectMembershipPolicy } from "./tsconfigPaths.mjs";
|
|
2
|
+
/**
|
|
3
|
+
* Match configured root files or a directory that can contain one.
|
|
4
|
+
*
|
|
5
|
+
* This is discovery, not dependency membership: imports outside these specs
|
|
6
|
+
* remain compiler inputs and are proven by the external-input snapshot.
|
|
7
|
+
* TypeScript's include grammar has only *, ?, ** and implicit directory globs.
|
|
8
|
+
* Unknown policies stay permissive; no filesystem existence probe is needed, so
|
|
9
|
+
* a newly created directory receives the same answer as an existing one.
|
|
10
|
+
*/
|
|
11
|
+
export declare function matchesProjectRootFile(location: string, policy: ITtscProjectMembershipPolicy, directory: boolean): boolean;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ITtscProjectMembershipPolicy } from "./tsconfigPaths";
|
|
2
|
+
/**
|
|
3
|
+
* Match configured root files or a directory that can contain one.
|
|
4
|
+
*
|
|
5
|
+
* This is discovery, not dependency membership: imports outside these specs
|
|
6
|
+
* remain compiler inputs and are proven by the external-input snapshot.
|
|
7
|
+
* TypeScript's include grammar has only *, ?, ** and implicit directory globs.
|
|
8
|
+
* Unknown policies stay permissive; no filesystem existence probe is needed, so
|
|
9
|
+
* a newly created directory receives the same answer as an existing one.
|
|
10
|
+
*/
|
|
11
|
+
export declare function matchesProjectRootFile(location: string, policy: ITtscProjectMembershipPolicy, directory: boolean): boolean;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var path = require('node:path');
|
|
4
|
+
|
|
5
|
+
const compiled = new WeakMap();
|
|
6
|
+
/**
|
|
7
|
+
* Match configured root files or a directory that can contain one.
|
|
8
|
+
*
|
|
9
|
+
* This is discovery, not dependency membership: imports outside these specs
|
|
10
|
+
* remain compiler inputs and are proven by the external-input snapshot.
|
|
11
|
+
* TypeScript's include grammar has only *, ?, ** and implicit directory globs.
|
|
12
|
+
* Unknown policies stay permissive; no filesystem existence probe is needed, so
|
|
13
|
+
* a newly created directory receives the same answer as an existing one.
|
|
14
|
+
*/
|
|
15
|
+
function matchesProjectRootFile(location, policy, directory) {
|
|
16
|
+
if (policy.rootFileSpecs === undefined)
|
|
17
|
+
return true;
|
|
18
|
+
let patterns = compiled.get(policy);
|
|
19
|
+
if (patterns === undefined) {
|
|
20
|
+
patterns = [
|
|
21
|
+
...policy.rootFileSpecs.files.map((spec) => compile(spec, true)),
|
|
22
|
+
...policy.rootFileSpecs.include.map((spec) => compile(spec, false)),
|
|
23
|
+
].filter((pattern) => pattern !== undefined);
|
|
24
|
+
compiled.set(policy, patterns);
|
|
25
|
+
}
|
|
26
|
+
return rootSpellings(location, policy).some((spelling) => {
|
|
27
|
+
const parts = spelling.replace(/\\/g, "/").split("/");
|
|
28
|
+
return patterns.some((pattern) => matches(parts, pattern, directory));
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Config ancestry is anchored physically, but the walk retains lexical paths.
|
|
33
|
+
* Match each equivalent project-root spelling without following child links.
|
|
34
|
+
* Native Windows watchers expand short names even when regular realpath keeps
|
|
35
|
+
* them. Keep patterns intact: a glob can begin above the root, and configDir
|
|
36
|
+
* can retain the requested spelling even when ancestry uses the physical one.
|
|
37
|
+
*/
|
|
38
|
+
function rootSpellings(location, policy) {
|
|
39
|
+
const resolved = path.resolve(location);
|
|
40
|
+
const root = policy.rootFileSpecs?.root;
|
|
41
|
+
if (root === undefined)
|
|
42
|
+
return [resolved];
|
|
43
|
+
const spellings = [
|
|
44
|
+
...new Set([root.path, root.realpath, root.nativepath ?? root.realpath]),
|
|
45
|
+
];
|
|
46
|
+
for (const spelling of spellings) {
|
|
47
|
+
const relative = path.relative(spelling, resolved);
|
|
48
|
+
if (relative !== ".." &&
|
|
49
|
+
!relative.startsWith(`..${path.sep}`) &&
|
|
50
|
+
!path.isAbsolute(relative))
|
|
51
|
+
return spellings.map((candidate) => path.resolve(candidate, relative));
|
|
52
|
+
}
|
|
53
|
+
return [resolved];
|
|
54
|
+
}
|
|
55
|
+
function compile(spec, literal) {
|
|
56
|
+
const parts = path.resolve(spec).replace(/\\/g, "/").split("/");
|
|
57
|
+
if (!literal) {
|
|
58
|
+
const last = parts.at(-1);
|
|
59
|
+
if (last === "**")
|
|
60
|
+
return undefined;
|
|
61
|
+
if (!/[.*?]/.test(last))
|
|
62
|
+
parts.push("**", "*");
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
literal,
|
|
66
|
+
components: parts.map((part) => {
|
|
67
|
+
if (!literal && part === "**")
|
|
68
|
+
return part;
|
|
69
|
+
const wildcard = !literal && /[*?]/.test(part);
|
|
70
|
+
if (!wildcard && process.platform === "linux")
|
|
71
|
+
return part;
|
|
72
|
+
const expression = [...part]
|
|
73
|
+
.map((char) => wildcard && char === "*"
|
|
74
|
+
? "[^/]*"
|
|
75
|
+
: wildcard && char === "?"
|
|
76
|
+
? "[^/]"
|
|
77
|
+
: char.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&"))
|
|
78
|
+
.join("");
|
|
79
|
+
// Case folding on macOS is conservative on case-sensitive volumes.
|
|
80
|
+
// Unicode simple folding also belongs to literal components: lowercasing
|
|
81
|
+
// alone misses equivalences such as Greek sigma/final sigma in Go.
|
|
82
|
+
return {
|
|
83
|
+
expression: new RegExp(`^${wildcard && (part.startsWith("*") || part.startsWith("?")) ? "(?!\\.)" : ""}${expression}$`, process.platform === "linux" ? "u" : "iu"),
|
|
84
|
+
wildcard,
|
|
85
|
+
};
|
|
86
|
+
}),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/** Iterative glob-state traversal avoids recursion on deep directory trees. */
|
|
90
|
+
function matches(parts, pattern, directory) {
|
|
91
|
+
const { components } = pattern;
|
|
92
|
+
let states = new Set([0]);
|
|
93
|
+
const expand = () => {
|
|
94
|
+
for (const state of states) {
|
|
95
|
+
if (!pattern.literal && components[state] === "**")
|
|
96
|
+
states.add(state + 1);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
for (const part of parts) {
|
|
100
|
+
expand();
|
|
101
|
+
const next = new Set();
|
|
102
|
+
for (const state of states) {
|
|
103
|
+
const component = components[state];
|
|
104
|
+
if (component === undefined)
|
|
105
|
+
continue;
|
|
106
|
+
if (!pattern.literal && component === "**") {
|
|
107
|
+
if (!part.startsWith(".") && !isPackageDirectory(part))
|
|
108
|
+
next.add(state);
|
|
109
|
+
}
|
|
110
|
+
else if (typeof component !== "string") {
|
|
111
|
+
if ((!component.wildcard || !isPackageDirectory(part)) &&
|
|
112
|
+
component.expression.test(part))
|
|
113
|
+
next.add(state + 1);
|
|
114
|
+
}
|
|
115
|
+
else if (component === part) {
|
|
116
|
+
next.add(state + 1);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (next.size === 0)
|
|
120
|
+
return false;
|
|
121
|
+
states = next;
|
|
122
|
+
}
|
|
123
|
+
expand();
|
|
124
|
+
// A directory needs a remaining filename component, not just a completed
|
|
125
|
+
// exact-file match; otherwise `include: ["*.ts"]` would descend into a
|
|
126
|
+
// directory named `artifact.ts` and watch its unrelated children.
|
|
127
|
+
return directory
|
|
128
|
+
? [...states].some((state) => state < components.length)
|
|
129
|
+
: states.has(components.length);
|
|
130
|
+
}
|
|
131
|
+
function isPackageDirectory(name) {
|
|
132
|
+
return /^(node_modules|bower_components|jspm_packages)$/i.test(name);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
exports.matchesProjectRootFile = matchesProjectRootFile;
|
|
136
|
+
//# sourceMappingURL=projectRootFiles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projectRootFiles.js","sources":["../../src/core/projectRootFiles.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
|
|
3
|
+
const compiled = new WeakMap();
|
|
4
|
+
/**
|
|
5
|
+
* Match configured root files or a directory that can contain one.
|
|
6
|
+
*
|
|
7
|
+
* This is discovery, not dependency membership: imports outside these specs
|
|
8
|
+
* remain compiler inputs and are proven by the external-input snapshot.
|
|
9
|
+
* TypeScript's include grammar has only *, ?, ** and implicit directory globs.
|
|
10
|
+
* Unknown policies stay permissive; no filesystem existence probe is needed, so
|
|
11
|
+
* a newly created directory receives the same answer as an existing one.
|
|
12
|
+
*/
|
|
13
|
+
function matchesProjectRootFile(location, policy, directory) {
|
|
14
|
+
if (policy.rootFileSpecs === undefined)
|
|
15
|
+
return true;
|
|
16
|
+
let patterns = compiled.get(policy);
|
|
17
|
+
if (patterns === undefined) {
|
|
18
|
+
patterns = [
|
|
19
|
+
...policy.rootFileSpecs.files.map((spec) => compile(spec, true)),
|
|
20
|
+
...policy.rootFileSpecs.include.map((spec) => compile(spec, false)),
|
|
21
|
+
].filter((pattern) => pattern !== undefined);
|
|
22
|
+
compiled.set(policy, patterns);
|
|
23
|
+
}
|
|
24
|
+
return rootSpellings(location, policy).some((spelling) => {
|
|
25
|
+
const parts = spelling.replace(/\\/g, "/").split("/");
|
|
26
|
+
return patterns.some((pattern) => matches(parts, pattern, directory));
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Config ancestry is anchored physically, but the walk retains lexical paths.
|
|
31
|
+
* Match each equivalent project-root spelling without following child links.
|
|
32
|
+
* Native Windows watchers expand short names even when regular realpath keeps
|
|
33
|
+
* them. Keep patterns intact: a glob can begin above the root, and configDir
|
|
34
|
+
* can retain the requested spelling even when ancestry uses the physical one.
|
|
35
|
+
*/
|
|
36
|
+
function rootSpellings(location, policy) {
|
|
37
|
+
const resolved = path.resolve(location);
|
|
38
|
+
const root = policy.rootFileSpecs?.root;
|
|
39
|
+
if (root === undefined)
|
|
40
|
+
return [resolved];
|
|
41
|
+
const spellings = [
|
|
42
|
+
...new Set([root.path, root.realpath, root.nativepath ?? root.realpath]),
|
|
43
|
+
];
|
|
44
|
+
for (const spelling of spellings) {
|
|
45
|
+
const relative = path.relative(spelling, resolved);
|
|
46
|
+
if (relative !== ".." &&
|
|
47
|
+
!relative.startsWith(`..${path.sep}`) &&
|
|
48
|
+
!path.isAbsolute(relative))
|
|
49
|
+
return spellings.map((candidate) => path.resolve(candidate, relative));
|
|
50
|
+
}
|
|
51
|
+
return [resolved];
|
|
52
|
+
}
|
|
53
|
+
function compile(spec, literal) {
|
|
54
|
+
const parts = path.resolve(spec).replace(/\\/g, "/").split("/");
|
|
55
|
+
if (!literal) {
|
|
56
|
+
const last = parts.at(-1);
|
|
57
|
+
if (last === "**")
|
|
58
|
+
return undefined;
|
|
59
|
+
if (!/[.*?]/.test(last))
|
|
60
|
+
parts.push("**", "*");
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
literal,
|
|
64
|
+
components: parts.map((part) => {
|
|
65
|
+
if (!literal && part === "**")
|
|
66
|
+
return part;
|
|
67
|
+
const wildcard = !literal && /[*?]/.test(part);
|
|
68
|
+
if (!wildcard && process.platform === "linux")
|
|
69
|
+
return part;
|
|
70
|
+
const expression = [...part]
|
|
71
|
+
.map((char) => wildcard && char === "*"
|
|
72
|
+
? "[^/]*"
|
|
73
|
+
: wildcard && char === "?"
|
|
74
|
+
? "[^/]"
|
|
75
|
+
: char.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&"))
|
|
76
|
+
.join("");
|
|
77
|
+
// Case folding on macOS is conservative on case-sensitive volumes.
|
|
78
|
+
// Unicode simple folding also belongs to literal components: lowercasing
|
|
79
|
+
// alone misses equivalences such as Greek sigma/final sigma in Go.
|
|
80
|
+
return {
|
|
81
|
+
expression: new RegExp(`^${wildcard && (part.startsWith("*") || part.startsWith("?")) ? "(?!\\.)" : ""}${expression}$`, process.platform === "linux" ? "u" : "iu"),
|
|
82
|
+
wildcard,
|
|
83
|
+
};
|
|
84
|
+
}),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/** Iterative glob-state traversal avoids recursion on deep directory trees. */
|
|
88
|
+
function matches(parts, pattern, directory) {
|
|
89
|
+
const { components } = pattern;
|
|
90
|
+
let states = new Set([0]);
|
|
91
|
+
const expand = () => {
|
|
92
|
+
for (const state of states) {
|
|
93
|
+
if (!pattern.literal && components[state] === "**")
|
|
94
|
+
states.add(state + 1);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
for (const part of parts) {
|
|
98
|
+
expand();
|
|
99
|
+
const next = new Set();
|
|
100
|
+
for (const state of states) {
|
|
101
|
+
const component = components[state];
|
|
102
|
+
if (component === undefined)
|
|
103
|
+
continue;
|
|
104
|
+
if (!pattern.literal && component === "**") {
|
|
105
|
+
if (!part.startsWith(".") && !isPackageDirectory(part))
|
|
106
|
+
next.add(state);
|
|
107
|
+
}
|
|
108
|
+
else if (typeof component !== "string") {
|
|
109
|
+
if ((!component.wildcard || !isPackageDirectory(part)) &&
|
|
110
|
+
component.expression.test(part))
|
|
111
|
+
next.add(state + 1);
|
|
112
|
+
}
|
|
113
|
+
else if (component === part) {
|
|
114
|
+
next.add(state + 1);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (next.size === 0)
|
|
118
|
+
return false;
|
|
119
|
+
states = next;
|
|
120
|
+
}
|
|
121
|
+
expand();
|
|
122
|
+
// A directory needs a remaining filename component, not just a completed
|
|
123
|
+
// exact-file match; otherwise `include: ["*.ts"]` would descend into a
|
|
124
|
+
// directory named `artifact.ts` and watch its unrelated children.
|
|
125
|
+
return directory
|
|
126
|
+
? [...states].some((state) => state < components.length)
|
|
127
|
+
: states.has(components.length);
|
|
128
|
+
}
|
|
129
|
+
function isPackageDirectory(name) {
|
|
130
|
+
return /^(node_modules|bower_components|jspm_packages)$/i.test(name);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export { matchesProjectRootFile };
|
|
134
|
+
//# sourceMappingURL=projectRootFiles.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projectRootFiles.mjs","sources":["../../src/core/projectRootFiles.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
package/lib/core/transform.js
CHANGED
|
@@ -8,6 +8,7 @@ var path = require('node:path');
|
|
|
8
8
|
var ttsc = require('ttsc');
|
|
9
9
|
var pathIdentity = require('ttsc/path-identity');
|
|
10
10
|
var projectDiscovery = require('./projectDiscovery.js');
|
|
11
|
+
var projectRootFiles = require('./projectRootFiles.js');
|
|
11
12
|
var tsconfigPaths = require('./tsconfigPaths.js');
|
|
12
13
|
|
|
13
14
|
const TTSC_SEMANTIC_CONFIG_PATH = "TTSC_SEMANTIC_CONFIG_PATH";
|
|
@@ -1577,6 +1578,20 @@ function matchesCachedSource(cached, file, source, epoch) {
|
|
|
1577
1578
|
const expected = cached.sourceHashes?.[identity] ??
|
|
1578
1579
|
cached.inputHashes[currentKey] ??
|
|
1579
1580
|
cached.externalInputHashes?.[identity];
|
|
1581
|
+
if (expected === undefined &&
|
|
1582
|
+
cached.result.type === "success" &&
|
|
1583
|
+
!projectRootFiles.matchesProjectRootFile(file, cached.membershipPolicy, false)) {
|
|
1584
|
+
const state = envelopeDerivation(cached);
|
|
1585
|
+
const outputs = (state.outputIndex ??= createEnvelopeKeyIndex(state, cached.projectRoot, cached.result.typescript));
|
|
1586
|
+
if (!outputs.has(identity)) {
|
|
1587
|
+
// Root discovery deliberately never hashed this unrelated module. Its
|
|
1588
|
+
// bytes cannot affect an output the compiler did not produce, but the
|
|
1589
|
+
// whole program must still be current before we reuse that absence: a
|
|
1590
|
+
// changed config or importer can bring this file into the next program.
|
|
1591
|
+
refreshFilesystemClockReference(TRANSFORM_CLOCK_REFERENCE_DIRECTORIES.get(cached), resultFilesystem(cached.result));
|
|
1592
|
+
return matchesCompleteInputSnapshot(cached, currentKey, source);
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1580
1595
|
if (expected !== hashText(source)) {
|
|
1581
1596
|
return false;
|
|
1582
1597
|
}
|
|
@@ -3012,7 +3027,8 @@ function walkProjectInputs(root, filesystem = DEFAULT_FILESYSTEM_OPERATIONS, pol
|
|
|
3012
3027
|
continue;
|
|
3013
3028
|
}
|
|
3014
3029
|
const file = path.join(current, entry.name);
|
|
3015
|
-
if (entry.isDirectory() && isExcludedProjectDirectory(file, policy))
|
|
3030
|
+
if ((entry.isDirectory() && isExcludedProjectDirectory(file, policy)) ||
|
|
3031
|
+
!projectRootFiles.matchesProjectRootFile(file, policy, entry.isDirectory())) {
|
|
3016
3032
|
continue;
|
|
3017
3033
|
}
|
|
3018
3034
|
const possible = isPossibleProgramEntry(entry, policy);
|
|
@@ -3317,31 +3333,29 @@ function insideExcludedProjectDirectory(location, policy, strictly) {
|
|
|
3317
3333
|
* name the host did not report is unattributable and always counts.
|
|
3318
3334
|
*/
|
|
3319
3335
|
function reportsProgramMembership(location, filename, policy, filesystem) {
|
|
3320
|
-
if (
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
// there either and the tracker must not be the one side that reacts.
|
|
3324
|
-
return !insideExcludedProjectDirectory(location, policy, true);
|
|
3336
|
+
if (!projectRootFiles.matchesProjectRootFile(location, policy, false) &&
|
|
3337
|
+
!projectRootFiles.matchesProjectRootFile(location, policy, true)) {
|
|
3338
|
+
return false;
|
|
3325
3339
|
}
|
|
3326
|
-
let directory;
|
|
3327
3340
|
try {
|
|
3328
|
-
|
|
3341
|
+
if (filesystem.lstat(location).isDirectory()) {
|
|
3342
|
+
return (projectRootFiles.matchesProjectRootFile(location, policy, true) &&
|
|
3343
|
+
!insideExcludedProjectDirectory(location, policy, false));
|
|
3344
|
+
}
|
|
3329
3345
|
}
|
|
3330
3346
|
catch {
|
|
3331
|
-
//
|
|
3332
|
-
// and a directory removed under this one reports its own contents leaving
|
|
3333
|
-
// through the watch that was opened on it.
|
|
3334
|
-
return false;
|
|
3347
|
+
// Deleted file names still need classification below.
|
|
3335
3348
|
}
|
|
3336
|
-
if (
|
|
3337
|
-
|
|
3349
|
+
if (isPossibleProgramFileName(filename, policy)) {
|
|
3350
|
+
// A name the program could admit. It still says nothing if it lies inside a
|
|
3351
|
+
// directory the walk never descends into, because the digest cannot see
|
|
3352
|
+
// there either and the tracker must not be the one side that reacts.
|
|
3353
|
+
return (projectRootFiles.matchesProjectRootFile(location, policy, false) &&
|
|
3354
|
+
!insideExcludedProjectDirectory(location, policy, true));
|
|
3338
3355
|
}
|
|
3339
|
-
//
|
|
3340
|
-
//
|
|
3341
|
-
|
|
3342
|
-
// `output.clean` do on every build, would otherwise void the generation once
|
|
3343
|
-
// per build on every host that has no build boundary.
|
|
3344
|
-
return !insideExcludedProjectDirectory(location, policy, false);
|
|
3356
|
+
// Removed directories report their source removals through their own watch.
|
|
3357
|
+
// A non-source file name cannot introduce program membership.
|
|
3358
|
+
return false;
|
|
3345
3359
|
}
|
|
3346
3360
|
/** Record enough exact mutation evidence without retaining an event stream. */
|
|
3347
3361
|
function recordProjectMutation(tracker, changed) {
|
|
@@ -3742,7 +3756,8 @@ function isProjectWalkPath(root, file, _identities = createHostPathIdentityConte
|
|
|
3742
3756
|
// a graph input the compiler really read in neither snapshot: absent from
|
|
3743
3757
|
// `inputHashes` because the walk skipped it, and absent from the out-of-walk
|
|
3744
3758
|
// snapshot because this predicate claimed the walk covered it.
|
|
3745
|
-
if (!isPossibleProgramFileName(path.basename(file), policy)
|
|
3759
|
+
if (!isPossibleProgramFileName(path.basename(file), policy) ||
|
|
3760
|
+
!projectRootFiles.matchesProjectRootFile(file, policy, false)) {
|
|
3746
3761
|
return false;
|
|
3747
3762
|
}
|
|
3748
3763
|
let current = resolvedRoot;
|