From 5dbf3572248941698088798c655b4c412e7ee0cb Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Tue, 14 Jul 2020 12:10:53 -0400 Subject: [PATCH] feat(compiler-cli): support getting resource dependencies for a source file (#38048) The compiler maintains an internal dependency graph of all resource dependencies for application source files. This information can be useful for tools that integrate the compiler and need to support file watching. This change adds a `getResourceDependencies` method to the `NgCompiler` class that allows compiler integrations to access resource dependencies of files within the compilation. PR Close #38048 --- .../src/ngtsc/core/src/compiler.ts | 11 ++++++ .../src/ngtsc/core/test/compiler_test.ts | 34 +++++++++++++++++++ .../incremental/src/dependency_tracking.ts | 6 ++++ 3 files changed, 51 insertions(+) diff --git a/packages/compiler-cli/src/ngtsc/core/src/compiler.ts b/packages/compiler-cli/src/ngtsc/core/src/compiler.ts index f783c8ae60..a867e72613 100644 --- a/packages/compiler-cli/src/ngtsc/core/src/compiler.ts +++ b/packages/compiler-cli/src/ngtsc/core/src/compiler.ts @@ -162,6 +162,17 @@ export class NgCompiler { this.ignoreForEmit = this.adapter.ignoreForEmit; } + /** + * Get the resource dependencies of a file. + * + * If the file is not part of the compilation, an empty array will be returned. + */ + getResourceDependencies(file: ts.SourceFile): string[] { + this.ensureAnalyzed(); + + return this.incrementalDriver.depGraph.getResourceDependencies(file); + } + /** * Get all Angular-related diagnostics for this compilation. * diff --git a/packages/compiler-cli/src/ngtsc/core/test/compiler_test.ts b/packages/compiler-cli/src/ngtsc/core/test/compiler_test.ts index 0a6b3ac118..9e873e720e 100644 --- a/packages/compiler-cli/src/ngtsc/core/test/compiler_test.ts +++ b/packages/compiler-cli/src/ngtsc/core/test/compiler_test.ts @@ -105,6 +105,40 @@ runInEachFileSystem(() => { expect(components).toEqual(new Set([CmpA, CmpC])); }); }); + + describe('getResourceDependencies', () => { + it('should return resource dependencies of a component source file', () => { + const COMPONENT = _('/cmp.ts'); + fs.writeFile(COMPONENT, ` + import {Component} from '@angular/core'; + @Component({ + selector: 'test-cmp', + templateUrl: './template.html', + styleUrls: ['./style.css'], + }) + export class Cmp {} + `); + fs.writeFile(_('/template.html'), `

Resource

`); + fs.writeFile(_('/style.css'), `h1 { }`); + + const options: NgCompilerOptions = { + strictTemplates: true, + }; + const baseHost = new NgtscCompilerHost(getFileSystem(), options); + const host = NgCompilerHost.wrap(baseHost, [COMPONENT], options, /* oldProgram */ null); + const program = ts.createProgram({host, options, rootNames: host.inputFiles}); + const compiler = new NgCompiler( + host, options, program, new ReusedProgramStrategy(program, host, options, []), + new NoopIncrementalBuildStrategy(), /** enableTemplateTypeChecker */ false); + + const deps = compiler.getResourceDependencies(getSourceFileOrError(program, COMPONENT)); + expect(deps.length).toBe(2); + expect(deps).toEqual(jasmine.arrayContaining([ + jasmine.stringMatching(/\/template.html$/), + jasmine.stringMatching(/\/style.css$/), + ])); + }); + }); }); }); diff --git a/packages/compiler-cli/src/ngtsc/incremental/src/dependency_tracking.ts b/packages/compiler-cli/src/ngtsc/incremental/src/dependency_tracking.ts index e884aefbaa..42fc122f00 100644 --- a/packages/compiler-cli/src/ngtsc/incremental/src/dependency_tracking.ts +++ b/packages/compiler-cli/src/ngtsc/incremental/src/dependency_tracking.ts @@ -53,6 +53,12 @@ export class FileDependencyGraph i } } + getResourceDependencies(from: T): AbsoluteFsPath[] { + const node = this.nodes.get(from); + + return node ? [...node.usesResources] : []; + } + isStale(sf: T, changedTsPaths: Set, changedResources: Set): boolean { return isLogicallyChanged(sf, this.nodeFor(sf), changedTsPaths, EMPTY_SET, changedResources); }