refactor(ivy): change ImportMode enum to ImportFlags (#34649)
Previously, `ReferenceEmitter.emit()` took an `ImportMode` enum value, where one value of the enum allowed forcing new imports to be generated when emitting a reference to some value or type. This commit refactors `ImportMode` to be an `ImportFlags` value instead. Using a bit field of flags will allow future customization of reference emitting. PR Close #34649
This commit is contained in:
parent
af015982f5
commit
5b9c96b9b8
@ -10,7 +10,7 @@ import {Expression, ExternalExpr, R3DependencyMetadata, R3Reference, R3ResolvedD
|
|||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {ErrorCode, FatalDiagnosticError, makeDiagnostic} from '../../diagnostics';
|
import {ErrorCode, FatalDiagnosticError, makeDiagnostic} from '../../diagnostics';
|
||||||
import {DefaultImportRecorder, ImportMode, Reference, ReferenceEmitter} from '../../imports';
|
import {DefaultImportRecorder, ImportFlags, Reference, ReferenceEmitter} from '../../imports';
|
||||||
import {ForeignFunctionResolver, PartialEvaluator} from '../../partial_evaluator';
|
import {ForeignFunctionResolver, PartialEvaluator} from '../../partial_evaluator';
|
||||||
import {ClassDeclaration, CtorParameter, Decorator, Import, ReflectionHost, TypeValueReference, isNamedClassDeclaration} from '../../reflection';
|
import {ClassDeclaration, CtorParameter, Decorator, Import, ReflectionHost, TypeValueReference, isNamedClassDeclaration} from '../../reflection';
|
||||||
import {DeclarationData} from '../../scope';
|
import {DeclarationData} from '../../scope';
|
||||||
@ -189,8 +189,8 @@ export function validateConstructorDependencies(
|
|||||||
export function toR3Reference(
|
export function toR3Reference(
|
||||||
valueRef: Reference, typeRef: Reference, valueContext: ts.SourceFile,
|
valueRef: Reference, typeRef: Reference, valueContext: ts.SourceFile,
|
||||||
typeContext: ts.SourceFile, refEmitter: ReferenceEmitter): R3Reference {
|
typeContext: ts.SourceFile, refEmitter: ReferenceEmitter): R3Reference {
|
||||||
const value = refEmitter.emit(valueRef, valueContext, ImportMode.UseExistingImport);
|
const value = refEmitter.emit(valueRef, valueContext);
|
||||||
const type = refEmitter.emit(typeRef, typeContext, ImportMode.ForceNewImport);
|
const type = refEmitter.emit(typeRef, typeContext, ImportFlags.ForceNewImport);
|
||||||
if (value === null || type === null) {
|
if (value === null || type === null) {
|
||||||
throw new Error(`Could not refer to ${ts.SyntaxKind[valueRef.node.kind]}`);
|
throw new Error(`Could not refer to ${ts.SyntaxKind[valueRef.node.kind]}`);
|
||||||
}
|
}
|
||||||
|
@ -11,5 +11,5 @@ export {ImportRewriter, NoopImportRewriter, R3SymbolsImportRewriter, validateAnd
|
|||||||
export {DefaultImportRecorder, DefaultImportTracker, NOOP_DEFAULT_IMPORT_RECORDER} from './src/default';
|
export {DefaultImportRecorder, DefaultImportTracker, NOOP_DEFAULT_IMPORT_RECORDER} from './src/default';
|
||||||
export {AbsoluteModuleStrategy, FileToModuleHost, FileToModuleStrategy, LocalIdentifierStrategy, LogicalProjectStrategy, ReferenceEmitStrategy, ReferenceEmitter, RelativePathStrategy} from './src/emitter';
|
export {AbsoluteModuleStrategy, FileToModuleHost, FileToModuleStrategy, LocalIdentifierStrategy, LogicalProjectStrategy, ReferenceEmitStrategy, ReferenceEmitter, RelativePathStrategy} from './src/emitter';
|
||||||
export {Reexport} from './src/reexport';
|
export {Reexport} from './src/reexport';
|
||||||
export {ImportMode, OwningModule, Reference} from './src/references';
|
export {ImportFlags, OwningModule, Reference} from './src/references';
|
||||||
export {ModuleResolver} from './src/resolver';
|
export {ModuleResolver} from './src/resolver';
|
||||||
|
@ -10,8 +10,10 @@ import {Expression, ExternalExpr} from '@angular/compiler';
|
|||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {ClassDeclaration, ReflectionHost, isNamedClassDeclaration} from '../../reflection';
|
import {ClassDeclaration, ReflectionHost, isNamedClassDeclaration} from '../../reflection';
|
||||||
import {FileToModuleHost, ReferenceEmitStrategy} from './emitter';
|
|
||||||
import {ImportMode, Reference} from './references';
|
import {FileToModuleHost, ImportFlags, ReferenceEmitStrategy} from './emitter';
|
||||||
|
import {Reference} from './references';
|
||||||
|
|
||||||
|
|
||||||
// Escape anything that isn't alphanumeric, '/' or '_'.
|
// Escape anything that isn't alphanumeric, '/' or '_'.
|
||||||
const CHARS_TO_ESCAPE = /[^a-zA-Z0-9/_]/g;
|
const CHARS_TO_ESCAPE = /[^a-zA-Z0-9/_]/g;
|
||||||
@ -206,7 +208,7 @@ export class PrivateExportAliasingHost implements AliasingHost {
|
|||||||
* directive or pipe, if it exists.
|
* directive or pipe, if it exists.
|
||||||
*/
|
*/
|
||||||
export class AliasStrategy implements ReferenceEmitStrategy {
|
export class AliasStrategy implements ReferenceEmitStrategy {
|
||||||
emit(ref: Reference<ts.Node>, context: ts.SourceFile, importMode: ImportMode): Expression|null {
|
emit(ref: Reference<ts.Node>, context: ts.SourceFile, importMode: ImportFlags): Expression|null {
|
||||||
return ref.alias;
|
return ref.alias;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ import {ReflectionHost} from '../../reflection';
|
|||||||
import {getSourceFile, isDeclaration, nodeNameForError} from '../../util/src/typescript';
|
import {getSourceFile, isDeclaration, nodeNameForError} from '../../util/src/typescript';
|
||||||
|
|
||||||
import {findExportedNameOfNode} from './find_export';
|
import {findExportedNameOfNode} from './find_export';
|
||||||
import {ImportMode, Reference} from './references';
|
import {Reference} from './references';
|
||||||
import {ModuleResolver} from './resolver';
|
import {ModuleResolver} from './resolver';
|
||||||
|
|
||||||
|
|
||||||
@ -29,6 +29,21 @@ export interface FileToModuleHost {
|
|||||||
fileNameToModuleName(importedFilePath: string, containingFilePath: string): string;
|
fileNameToModuleName(importedFilePath: string, containingFilePath: string): string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flags which alter the imports generated by the `ReferenceEmitter`.
|
||||||
|
*/
|
||||||
|
export enum ImportFlags {
|
||||||
|
None = 0x00,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 = 0x01,
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A particular strategy for generating an expression which refers to a `Reference`.
|
* A particular strategy for generating an expression which refers to a `Reference`.
|
||||||
*
|
*
|
||||||
@ -51,7 +66,7 @@ export interface ReferenceEmitStrategy {
|
|||||||
* @param importMode a flag which controls whether imports should be generated or not
|
* @param importMode a flag which controls whether imports should be generated or not
|
||||||
* @returns an `Expression` which refers to the `Reference`, or `null` if none can be generated
|
* @returns an `Expression` which refers to the `Reference`, or `null` if none can be generated
|
||||||
*/
|
*/
|
||||||
emit(ref: Reference, context: ts.SourceFile, importMode: ImportMode): Expression|null;
|
emit(ref: Reference, context: ts.SourceFile, importFlags: ImportFlags): Expression|null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,11 +78,10 @@ export interface ReferenceEmitStrategy {
|
|||||||
export class ReferenceEmitter {
|
export class ReferenceEmitter {
|
||||||
constructor(private strategies: ReferenceEmitStrategy[]) {}
|
constructor(private strategies: ReferenceEmitStrategy[]) {}
|
||||||
|
|
||||||
emit(
|
emit(ref: Reference, context: ts.SourceFile, importFlags: ImportFlags = ImportFlags.None):
|
||||||
ref: Reference, context: ts.SourceFile,
|
Expression {
|
||||||
importMode: ImportMode = ImportMode.UseExistingImport): Expression {
|
|
||||||
for (const strategy of this.strategies) {
|
for (const strategy of this.strategies) {
|
||||||
const emitted = strategy.emit(ref, context, importMode);
|
const emitted = strategy.emit(ref, context, importFlags);
|
||||||
if (emitted !== null) {
|
if (emitted !== null) {
|
||||||
return emitted;
|
return emitted;
|
||||||
}
|
}
|
||||||
@ -82,10 +96,10 @@ export class ReferenceEmitter {
|
|||||||
* such identifiers are available.
|
* such identifiers are available.
|
||||||
*/
|
*/
|
||||||
export class LocalIdentifierStrategy implements ReferenceEmitStrategy {
|
export class LocalIdentifierStrategy implements ReferenceEmitStrategy {
|
||||||
emit(ref: Reference<ts.Node>, context: ts.SourceFile, importMode: ImportMode): Expression|null {
|
emit(ref: Reference<ts.Node>, context: ts.SourceFile, importFlags: ImportFlags): Expression|null {
|
||||||
// If the emitter has specified ForceNewImport, then LocalIdentifierStrategy should not use a
|
// If the emitter has specified ForceNewImport, then LocalIdentifierStrategy should not use a
|
||||||
// local identifier at all, *except* in the source file where the node is actually declared.
|
// local identifier at all, *except* in the source file where the node is actually declared.
|
||||||
if (importMode === ImportMode.ForceNewImport &&
|
if (importFlags & ImportFlags.ForceNewImport &&
|
||||||
getSourceFile(ref.node) !== getSourceFile(context)) {
|
getSourceFile(ref.node) !== getSourceFile(context)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -121,7 +135,7 @@ export class AbsoluteModuleStrategy implements ReferenceEmitStrategy {
|
|||||||
protected program: ts.Program, protected checker: ts.TypeChecker,
|
protected program: ts.Program, protected checker: ts.TypeChecker,
|
||||||
protected moduleResolver: ModuleResolver, private reflectionHost: ReflectionHost) {}
|
protected moduleResolver: ModuleResolver, private reflectionHost: ReflectionHost) {}
|
||||||
|
|
||||||
emit(ref: Reference<ts.Node>, context: ts.SourceFile, importMode: ImportMode): Expression|null {
|
emit(ref: Reference<ts.Node>, context: ts.SourceFile): Expression|null {
|
||||||
if (ref.bestGuessOwningModule === null) {
|
if (ref.bestGuessOwningModule === null) {
|
||||||
// There is no module name available for this Reference, meaning it was arrived at via a
|
// There is no module name available for this Reference, meaning it was arrived at via a
|
||||||
// relative path.
|
// relative path.
|
||||||
|
@ -11,11 +11,6 @@ import * as ts from 'typescript';
|
|||||||
|
|
||||||
import {identifierOfNode} from '../../util/src/typescript';
|
import {identifierOfNode} from '../../util/src/typescript';
|
||||||
|
|
||||||
export enum ImportMode {
|
|
||||||
UseExistingImport,
|
|
||||||
ForceNewImport,
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface OwningModule {
|
export interface OwningModule {
|
||||||
specifier: string;
|
specifier: string;
|
||||||
resolutionContext: string;
|
resolutionContext: string;
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
import {ExpressionType, ExternalExpr, R3Identifiers as Identifiers, Type} from '@angular/compiler';
|
import {ExpressionType, ExternalExpr, R3Identifiers as Identifiers, Type} from '@angular/compiler';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {ImportMode, Reference, ReferenceEmitter} from '../../imports';
|
import {ImportFlags, Reference, ReferenceEmitter} from '../../imports';
|
||||||
import {PartialEvaluator, ResolvedValueMap} from '../../partial_evaluator';
|
import {PartialEvaluator, ResolvedValueMap} from '../../partial_evaluator';
|
||||||
import {ReflectionHost} from '../../reflection';
|
import {ReflectionHost} from '../../reflection';
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ export class ModuleWithProvidersScanner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ngModuleExpr =
|
const ngModuleExpr =
|
||||||
this.emitter.emit(ngModule, decl.getSourceFile(), ImportMode.ForceNewImport);
|
this.emitter.emit(ngModule, decl.getSourceFile(), ImportFlags.ForceNewImport);
|
||||||
const ngModuleType = new ExpressionType(ngModuleExpr);
|
const ngModuleType = new ExpressionType(ngModuleExpr);
|
||||||
const mwpNgType = new ExpressionType(
|
const mwpNgType = new ExpressionType(
|
||||||
new ExternalExpr(Identifiers.ModuleWithProviders), /* modifiers */ null, [ngModuleType]);
|
new ExternalExpr(Identifiers.ModuleWithProviders), /* modifiers */ null, [ngModuleType]);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user