fix(ivy): ensure ngcc compiles `@angular/core` with correct internal imports (#26236)

PR Close #26236
This commit is contained in:
Pete Bacon Darwin 2018-10-03 16:59:32 +01:00 committed by Jason Aden
parent 807070fe83
commit 83302d193e
20 changed files with 357 additions and 210 deletions

View File

@ -48,16 +48,17 @@ export class Analyzer {
handlers: DecoratorHandler<any, any>[] = [
new BaseDefDecoratorHandler(this.typeChecker, this.host),
new ComponentDecoratorHandler(
this.typeChecker, this.host, this.scopeRegistry, false, this.resourceLoader, this.rootDirs),
new DirectiveDecoratorHandler(this.typeChecker, this.host, this.scopeRegistry, false),
new InjectableDecoratorHandler(this.host, false),
new NgModuleDecoratorHandler(this.typeChecker, this.host, this.scopeRegistry, false),
new PipeDecoratorHandler(this.typeChecker, this.host, this.scopeRegistry, false),
this.typeChecker, this.host, this.scopeRegistry, this.isCore, this.resourceLoader,
this.rootDirs),
new DirectiveDecoratorHandler(this.typeChecker, this.host, this.scopeRegistry, this.isCore),
new InjectableDecoratorHandler(this.host, this.isCore),
new NgModuleDecoratorHandler(this.typeChecker, this.host, this.scopeRegistry, this.isCore),
new PipeDecoratorHandler(this.typeChecker, this.host, this.scopeRegistry, this.isCore),
];
constructor(
private typeChecker: ts.TypeChecker, private host: NgccReflectionHost,
private rootDirs: string[]) {}
private rootDirs: string[], private isCore: boolean) {}
/**
* Analyize a parsed file to generate the information about decorated classes that

View File

@ -13,7 +13,9 @@ import {DtsMapper} from './dts_mapper';
import {Fesm2015ReflectionHost} from './fesm2015_host';
export class Esm2015ReflectionHost extends Fesm2015ReflectionHost {
constructor(checker: ts.TypeChecker, protected dtsMapper: DtsMapper) { super(checker); }
constructor(isCore: boolean, checker: ts.TypeChecker, protected dtsMapper: DtsMapper) {
super(isCore, checker);
}
/**
* Get the number of generic type parameters of a given class.

View File

@ -31,7 +31,7 @@ import {Fesm2015ReflectionHost, ParamInfo, getPropertyValueFromSymbol, isAssignm
*
*/
export class Esm5ReflectionHost extends Fesm2015ReflectionHost {
constructor(checker: ts.TypeChecker) { super(checker); }
constructor(isCore: boolean, checker: ts.TypeChecker) { super(isCore, checker); }
/**
* Check whether the given node actually represents a class.

View File

@ -9,7 +9,7 @@
import {normalize} from 'canonical-path';
import * as ts from 'typescript';
import {ClassMember, ClassMemberKind, CtorParameter, Decorator} from '../../../ngtsc/host';
import {ClassMember, ClassMemberKind, CtorParameter, Decorator, Import} from '../../../ngtsc/host';
import {TypeScriptReflectionHost, reflectObjectLiteral} from '../../../ngtsc/metadata';
import {findAll, getNameText, isDefined} from '../utils';
@ -48,7 +48,7 @@ export const CONSTRUCTOR_PARAMS = 'ctorParameters' as ts.__String;
* a static method called `ctorParameters`.
*/
export class Fesm2015ReflectionHost extends TypeScriptReflectionHost implements NgccReflectionHost {
constructor(checker: ts.TypeChecker) { super(checker); }
constructor(protected isCore: boolean, checker: ts.TypeChecker) { super(checker); }
/**
* Examine a declaration (for example, of a class or function) and return metadata about any
@ -281,6 +281,19 @@ export class Fesm2015ReflectionHost extends TypeScriptReflectionHost implements
return null;
}
/**
* Determine if an identifier was imported from another module and return `Import` metadata
* describing its origin.
*
* @param id a TypeScript `ts.Identifer` to reflect.
*
* @returns metadata about the `Import` if the identifier was imported from another module, or
* `null` if the identifier doesn't resolve to an import but instead is locally defined.
*/
getImportOfIdentifier(id: ts.Identifier): Import|null {
return super.getImportOfIdentifier(id) || this.getImportOfNamespacedIdentifier(id);
}
///////////// Protected Helpers /////////////
/**
@ -336,7 +349,8 @@ export class Fesm2015ReflectionHost extends TypeScriptReflectionHost implements
decoratorsIdentifier.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
// AST of the array of decorator values
const decoratorsArray = decoratorsIdentifier.parent.right;
return this.reflectDecorators(decoratorsArray).filter(isImportedFromCore);
return this.reflectDecorators(decoratorsArray)
.filter(decorator => this.isFromCore(decorator));
}
}
return null;
@ -362,7 +376,8 @@ export class Fesm2015ReflectionHost extends TypeScriptReflectionHost implements
helperCalls.forEach(helperCall => {
const {classDecorators} =
this.reflectDecoratorsFromHelperCall(helperCall, makeClassTargetFilter(symbol.name));
classDecorators.filter(isImportedFromCore).forEach(decorator => decorators.push(decorator));
classDecorators.filter(decorator => this.isFromCore(decorator))
.forEach(decorator => decorators.push(decorator));
});
return decorators.length ? decorators : null;
}
@ -405,7 +420,8 @@ export class Fesm2015ReflectionHost extends TypeScriptReflectionHost implements
if (propDecoratorsMap && ts.isObjectLiteralExpression(propDecoratorsMap)) {
const propertiesMap = reflectObjectLiteral(propDecoratorsMap);
propertiesMap.forEach((value, name) => {
const decorators = this.reflectDecorators(value).filter(isImportedFromCore);
const decorators =
this.reflectDecorators(value).filter(decorator => this.isFromCore(decorator));
if (decorators.length) {
memberDecorators.set(name, decorators);
}
@ -437,7 +453,7 @@ export class Fesm2015ReflectionHost extends TypeScriptReflectionHost implements
memberDecorators.forEach((decorators, memberName) => {
if (memberName) {
const memberDecorators = memberDecoratorMap.get(memberName) || [];
const coreDecorators = decorators.filter(isImportedFromCore);
const coreDecorators = decorators.filter(decorator => this.isFromCore(decorator));
memberDecoratorMap.set(memberName, memberDecorators.concat(coreDecorators));
}
});
@ -731,8 +747,9 @@ export class Fesm2015ReflectionHost extends TypeScriptReflectionHost implements
.map(paramInfo => {
const type = paramInfo && paramInfo.get('type') || null;
const decoratorInfo = paramInfo && paramInfo.get('decorators') || null;
const decorators =
decoratorInfo && this.reflectDecorators(decoratorInfo).filter(isImportedFromCore);
const decorators = decoratorInfo &&
this.reflectDecorators(decoratorInfo)
.filter(decorator => this.isFromCore(decorator));
return {type, decorators};
});
}
@ -816,6 +833,70 @@ export class Fesm2015ReflectionHost extends TypeScriptReflectionHost implements
protected getStatementsForClass(classSymbol: ts.Symbol): ts.Statement[] {
return Array.from(classSymbol.valueDeclaration.getSourceFile().statements);
}
/**
* Try to get the import info for this identifier as though it is a namespaced import.
* For example, if the identifier is the `__metadata` part of a property access chain like:
*
* ```
* tslib_1.__metadata
* ```
*
* then it might be that `tslib_1` is a namespace import such as:
*
* ```
* import * as tslib_1 from 'tslib';
* ```
* @param id the TypeScript identifier to find the import info for.
* @returns The import info if this is a namespaced import or `null`.
*/
protected getImportOfNamespacedIdentifier(id: ts.Identifier): Import|null {
if (!(ts.isPropertyAccessExpression(id.parent) && id.parent.name === id)) {
return null;
}
const namespaceIdentifier = getFarLeftIdentifier(id.parent);
const namespaceSymbol =
namespaceIdentifier && this.checker.getSymbolAtLocation(namespaceIdentifier);
const declaration = namespaceSymbol && namespaceSymbol.declarations.length === 1 ?
namespaceSymbol.declarations[0] :
null;
const namespaceDeclaration =
declaration && ts.isNamespaceImport(declaration) ? declaration : null;
if (!namespaceDeclaration) {
return null;
}
const importDeclaration = namespaceDeclaration.parent.parent;
if (!ts.isStringLiteral(importDeclaration.moduleSpecifier)) {
// Should not happen as this would be invalid TypesScript
return null;
}
return {
from: importDeclaration.moduleSpecifier.text,
name: id.text,
};
}
/**
* Test whether a decorator was imported from `@angular/core`.
*
* Is the decorator:
* * externally imported from `@angulare/core`?
* * the current hosted program is actually `@angular/core` and
* - relatively internally imported; or
* - not imported, from the current file.
*
* @param decorator the decorator to test.
*/
isFromCore(decorator: Decorator): boolean {
if (this.isCore) {
return !decorator.import || /^\./.test(decorator.import.from);
} else {
return !!decorator.import && decorator.import.from === '@angular/core';
}
}
}
///////////// Exported Helpers /////////////
@ -846,24 +927,6 @@ export function isAssignment(expression: ts.Expression):
expression.operatorToken.kind === ts.SyntaxKind.EqualsToken;
}
/**
* Test whether a decorator was imported from `@angular/core`.
*
* Is the decorator:
* * extermally mported from `@angulare/core`?
* * relatively internally imported where the decoratee is already in `@angular/core`?
*
* Note we do not support decorators that are not imported at all.
*
* @param decorator the decorator to test.
*/
export function isImportedFromCore(decorator: Decorator): boolean {
const importFrom = decorator.import && decorator.import.from || '';
return importFrom === '@angular/core' ||
(/^\./.test(importFrom) &&
/node_modules[\\\/]@angular[\\\/]core/.test(decorator.node.getSourceFile().fileName));
}
/**
* The type of a function that can be used to filter out helpers based on their target.
* This is used in `reflectDecoratorsFromHelperCall()`.
@ -952,3 +1015,16 @@ function isClassMemberType(node: ts.Declaration): node is ts.ClassElement|
ts.PropertyAccessExpression|ts.BinaryExpression {
return ts.isClassElement(node) || isPropertyAccess(node) || ts.isBinaryExpression(node);
}
/**
* Compute the left most identifier in a property access chain. E.g. the `a` of `a.b.c.d`.
* @param propertyAccess The starting property access expression from which we want to compute
* the left most identifier.
* @returns the left most identifier in the chain or `null` if it is not an identifier.
*/
function getFarLeftIdentifier(propertyAccess: ts.PropertyAccessExpression): ts.Identifier|null {
while (ts.isPropertyAccessExpression(propertyAccess.expression)) {
propertyAccess = propertyAccess.expression;
}
return ts.isIdentifier(propertyAccess.expression) ? propertyAccess.expression : null;
}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {dirname, relative, resolve} from 'canonical-path';
import {existsSync, readFileSync, writeFileSync} from 'fs';
import {existsSync, lstatSync, readFileSync, readdirSync, writeFileSync} from 'fs';
import {mkdir, mv} from 'shelljs';
import * as ts from 'typescript';
@ -24,10 +24,10 @@ import {FileParser} from '../parsing/file_parser';
import {Esm2015Renderer} from '../rendering/esm2015_renderer';
import {Esm5Renderer} from '../rendering/esm5_renderer';
import {FileInfo, Renderer} from '../rendering/renderer';
import {checkMarkerFile, writeMarkerFile} from './build_marker';
import {EntryPoint, EntryPointFormat} from './entry_point';
/**
* A Package is stored in a directory on disk and that directory can contain one or more package
* formats - e.g. fesm2015, UMD, etc. Additionally, each package provides typings (`.d.ts` files).
@ -78,14 +78,19 @@ export class Transformer {
throw new Error(
`Missing entry point file for format, ${format}, in package, ${entryPoint.path}.`);
}
const packageProgram = ts.createProgram([entryPointFilePath], options, host);
const isCore = entryPoint.name === '@angular/core';
const r3SymbolsPath = isCore ? this.findR3SymbolsPath(dirname(entryPointFilePath)) : null;
const rootPaths = r3SymbolsPath ? [entryPointFilePath, r3SymbolsPath] : [entryPointFilePath];
const packageProgram = ts.createProgram(rootPaths, options, host);
const typeChecker = packageProgram.getTypeChecker();
const dtsMapper = new DtsMapper(dirname(entryPointFilePath), dirname(entryPoint.typings));
const reflectionHost = this.getHost(format, packageProgram, dtsMapper);
const reflectionHost = this.getHost(isCore, format, packageProgram, dtsMapper);
const r3SymbolsFile = r3SymbolsPath && packageProgram.getSourceFile(r3SymbolsPath) || null;
const parser = this.getFileParser(format, packageProgram, reflectionHost);
const analyzer = new Analyzer(typeChecker, reflectionHost, rootDirs);
const renderer = this.getRenderer(format, packageProgram, reflectionHost);
const analyzer = new Analyzer(typeChecker, reflectionHost, rootDirs, isCore);
const renderer =
this.getRenderer(format, packageProgram, reflectionHost, isCore, r3SymbolsFile);
// Parse and analyze the files.
const entryPointFile = packageProgram.getSourceFile(entryPointFilePath) !;
@ -111,15 +116,16 @@ export class Transformer {
writeMarkerFile(entryPoint, format);
}
getHost(format: string, program: ts.Program, dtsMapper: DtsMapper): NgccReflectionHost {
getHost(isCore: boolean, format: string, program: ts.Program, dtsMapper: DtsMapper):
NgccReflectionHost {
switch (format) {
case 'esm2015':
return new Esm2015ReflectionHost(program.getTypeChecker(), dtsMapper);
return new Esm2015ReflectionHost(isCore, program.getTypeChecker(), dtsMapper);
case 'fesm2015':
return new Fesm2015ReflectionHost(program.getTypeChecker());
return new Fesm2015ReflectionHost(isCore, program.getTypeChecker());
case 'esm5':
case 'fesm5':
return new Esm5ReflectionHost(program.getTypeChecker());
return new Esm5ReflectionHost(isCore, program.getTypeChecker());
default:
throw new Error(`Relection host for "${format}" not yet implemented.`);
}
@ -138,14 +144,16 @@ export class Transformer {
}
}
getRenderer(format: string, program: ts.Program, host: NgccReflectionHost): Renderer {
getRenderer(
format: string, program: ts.Program, host: NgccReflectionHost, isCore: boolean,
rewriteCoreImportsTo: ts.SourceFile|null): Renderer {
switch (format) {
case 'esm2015':
case 'fesm2015':
return new Esm2015Renderer(host);
return new Esm2015Renderer(host, isCore, rewriteCoreImportsTo);
case 'esm5':
case 'fesm5':
return new Esm5Renderer(host);
return new Esm5Renderer(host, isCore, rewriteCoreImportsTo);
default:
throw new Error(`Renderer for "${format}" not yet implemented.`);
}
@ -210,4 +218,32 @@ export class Transformer {
}
writeFileSync(file.path, file.contents, 'utf8');
}
findR3SymbolsPath(directory: string): string|null {
const r3SymbolsFilePath = resolve(directory, 'r3_symbols.js');
if (existsSync(r3SymbolsFilePath)) {
return r3SymbolsFilePath;
}
const subDirectories =
readdirSync(directory)
// Not interested in hidden files
.filter(p => !p.startsWith('.'))
// Ignore node_modules
.filter(p => p !== 'node_modules')
// Only interested in directories (and only those that are not symlinks)
.filter(p => {
const stat = lstatSync(resolve(directory, p));
return stat.isDirectory() && !stat.isSymbolicLink();
});
for (const subDirectory of subDirectories) {
const r3SymbolsFilePath = this.findR3SymbolsPath(resolve(directory, subDirectory));
if (r3SymbolsFilePath) {
return r3SymbolsFilePath;
}
}
return null;
}
}

View File

@ -0,0 +1,21 @@
/**
* @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 {ImportManager} from '../../../ngtsc/translator';
export class NgccImportManager extends ImportManager {
constructor(private isFlat: boolean, isCore: boolean, prefix?: string) { super(isCore, prefix); }
generateNamedImport(moduleName: string, symbol: string): string|null {
if (this.isFlat && this.isCore && moduleName === '@angular/core') {
return null;
}
return super.generateNamedImport(moduleName, symbol);
}
}

View File

@ -14,7 +14,8 @@ import {SourceMapConsumer, SourceMapGenerator, RawSourceMap} from 'source-map';
import * as ts from 'typescript';
import {Decorator} from '../../../ngtsc/host';
import {ImportManager, translateStatement} from '../../../ngtsc/translator';
import {translateStatement} from '../../../ngtsc/translator';
import {NgccImportManager} from './ngcc_import_manager';
import {AnalyzedClass, AnalyzedFile} from '../analyzer';
import {IMPORT_PREFIX} from '../constants';
import {NgccReflectionHost} from '../host/ngcc_host';
@ -64,7 +65,9 @@ export interface FileInfo {
* implement the `addImports`, `addDefinitions` and `removeDecorators` abstract methods.
*/
export abstract class Renderer {
constructor(protected host: NgccReflectionHost) {}
constructor(
protected host: NgccReflectionHost, protected isCore: boolean,
protected rewriteCoreImportsTo: ts.SourceFile|null) {}
/**
* Render the source code and source-map for an Analyzed file.
@ -72,7 +75,8 @@ export abstract class Renderer {
* @param targetPath The absolute path where the rendered file will be written.
*/
renderFile(file: AnalyzedFile, targetPath: string): RenderResult {
const importManager = new ImportManager(false, IMPORT_PREFIX);
const importManager =
new NgccImportManager(!this.rewriteCoreImportsTo, this.isCore, IMPORT_PREFIX);
const input = this.extractSourceMap(file.sourceFile);
const outputText = new MagicString(input.source);
@ -88,7 +92,9 @@ export abstract class Renderer {
outputText, renderConstantPool(file.sourceFile, file.constantPool, importManager),
file.sourceFile);
this.addImports(outputText, importManager.getAllImports(file.sourceFile.fileName, null));
this.addImports(
outputText,
importManager.getAllImports(file.sourceFile.fileName, this.rewriteCoreImportsTo));
// TODO: remove contructor param metadata and property decorators (we need info from the
// handlers to do this)
@ -241,7 +247,7 @@ export function mergeSourceMaps(
* Render the constant pool as source code for the given class.
*/
export function renderConstantPool(
sourceFile: ts.SourceFile, constantPool: ConstantPool, imports: ImportManager): string {
sourceFile: ts.SourceFile, constantPool: ConstantPool, imports: NgccImportManager): string {
const printer = ts.createPrinter();
return constantPool.statements.map(stmt => translateStatement(stmt, imports))
.map(stmt => printer.printNode(ts.EmitHint.Unspecified, stmt, sourceFile))
@ -257,7 +263,7 @@ export function renderConstantPool(
* @param imports An object that tracks the imports that are needed by the rendered definitions.
*/
export function renderDefinitions(
sourceFile: ts.SourceFile, analyzedClass: AnalyzedClass, imports: ImportManager): string {
sourceFile: ts.SourceFile, analyzedClass: AnalyzedClass, imports: NgccImportManager): string {
const printer = ts.createPrinter();
const name = (analyzedClass.declaration as ts.NamedDeclaration).name !;
const definitions =

View File

@ -80,7 +80,8 @@ describe('Analyzer', () => {
program = makeProgram(TEST_PROGRAM);
const file = createParsedFile(program);
const analyzer = new Analyzer(
program.getTypeChecker(), new Fesm2015ReflectionHost(program.getTypeChecker()), ['']);
program.getTypeChecker(), new Fesm2015ReflectionHost(false, program.getTypeChecker()),
[''], false);
testHandler = createTestHandler();
analyzer.handlers = [testHandler];
result = analyzer.analyzeFile(file);

View File

@ -58,7 +58,7 @@ describe('Esm2015ReflectionHost', () => {
const program = makeProgram(CLASSES[0]);
const dtsMapper = new DtsMapper('/src', '/typings');
const host = new Esm2015ReflectionHost(program.getTypeChecker(), dtsMapper);
const host = new Esm2015ReflectionHost(false, program.getTypeChecker(), dtsMapper);
const noTypeParamClass =
getDeclaration(program, '/src/class.js', 'NoTypeParam', ts.isClassDeclaration);
expect(host.getGenericArityOfClass(noTypeParamClass)).toBe(0);
@ -76,7 +76,7 @@ describe('Esm2015ReflectionHost', () => {
() => {
const program = makeProgram(MARKER_FILE);
const dtsMapper = new DtsMapper('/src', '/typings');
const host = new Esm2015ReflectionHost(program.getTypeChecker(), dtsMapper);
const host = new Esm2015ReflectionHost(false, program.getTypeChecker(), dtsMapper);
const file = program.getSourceFile(MARKER_FILE.name) !;
const declarations = host.getSwitchableDeclarations(file);
expect(declarations.map(d => [d.name.getText(), d.initializer !.getText()])).toEqual([

View File

@ -16,7 +16,7 @@ const FILES = [
{
name: '/some_directive.js',
contents: `
import * as tslib_1 from "tslib";
import * as tslib_1 from 'tslib';
import { Directive, Inject, InjectionToken, Input } from '@angular/core';
var INJECTED_TOKEN = new InjectionToken('injected');
var ViewContainerRef = /** @class */ (function () {
@ -60,7 +60,7 @@ const FILES = [
{
name: '/node_modules/@angular/core/some_directive.js',
contents: `
import * as tslib_1 from "tslib";
import * as tslib_1 from 'tslib';
import { Directive, Input } from './directives';
var SomeDirective = /** @class */ (function () {
function SomeDirective() {
@ -81,7 +81,7 @@ export { SomeDirective };
{
name: '/ngmodule.js',
contents: `
import * as tslib_1 from "tslib";
import * as tslib_1 from 'tslib';
import { NgModule } from '@angular/core';
var HttpClientXsrfModule = /** @class */ (function () {
function HttpClientXsrfModule() {
@ -119,7 +119,7 @@ describe('Esm5ReflectionHost [import helper style]', () => {
describe('getDecoratorsOfDeclaration()', () => {
it('should find the decorators on a class', () => {
const program = makeProgram(fileSystem.files[0]);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
@ -144,7 +144,7 @@ describe('Esm5ReflectionHost [import helper style]', () => {
{});
const program = makeProgram(fileSystem.files[0]);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
@ -159,7 +159,7 @@ describe('Esm5ReflectionHost [import helper style]', () => {
it('should support decorators being used inside @angular/core', () => {
const program = makeProgram(fileSystem.files[1]);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(true, program.getTypeChecker());
const classNode = getDeclaration(
program, '/node_modules/@angular/core/some_directive.js', 'SomeDirective',
ts.isVariableDeclaration);
@ -180,7 +180,7 @@ describe('Esm5ReflectionHost [import helper style]', () => {
describe('getMembersOfClass()', () => {
it('should find decorated members on a class', () => {
const program = makeProgram(fileSystem.files[0]);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
const members = host.getMembersOfClass(classNode);
@ -198,7 +198,7 @@ describe('Esm5ReflectionHost [import helper style]', () => {
it('should find non decorated properties on a class', () => {
const program = makeProgram(fileSystem.files[0]);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
const members = host.getMembersOfClass(classNode);
@ -212,7 +212,7 @@ describe('Esm5ReflectionHost [import helper style]', () => {
it('should find static methods on a class', () => {
const program = makeProgram(fileSystem.files[0]);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
const members = host.getMembersOfClass(classNode);
@ -225,7 +225,7 @@ describe('Esm5ReflectionHost [import helper style]', () => {
it('should find static properties on a class', () => {
const program = makeProgram(fileSystem.files[0]);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
const members = host.getMembersOfClass(classNode);
@ -242,7 +242,7 @@ describe('Esm5ReflectionHost [import helper style]', () => {
spyOn(Esm5ReflectionHost.prototype, 'getImportOfIdentifier').and.returnValue({});
const program = makeProgram(fileSystem.files[0]);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
@ -253,7 +253,7 @@ describe('Esm5ReflectionHost [import helper style]', () => {
it('should support decorators being used inside @angular/core', () => {
const program = makeProgram(fileSystem.files[1]);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(true, program.getTypeChecker());
const classNode = getDeclaration(
program, '/node_modules/@angular/core/some_directive.js', 'SomeDirective',
ts.isVariableDeclaration);
@ -269,7 +269,7 @@ describe('Esm5ReflectionHost [import helper style]', () => {
describe('getConstructorParameters', () => {
it('should find the decorated constructor parameters', () => {
const program = makeProgram(fileSystem.files[0]);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
const parameters = host.getConstructorParameters(classNode);
@ -290,7 +290,7 @@ describe('Esm5ReflectionHost [import helper style]', () => {
.and.returnValue(mockImportInfo);
const program = makeProgram(fileSystem.files[0]);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
const parameters = host.getConstructorParameters(classNode);
@ -308,7 +308,7 @@ describe('Esm5ReflectionHost [import helper style]', () => {
describe('getDeclarationOfIdentifier', () => {
it('should return the declaration of a locally defined identifier', () => {
const program = makeProgram(fileSystem.files[0]);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
const ctrDecorators = host.getConstructorParameters(classNode) !;
@ -324,7 +324,7 @@ describe('Esm5ReflectionHost [import helper style]', () => {
it('should return the declaration of an externally defined identifier', () => {
const program = makeProgram(fileSystem.files[0]);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
const classDecorators = host.getDecoratorsOfDeclaration(classNode) !;
@ -349,7 +349,7 @@ describe('Esm5ReflectionHost [import helper style]', () => {
describe('getVariableValue', () => {
it('should find the "actual" declaration of an aliased variable identifier', () => {
const program = makeProgram(fileSystem.files[2]);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const ngModuleRef = findVariableDeclaration(
program.getSourceFile(fileSystem.files[2].name) !, 'HttpClientXsrfModule_1');
@ -364,7 +364,7 @@ describe('Esm5ReflectionHost [import helper style]', () => {
it('should return undefined if the variable has no assignment', () => {
const program = makeProgram(fileSystem.files[2]);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const missingValue = findVariableDeclaration(
program.getSourceFile(fileSystem.files[2].name) !, 'missingValue');
const value = host.getVariableValue(missingValue !);
@ -373,7 +373,7 @@ describe('Esm5ReflectionHost [import helper style]', () => {
it('should return null if the variable is not assigned from a call to __decorate', () => {
const program = makeProgram(fileSystem.files[2]);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const nonDecoratedVar = findVariableDeclaration(
program.getSourceFile(fileSystem.files[2].name) !, 'nonDecoratedVar');
const value = host.getVariableValue(nonDecoratedVar !);

View File

@ -432,7 +432,7 @@ describe('Esm5ReflectionHost', () => {
describe('getDecoratorsOfDeclaration()', () => {
it('should find the decorators on a class', () => {
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isVariableDeclaration);
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
@ -450,7 +450,7 @@ describe('Esm5ReflectionHost', () => {
it('should return null if the symbol is not a class', () => {
const program = makeProgram(FOO_FUNCTION_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const functionNode =
getDeclaration(program, FOO_FUNCTION_FILE.name, 'foo', ts.isFunctionDeclaration);
const decorators = host.getDecoratorsOfDeclaration(functionNode);
@ -459,7 +459,7 @@ describe('Esm5ReflectionHost', () => {
it('should return null if there are no decorators', () => {
const program = makeProgram(SIMPLE_CLASS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode =
getDeclaration(program, SIMPLE_CLASS_FILE.name, 'EmptyClass', ts.isVariableDeclaration);
const decorators = host.getDecoratorsOfDeclaration(classNode);
@ -468,7 +468,7 @@ describe('Esm5ReflectionHost', () => {
it('should ignore `decorators` if it is not an array literal', () => {
const program = makeProgram(INVALID_DECORATORS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_DECORATORS_FILE.name, 'NotArrayLiteral', ts.isVariableDeclaration);
const decorators = host.getDecoratorsOfDeclaration(classNode);
@ -477,7 +477,7 @@ describe('Esm5ReflectionHost', () => {
it('should ignore decorator elements that are not object literals', () => {
const program = makeProgram(INVALID_DECORATORS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_DECORATORS_FILE.name, 'NotObjectLiteral', ts.isVariableDeclaration);
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
@ -488,7 +488,7 @@ describe('Esm5ReflectionHost', () => {
it('should ignore decorator elements that have no `type` property', () => {
const program = makeProgram(INVALID_DECORATORS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_DECORATORS_FILE.name, 'NoTypeProperty', ts.isVariableDeclaration);
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
@ -499,7 +499,7 @@ describe('Esm5ReflectionHost', () => {
it('should ignore decorator elements whose `type` value is not an identifier', () => {
const program = makeProgram(INVALID_DECORATORS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_DECORATORS_FILE.name, 'NotIdentifier', ts.isVariableDeclaration);
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
@ -514,7 +514,7 @@ describe('Esm5ReflectionHost', () => {
.and.returnValue(mockImportInfo);
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isVariableDeclaration);
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
@ -529,7 +529,7 @@ describe('Esm5ReflectionHost', () => {
describe('(returned decorators `args`)', () => {
it('should be an empty array if decorator has no `args` property', () => {
const program = makeProgram(INVALID_DECORATOR_ARGS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_DECORATOR_ARGS_FILE.name, 'NoArgsProperty', ts.isVariableDeclaration);
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
@ -541,7 +541,7 @@ describe('Esm5ReflectionHost', () => {
it('should be an empty array if decorator\'s `args` has no property assignment', () => {
const program = makeProgram(INVALID_DECORATOR_ARGS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_DECORATOR_ARGS_FILE.name, 'NoPropertyAssignment',
ts.isVariableDeclaration);
@ -554,7 +554,7 @@ describe('Esm5ReflectionHost', () => {
it('should be an empty array if `args` property value is not an array literal', () => {
const program = makeProgram(INVALID_DECORATOR_ARGS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_DECORATOR_ARGS_FILE.name, 'NotArrayLiteral', ts.isVariableDeclaration);
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
@ -569,7 +569,7 @@ describe('Esm5ReflectionHost', () => {
describe('getMembersOfClass()', () => {
it('should find decorated members on a class', () => {
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isVariableDeclaration);
const members = host.getMembersOfClass(classNode);
@ -587,7 +587,7 @@ describe('Esm5ReflectionHost', () => {
it('should find non decorated properties on a class', () => {
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isVariableDeclaration);
const members = host.getMembersOfClass(classNode);
@ -601,7 +601,7 @@ describe('Esm5ReflectionHost', () => {
it('should find static methods on a class', () => {
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isVariableDeclaration);
const members = host.getMembersOfClass(classNode);
@ -614,7 +614,7 @@ describe('Esm5ReflectionHost', () => {
it('should find static properties on a class', () => {
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isVariableDeclaration);
const members = host.getMembersOfClass(classNode);
@ -628,7 +628,7 @@ describe('Esm5ReflectionHost', () => {
it('should throw if the symbol is not a class', () => {
const program = makeProgram(FOO_FUNCTION_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const functionNode =
getDeclaration(program, FOO_FUNCTION_FILE.name, 'foo', ts.isFunctionDeclaration);
expect(() => {
@ -638,7 +638,7 @@ describe('Esm5ReflectionHost', () => {
it('should return an empty array if there are no prop decorators', () => {
const program = makeProgram(SIMPLE_CLASS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode =
getDeclaration(program, SIMPLE_CLASS_FILE.name, 'EmptyClass', ts.isVariableDeclaration);
const members = host.getMembersOfClass(classNode);
@ -649,7 +649,7 @@ describe('Esm5ReflectionHost', () => {
it('should not process decorated properties in `propDecorators` if it is not an object literal',
() => {
const program = makeProgram(INVALID_PROP_DECORATORS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_PROP_DECORATORS_FILE.name, 'NotObjectLiteral',
ts.isVariableDeclaration);
@ -660,7 +660,7 @@ describe('Esm5ReflectionHost', () => {
it('should ignore prop decorator elements that are not object literals', () => {
const program = makeProgram(INVALID_PROP_DECORATORS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_PROP_DECORATORS_FILE.name, 'NotObjectLiteralProp',
ts.isVariableDeclaration);
@ -674,7 +674,7 @@ describe('Esm5ReflectionHost', () => {
it('should ignore prop decorator elements that have no `type` property', () => {
const program = makeProgram(INVALID_PROP_DECORATORS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_PROP_DECORATORS_FILE.name, 'NoTypeProperty', ts.isVariableDeclaration);
const members = host.getMembersOfClass(classNode);
@ -687,7 +687,7 @@ describe('Esm5ReflectionHost', () => {
it('should ignore prop decorator elements whose `type` value is not an identifier', () => {
const program = makeProgram(INVALID_PROP_DECORATORS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_PROP_DECORATORS_FILE.name, 'NotIdentifier', ts.isVariableDeclaration);
const members = host.getMembersOfClass(classNode);
@ -706,7 +706,7 @@ describe('Esm5ReflectionHost', () => {
});
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isVariableDeclaration);
const members = host.getMembersOfClass(classNode);
@ -722,7 +722,7 @@ describe('Esm5ReflectionHost', () => {
describe('(returned prop decorators `args`)', () => {
it('should be an empty array if prop decorator has no `args` property', () => {
const program = makeProgram(INVALID_PROP_DECORATOR_ARGS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_PROP_DECORATOR_ARGS_FILE.name, 'NoArgsProperty',
ts.isVariableDeclaration);
@ -737,7 +737,7 @@ describe('Esm5ReflectionHost', () => {
it('should be an empty array if prop decorator\'s `args` has no property assignment', () => {
const program = makeProgram(INVALID_PROP_DECORATOR_ARGS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_PROP_DECORATOR_ARGS_FILE.name, 'NoPropertyAssignment',
ts.isVariableDeclaration);
@ -752,7 +752,7 @@ describe('Esm5ReflectionHost', () => {
it('should be an empty array if `args` property value is not an array literal', () => {
const program = makeProgram(INVALID_PROP_DECORATOR_ARGS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_PROP_DECORATOR_ARGS_FILE.name, 'NotArrayLiteral',
ts.isVariableDeclaration);
@ -770,7 +770,7 @@ describe('Esm5ReflectionHost', () => {
describe('getConstructorParameters', () => {
it('should find the decorated constructor parameters', () => {
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isVariableDeclaration);
const parameters = host.getConstructorParameters(classNode);
@ -786,7 +786,7 @@ describe('Esm5ReflectionHost', () => {
it('should throw if the symbol is not a class', () => {
const program = makeProgram(FOO_FUNCTION_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const functionNode =
getDeclaration(program, FOO_FUNCTION_FILE.name, 'foo', ts.isFunctionDeclaration);
expect(() => { host.getConstructorParameters(functionNode); })
@ -799,7 +799,7 @@ describe('Esm5ReflectionHost', () => {
it('should return an array even if there are no decorators', () => {
const program = makeProgram(SIMPLE_CLASS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, SIMPLE_CLASS_FILE.name, 'NoDecoratorConstructorClass', ts.isVariableDeclaration);
const parameters = host.getConstructorParameters(classNode);
@ -812,7 +812,7 @@ describe('Esm5ReflectionHost', () => {
it('should return an empty array if there are no constructor parameters', () => {
const program = makeProgram(INVALID_CTOR_DECORATORS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_CTOR_DECORATORS_FILE.name, 'NoParameters', ts.isVariableDeclaration);
const parameters = host.getConstructorParameters(classNode);
@ -825,7 +825,7 @@ describe('Esm5ReflectionHost', () => {
it('should ignore `ctorParameters` if it does not return an array literal', () => {
const program = makeProgram(INVALID_CTOR_DECORATORS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_CTOR_DECORATORS_FILE.name, 'NotArrayLiteral', ts.isVariableDeclaration);
const parameters = host.getConstructorParameters(classNode);
@ -840,7 +840,7 @@ describe('Esm5ReflectionHost', () => {
describe('(returned parameters `decorators`)', () => {
it('should ignore param decorator elements that are not object literals', () => {
const program = makeProgram(INVALID_CTOR_DECORATORS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_CTOR_DECORATORS_FILE.name, 'NotObjectLiteral',
ts.isVariableDeclaration);
@ -859,7 +859,7 @@ describe('Esm5ReflectionHost', () => {
it('should ignore param decorator elements that have no `type` property', () => {
const program = makeProgram(INVALID_CTOR_DECORATORS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_CTOR_DECORATORS_FILE.name, 'NoTypeProperty', ts.isVariableDeclaration);
const parameters = host.getConstructorParameters(classNode);
@ -871,7 +871,7 @@ describe('Esm5ReflectionHost', () => {
it('should ignore param decorator elements whose `type` value is not an identifier', () => {
const program = makeProgram(INVALID_CTOR_DECORATORS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_CTOR_DECORATORS_FILE.name, 'NotIdentifier', ts.isVariableDeclaration);
const parameters = host.getConstructorParameters(classNode);
@ -887,7 +887,7 @@ describe('Esm5ReflectionHost', () => {
.and.returnValue(mockImportInfo);
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isVariableDeclaration);
const parameters = host.getConstructorParameters(classNode);
@ -904,7 +904,7 @@ describe('Esm5ReflectionHost', () => {
describe('(returned parameters `decorators.args`)', () => {
it('should be an empty array if param decorator has no `args` property', () => {
const program = makeProgram(INVALID_CTOR_DECORATOR_ARGS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_CTOR_DECORATOR_ARGS_FILE.name, 'NoArgsProperty',
ts.isVariableDeclaration);
@ -919,7 +919,7 @@ describe('Esm5ReflectionHost', () => {
it('should be an empty array if param decorator\'s `args` has no property assignment', () => {
const program = makeProgram(INVALID_CTOR_DECORATOR_ARGS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_CTOR_DECORATOR_ARGS_FILE.name, 'NoPropertyAssignment',
ts.isVariableDeclaration);
@ -933,7 +933,7 @@ describe('Esm5ReflectionHost', () => {
it('should be an empty array if `args` property value is not an array literal', () => {
const program = makeProgram(INVALID_CTOR_DECORATOR_ARGS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_CTOR_DECORATOR_ARGS_FILE.name, 'NotArrayLiteral',
ts.isVariableDeclaration);
@ -950,7 +950,7 @@ describe('Esm5ReflectionHost', () => {
describe('getDefinitionOfFunction()', () => {
it('should return an object describing the function declaration passed as an argument', () => {
const program = makeProgram(FUNCTION_BODY_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const fooNode =
getDeclaration(program, FUNCTION_BODY_FILE.name, 'foo', ts.isFunctionDeclaration) !;
@ -998,7 +998,7 @@ describe('Esm5ReflectionHost', () => {
describe('getImportOfIdentifier', () => {
it('should find the import of an identifier', () => {
const program = makeProgram(...IMPORTS_FILES);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const variableNode =
getDeclaration(program, IMPORTS_FILES[1].name, 'b', ts.isVariableDeclaration);
const importOfIdent = host.getImportOfIdentifier(variableNode.initializer as ts.Identifier);
@ -1008,7 +1008,7 @@ describe('Esm5ReflectionHost', () => {
it('should find the name by which the identifier was exported, not imported', () => {
const program = makeProgram(...IMPORTS_FILES);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const variableNode =
getDeclaration(program, IMPORTS_FILES[1].name, 'c', ts.isVariableDeclaration);
const importOfIdent = host.getImportOfIdentifier(variableNode.initializer as ts.Identifier);
@ -1018,7 +1018,7 @@ describe('Esm5ReflectionHost', () => {
it('should return null if the identifier was not imported', () => {
const program = makeProgram(...IMPORTS_FILES);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const variableNode =
getDeclaration(program, IMPORTS_FILES[1].name, 'd', ts.isVariableDeclaration);
const importOfIdent = host.getImportOfIdentifier(variableNode.initializer as ts.Identifier);
@ -1030,7 +1030,7 @@ describe('Esm5ReflectionHost', () => {
describe('getDeclarationOfIdentifier', () => {
it('should return the declaration of a locally defined identifier', () => {
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isVariableDeclaration);
const ctrDecorators = host.getConstructorParameters(classNode) !;
@ -1046,7 +1046,7 @@ describe('Esm5ReflectionHost', () => {
it('should return the declaration of an externally defined identifier', () => {
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isVariableDeclaration);
const classDecorators = host.getDecoratorsOfDeclaration(classNode) !;
@ -1066,7 +1066,7 @@ describe('Esm5ReflectionHost', () => {
describe('getExportsOfModule()', () => {
it('should return a map of all the exports from a given module', () => {
const program = makeProgram(...EXPORTS_FILES);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const file = program.getSourceFile(EXPORTS_FILES[1].name) !;
const exportDeclarations = host.getExportsOfModule(file);
expect(exportDeclarations).not.toBe(null);
@ -1116,7 +1116,7 @@ describe('Esm5ReflectionHost', () => {
const mockSymbol = {} as ts.Symbol;
superGetClassSymbolSpy.and.returnValue(mockSymbol);
const host = new Esm5ReflectionHost({} as any);
const host = new Esm5ReflectionHost(false, {} as any);
expect(host.getClassSymbol(mockNode)).toBe(mockSymbol);
expect(superGetClassSymbolSpy).toHaveBeenCalledWith(mockNode);
@ -1124,7 +1124,7 @@ describe('Esm5ReflectionHost', () => {
it('should return the class symbol for an ES5 class (outer variable declaration)', () => {
const program = makeProgram(SIMPLE_CLASS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const node =
getDeclaration(program, SIMPLE_CLASS_FILE.name, 'EmptyClass', ts.isVariableDeclaration);
expect(host.getClassSymbol(node)).toBeDefined();
@ -1132,7 +1132,7 @@ describe('Esm5ReflectionHost', () => {
it('should return the class symbol for an ES5 class (inner function declaration)', () => {
const program = makeProgram(SIMPLE_CLASS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const outerNode =
getDeclaration(program, SIMPLE_CLASS_FILE.name, 'EmptyClass', ts.isVariableDeclaration);
const innerNode =
@ -1146,7 +1146,7 @@ describe('Esm5ReflectionHost', () => {
it('should return the same class symbol (of the inner declaration) for outer and inner declarations',
() => {
const program = makeProgram(SIMPLE_CLASS_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const outerNode = getDeclaration(
program, SIMPLE_CLASS_FILE.name, 'EmptyClass', ts.isVariableDeclaration);
const innerNode = (((outerNode.initializer as ts.ParenthesizedExpression)
@ -1160,7 +1160,7 @@ describe('Esm5ReflectionHost', () => {
it('should return undefined if node is not an ES5 class', () => {
const program = makeProgram(FOO_FUNCTION_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const node = getDeclaration(program, FOO_FUNCTION_FILE.name, 'foo', ts.isFunctionDeclaration);
expect(host.getClassSymbol(node)).toBeUndefined();
});
@ -1173,7 +1173,7 @@ describe('Esm5ReflectionHost', () => {
let getClassSymbolSpy: jasmine.Spy;
beforeEach(() => {
host = new Esm5ReflectionHost(null as any);
host = new Esm5ReflectionHost(false, null as any);
mockNode = {} as any;
superIsClassSpy = spyOn(Fesm2015ReflectionHost.prototype, 'isClass');

View File

@ -104,7 +104,7 @@ describe('Fesm2015ReflectionHost [import helper style]', () => {
describe('getDecoratorsOfDeclaration()', () => {
it('should find the decorators on a class', () => {
const program = makeProgram(fileSystem.files[0]);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
@ -128,7 +128,7 @@ describe('Fesm2015ReflectionHost [import helper style]', () => {
{});
const program = makeProgram(fileSystem.files[0]);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
@ -143,7 +143,7 @@ describe('Fesm2015ReflectionHost [import helper style]', () => {
it('should support decorators being used inside @angular/core', () => {
const program = makeProgram(fileSystem.files[1]);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(true, program.getTypeChecker());
const classNode = getDeclaration(
program, '/node_modules/@angular/core/some_directive.js', 'SomeDirective',
ts.isVariableDeclaration);
@ -164,7 +164,7 @@ describe('Fesm2015ReflectionHost [import helper style]', () => {
describe('getMembersOfClass()', () => {
it('should find decorated members on a class', () => {
const program = makeProgram(fileSystem.files[0]);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
const members = host.getMembersOfClass(classNode);
@ -182,7 +182,7 @@ describe('Fesm2015ReflectionHost [import helper style]', () => {
it('should find non decorated properties on a class', () => {
const program = makeProgram(fileSystem.files[0]);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
const members = host.getMembersOfClass(classNode);
@ -196,7 +196,7 @@ describe('Fesm2015ReflectionHost [import helper style]', () => {
it('should find static methods on a class', () => {
const program = makeProgram(fileSystem.files[0]);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
const members = host.getMembersOfClass(classNode);
@ -209,7 +209,7 @@ describe('Fesm2015ReflectionHost [import helper style]', () => {
it('should find static properties on a class', () => {
const program = makeProgram(fileSystem.files[0]);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
@ -226,7 +226,7 @@ describe('Fesm2015ReflectionHost [import helper style]', () => {
spyOn(Fesm2015ReflectionHost.prototype, 'getImportOfIdentifier').and.returnValue({});
const program = makeProgram(fileSystem.files[0]);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
@ -237,7 +237,7 @@ describe('Fesm2015ReflectionHost [import helper style]', () => {
it('should support decorators being used inside @angular/core', () => {
const program = makeProgram(fileSystem.files[1]);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(true, program.getTypeChecker());
const classNode = getDeclaration(
program, '/node_modules/@angular/core/some_directive.js', 'SomeDirective',
ts.isVariableDeclaration);
@ -253,7 +253,7 @@ describe('Fesm2015ReflectionHost [import helper style]', () => {
describe('getConstructorParameters', () => {
it('should find the decorated constructor parameters', () => {
const program = makeProgram(fileSystem.files[0]);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
const parameters = host.getConstructorParameters(classNode);
@ -274,7 +274,7 @@ describe('Fesm2015ReflectionHost [import helper style]', () => {
.and.returnValue(mockImportInfo);
const program = makeProgram(fileSystem.files[0]);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
const parameters = host.getConstructorParameters(classNode);
@ -292,7 +292,7 @@ describe('Fesm2015ReflectionHost [import helper style]', () => {
describe('getDeclarationOfIdentifier', () => {
it('should return the declaration of a locally defined identifier', () => {
const program = makeProgram(fileSystem.files[0]);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
const ctrDecorators = host.getConstructorParameters(classNode) !;
@ -308,7 +308,7 @@ describe('Fesm2015ReflectionHost [import helper style]', () => {
it('should return the declaration of an externally defined identifier', () => {
const program = makeProgram(fileSystem.files[0]);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, '/some_directive.js', 'SomeDirective', ts.isVariableDeclaration);
const classDecorators = host.getDecoratorsOfDeclaration(classNode) !;
@ -331,7 +331,7 @@ describe('Fesm2015ReflectionHost [import helper style]', () => {
describe('getVariableValue', () => {
it('should find the "actual" declaration of an aliased variable identifier', () => {
const program = makeProgram(fileSystem.files[2]);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const ngModuleRef = findVariableDeclaration(
program.getSourceFile(fileSystem.files[2].name) !, 'HttpClientXsrfModule_1');
@ -346,7 +346,7 @@ describe('Fesm2015ReflectionHost [import helper style]', () => {
it('should return null if the variable has no assignment', () => {
const program = makeProgram(fileSystem.files[2]);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const missingValue = findVariableDeclaration(
program.getSourceFile(fileSystem.files[2].name) !, 'missingValue');
const value = host.getVariableValue(missingValue !);
@ -355,7 +355,7 @@ describe('Fesm2015ReflectionHost [import helper style]', () => {
it('should return null if the variable is not assigned from a call to __decorate', () => {
const program = makeProgram(fileSystem.files[2]);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const nonDecoratedVar = findVariableDeclaration(
program.getSourceFile(fileSystem.files[2].name) !, 'nonDecoratedVar');
const value = host.getVariableValue(nonDecoratedVar !);

View File

@ -397,7 +397,7 @@ describe('Fesm2015ReflectionHost', () => {
describe('getDecoratorsOfDeclaration()', () => {
it('should find the decorators on a class', () => {
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode =
getDeclaration(program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isClassDeclaration);
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
@ -415,7 +415,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should return null if the symbol is not a class', () => {
const program = makeProgram(FOO_FUNCTION_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const functionNode =
getDeclaration(program, FOO_FUNCTION_FILE.name, 'foo', ts.isFunctionDeclaration);
const decorators = host.getDecoratorsOfDeclaration(functionNode);
@ -424,7 +424,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should return null if there are no decorators', () => {
const program = makeProgram(SIMPLE_CLASS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode =
getDeclaration(program, SIMPLE_CLASS_FILE.name, 'EmptyClass', ts.isClassDeclaration);
const decorators = host.getDecoratorsOfDeclaration(classNode);
@ -433,7 +433,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should ignore `decorators` if it is not an array literal', () => {
const program = makeProgram(INVALID_DECORATORS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_DECORATORS_FILE.name, 'NotArrayLiteral', ts.isClassDeclaration);
const decorators = host.getDecoratorsOfDeclaration(classNode);
@ -442,7 +442,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should ignore decorator elements that are not object literals', () => {
const program = makeProgram(INVALID_DECORATORS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_DECORATORS_FILE.name, 'NotObjectLiteral', ts.isClassDeclaration);
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
@ -453,7 +453,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should ignore decorator elements that have no `type` property', () => {
const program = makeProgram(INVALID_DECORATORS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_DECORATORS_FILE.name, 'NoTypeProperty', ts.isClassDeclaration);
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
@ -464,7 +464,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should ignore decorator elements whose `type` value is not an identifier', () => {
const program = makeProgram(INVALID_DECORATORS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_DECORATORS_FILE.name, 'NotIdentifier', ts.isClassDeclaration);
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
@ -479,7 +479,7 @@ describe('Fesm2015ReflectionHost', () => {
.and.returnValue(mockImportInfo);
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode =
getDeclaration(program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isClassDeclaration);
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
@ -494,7 +494,7 @@ describe('Fesm2015ReflectionHost', () => {
describe('(returned decorators `args`)', () => {
it('should be an empty array if decorator has no `args` property', () => {
const program = makeProgram(INVALID_DECORATOR_ARGS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_DECORATOR_ARGS_FILE.name, 'NoArgsProperty', ts.isClassDeclaration);
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
@ -506,7 +506,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should be an empty array if decorator\'s `args` has no property assignment', () => {
const program = makeProgram(INVALID_DECORATOR_ARGS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_DECORATOR_ARGS_FILE.name, 'NoPropertyAssignment',
ts.isClassDeclaration);
@ -519,7 +519,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should be an empty array if `args` property value is not an array literal', () => {
const program = makeProgram(INVALID_DECORATOR_ARGS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_DECORATOR_ARGS_FILE.name, 'NotArrayLiteral', ts.isClassDeclaration);
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
@ -534,7 +534,7 @@ describe('Fesm2015ReflectionHost', () => {
describe('getMembersOfClass()', () => {
it('should find decorated properties on a class', () => {
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode =
getDeclaration(program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isClassDeclaration);
const members = host.getMembersOfClass(classNode);
@ -552,7 +552,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should find non decorated properties on a class', () => {
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode =
getDeclaration(program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isClassDeclaration);
const members = host.getMembersOfClass(classNode);
@ -566,7 +566,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should find static methods on a class', () => {
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode =
getDeclaration(program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isClassDeclaration);
const members = host.getMembersOfClass(classNode);
@ -579,7 +579,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should find static properties on a class', () => {
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode =
getDeclaration(program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isClassDeclaration);
const members = host.getMembersOfClass(classNode);
@ -593,7 +593,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should throw if the symbol is not a class', () => {
const program = makeProgram(FOO_FUNCTION_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const functionNode =
getDeclaration(program, FOO_FUNCTION_FILE.name, 'foo', ts.isFunctionDeclaration);
expect(() => {
@ -603,7 +603,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should return an empty array if there are no prop decorators', () => {
const program = makeProgram(SIMPLE_CLASS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode =
getDeclaration(program, SIMPLE_CLASS_FILE.name, 'EmptyClass', ts.isClassDeclaration);
const members = host.getMembersOfClass(classNode);
@ -614,7 +614,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should not process decorated properties in `propDecorators` if it is not an object literal',
() => {
const program = makeProgram(INVALID_PROP_DECORATORS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_PROP_DECORATORS_FILE.name, 'NotObjectLiteral', ts.isClassDeclaration);
const members = host.getMembersOfClass(classNode);
@ -624,7 +624,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should ignore prop decorator elements that are not object literals', () => {
const program = makeProgram(INVALID_PROP_DECORATORS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_PROP_DECORATORS_FILE.name, 'NotObjectLiteralProp',
ts.isClassDeclaration);
@ -638,7 +638,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should ignore prop decorator elements that have no `type` property', () => {
const program = makeProgram(INVALID_PROP_DECORATORS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_PROP_DECORATORS_FILE.name, 'NoTypeProperty', ts.isClassDeclaration);
const members = host.getMembersOfClass(classNode);
@ -651,7 +651,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should ignore prop decorator elements whose `type` value is not an identifier', () => {
const program = makeProgram(INVALID_PROP_DECORATORS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_PROP_DECORATORS_FILE.name, 'NotIdentifier', ts.isClassDeclaration);
const members = host.getMembersOfClass(classNode);
@ -671,7 +671,7 @@ describe('Fesm2015ReflectionHost', () => {
});
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode =
getDeclaration(program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isClassDeclaration);
const members = host.getMembersOfClass(classNode);
@ -693,7 +693,7 @@ describe('Fesm2015ReflectionHost', () => {
describe('(returned prop decorators `args`)', () => {
it('should be an empty array if prop decorator has no `args` property', () => {
const program = makeProgram(INVALID_PROP_DECORATOR_ARGS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_PROP_DECORATOR_ARGS_FILE.name, 'NoArgsProperty',
ts.isClassDeclaration);
@ -708,7 +708,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should be an empty array if prop decorator\'s `args` has no property assignment', () => {
const program = makeProgram(INVALID_PROP_DECORATOR_ARGS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_PROP_DECORATOR_ARGS_FILE.name, 'NoPropertyAssignment',
ts.isClassDeclaration);
@ -723,7 +723,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should be an empty array if `args` property value is not an array literal', () => {
const program = makeProgram(INVALID_PROP_DECORATOR_ARGS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_PROP_DECORATOR_ARGS_FILE.name, 'NotArrayLiteral',
ts.isClassDeclaration);
@ -741,7 +741,7 @@ describe('Fesm2015ReflectionHost', () => {
describe('getConstructorParameters()', () => {
it('should find the decorated constructor parameters', () => {
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode =
getDeclaration(program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isClassDeclaration);
const parameters = host.getConstructorParameters(classNode) !;
@ -757,7 +757,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should throw if the symbol is not a class', () => {
const program = makeProgram(FOO_FUNCTION_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const functionNode =
getDeclaration(program, FOO_FUNCTION_FILE.name, 'foo', ts.isFunctionDeclaration);
expect(() => { host.getConstructorParameters(functionNode); })
@ -767,7 +767,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should return `null` if there is no constructor', () => {
const program = makeProgram(SIMPLE_CLASS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode =
getDeclaration(program, SIMPLE_CLASS_FILE.name, 'EmptyClass', ts.isClassDeclaration);
const parameters = host.getConstructorParameters(classNode);
@ -776,7 +776,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should return an array even if there are no decorators', () => {
const program = makeProgram(SIMPLE_CLASS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, SIMPLE_CLASS_FILE.name, 'NoDecoratorConstructorClass', ts.isClassDeclaration);
const parameters = host.getConstructorParameters(classNode) !;
@ -789,7 +789,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should return an empty array if there are no constructor parameters', () => {
const program = makeProgram(INVALID_CTOR_DECORATORS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_CTOR_DECORATORS_FILE.name, 'NoParameters', ts.isClassDeclaration);
const parameters = host.getConstructorParameters(classNode);
@ -799,7 +799,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should ignore decorators that are not imported from core', () => {
const program = makeProgram(INVALID_CTOR_DECORATORS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_CTOR_DECORATORS_FILE.name, 'NotFromCore', ts.isClassDeclaration);
const parameters = host.getConstructorParameters(classNode) !;
@ -813,7 +813,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should ignore `ctorParameters` if it is not an arrow function', () => {
const program = makeProgram(INVALID_CTOR_DECORATORS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_CTOR_DECORATORS_FILE.name, 'NotArrowFunction', ts.isClassDeclaration);
const parameters = host.getConstructorParameters(classNode) !;
@ -827,7 +827,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should ignore `ctorParameters` if it does not return an array literal', () => {
const program = makeProgram(INVALID_CTOR_DECORATORS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_CTOR_DECORATORS_FILE.name, 'NotArrayLiteral', ts.isClassDeclaration);
const parameters = host.getConstructorParameters(classNode) !;
@ -842,7 +842,7 @@ describe('Fesm2015ReflectionHost', () => {
describe('(returned parameters `decorators`)', () => {
it('should ignore param decorator elements that are not object literals', () => {
const program = makeProgram(INVALID_CTOR_DECORATORS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_CTOR_DECORATORS_FILE.name, 'NotObjectLiteral', ts.isClassDeclaration);
const parameters = host.getConstructorParameters(classNode);
@ -860,7 +860,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should ignore param decorator elements that have no `type` property', () => {
const program = makeProgram(INVALID_CTOR_DECORATORS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_CTOR_DECORATORS_FILE.name, 'NoTypeProperty', ts.isClassDeclaration);
const parameters = host.getConstructorParameters(classNode);
@ -872,7 +872,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should ignore param decorator elements whose `type` value is not an identifier', () => {
const program = makeProgram(INVALID_CTOR_DECORATORS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_CTOR_DECORATORS_FILE.name, 'NotIdentifier', ts.isClassDeclaration);
const parameters = host.getConstructorParameters(classNode);
@ -888,7 +888,7 @@ describe('Fesm2015ReflectionHost', () => {
.and.returnValue(mockImportInfo);
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isClassDeclaration);
const parameters = host.getConstructorParameters(classNode) !;
@ -905,7 +905,7 @@ describe('Fesm2015ReflectionHost', () => {
describe('(returned parameters `decorators.args`)', () => {
it('should be an empty array if param decorator has no `args` property', () => {
const program = makeProgram(INVALID_CTOR_DECORATOR_ARGS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_CTOR_DECORATOR_ARGS_FILE.name, 'NoArgsProperty',
ts.isClassDeclaration);
@ -920,7 +920,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should be an empty array if param decorator\'s `args` has no property assignment', () => {
const program = makeProgram(INVALID_CTOR_DECORATOR_ARGS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_CTOR_DECORATOR_ARGS_FILE.name, 'NoPropertyAssignment',
ts.isClassDeclaration);
@ -934,7 +934,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should be an empty array if `args` property value is not an array literal', () => {
const program = makeProgram(INVALID_CTOR_DECORATOR_ARGS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_CTOR_DECORATOR_ARGS_FILE.name, 'NotArrayLiteral',
ts.isClassDeclaration);
@ -951,7 +951,7 @@ describe('Fesm2015ReflectionHost', () => {
describe('getDefinitionOfFunction()', () => {
it('should return an object describing the function declaration passed as an argument', () => {
const program = makeProgram(FUNCTION_BODY_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const fooNode =
getDeclaration(program, FUNCTION_BODY_FILE.name, 'foo', ts.isFunctionDeclaration) !;
@ -1013,7 +1013,7 @@ describe('Fesm2015ReflectionHost', () => {
describe('getImportOfIdentifier()', () => {
it('should find the import of an identifier', () => {
const program = makeProgram(...IMPORTS_FILES);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const variableNode =
getDeclaration(program, IMPORTS_FILES[1].name, 'b', ts.isVariableDeclaration);
const importOfIdent = host.getImportOfIdentifier(variableNode.initializer as ts.Identifier);
@ -1023,7 +1023,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should find the name by which the identifier was exported, not imported', () => {
const program = makeProgram(...IMPORTS_FILES);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const variableNode =
getDeclaration(program, IMPORTS_FILES[1].name, 'c', ts.isVariableDeclaration);
const importOfIdent = host.getImportOfIdentifier(variableNode.initializer as ts.Identifier);
@ -1033,7 +1033,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should return null if the identifier was not imported', () => {
const program = makeProgram(...IMPORTS_FILES);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const variableNode =
getDeclaration(program, IMPORTS_FILES[1].name, 'd', ts.isVariableDeclaration);
const importOfIdent = host.getImportOfIdentifier(variableNode.initializer as ts.Identifier);
@ -1045,7 +1045,7 @@ describe('Fesm2015ReflectionHost', () => {
describe('getDeclarationOfIdentifier()', () => {
it('should return the declaration of a locally defined identifier', () => {
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode =
getDeclaration(program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isClassDeclaration);
const ctrDecorators = host.getConstructorParameters(classNode) !;
@ -1061,7 +1061,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should return the declaration of an externally defined identifier', () => {
const program = makeProgram(SOME_DIRECTIVE_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const classNode =
getDeclaration(program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isClassDeclaration);
const classDecorators = host.getDecoratorsOfDeclaration(classNode) !;
@ -1081,7 +1081,7 @@ describe('Fesm2015ReflectionHost', () => {
describe('getExportsOfModule()', () => {
it('should return a map of all the exports from a given module', () => {
const program = makeProgram(...EXPORTS_FILES);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const file = program.getSourceFile(EXPORTS_FILES[1].name) !;
const exportDeclarations = host.getExportsOfModule(file);
expect(exportDeclarations).not.toBe(null);
@ -1116,7 +1116,7 @@ describe('Fesm2015ReflectionHost', () => {
describe('isClass()', () => {
it('should return true if a given node is a TS class declaration', () => {
const program = makeProgram(SIMPLE_CLASS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const node =
getDeclaration(program, SIMPLE_CLASS_FILE.name, 'EmptyClass', ts.isClassDeclaration);
expect(host.isClass(node)).toBe(true);
@ -1124,7 +1124,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should return false if a given node is a TS function declaration', () => {
const program = makeProgram(FOO_FUNCTION_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const node = getDeclaration(program, FOO_FUNCTION_FILE.name, 'foo', ts.isFunctionDeclaration);
expect(host.isClass(node)).toBe(false);
});
@ -1133,7 +1133,7 @@ describe('Fesm2015ReflectionHost', () => {
describe('getGenericArityOfClass()', () => {
it('should return 0 for a basic class', () => {
const program = makeProgram(SIMPLE_CLASS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const node =
getDeclaration(program, SIMPLE_CLASS_FILE.name, 'EmptyClass', ts.isClassDeclaration);
expect(host.getGenericArityOfClass(node)).toBe(0);
@ -1144,7 +1144,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should return a collection of all the switchable variable declarations in the given module',
() => {
const program = makeProgram(MARKER_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const file = program.getSourceFile(MARKER_FILE.name) !;
const declarations = host.getSwitchableDeclarations(file);
expect(declarations.map(d => [d.name.getText(), d.initializer !.getText()])).toEqual([

View File

@ -47,7 +47,7 @@ describe('Esm2015FileParser', () => {
describe('parseFile()', () => {
it('should return an array of object for each class that is exported and decorated', () => {
const program = makeProgram(BASIC_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const parser = new Esm2015FileParser(program, host);
const parsedFiles = parser.parseFile(program.getSourceFile(BASIC_FILE.name) !);

View File

@ -49,7 +49,7 @@ describe('Esm5FileParser', () => {
describe('getDecoratedClasses()', () => {
it('should return an array of object for each class that is exported and decorated', () => {
const program = makeProgram(BASIC_FILE);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const parser = new Esm5FileParser(program, host);
const parsedFiles = parser.parseFile(program.getSourceFile(BASIC_FILE.name) !);

View File

@ -15,10 +15,10 @@ import {Esm2015Renderer} from '../../src/rendering/esm2015_renderer';
function setup(file: {name: string, contents: string}) {
const program = makeProgram(file);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const parser = new Esm2015FileParser(program, host);
const analyzer = new Analyzer(program.getTypeChecker(), host, ['']);
const renderer = new Esm2015Renderer(host);
const analyzer = new Analyzer(program.getTypeChecker(), host, [''], false);
const renderer = new Esm2015Renderer(host, false, null);
return {analyzer, host, parser, program, renderer};
}

View File

@ -15,10 +15,10 @@ import {Esm5Renderer} from '../../src/rendering/esm5_renderer';
function setup(file: {name: string, contents: string}) {
const program = makeProgram(file);
const host = new Esm5ReflectionHost(program.getTypeChecker());
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const parser = new Esm5FileParser(program, host);
const analyzer = new Analyzer(program.getTypeChecker(), host, ['']);
const renderer = new Esm5Renderer(host);
const analyzer = new Analyzer(program.getTypeChecker(), host, [''], false);
const renderer = new Esm5Renderer(host, false, null);
return {analyzer, host, parser, program, renderer};
}

View File

@ -35,7 +35,7 @@ class TestRenderer extends Renderer {
}
function createTestRenderer() {
const renderer = new TestRenderer({} as Fesm2015ReflectionHost);
const renderer = new TestRenderer({} as Fesm2015ReflectionHost, false, null);
spyOn(renderer, 'addImports').and.callThrough();
spyOn(renderer, 'addDefinitions').and.callThrough();
spyOn(renderer, 'removeDecorators').and.callThrough();
@ -44,9 +44,9 @@ function createTestRenderer() {
function analyze(file: {name: string, contents: string}) {
const program = makeProgram(file);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const parser = new Esm2015FileParser(program, host);
const analyzer = new Analyzer(program.getTypeChecker(), host, ['']);
const analyzer = new Analyzer(program.getTypeChecker(), host, [''], false);
const parsedFiles = parser.parseFile(program.getSourceFile(file.name) !);
return parsedFiles.map(file => analyzer.analyzeFile(file));

View File

@ -294,7 +294,6 @@ describe('ngtsc metadata', () => {
const host = new TypeScriptReflectionHost(checker);
const result = getDeclaration(program, 'entry.ts', 'target$', ts.isVariableDeclaration);
const res = staticallyResolve(result.initializer !, host, checker);
console.error(res);
expect(res instanceof Reference).toBe(true);
});
});

View File

@ -53,9 +53,9 @@ export class ImportManager {
private moduleToIndex = new Map<string, string>();
private nextIndex = 0;
constructor(private isCore: boolean, private prefix = 'i') {}
constructor(protected isCore: boolean, private prefix = 'i') {}
generateNamedImport(moduleName: string, symbol: string): string {
generateNamedImport(moduleName: string, symbol: string): string|null {
if (!this.moduleToIndex.has(moduleName)) {
this.moduleToIndex.set(moduleName, `${this.prefix}${this.nextIndex++}`);
}
@ -206,13 +206,18 @@ class ExpressionTranslatorVisitor implements ExpressionVisitor, StatementVisitor
}
}
visitExternalExpr(ast: ExternalExpr, context: Context): ts.PropertyAccessExpression {
visitExternalExpr(ast: ExternalExpr, context: Context): ts.PropertyAccessExpression
|ts.Identifier {
if (ast.value.moduleName === null || ast.value.name === null) {
throw new Error(`Import unknown module or symbol ${ast.value}`);
}
return ts.createPropertyAccess(
ts.createIdentifier(this.imports.generateNamedImport(ast.value.moduleName, ast.value.name)),
ts.createIdentifier(ast.value.name));
const importIdentifier = this.imports.generateNamedImport(ast.value.moduleName, ast.value.name);
if (importIdentifier === null) {
return ts.createIdentifier(ast.value.name);
} else {
return ts.createPropertyAccess(
ts.createIdentifier(importIdentifier), ts.createIdentifier(ast.value.name));
}
}
visitConditionalExpr(ast: ConditionalExpr, context: Context): ts.ParenthesizedExpression {