refactor(ivy): use ClassDeclaration
in more ReflectionHost
methods (#29209)
PR Close #29209
This commit is contained in:

committed by
Miško Hevery

parent
bb6a3632f6
commit
2790352d04
@ -21,7 +21,6 @@ ts_library(
|
||||
"//packages/compiler-cli/src/ngtsc/scope",
|
||||
"//packages/compiler-cli/src/ngtsc/testing",
|
||||
"//packages/compiler-cli/src/ngtsc/translator",
|
||||
"//packages/compiler-cli/src/ngtsc/util",
|
||||
"@npm//typescript",
|
||||
],
|
||||
)
|
||||
|
@ -12,10 +12,9 @@ import {CycleAnalyzer, ImportGraph} from '../../cycles';
|
||||
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
|
||||
import {ModuleResolver, NOOP_DEFAULT_IMPORT_RECORDER, ReferenceEmitter} from '../../imports';
|
||||
import {PartialEvaluator} from '../../partial_evaluator';
|
||||
import {TypeScriptReflectionHost} from '../../reflection';
|
||||
import {TypeScriptReflectionHost, isNamedClassDeclaration} from '../../reflection';
|
||||
import {LocalModuleScopeRegistry, MetadataDtsModuleScopeResolver} from '../../scope';
|
||||
import {getDeclaration, makeProgram} from '../../testing/in_memory_typescript';
|
||||
import {isNamedClassDeclaration} from '../../util/src/typescript';
|
||||
import {ResourceLoader} from '../src/api';
|
||||
import {ComponentDecoratorHandler} from '../src/component';
|
||||
|
||||
|
@ -10,10 +10,9 @@ import * as ts from 'typescript';
|
||||
|
||||
import {NOOP_DEFAULT_IMPORT_RECORDER, ReferenceEmitter} from '../../imports';
|
||||
import {PartialEvaluator} from '../../partial_evaluator';
|
||||
import {TypeScriptReflectionHost} from '../../reflection';
|
||||
import {ClassDeclaration, TypeScriptReflectionHost, isNamedClassDeclaration} from '../../reflection';
|
||||
import {LocalModuleScopeRegistry, MetadataDtsModuleScopeResolver} from '../../scope';
|
||||
import {getDeclaration, makeProgram} from '../../testing/in_memory_typescript';
|
||||
import {isNamedClassDeclaration} from '../../util/src/typescript';
|
||||
import {DirectiveDecoratorHandler} from '../src/directive';
|
||||
|
||||
|
||||
@ -79,5 +78,5 @@ describe('DirectiveDecoratorHandler', () => {
|
||||
class TestReflectionHost extends TypeScriptReflectionHost {
|
||||
hasBaseClassReturnValue = false;
|
||||
|
||||
hasBaseClass(node: ts.Declaration): boolean { return this.hasBaseClassReturnValue; }
|
||||
hasBaseClass(clazz: ClassDeclaration): boolean { return this.hasBaseClassReturnValue; }
|
||||
}
|
||||
|
@ -12,10 +12,9 @@ import * as ts from 'typescript';
|
||||
|
||||
import {LocalIdentifierStrategy, NOOP_DEFAULT_IMPORT_RECORDER, ReferenceEmitter} from '../../imports';
|
||||
import {PartialEvaluator} from '../../partial_evaluator';
|
||||
import {TypeScriptReflectionHost} from '../../reflection';
|
||||
import {TypeScriptReflectionHost, isNamedClassDeclaration} from '../../reflection';
|
||||
import {LocalModuleScopeRegistry, MetadataDtsModuleScopeResolver} from '../../scope';
|
||||
import {getDeclaration, makeProgram} from '../../testing/in_memory_typescript';
|
||||
import {isNamedClassDeclaration} from '../../util/src/typescript';
|
||||
import {NgModuleDecoratorHandler} from '../src/ng_module';
|
||||
import {NoopReferencesRegistry} from '../src/references_registry';
|
||||
|
||||
|
@ -8,4 +8,5 @@
|
||||
|
||||
export * from './src/host';
|
||||
export {typeNodeToValueExpr} from './src/type_to_value';
|
||||
export {TypeScriptReflectionHost, filterToMembersWithDecorator, reflectIdentifierOfDeclaration, reflectNameOfDeclaration, reflectObjectLiteral, reflectTypeEntityToDeclaration} from './src/typescript';
|
||||
export {TypeScriptReflectionHost, filterToMembersWithDecorator, reflectIdentifierOfDeclaration, reflectNameOfDeclaration, reflectObjectLiteral, reflectTypeEntityToDeclaration} from './src/typescript';
|
||||
export {isNamedClassDeclaration, isNamedFunctionDeclaration, isNamedVariableDeclaration} from './src/util';
|
||||
|
@ -362,16 +362,13 @@ export interface ReflectionHost {
|
||||
* Examine a declaration which should be of a class, and return metadata about the members of the
|
||||
* class.
|
||||
*
|
||||
* @param declaration a TypeScript `ts.Declaration` node representing the class over which to
|
||||
* reflect. If the source is in ES6 format, this will be a `ts.ClassDeclaration` node. If the
|
||||
* source is in ES5 format, this might be a `ts.VariableDeclaration` as classes in ES5 are
|
||||
* represented as the result of an IIFE execution.
|
||||
* @param clazz a `ClassDeclaration` representing the class over which to reflect.
|
||||
*
|
||||
* @returns an array of `ClassMember` metadata representing the members of the class.
|
||||
*
|
||||
* @throws if `declaration` does not resolve to a class declaration.
|
||||
*/
|
||||
getMembersOfClass(clazz: ts.Declaration): ClassMember[];
|
||||
getMembersOfClass(clazz: ClassDeclaration): ClassMember[];
|
||||
|
||||
/**
|
||||
* Reflect over the constructor of a class and return metadata about its parameters.
|
||||
@ -379,16 +376,13 @@ export interface ReflectionHost {
|
||||
* This method only looks at the constructor of a class directly and not at any inherited
|
||||
* constructors.
|
||||
*
|
||||
* @param declaration a TypeScript `ts.Declaration` node representing the class over which to
|
||||
* reflect. If the source is in ES6 format, this will be a `ts.ClassDeclaration` node. If the
|
||||
* source is in ES5 format, this might be a `ts.VariableDeclaration` as classes in ES5 are
|
||||
* represented as the result of an IIFE execution.
|
||||
* @param clazz a `ClassDeclaration` representing the class over which to reflect.
|
||||
*
|
||||
* @returns an array of `Parameter` metadata representing the parameters of the constructor, if
|
||||
* a constructor exists. If the constructor exists and has 0 parameters, this array will be empty.
|
||||
* If the class has no constructor, this method returns `null`.
|
||||
*/
|
||||
getConstructorParameters(declaration: ts.Declaration): CtorParameter[]|null;
|
||||
getConstructorParameters(clazz: ClassDeclaration): CtorParameter[]|null;
|
||||
|
||||
/**
|
||||
* Reflect over a function and return metadata about its parameters and body.
|
||||
@ -478,17 +472,21 @@ export interface ReflectionHost {
|
||||
isClass(node: ts.Node): node is ClassDeclaration;
|
||||
|
||||
/**
|
||||
* Determines whether the given declaration has a base class.
|
||||
* Determines whether the given declaration, which should be a class, has a base class.
|
||||
*
|
||||
* @param clazz a `ClassDeclaration` representing the class over which to reflect.
|
||||
*/
|
||||
hasBaseClass(node: ts.Declaration): boolean;
|
||||
hasBaseClass(clazz: ClassDeclaration): boolean;
|
||||
|
||||
/**
|
||||
* Get the number of generic type parameters of a given class.
|
||||
*
|
||||
* @param clazz a `ClassDeclaration` representing the class over which to reflect.
|
||||
*
|
||||
* @returns the number of type parameters of the class, if known, or `null` if the declaration
|
||||
* is not a class or has an unknown number of type parameters.
|
||||
*/
|
||||
getGenericArityOfClass(clazz: ts.Declaration): number|null;
|
||||
getGenericArityOfClass(clazz: ClassDeclaration): number|null;
|
||||
|
||||
/**
|
||||
* Find the assigned value of a variable declaration.
|
||||
|
@ -26,17 +26,17 @@ export class TypeScriptReflectionHost implements ReflectionHost {
|
||||
.filter((dec): dec is Decorator => dec !== null);
|
||||
}
|
||||
|
||||
getMembersOfClass(declaration: ts.Declaration): ClassMember[] {
|
||||
const clazz = castDeclarationToClassOrDie(declaration);
|
||||
return clazz.members.map(member => this._reflectMember(member))
|
||||
getMembersOfClass(clazz: ClassDeclaration): ClassMember[] {
|
||||
const tsClazz = castDeclarationToClassOrDie(clazz);
|
||||
return tsClazz.members.map(member => this._reflectMember(member))
|
||||
.filter((member): member is ClassMember => member !== null);
|
||||
}
|
||||
|
||||
getConstructorParameters(declaration: ts.Declaration): CtorParameter[]|null {
|
||||
const clazz = castDeclarationToClassOrDie(declaration);
|
||||
getConstructorParameters(clazz: ClassDeclaration): CtorParameter[]|null {
|
||||
const tsClazz = castDeclarationToClassOrDie(clazz);
|
||||
|
||||
// First, find the constructor.
|
||||
const ctor = clazz.members.find(ts.isConstructorDeclaration);
|
||||
const ctor = tsClazz.members.find(ts.isConstructorDeclaration);
|
||||
if (ctor === undefined) {
|
||||
return null;
|
||||
}
|
||||
@ -139,9 +139,9 @@ export class TypeScriptReflectionHost implements ReflectionHost {
|
||||
return ts.isClassDeclaration(node) && (node.name !== undefined) && ts.isIdentifier(node.name);
|
||||
}
|
||||
|
||||
hasBaseClass(node: ts.Declaration): boolean {
|
||||
return ts.isClassDeclaration(node) && node.heritageClauses !== undefined &&
|
||||
node.heritageClauses.some(clause => clause.token === ts.SyntaxKind.ExtendsKeyword);
|
||||
hasBaseClass(clazz: ClassDeclaration): boolean {
|
||||
return ts.isClassDeclaration(clazz) && clazz.heritageClauses !== undefined &&
|
||||
clazz.heritageClauses.some(clause => clause.token === ts.SyntaxKind.ExtendsKeyword);
|
||||
}
|
||||
|
||||
getDeclarationOfIdentifier(id: ts.Identifier): Declaration|null {
|
||||
@ -166,7 +166,7 @@ export class TypeScriptReflectionHost implements ReflectionHost {
|
||||
};
|
||||
}
|
||||
|
||||
getGenericArityOfClass(clazz: ts.Declaration): number|null {
|
||||
getGenericArityOfClass(clazz: ClassDeclaration): number|null {
|
||||
if (!ts.isClassDeclaration(clazz)) {
|
||||
return null;
|
||||
}
|
||||
@ -419,7 +419,8 @@ export function reflectObjectLiteral(node: ts.ObjectLiteralExpression): Map<stri
|
||||
return map;
|
||||
}
|
||||
|
||||
function castDeclarationToClassOrDie(declaration: ts.Declaration): ts.ClassDeclaration {
|
||||
function castDeclarationToClassOrDie(declaration: ClassDeclaration):
|
||||
ClassDeclaration<ts.ClassDeclaration> {
|
||||
if (!ts.isClassDeclaration(declaration)) {
|
||||
throw new Error(
|
||||
`Reflecting on a ${ts.SyntaxKind[declaration.kind]} instead of a ClassDeclaration.`);
|
||||
|
27
packages/compiler-cli/src/ngtsc/reflection/src/util.ts
Normal file
27
packages/compiler-cli/src/ngtsc/reflection/src/util.ts
Normal file
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* @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 {ClassDeclaration} from './host';
|
||||
|
||||
|
||||
export function isNamedClassDeclaration(node: ts.Node):
|
||||
node is ClassDeclaration<ts.ClassDeclaration>&{name: ts.Identifier} {
|
||||
return ts.isClassDeclaration(node) && (node.name !== undefined);
|
||||
}
|
||||
|
||||
export function isNamedFunctionDeclaration(node: ts.Node):
|
||||
node is ClassDeclaration<ts.FunctionDeclaration>&{name: ts.Identifier} {
|
||||
return ts.isFunctionDeclaration(node) && (node.name !== undefined);
|
||||
}
|
||||
|
||||
export function isNamedVariableDeclaration(node: ts.Node):
|
||||
node is ClassDeclaration<ts.VariableDeclaration>&{name: ts.Identifier} {
|
||||
return ts.isVariableDeclaration(node) && (node.name !== undefined);
|
||||
}
|
@ -11,6 +11,7 @@ import * as ts from 'typescript';
|
||||
import {getDeclaration, makeProgram} from '../../testing/in_memory_typescript';
|
||||
import {CtorParameter} from '../src/host';
|
||||
import {TypeScriptReflectionHost} from '../src/typescript';
|
||||
import {isNamedClassDeclaration} from '../src/util';
|
||||
|
||||
describe('reflector', () => {
|
||||
describe('ctor params', () => {
|
||||
@ -25,7 +26,7 @@ describe('reflector', () => {
|
||||
}
|
||||
`
|
||||
}]);
|
||||
const clazz = getDeclaration(program, 'entry.ts', 'Foo', ts.isClassDeclaration);
|
||||
const clazz = getDeclaration(program, 'entry.ts', 'Foo', isNamedClassDeclaration);
|
||||
const checker = program.getTypeChecker();
|
||||
const host = new TypeScriptReflectionHost(checker);
|
||||
const args = host.getConstructorParameters(clazz) !;
|
||||
@ -54,7 +55,7 @@ describe('reflector', () => {
|
||||
`
|
||||
}
|
||||
]);
|
||||
const clazz = getDeclaration(program, 'entry.ts', 'Foo', ts.isClassDeclaration);
|
||||
const clazz = getDeclaration(program, 'entry.ts', 'Foo', isNamedClassDeclaration);
|
||||
const checker = program.getTypeChecker();
|
||||
const host = new TypeScriptReflectionHost(checker);
|
||||
const args = host.getConstructorParameters(clazz) !;
|
||||
@ -83,7 +84,7 @@ describe('reflector', () => {
|
||||
`
|
||||
}
|
||||
]);
|
||||
const clazz = getDeclaration(program, 'entry.ts', 'Foo', ts.isClassDeclaration);
|
||||
const clazz = getDeclaration(program, 'entry.ts', 'Foo', isNamedClassDeclaration);
|
||||
const checker = program.getTypeChecker();
|
||||
const host = new TypeScriptReflectionHost(checker);
|
||||
const args = host.getConstructorParameters(clazz) !;
|
||||
@ -111,7 +112,7 @@ describe('reflector', () => {
|
||||
`
|
||||
}
|
||||
]);
|
||||
const clazz = getDeclaration(program, 'entry.ts', 'Foo', ts.isClassDeclaration);
|
||||
const clazz = getDeclaration(program, 'entry.ts', 'Foo', isNamedClassDeclaration);
|
||||
const checker = program.getTypeChecker();
|
||||
const host = new TypeScriptReflectionHost(checker);
|
||||
const args = host.getConstructorParameters(clazz) !;
|
||||
@ -139,7 +140,7 @@ describe('reflector', () => {
|
||||
`
|
||||
}
|
||||
]);
|
||||
const clazz = getDeclaration(program, 'entry.ts', 'Foo', ts.isClassDeclaration);
|
||||
const clazz = getDeclaration(program, 'entry.ts', 'Foo', isNamedClassDeclaration);
|
||||
const checker = program.getTypeChecker();
|
||||
const host = new TypeScriptReflectionHost(checker);
|
||||
const args = host.getConstructorParameters(clazz) !;
|
||||
@ -166,7 +167,7 @@ describe('reflector', () => {
|
||||
`
|
||||
}
|
||||
]);
|
||||
const clazz = getDeclaration(program, 'entry.ts', 'Foo', ts.isClassDeclaration);
|
||||
const clazz = getDeclaration(program, 'entry.ts', 'Foo', isNamedClassDeclaration);
|
||||
const checker = program.getTypeChecker();
|
||||
const host = new TypeScriptReflectionHost(checker);
|
||||
const args = host.getConstructorParameters(clazz) !;
|
||||
@ -198,7 +199,7 @@ describe('reflector', () => {
|
||||
`
|
||||
}
|
||||
]);
|
||||
const clazz = getDeclaration(program, 'entry.ts', 'Foo', ts.isClassDeclaration);
|
||||
const clazz = getDeclaration(program, 'entry.ts', 'Foo', isNamedClassDeclaration);
|
||||
const checker = program.getTypeChecker();
|
||||
const host = new TypeScriptReflectionHost(checker);
|
||||
const args = host.getConstructorParameters(clazz) !;
|
||||
@ -292,4 +293,4 @@ function argExpressionToString(name: ts.Node | null): string {
|
||||
} else {
|
||||
throw new Error(`Unexpected node in arg expression: ${ts.SyntaxKind[name.kind]}.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -139,7 +139,8 @@ export class MetadataDtsModuleScopeResolver implements DtsModuleScopeResolver {
|
||||
*
|
||||
* @param ref `Reference` to the class of interest, with the context of how it was obtained.
|
||||
*/
|
||||
private readModuleMetadataFromClass(ref: Reference<ts.Declaration>): RawDependencyMetadata|null {
|
||||
private readModuleMetadataFromClass(ref: Reference<ClassDeclaration>): RawDependencyMetadata
|
||||
|null {
|
||||
const clazz = ref.node;
|
||||
const resolutionContext = clazz.getSourceFile().fileName;
|
||||
// This operation is explicitly not memoized, as it depends on `ref.ownedByModuleGuess`.
|
||||
|
@ -9,8 +9,8 @@
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {Reference} from '../../imports';
|
||||
import {ClassDeclaration, ClassMemberKind, ReflectionHost, reflectTypeEntityToDeclaration} from '../../reflection';
|
||||
import {isNamedClassDeclaration, nodeDebugInfo} from '../../util/src/typescript';
|
||||
import {ClassDeclaration, ClassMemberKind, ReflectionHost, isNamedClassDeclaration, reflectTypeEntityToDeclaration} from '../../reflection';
|
||||
import {nodeDebugInfo} from '../../util/src/typescript';
|
||||
|
||||
export function extractReferencesFromType(
|
||||
checker: ts.TypeChecker, def: ts.TypeNode, ngModuleImportedFrom: string | null,
|
||||
@ -77,7 +77,7 @@ export function readStringArrayType(type: ts.TypeNode): string[] {
|
||||
}
|
||||
|
||||
|
||||
export function extractDirectiveGuards(node: ts.Declaration, reflector: ReflectionHost): {
|
||||
export function extractDirectiveGuards(node: ClassDeclaration, reflector: ReflectionHost): {
|
||||
ngTemplateGuards: string[],
|
||||
hasNgTemplateContextGuard: boolean,
|
||||
} {
|
||||
@ -88,7 +88,7 @@ export function extractDirectiveGuards(node: ts.Declaration, reflector: Reflecti
|
||||
return {hasNgTemplateContextGuard, ngTemplateGuards};
|
||||
}
|
||||
|
||||
function nodeStaticMethodNames(node: ts.Declaration, reflector: ReflectionHost): string[] {
|
||||
function nodeStaticMethodNames(node: ClassDeclaration, reflector: ReflectionHost): string[] {
|
||||
return reflector.getMembersOfClass(node)
|
||||
.filter(member => member.kind === ClassMemberKind.Method && member.isStatic)
|
||||
.map(member => member.name);
|
||||
|
@ -11,9 +11,9 @@ import * as ts from 'typescript';
|
||||
|
||||
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
|
||||
import {ImportRewriter} from '../../imports';
|
||||
import {ClassDeclaration, ReflectionHost, reflectNameOfDeclaration} from '../../reflection';
|
||||
import {ClassDeclaration, ReflectionHost, isNamedClassDeclaration, reflectNameOfDeclaration} from '../../reflection';
|
||||
import {TypeCheckContext} from '../../typecheck';
|
||||
import {getSourceFile, isNamedClassDeclaration} from '../../util/src/typescript';
|
||||
import {getSourceFile} from '../../util/src/typescript';
|
||||
|
||||
import {AnalysisOutput, CompileResult, DecoratorHandler, DetectResult, HandlerPrecedence} from './api';
|
||||
import {DtsFileTransformer} from './declaration';
|
||||
|
@ -67,12 +67,11 @@ export class NgTscPlugin implements TscPlugin {
|
||||
const afterDeclarations: Array<ts.TransformerFactory<ts.SourceFile|ts.Bundle>> =
|
||||
[(context: ts.TransformationContext) => (sf: ts.SourceFile | ts.Bundle) => {
|
||||
const visitor = (node: ts.Node): ts.Node => {
|
||||
if (node.kind === ts.SyntaxKind.ClassDeclaration) {
|
||||
const clz = node as ts.ClassDeclaration;
|
||||
if (ts.isClassDeclaration(node)) {
|
||||
// For demo purposes, transform the class name in the .d.ts output
|
||||
return ts.updateClassDeclaration(
|
||||
clz, clz.decorators, node.modifiers, ts.createIdentifier('NEWNAME'),
|
||||
clz.typeParameters, clz.heritageClauses, clz.members);
|
||||
node, node.decorators, node.modifiers, ts.createIdentifier('NEWNAME'),
|
||||
node.typeParameters, node.heritageClauses, node.members);
|
||||
}
|
||||
return ts.visitEachChild(node, visitor, context);
|
||||
};
|
||||
|
@ -12,6 +12,7 @@ ts_library(
|
||||
"//packages:types",
|
||||
"//packages/compiler-cli/src/ngtsc/imports",
|
||||
"//packages/compiler-cli/src/ngtsc/path",
|
||||
"//packages/compiler-cli/src/ngtsc/reflection",
|
||||
"//packages/compiler-cli/src/ngtsc/testing",
|
||||
"//packages/compiler-cli/src/ngtsc/typecheck",
|
||||
"//packages/compiler-cli/src/ngtsc/util",
|
||||
|
@ -10,8 +10,9 @@ import * as ts from 'typescript';
|
||||
|
||||
import {AbsoluteModuleStrategy, LocalIdentifierStrategy, LogicalProjectStrategy, ReferenceEmitter} from '../../imports';
|
||||
import {LogicalFileSystem} from '../../path';
|
||||
import {isNamedClassDeclaration} from '../../reflection';
|
||||
import {getDeclaration, makeProgram} from '../../testing/in_memory_typescript';
|
||||
import {getRootDirs, isNamedClassDeclaration} from '../../util/src/typescript';
|
||||
import {getRootDirs} from '../../util/src/typescript';
|
||||
import {TypeCheckContext} from '../src/context';
|
||||
import {TypeCheckProgramHost} from '../src/host';
|
||||
|
||||
|
@ -60,11 +60,6 @@ export function isDeclaration(node: ts.Node): node is ts.Declaration {
|
||||
ts.isFunctionDeclaration(node) || ts.isVariableDeclaration(node);
|
||||
}
|
||||
|
||||
export function isNamedClassDeclaration(node: ts.Node): node is ts.ClassDeclaration&
|
||||
{name: ts.Identifier} {
|
||||
return ts.isClassDeclaration(node) && (node.name !== undefined);
|
||||
}
|
||||
|
||||
export function isExported(node: ts.Declaration): boolean {
|
||||
let topLevel: ts.Node = node;
|
||||
if (ts.isVariableDeclaration(node) && ts.isVariableDeclarationList(node.parent)) {
|
||||
|
Reference in New Issue
Block a user