66 * found in the LICENSE file at https://angular.dev/license
77 */
88
9+ import { toPosixPath } from '../../utils/path' ;
910import { ExecutionResult } from './execution-result' ;
1011import type {
1112 BundleResult ,
@@ -15,10 +16,12 @@ import type {
1516} from './types' ;
1617
1718/**
18- * Encapsulates incremental compilation state, watched compilation file tracking,
19- * and execution results across watch-mode rebuilds.
19+ * Encapsulates incremental compilation state, transitive resource reference tracking,
20+ * watched compilation file tracking, and execution results across watch-mode rebuilds.
2021 */
2122export class BuilderState {
23+ readonly #referencingFiles = new Map < string , Set < string > > ( ) ;
24+ readonly #referencedByFile = new Map < string , Set < string > > ( ) ;
2225 readonly #watchedCompilationFiles = new Set < string > ( ) ;
2326 readonly #pendingCompilationFiles = new Set < string > ( ) ;
2427
@@ -116,6 +119,82 @@ export class BuilderState {
116119 return this . #executionResult;
117120 }
118121
122+ /**
123+ * Records transitive resource dependencies (such as Sass partials) for a containing
124+ * component or stylesheet file, pruning any previously recorded references for that
125+ * containing file and registering the current references in `watchedCompilationFiles`.
126+ *
127+ * @param containingFile Path of the referencing component or stylesheet file.
128+ * @param referencedFiles Paths of the referenced files.
129+ */
130+ addFileReferences ( containingFile : string , referencedFiles : Iterable < string > ) : void {
131+ const posixContainingFile = toPosixPath ( containingFile ) ;
132+
133+ let forwardReferences = this . #referencedByFile. get ( posixContainingFile ) ;
134+ if ( forwardReferences ) {
135+ for ( const prevRef of forwardReferences ) {
136+ const referencing = this . #referencingFiles. get ( prevRef ) ;
137+ if ( referencing ) {
138+ referencing . delete ( posixContainingFile ) ;
139+ if ( referencing . size === 0 ) {
140+ this . #referencingFiles. delete ( prevRef ) ;
141+ }
142+ }
143+ }
144+ forwardReferences . clear ( ) ;
145+ }
146+
147+ for ( const file of referencedFiles ) {
148+ const posixFile = toPosixPath ( file ) ;
149+ this . #watchedCompilationFiles. add ( posixFile ) ;
150+ if ( posixFile === posixContainingFile ) {
151+ continue ;
152+ }
153+
154+ if ( ! forwardReferences ) {
155+ forwardReferences = new Set ( ) ;
156+ this . #referencedByFile. set ( posixContainingFile , forwardReferences ) ;
157+ }
158+ forwardReferences . add ( posixFile ) ;
159+
160+ let referencing = this . #referencingFiles. get ( posixFile ) ;
161+ if ( ! referencing ) {
162+ referencing = new Set ( ) ;
163+ this . #referencingFiles. set ( posixFile , referencing ) ;
164+ }
165+ referencing . add ( posixContainingFile ) ;
166+ }
167+
168+ if ( forwardReferences ?. size === 0 ) {
169+ this . #referencedByFile. delete ( posixContainingFile ) ;
170+ }
171+ }
172+
173+ /**
174+ * Expands a set of changed files with all transitively referencing files
175+ * (e.g., partial `.scss` -> component `.scss` -> component `.ts`).
176+ *
177+ * @param files Initial changed file paths.
178+ * @returns Set of POSIX paths including all transitively referencing files.
179+ */
180+ expandChangedFiles ( files : Iterable < string > ) : Set < string > {
181+ const expanded = new Set < string > ( ) ;
182+ for ( const file of files ) {
183+ expanded . add ( toPosixPath ( file ) ) ;
184+ }
185+
186+ for ( const file of expanded ) {
187+ const referencing = this . #referencingFiles. get ( file ) ;
188+ if ( referencing ) {
189+ for ( const refFile of referencing ) {
190+ expanded . add ( refFile ) ;
191+ }
192+ }
193+ }
194+
195+ return expanded ;
196+ }
197+
119198 /**
120199 * Determines whether compilation and bundling need to run for the current build iteration.
121200 * Also records incoming modified files so they are retained if the iteration aborts early.
@@ -235,6 +314,8 @@ export class BuilderState {
235314 this . pendingChangedEsmFiles . clear ( ) ;
236315 this . pendingChangedDtsFiles . clear ( ) ;
237316 this . #pendingCompilationFiles. clear ( ) ;
317+ this . #referencingFiles. clear ( ) ;
318+ this . #referencedByFile. clear ( ) ;
238319 this . #watchedCompilationFiles. clear ( ) ;
239320 }
240321}
0 commit comments