@angular/compiler-cli
Version:
Angular - the compiler CLI for Node.js
236 lines (235 loc) • 10.4 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 { Expression } from '@angular/compiler';
import ts from 'typescript';
import { UnifiedModulesHost } from '../../core/api';
import { LogicalFileSystem } from '../../file_system';
import { DeclarationNode, ReflectionHost } from '../../reflection';
import { Reference } from './references';
import { ModuleResolver } from './resolver';
/**
* Flags which alter the imports generated by the `ReferenceEmitter`.
*/
export declare enum ImportFlags {
None = 0,
/**
* Force the generation of a new import when generating a reference, even if an identifier already
* exists in the target file which could be used instead.
*
* This is sometimes required if there's a risk TypeScript might remove imports during emit.
*/
ForceNewImport = 1,
/**
* Don't make use of any aliasing information when emitting a reference.
*
* This is sometimes required if emitting into a context where generated references will be fed
* into TypeScript and type-checked (such as in template type-checking).
*/
NoAliasing = 2,
/**
* Indicates that an import to a type-only declaration is allowed.
*
* For references that occur in type-positions, the referred declaration may be a type-only
* declaration that is not retained during emit. Including this flag allows to emit references to
* type-only declarations as used in e.g. template type-checking.
*/
AllowTypeImports = 4,
/**
* Indicates that importing from a declaration file using a relative import path is allowed.
*
* The generated imports should normally use module specifiers that are valid for use in
* production code, where arbitrary relative imports into e.g. node_modules are not allowed. For
* template type-checking code it is however acceptable to use relative imports, as such files are
* never emitted to JS code.
*
* Non-declaration files have to be contained within a configured `rootDir` so using relative
* paths may not be possible for those, hence this flag only applies when importing from a
* declaration file.
*/
AllowRelativeDtsImports = 8,
/**
* Indicates that references coming from ambient imports are allowed.
*/
AllowAmbientReferences = 16
}
/**
* An emitter strategy has the ability to indicate which `ts.SourceFile` is being imported by the
* expression that it has generated. This information is useful for consumers of the emitted
* reference that would otherwise have to perform a relatively expensive module resolution step,
* e.g. for cyclic import analysis. In cases the emitter is unable to definitively determine the
* imported source file or a computation would be required to actually determine the imported
* source file, then `'unknown'` should be returned. If the generated expression does not represent
* an import then `null` should be used.
*/
export type ImportedFile = ts.SourceFile | 'unknown' | null;
export declare enum ReferenceEmitKind {
Success = 0,
Failed = 1
}
/**
* Represents the emitted expression of a `Reference` that is valid in the source file it was
* emitted from.
*/
export interface EmittedReference {
kind: ReferenceEmitKind.Success;
/**
* The expression that refers to `Reference`.
*/
expression: Expression;
/**
* The `ts.SourceFile` that is imported by `expression`. This is not necessarily the source file
* of the `Reference`'s declaration node, as the reference may have been rewritten through an
* alias export. It could also be `null` if `expression` is a local identifier, or `'unknown'` if
* the exact source file that is being imported is not known to the emitter.
*/
importedFile: ImportedFile;
}
/**
* Represents a failure to emit a `Reference` into a different source file.
*/
export interface FailedEmitResult {
kind: ReferenceEmitKind.Failed;
/**
* The reference that could not be emitted.
*/
ref: Reference;
/**
* The source file into which the reference was requested to be emitted.
*/
context: ts.SourceFile;
/**
* Describes why the reference could not be emitted. This may be shown in a diagnostic.
*/
reason: string;
}
export type ReferenceEmitResult = EmittedReference | FailedEmitResult;
/**
* Verifies that a reference was emitted successfully, or raises a `FatalDiagnosticError` otherwise.
* @param result The emit result that should have been successful.
* @param origin The node that is used to report the failure diagnostic.
* @param typeKind The kind of the symbol that the reference represents, e.g. 'component' or
* 'class'.
*/
export declare function assertSuccessfulReferenceEmit(result: ReferenceEmitResult, origin: ts.Node, typeKind: string): asserts result is EmittedReference;
/**
* A particular strategy for generating an expression which refers to a `Reference`.
*
* There are many potential ways a given `Reference` could be referred to in the context of a given
* file. A local declaration could be available, the `Reference` could be importable via a relative
* import within the project, or an absolute import into `node_modules` might be necessary.
*
* Different `ReferenceEmitStrategy` implementations implement specific logic for generating such
* references. A single strategy (such as using a local declaration) may not always be able to
* generate an expression for every `Reference` (for example, if no local identifier is available),
* and may return `null` in such a case.
*/
export interface ReferenceEmitStrategy {
/**
* Emit an `Expression` which refers to the given `Reference` in the context of a particular
* source file, if possible.
*
* @param ref the `Reference` for which to generate an expression
* @param context the source file in which the `Expression` must be valid
* @param importFlags a flag which controls whether imports should be generated or not
* @returns an `EmittedReference` which refers to the `Reference`, or `null` if none can be
* generated
*/
emit(ref: Reference, context: ts.SourceFile, importFlags: ImportFlags): ReferenceEmitResult | null;
}
/**
* Generates `Expression`s which refer to `Reference`s in a given context.
*
* A `ReferenceEmitter` uses one or more `ReferenceEmitStrategy` implementations to produce an
* `Expression` which refers to a `Reference` in the context of a particular file.
*/
export declare class ReferenceEmitter {
private strategies;
constructor(strategies: ReferenceEmitStrategy[]);
emit(ref: Reference, context: ts.SourceFile, importFlags?: ImportFlags): ReferenceEmitResult;
}
/**
* A `ReferenceEmitStrategy` which will refer to declarations by any local `ts.Identifier`s, if
* such identifiers are available.
*/
export declare class LocalIdentifierStrategy implements ReferenceEmitStrategy {
emit(ref: Reference, context: ts.SourceFile, importFlags: ImportFlags): EmittedReference | null;
}
/**
* Represents the exported declarations from a module source file.
*/
interface ModuleExports {
/**
* The source file of the module.
*/
module: ts.SourceFile | null;
/**
* The map of declarations to their exported name.
*/
exportMap: Map<DeclarationNode, string> | null;
}
/**
* A `ReferenceEmitStrategy` which will refer to declarations that come from `node_modules` using
* an absolute import.
*
* Part of this strategy involves looking at the target entry point and identifying the exported
* name of the targeted declaration, as it might be different from the declared name (e.g. a
* directive might be declared as FooDirImpl, but exported as FooDir). If no export can be found
* which maps back to the original directive, an error is thrown.
*/
export declare class AbsoluteModuleStrategy implements ReferenceEmitStrategy {
protected program: ts.Program;
protected checker: ts.TypeChecker;
protected moduleResolver: ModuleResolver;
private reflectionHost;
/**
* A cache of the exports of specific modules, because resolving a module to its exports is a
* costly operation.
*/
private moduleExportsCache;
constructor(program: ts.Program, checker: ts.TypeChecker, moduleResolver: ModuleResolver, reflectionHost: ReflectionHost);
emit(ref: Reference, context: ts.SourceFile, importFlags: ImportFlags): ReferenceEmitResult | null;
private getExportsOfModule;
protected enumerateExportsOfModule(specifier: string, fromFile: string): ModuleExports;
}
/**
* A `ReferenceEmitStrategy` which will refer to declarations via relative paths, provided they're
* both in the logical project "space" of paths.
*
* This is trickier than it sounds, as the two files may be in different root directories in the
* project. Simply calculating a file system relative path between the two is not sufficient.
* Instead, `LogicalProjectPath`s are used.
*/
export declare class LogicalProjectStrategy implements ReferenceEmitStrategy {
private reflector;
private logicalFs;
private relativePathStrategy;
constructor(reflector: ReflectionHost, logicalFs: LogicalFileSystem);
emit(ref: Reference, context: ts.SourceFile, importFlags: ImportFlags): ReferenceEmitResult | null;
}
/**
* A `ReferenceEmitStrategy` which constructs relatives paths between `ts.SourceFile`s.
*
* This strategy can be used if there is no `rootDir`/`rootDirs` structure for the project which
* necessitates the stronger logic of `LogicalProjectStrategy`.
*/
export declare class RelativePathStrategy implements ReferenceEmitStrategy {
private reflector;
constructor(reflector: ReflectionHost);
emit(ref: Reference, context: ts.SourceFile): ReferenceEmitResult | null;
}
/**
* A `ReferenceEmitStrategy` which uses a `UnifiedModulesHost` to generate absolute import
* references.
*/
export declare class UnifiedModulesStrategy implements ReferenceEmitStrategy {
private reflector;
private unifiedModulesHost;
constructor(reflector: ReflectionHost, unifiedModulesHost: UnifiedModulesHost);
emit(ref: Reference, context: ts.SourceFile): EmittedReference | null;
}
export {};