/** * @license * Copyright Google LLC 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.dev/license */ import ts from 'typescript'; import { AliasingHost, Reference, ReferenceEmitter } from '../../imports'; import { DirectiveMeta, MetadataReader, MetadataRegistry, NgModuleMeta, PipeMeta } from '../../metadata'; import { ClassDeclaration } from '../../reflection'; import { ComponentScopeReader, LocalModuleScope, RemoteScope } from './api'; import { DtsModuleScopeResolver } from './dependency'; export interface LocalNgModuleData { declarations: Reference[]; imports: Reference[]; exports: Reference[]; } /** * A registry which collects information about NgModules, Directives, Components, and Pipes which * are local (declared in the ts.Program being compiled), and can produce `LocalModuleScope`s * which summarize the compilation scope of a component. * * This class implements the logic of NgModule declarations, imports, and exports and can produce, * for a given component, the set of directives and pipes which are "visible" in that component's * template. * * The `LocalModuleScopeRegistry` has two "modes" of operation. During analysis, data for each * individual NgModule, Directive, Component, and Pipe is added to the registry. No attempt is made * to traverse or validate the NgModule graph (imports, exports, etc). After analysis, one of * `getScopeOfModule` or `getScopeForComponent` can be called, which traverses the NgModule graph * and applies the NgModule logic to generate a `LocalModuleScope`, the full scope for the given * module or component. * * The `LocalModuleScopeRegistry` is also capable of producing `ts.Diagnostic` errors when Angular * semantics are violated. */ export declare class LocalModuleScopeRegistry implements MetadataRegistry, ComponentScopeReader { private localReader; private fullReader; private dependencyScopeReader; private refEmitter; private aliasingHost; /** * Tracks whether the registry has been asked to produce scopes for a module or component. Once * this is true, the registry cannot accept registrations of new directives/pipes/modules as it * would invalidate the cached scope data. */ private sealed; /** * A map of components from the current compilation unit to the NgModule which declared them. * * As components and directives are not distinguished at the NgModule level, this map may also * contain directives. This doesn't cause any problems but isn't useful as there is no concept of * a directive's compilation scope. */ private declarationToModule; /** * This maps from the directive/pipe class to a map of data for each NgModule that declares the * directive/pipe. This data is needed to produce an error for the given class. */ private duplicateDeclarations; private moduleToRef; /** * A cache of calculated `LocalModuleScope`s for each NgModule declared in the current program. */ private cache; /** * Tracks the `RemoteScope` for components requiring "remote scoping". * * Remote scoping is when the set of directives which apply to a given component is set in the * NgModule's file instead of directly on the component def (which is sometimes needed to get * around cyclic import issues). This is not used in calculation of `LocalModuleScope`s, but is * tracked here for convenience. */ private remoteScoping; /** * Tracks errors accumulated in the processing of scopes for each module declaration. */ private scopeErrors; /** * Tracks which NgModules have directives/pipes that are declared in more than one module. */ private modulesWithStructuralErrors; constructor(localReader: MetadataReader, fullReader: MetadataReader, dependencyScopeReader: DtsModuleScopeResolver, refEmitter: ReferenceEmitter, aliasingHost: AliasingHost | null); /** * Add an NgModule's data to the registry. */ registerNgModuleMetadata(data: NgModuleMeta): void; registerDirectiveMetadata(directive: DirectiveMeta): void; registerPipeMetadata(pipe: PipeMeta): void; getScopeForComponent(clazz: ClassDeclaration): LocalModuleScope | null; /** * If `node` is declared in more than one NgModule (duplicate declaration), then get the * `DeclarationData` for each offending declaration. * * Ordinarily a class is only declared in one NgModule, in which case this function returns * `null`. */ getDuplicateDeclarations(node: ClassDeclaration): DeclarationData[] | null; /** * Collects registered data for a module and its directives/pipes and convert it into a full * `LocalModuleScope`. * * This method implements the logic of NgModule imports and exports. It returns the * `LocalModuleScope` for the given NgModule if one can be produced, `null` if no scope was ever * defined, or the string `'error'` if the scope contained errors. */ getScopeOfModule(clazz: ClassDeclaration): LocalModuleScope | null; /** * Retrieves any `ts.Diagnostic`s produced during the calculation of the `LocalModuleScope` for * the given NgModule, or `null` if no errors were present. */ getDiagnosticsOfModule(clazz: ClassDeclaration): ts.Diagnostic[] | null; private registerDeclarationOfModule; /** * Implementation of `getScopeOfModule` which accepts a reference to a class. */ private getScopeOfModuleReference; /** * Check whether a component requires remote scoping. */ getRemoteScope(node: ClassDeclaration): RemoteScope | null; /** * Set a component as requiring remote scoping, with the given directives and pipes to be * registered remotely. */ setComponentRemoteScope(node: ClassDeclaration, directives: Reference[], pipes: Reference[]): void; /** * Look up the `ExportScope` of a given `Reference` to an NgModule. * * The NgModule in question may be declared locally in the current ts.Program, or it may be * declared in a .d.ts file. * * @returns `null` if no scope could be found, or `'invalid'` if the `Reference` is not a valid * NgModule. * * May also contribute diagnostics of its own by adding to the given `diagnostics` * array parameter. */ private getExportedScope; private getReexports; private assertCollecting; } export interface DeclarationData { ngModule: ClassDeclaration; ref: Reference; rawDeclarations: ts.Expression | null; }