feat(ivy): register references from NgModule annotations (#26906)
The `NgModuleDecoratorHandler` can now register all the references that it finds in the `NgModule` metadata, such as `declarations`, `imports`, `exports` etc. This information can then be used by ngcc to work out if any of these references are internal only and need to be manually exported from a library's entry-point. PR Close #26906
This commit is contained in:

committed by
Igor Minar

parent
b93c1dffa1
commit
4a70b669be
@ -10,6 +10,7 @@ import * as ts from 'typescript';
|
||||
import {Decorator} from '../../../ngtsc/host';
|
||||
import {DecoratorHandler} from '../../../ngtsc/transform';
|
||||
import {DecorationAnalyses, DecorationAnalyzer} from '../../src/analysis/decoration_analyzer';
|
||||
import {NgccReferencesRegistry} from '../../src/analysis/ngcc_references_registry';
|
||||
import {Esm2015ReflectionHost} from '../../src/host/esm2015_host';
|
||||
|
||||
import {makeProgram} from '../helpers/utils';
|
||||
@ -84,9 +85,10 @@ describe('DecorationAnalyzer', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
program = makeProgram(TEST_PROGRAM);
|
||||
const analyzer = new DecorationAnalyzer(
|
||||
program.getTypeChecker(), new Esm2015ReflectionHost(false, program.getTypeChecker()),
|
||||
[''], false);
|
||||
const host = new Esm2015ReflectionHost(false, program.getTypeChecker());
|
||||
const referencesRegistry = new NgccReferencesRegistry(host);
|
||||
const analyzer =
|
||||
new DecorationAnalyzer(program.getTypeChecker(), host, referencesRegistry, [''], false);
|
||||
testHandler = createTestHandler();
|
||||
analyzer.handlers = [testHandler];
|
||||
result = analyzer.analyzeProgram(program);
|
||||
@ -126,9 +128,10 @@ describe('DecorationAnalyzer', () => {
|
||||
it('should analyze an internally imported component, which is not publicly exported from the entry-point',
|
||||
() => {
|
||||
const program = makeProgram(...INTERNAL_COMPONENT_PROGRAM);
|
||||
const host = new Esm2015ReflectionHost(false, program.getTypeChecker());
|
||||
const referencesRegistry = new NgccReferencesRegistry(host);
|
||||
const analyzer = new DecorationAnalyzer(
|
||||
program.getTypeChecker(), new Esm2015ReflectionHost(false, program.getTypeChecker()),
|
||||
[''], false);
|
||||
program.getTypeChecker(), host, referencesRegistry, [''], false);
|
||||
const testHandler = createTestHandler();
|
||||
analyzer.handlers = [testHandler];
|
||||
const result = analyzer.analyzeProgram(program);
|
||||
@ -142,9 +145,10 @@ describe('DecorationAnalyzer', () => {
|
||||
|
||||
it('should analyze an internally defined component, which is not exported at all', () => {
|
||||
const program = makeProgram(...INTERNAL_COMPONENT_PROGRAM);
|
||||
const analyzer = new DecorationAnalyzer(
|
||||
program.getTypeChecker(), new Esm2015ReflectionHost(false, program.getTypeChecker()),
|
||||
[''], false);
|
||||
const host = new Esm2015ReflectionHost(false, program.getTypeChecker());
|
||||
const referencesRegistry = new NgccReferencesRegistry(host);
|
||||
const analyzer =
|
||||
new DecorationAnalyzer(program.getTypeChecker(), host, referencesRegistry, [''], false);
|
||||
const testHandler = createTestHandler();
|
||||
analyzer.handlers = [testHandler];
|
||||
const result = analyzer.analyzeProgram(program);
|
||||
|
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {Reference, TypeScriptReflectionHost, staticallyResolve} from '../../../ngtsc/metadata';
|
||||
import {getDeclaration, makeProgram} from '../../../ngtsc/testing/in_memory_typescript';
|
||||
import {NgccReferencesRegistry} from '../../src/analysis/ngcc_references_registry';
|
||||
|
||||
describe('NgccReferencesRegistry', () => {
|
||||
it('should return a mapping from resolved reference identifiers to their declarations', () => {
|
||||
const {program} = makeProgram([{
|
||||
name: 'index.ts',
|
||||
contents: `
|
||||
export class SomeClass {}
|
||||
export function someFunction() {}
|
||||
export const someVariable = 42;
|
||||
|
||||
export const testArray = [SomeClass, someFunction, someVariable];
|
||||
`
|
||||
}]);
|
||||
|
||||
const checker = program.getTypeChecker();
|
||||
|
||||
const testArrayDeclaration =
|
||||
getDeclaration(program, 'index.ts', 'testArray', ts.isVariableDeclaration);
|
||||
const someClassDecl = getDeclaration(program, 'index.ts', 'SomeClass', ts.isClassDeclaration);
|
||||
const someFunctionDecl =
|
||||
getDeclaration(program, 'index.ts', 'someFunction', ts.isFunctionDeclaration);
|
||||
const someVariableDecl =
|
||||
getDeclaration(program, 'index.ts', 'someVariable', ts.isVariableDeclaration);
|
||||
const testArrayExpression = testArrayDeclaration.initializer !;
|
||||
|
||||
const host = new TypeScriptReflectionHost(checker);
|
||||
const registry = new NgccReferencesRegistry(host);
|
||||
|
||||
const references =
|
||||
staticallyResolve(testArrayExpression, host, checker) as Reference<ts.Declaration>[];
|
||||
registry.add(...references);
|
||||
|
||||
const map = registry.getDeclarationMap();
|
||||
expect(map.size).toEqual(2);
|
||||
expect(map.get(someClassDecl.name !) !.node).toBe(someClassDecl);
|
||||
expect(map.get(someFunctionDecl.name !) !.node).toBe(someFunctionDecl);
|
||||
expect(map.has(someVariableDecl.name as ts.Identifier)).toBe(false);
|
||||
});
|
||||
});
|
@ -12,6 +12,7 @@ import MagicString from 'magic-string';
|
||||
import {fromObject, generateMapFileComment} from 'convert-source-map';
|
||||
import {makeProgram} from '../helpers/utils';
|
||||
import {CompiledClass, DecorationAnalyzer} from '../../src/analysis/decoration_analyzer';
|
||||
import {NgccReferencesRegistry} from '../../src/analysis/ngcc_references_registry';
|
||||
import {SwitchMarkerAnalyzer} from '../../src/analysis/switch_marker_analyzer';
|
||||
import {BundleInfo, createBundleInfo} from '../../src/packages/bundle';
|
||||
import {Esm2015ReflectionHost} from '../../src/host/esm2015_host';
|
||||
@ -46,8 +47,10 @@ function createTestRenderer(
|
||||
options.rewriteCoreImportsTo ? program.getSourceFile(options.rewriteCoreImportsTo) ! : null;
|
||||
const bundle = createBundleInfo(options.isCore || false, rewriteCoreImportsTo, null);
|
||||
const host = new Esm2015ReflectionHost(bundle.isCore, program.getTypeChecker());
|
||||
const referencesRegistry = new NgccReferencesRegistry(host);
|
||||
const decorationAnalyses =
|
||||
new DecorationAnalyzer(program.getTypeChecker(), host, [''], bundle.isCore)
|
||||
new DecorationAnalyzer(
|
||||
program.getTypeChecker(), host, referencesRegistry, [''], bundle.isCore)
|
||||
.analyzeProgram(program);
|
||||
const switchMarkerAnalyses = new SwitchMarkerAnalyzer(host).analyzeProgram(program);
|
||||
const renderer = new TestRenderer(host, bundle);
|
||||
|
Reference in New Issue
Block a user