@angular/compiler-cli
Version:
Angular - the compiler CLI for Node.js
345 lines (344 loc) • 12.7 kB
TypeScript
/**
* @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 { DirectiveMeta as T2DirectiveMeta, Expression, SchemaMetadata, ExternalReference } from '@angular/compiler';
import ts from 'typescript';
import { Reference } from '../../imports';
import { ClassDeclaration } from '../../reflection';
import { ClassPropertyMapping, ClassPropertyName, InputOrOutput } from './property_mapping';
/**
* Metadata collected for an `NgModule`.
*/
export interface NgModuleMeta {
kind: MetaKind.NgModule;
ref: Reference<ClassDeclaration>;
declarations: Reference<ClassDeclaration>[];
imports: Reference<ClassDeclaration>[];
exports: Reference<ClassDeclaration>[];
schemas: SchemaMetadata[];
/**
* Whether the module had some issue being analyzed.
* This means it likely does not have complete and reliable metadata.
*/
isPoisoned: boolean;
/**
* The raw `ts.Expression` which gave rise to `declarations`, if one exists.
*
* If this is `null`, then either no declarations exist, or no expression was available (likely
* because the module came from a .d.ts file).
*/
rawDeclarations: ts.Expression | null;
/**
* The raw `ts.Expression` which gave rise to `imports`, if one exists.
*
* If this is `null`, then either no imports exist, or no expression was available (likely
* because the module came from a .d.ts file).
*/
rawImports: ts.Expression | null;
/**
* The raw `ts.Expression` which gave rise to `exports`, if one exists.
*
* If this is `null`, then either no exports exist, or no expression was available (likely
* because the module came from a .d.ts file).
*/
rawExports: ts.Expression | null;
/**
* The primary decorator associated with this `ngModule`.
*
* If this is `null`, no decorator exists, meaning it's probably from a .d.ts file.
*/
decorator: ts.Decorator | null;
/**
* Whether this NgModule may declare providers.
*
* If the compiler does not know if the NgModule may declare providers, this will be `true` (for
* example, NgModules declared outside the current compilation are assumed to declare providers).
*/
mayDeclareProviders: boolean;
}
/**
* Typing metadata collected for a directive within an NgModule's scope.
*/
export interface DirectiveTypeCheckMeta {
/**
* List of static `ngTemplateGuard_xx` members found on the Directive's class.
* @see `TemplateGuardMeta`
*/
ngTemplateGuards: TemplateGuardMeta[];
/**
* Whether the Directive's class has a static ngTemplateContextGuard function.
*/
hasNgTemplateContextGuard: boolean;
/**
* The set of input fields which have a corresponding static `ngAcceptInputType_` on the
* Directive's class. This allows inputs to accept a wider range of types and coerce the input to
* a narrower type with a getter/setter. See https://angular.dev/tools/cli/template-typecheck.
*/
coercedInputFields: Set<ClassPropertyName>;
/**
* The set of input fields which map to `readonly`, `private`, or `protected` members in the
* Directive's class.
*/
restrictedInputFields: Set<ClassPropertyName>;
/**
* The set of input fields which are declared as string literal members in the Directive's class.
* We need to track these separately because these fields may not be valid JS identifiers so
* we cannot use them with property access expressions when assigning inputs.
*/
stringLiteralInputFields: Set<ClassPropertyName>;
/**
* The set of input fields which do not have corresponding members in the Directive's class.
*/
undeclaredInputFields: Set<ClassPropertyName>;
/**
* Whether the Directive's class is generic, i.e. `class MyDir<T> {...}`.
*/
isGeneric: boolean;
}
/**
* Disambiguates different kinds of compiler metadata objects.
*/
export declare enum MetaKind {
Directive = 0,
Pipe = 1,
NgModule = 2
}
/**
* Possible ways that a directive can be matched.
*/
export declare enum MatchSource {
/** The directive was matched by its selector. */
Selector = 0,
/** The directive was applied as a host directive. */
HostDirective = 1
}
/** Metadata for a single input mapping. */
export type InputMapping = InputOrOutput & {
required: boolean;
/**
* Transform for the input. Null if no transform is configured.
*
* For signal-based inputs, this is always `null` even if a transform
* is configured. Signal inputs capture their transform write type
* automatically in the `InputSignal`, nor is there a need to emit a
* reference to the transform.
*
* For zone-based decorator `@Input`s this is different because the transform
* write type needs to be captured in a coercion member as the decorator information
* is lost in the `.d.ts` for type-checking.
*/
transform: DecoratorInputTransform | null;
};
/** Metadata for a model mapping. */
export interface ModelMapping {
/** Node defining the model mapping. */
call: ts.CallExpression;
/** Information about the input declared by the model. */
input: InputMapping;
/** Information about the output implicitly declared by the model. */
output: InputOrOutput;
}
/** Metadata for an `@Input()` transform function. */
export interface DecoratorInputTransform {
/**
* Reference to the transform function so that it can be
* referenced when the input metadata is emitted in the declaration.
*/
node: ts.Node;
/**
* Emittable type for the input transform. Null for signal inputs
*
* This type will be used for inputs to capture the transform type
* for type-checking in corresponding `ngAcceptInputType_` members.
*/
type: Reference<ts.TypeNode>;
}
/**
* Metadata collected for a directive within an NgModule's scope.
*/
export interface DirectiveMeta extends T2DirectiveMeta, DirectiveTypeCheckMeta {
kind: MetaKind.Directive;
/** Way in which the directive was matched. */
matchSource: MatchSource;
ref: Reference<ClassDeclaration>;
/**
* Unparsed selector of the directive, or null if the directive does not have a selector.
*/
selector: string | null;
queries: string[];
/**
* A mapping of input field names to the property names.
*/
inputs: ClassPropertyMapping<InputMapping>;
/**
* List of input fields that were defined in the class decorator
* metadata. Null for directives extracted from `.d.ts`
*/
inputFieldNamesFromMetadataArray: Set<string> | null;
/**
* A mapping of output field names to the property names.
*/
outputs: ClassPropertyMapping;
/**
* A `Reference` to the base class for the directive, if one was detected.
*
* A value of `'dynamic'` indicates that while the analyzer detected that this directive extends
* another type, it could not statically determine the base class.
*/
baseClass: Reference<ClassDeclaration> | 'dynamic' | null;
/**
* Whether the directive had some issue with its declaration that means it might not have complete
* and reliable metadata.
*/
isPoisoned: boolean;
/**
* Whether the directive is likely a structural directive (injects `TemplateRef`).
*/
isStructural: boolean;
/**
* Whether the directive is a standalone entity.
*/
isStandalone: boolean;
/**
* Whether the directive is a signal entity.
*/
isSignal: boolean;
/**
* For standalone components, the list of imported types.
*/
imports: Reference<ClassDeclaration>[] | null;
/**
* Node declaring the `imports` of a standalone component. Used to produce diagnostics.
*/
rawImports: ts.Expression | null;
/**
* For standalone components, the list of imported types that can be used
* in `@defer` blocks (when only explicit dependencies are allowed).
*/
deferredImports: Reference<ClassDeclaration>[] | null;
/**
* For standalone components, the list of schemas declared.
*/
schemas: SchemaMetadata[] | null;
/**
* The primary decorator associated with this directive.
*
* If this is `null`, no decorator exists, meaning it's probably from a .d.ts file.
*/
decorator: ts.Decorator | null;
/** Additional directives applied to the directive host. */
hostDirectives: HostDirectiveMeta[] | null;
/**
* Whether the directive should be assumed to export providers if imported as a standalone type.
*/
assumedToExportProviders: boolean;
/**
* Whether this class was imported into a standalone component's
* scope via `@Component.deferredImports` field.
*/
isExplicitlyDeferred: boolean;
/** Whether selectorless is enabled for the specific component. */
selectorlessEnabled: boolean;
/**
* Names of the symbols within the source file that are referenced directly inside the template.
*/
localReferencedSymbols: Set<string> | null;
}
/** Metadata collected about an additional directive that is being applied to a directive host. */
export interface HostDirectiveMeta {
/**
* Reference to the host directive class.
*
* Only in local compilation mode this can be Expression
* which indicates the expression could not be resolved due to being imported from some external
* file. In this case, the expression is the raw expression as appears in the decorator.
*/
directive: Reference<ClassDeclaration> | Expression | ExternalReference;
/** Whether the reference to the host directive is a forward reference. */
isForwardReference: boolean;
/** Inputs from the host directive that have been exposed. */
inputs: {
[publicName: string]: string;
} | null;
/** Outputs from the host directive that have been exposed. */
outputs: {
[publicName: string]: string;
} | null;
}
/**
* Metadata collected about an additional directive that is being applied to a directive host in
* global compilation mode.
*/
export interface HostDirectiveMetaForGlobalMode extends HostDirectiveMeta {
directive: Reference<ClassDeclaration>;
}
/**
* Metadata collected about an additional directive that is being applied to a directive host in
* local compilation mode.
*/
export interface HostDirectiveMetaForLocalMode extends HostDirectiveMeta {
directive: Expression;
}
/**
* Metadata that describes a template guard for one of the directive's inputs.
*/
export interface TemplateGuardMeta {
/**
* The input name that this guard should be applied to.
*/
inputName: string;
/**
* Represents the type of the template guard.
*
* - 'invocation' means that a call to the template guard function is emitted so that its return
* type can result in narrowing of the input type.
* - 'binding' means that the input binding expression itself is used as template guard.
*/
type: 'invocation' | 'binding';
}
/**
* Metadata for a pipe within an NgModule's scope.
*/
export interface PipeMeta {
kind: MetaKind.Pipe;
ref: Reference<ClassDeclaration>;
name: string | null;
nameExpr: ts.Expression | null;
isStandalone: boolean;
isPure: boolean;
decorator: ts.Decorator | null;
isExplicitlyDeferred: boolean;
}
/**
* Reads metadata for directives, pipes, and modules from a particular source, such as .d.ts files
* or a registry.
*/
export interface MetadataReader {
getDirectiveMetadata(node: Reference<ClassDeclaration>): DirectiveMeta | null;
getNgModuleMetadata(node: Reference<ClassDeclaration>): NgModuleMeta | null;
getPipeMetadata(node: Reference<ClassDeclaration>): PipeMeta | null;
}
/**
* A MetadataReader which also allows access to the set of all known trait classes.
*/
export interface MetadataReaderWithIndex extends MetadataReader {
getKnown(kind: MetaKind): Array<ClassDeclaration>;
}
/**
* An NgModuleIndex allows access to information about traits exported by NgModules.
*/
export interface NgModuleIndex {
getNgModulesExporting(directiveOrPipe: ClassDeclaration): Array<Reference<ClassDeclaration>>;
}
/**
* Registers new metadata for directives, pipes, and modules.
*/
export interface MetadataRegistry {
registerDirectiveMetadata(meta: DirectiveMeta): void;
registerNgModuleMetadata(meta: NgModuleMeta): void;
registerPipeMetadata(meta: PipeMeta): void;
}