refactor(tsc-wrapped): update tsc-wrapped to pass strictNullCheck (#18160)
PR Close #18160
This commit is contained in:
parent
619e625ee2
commit
abee785821
5
build.sh
5
build.sh
|
@ -419,6 +419,11 @@ if [[ ${BUILD_TOOLS} == true || ${BUILD_ALL} == true ]]; then
|
||||||
$(npm bin)/tsc -p packages/tsc-wrapped/tsconfig-build.json
|
$(npm bin)/tsc -p packages/tsc-wrapped/tsconfig-build.json
|
||||||
cp ./packages/tsc-wrapped/package.json ./dist/packages-dist/tsc-wrapped
|
cp ./packages/tsc-wrapped/package.json ./dist/packages-dist/tsc-wrapped
|
||||||
cp ./packages/tsc-wrapped/README.md ./dist/packages-dist/tsc-wrapped
|
cp ./packages/tsc-wrapped/README.md ./dist/packages-dist/tsc-wrapped
|
||||||
|
(
|
||||||
|
cd dist/packages-dist/tsc-wrapped
|
||||||
|
echo "====== EXECUTE: perl -p -i -e \"s/0\.0\.0\-PLACEHOLDER/${VERSION}/g\" $""(grep -ril 0\.0\.0\-PLACEHOLDER .)"
|
||||||
|
perl -p -i -e "s/0\.0\.0\-PLACEHOLDER/${VERSION}/g" $(grep -ril 0\.0\.0\-PLACEHOLDER .) < /dev/null 2> /dev/null
|
||||||
|
)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for PACKAGE in ${PACKAGES[@]}
|
for PACKAGE in ${PACKAGES[@]}
|
||||||
|
|
|
@ -100,8 +100,8 @@ export class CodeGenerator {
|
||||||
}
|
}
|
||||||
const {compiler: aotCompiler} = compiler.createAotCompiler(ngCompilerHost, {
|
const {compiler: aotCompiler} = compiler.createAotCompiler(ngCompilerHost, {
|
||||||
translations: transContent,
|
translations: transContent,
|
||||||
i18nFormat: cliOptions.i18nFormat,
|
i18nFormat: cliOptions.i18nFormat || undefined,
|
||||||
locale: cliOptions.locale, missingTranslation,
|
locale: cliOptions.locale || undefined, missingTranslation,
|
||||||
enableLegacyTemplate: options.enableLegacyTemplate !== false,
|
enableLegacyTemplate: options.enableLegacyTemplate !== false,
|
||||||
enableSummariesForJit: options.enableSummariesForJit !== false,
|
enableSummariesForJit: options.enableSummariesForJit !== false,
|
||||||
});
|
});
|
||||||
|
|
|
@ -405,7 +405,7 @@ export class MockMetadataBundlerHost implements MetadataBundlerHost {
|
||||||
|
|
||||||
constructor(private host: ts.CompilerHost) {}
|
constructor(private host: ts.CompilerHost) {}
|
||||||
|
|
||||||
getMetadataFor(moduleName: string): ModuleMetadata {
|
getMetadataFor(moduleName: string): ModuleMetadata|undefined {
|
||||||
const source = this.host.getSourceFile(moduleName + '.ts', ts.ScriptTarget.Latest);
|
const source = this.host.getSourceFile(moduleName + '.ts', ts.ScriptTarget.Latest);
|
||||||
return this.collector.getMetadata(source);
|
return this.collector.getMetadata(source);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,9 @@ export interface BundledModule {
|
||||||
privates: BundlePrivateEntry[];
|
privates: BundlePrivateEntry[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MetadataBundlerHost { getMetadataFor(moduleName: string): ModuleMetadata; }
|
export interface MetadataBundlerHost {
|
||||||
|
getMetadataFor(moduleName: string): ModuleMetadata|undefined;
|
||||||
|
}
|
||||||
|
|
||||||
type StaticsMetadata = {
|
type StaticsMetadata = {
|
||||||
[name: string]: MetadataValue | FunctionMetadata;
|
[name: string]: MetadataValue | FunctionMetadata;
|
||||||
|
@ -78,7 +80,7 @@ type StaticsMetadata = {
|
||||||
|
|
||||||
export class MetadataBundler {
|
export class MetadataBundler {
|
||||||
private symbolMap = new Map<string, Symbol>();
|
private symbolMap = new Map<string, Symbol>();
|
||||||
private metadataCache = new Map<string, ModuleMetadata>();
|
private metadataCache = new Map<string, ModuleMetadata|undefined>();
|
||||||
private exports = new Map<string, Symbol[]>();
|
private exports = new Map<string, Symbol[]>();
|
||||||
private rootModule: string;
|
private rootModule: string;
|
||||||
private exported: Set<Symbol>;
|
private exported: Set<Symbol>;
|
||||||
|
@ -98,14 +100,14 @@ export class MetadataBundler {
|
||||||
const privates = Array.from(this.symbolMap.values())
|
const privates = Array.from(this.symbolMap.values())
|
||||||
.filter(s => s.referenced && s.isPrivate)
|
.filter(s => s.referenced && s.isPrivate)
|
||||||
.map(s => ({
|
.map(s => ({
|
||||||
privateName: s.privateName,
|
privateName: s.privateName !,
|
||||||
name: s.declaration.name,
|
name: s.declaration !.name,
|
||||||
module: s.declaration.module
|
module: s.declaration !.module
|
||||||
}));
|
}));
|
||||||
const origins = Array.from(this.symbolMap.values())
|
const origins = Array.from(this.symbolMap.values())
|
||||||
.filter(s => s.referenced && !s.reexport)
|
.filter(s => s.referenced && !s.reexport)
|
||||||
.reduce<{[name: string]: string}>((p, s) => {
|
.reduce<{[name: string]: string}>((p, s) => {
|
||||||
p[s.isPrivate ? s.privateName : s.name] = s.declaration.module;
|
p[s.isPrivate ? s.privateName ! : s.name] = s.declaration !.module;
|
||||||
return p;
|
return p;
|
||||||
}, {});
|
}, {});
|
||||||
const exports = this.getReExports(exportedSymbols);
|
const exports = this.getReExports(exportedSymbols);
|
||||||
|
@ -114,7 +116,7 @@ export class MetadataBundler {
|
||||||
__symbolic: 'module',
|
__symbolic: 'module',
|
||||||
version: VERSION,
|
version: VERSION,
|
||||||
exports: exports.length ? exports : undefined, metadata, origins,
|
exports: exports.length ? exports : undefined, metadata, origins,
|
||||||
importAs: this.importAs
|
importAs: this.importAs !
|
||||||
},
|
},
|
||||||
privates
|
privates
|
||||||
};
|
};
|
||||||
|
@ -124,7 +126,7 @@ export class MetadataBundler {
|
||||||
return resolveModule(importName, from);
|
return resolveModule(importName, from);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getMetadata(moduleName: string): ModuleMetadata {
|
private getMetadata(moduleName: string): ModuleMetadata|undefined {
|
||||||
let result = this.metadataCache.get(moduleName);
|
let result = this.metadataCache.get(moduleName);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
if (moduleName.startsWith('.')) {
|
if (moduleName.startsWith('.')) {
|
||||||
|
@ -138,7 +140,7 @@ export class MetadataBundler {
|
||||||
|
|
||||||
private exportAll(moduleName: string): Symbol[] {
|
private exportAll(moduleName: string): Symbol[] {
|
||||||
const module = this.getMetadata(moduleName);
|
const module = this.getMetadata(moduleName);
|
||||||
let result: Symbol[] = this.exports.get(moduleName);
|
let result = this.exports.get(moduleName);
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
return result;
|
return result;
|
||||||
|
@ -148,7 +150,7 @@ export class MetadataBundler {
|
||||||
|
|
||||||
const exportSymbol = (exportedSymbol: Symbol, exportAs: string) => {
|
const exportSymbol = (exportedSymbol: Symbol, exportAs: string) => {
|
||||||
const symbol = this.symbolOf(moduleName, exportAs);
|
const symbol = this.symbolOf(moduleName, exportAs);
|
||||||
result.push(symbol);
|
result !.push(symbol);
|
||||||
exportedSymbol.reexportedAs = symbol;
|
exportedSymbol.reexportedAs = symbol;
|
||||||
symbol.exports = exportedSymbol;
|
symbol.exports = exportedSymbol;
|
||||||
};
|
};
|
||||||
|
@ -266,7 +268,7 @@ export class MetadataBundler {
|
||||||
name = newPrivateName();
|
name = newPrivateName();
|
||||||
symbol.privateName = name;
|
symbol.privateName = name;
|
||||||
}
|
}
|
||||||
result[name] = symbol.value;
|
result[name] = symbol.value !;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -279,9 +281,10 @@ export class MetadataBundler {
|
||||||
const exportAlls = new Set<string>();
|
const exportAlls = new Set<string>();
|
||||||
for (const symbol of exportedSymbols) {
|
for (const symbol of exportedSymbols) {
|
||||||
if (symbol.reexport) {
|
if (symbol.reexport) {
|
||||||
const declaration = symbol.declaration;
|
// symbol.declaration is guarenteed to be defined during the phase this method is called.
|
||||||
|
const declaration = symbol.declaration !;
|
||||||
const module = declaration.module;
|
const module = declaration.module;
|
||||||
if (declaration.name == '*') {
|
if (declaration !.name == '*') {
|
||||||
// Reexport all the symbols.
|
// Reexport all the symbols.
|
||||||
exportAlls.add(declaration.module);
|
exportAlls.add(declaration.module);
|
||||||
} else {
|
} else {
|
||||||
|
@ -304,11 +307,13 @@ export class MetadataBundler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private convertSymbol(symbol: Symbol) {
|
private convertSymbol(symbol: Symbol) {
|
||||||
const canonicalSymbol = symbol.canonicalSymbol;
|
// canonicalSymbol is ensured to be defined before this is called.
|
||||||
|
const canonicalSymbol = symbol.canonicalSymbol !;
|
||||||
|
|
||||||
if (!canonicalSymbol.referenced) {
|
if (!canonicalSymbol.referenced) {
|
||||||
canonicalSymbol.referenced = true;
|
canonicalSymbol.referenced = true;
|
||||||
const declaration = canonicalSymbol.declaration;
|
// declaration is ensured to be definded before this method is called.
|
||||||
|
const declaration = canonicalSymbol.declaration !;
|
||||||
const module = this.getMetadata(declaration.module);
|
const module = this.getMetadata(declaration.module);
|
||||||
if (module) {
|
if (module) {
|
||||||
const value = module.metadata[declaration.name];
|
const value = module.metadata[declaration.name];
|
||||||
|
@ -336,10 +341,10 @@ export class MetadataBundler {
|
||||||
return {
|
return {
|
||||||
__symbolic: 'class',
|
__symbolic: 'class',
|
||||||
arity: value.arity,
|
arity: value.arity,
|
||||||
extends: this.convertExpression(moduleName, value.extends),
|
extends: this.convertExpression(moduleName, value.extends) !,
|
||||||
decorators:
|
decorators:
|
||||||
value.decorators && value.decorators.map(d => this.convertExpression(moduleName, d)),
|
value.decorators && value.decorators.map(d => this.convertExpression(moduleName, d) !),
|
||||||
members: this.convertMembers(moduleName, value.members),
|
members: this.convertMembers(moduleName, value.members !),
|
||||||
statics: value.statics && this.convertStatics(moduleName, value.statics)
|
statics: value.statics && this.convertStatics(moduleName, value.statics)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -356,11 +361,11 @@ export class MetadataBundler {
|
||||||
private convertMember(moduleName: string, member: MemberMetadata) {
|
private convertMember(moduleName: string, member: MemberMetadata) {
|
||||||
const result: MemberMetadata = {__symbolic: member.__symbolic};
|
const result: MemberMetadata = {__symbolic: member.__symbolic};
|
||||||
result.decorators =
|
result.decorators =
|
||||||
member.decorators && member.decorators.map(d => this.convertExpression(moduleName, d));
|
member.decorators && member.decorators.map(d => this.convertExpression(moduleName, d) !);
|
||||||
if (isMethodMetadata(member)) {
|
if (isMethodMetadata(member)) {
|
||||||
(result as MethodMetadata).parameterDecorators = member.parameterDecorators &&
|
(result as MethodMetadata).parameterDecorators = member.parameterDecorators &&
|
||||||
member.parameterDecorators.map(
|
member.parameterDecorators.map(
|
||||||
d => d && d.map(p => this.convertExpression(moduleName, p)));
|
d => d && d.map(p => this.convertExpression(moduleName, p) !));
|
||||||
if (isConstructorMetadata(member)) {
|
if (isConstructorMetadata(member)) {
|
||||||
if (member.parameters) {
|
if (member.parameters) {
|
||||||
(result as ConstructorMetadata).parameters =
|
(result as ConstructorMetadata).parameters =
|
||||||
|
@ -397,7 +402,7 @@ export class MetadataBundler {
|
||||||
return this.convertError(moduleName, value);
|
return this.convertError(moduleName, value);
|
||||||
}
|
}
|
||||||
if (isMetadataSymbolicExpression(value)) {
|
if (isMetadataSymbolicExpression(value)) {
|
||||||
return this.convertExpression(moduleName, value);
|
return this.convertExpression(moduleName, value) !;
|
||||||
}
|
}
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
return value.map(v => this.convertValue(moduleName, v));
|
return value.map(v => this.convertValue(moduleName, v));
|
||||||
|
@ -413,8 +418,8 @@ export class MetadataBundler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private convertExpression(
|
private convertExpression(
|
||||||
moduleName: string, value: MetadataSymbolicExpression|MetadataError|
|
moduleName: string, value: MetadataSymbolicExpression|MetadataError|null|
|
||||||
undefined): MetadataSymbolicExpression|MetadataError|undefined {
|
undefined): MetadataSymbolicExpression|MetadataError|undefined|null {
|
||||||
if (value) {
|
if (value) {
|
||||||
switch (value.__symbolic) {
|
switch (value.__symbolic) {
|
||||||
case 'error':
|
case 'error':
|
||||||
|
@ -439,9 +444,9 @@ export class MetadataBundler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private convertReference(moduleName: string, value: MetadataSymbolicReferenceExpression):
|
private convertReference(moduleName: string, value: MetadataSymbolicReferenceExpression):
|
||||||
MetadataSymbolicReferenceExpression|MetadataError {
|
MetadataSymbolicReferenceExpression|MetadataError|undefined {
|
||||||
const createReference = (symbol: Symbol): MetadataSymbolicReferenceExpression => {
|
const createReference = (symbol: Symbol): MetadataSymbolicReferenceExpression => {
|
||||||
const declaration = symbol.declaration;
|
const declaration = symbol.declaration !;
|
||||||
if (declaration.module.startsWith('.')) {
|
if (declaration.module.startsWith('.')) {
|
||||||
// Reference to a symbol defined in the module. Ensure it is converted then return a
|
// Reference to a symbol defined in the module. Ensure it is converted then return a
|
||||||
// references to the final symbol.
|
// references to the final symbol.
|
||||||
|
@ -450,11 +455,11 @@ export class MetadataBundler {
|
||||||
__symbolic: 'reference',
|
__symbolic: 'reference',
|
||||||
get name() {
|
get name() {
|
||||||
// Resolved lazily because private names are assigned late.
|
// Resolved lazily because private names are assigned late.
|
||||||
const canonicalSymbol = symbol.canonicalSymbol;
|
const canonicalSymbol = symbol.canonicalSymbol !;
|
||||||
if (canonicalSymbol.isPrivate == null) {
|
if (canonicalSymbol.isPrivate == null) {
|
||||||
throw Error('Invalid state: isPrivate was not initialized');
|
throw Error('Invalid state: isPrivate was not initialized');
|
||||||
}
|
}
|
||||||
return canonicalSymbol.isPrivate ? canonicalSymbol.privateName : canonicalSymbol.name;
|
return canonicalSymbol.isPrivate ? canonicalSymbol.privateName ! : canonicalSymbol.name;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
@ -564,7 +569,7 @@ export class CompilerHostAdapter implements MetadataBundlerHost {
|
||||||
|
|
||||||
constructor(private host: ts.CompilerHost) {}
|
constructor(private host: ts.CompilerHost) {}
|
||||||
|
|
||||||
getMetadataFor(fileName: string): ModuleMetadata {
|
getMetadataFor(fileName: string): ModuleMetadata|undefined {
|
||||||
const sourceFile = this.host.getSourceFile(fileName + '.ts', ts.ScriptTarget.Latest);
|
const sourceFile = this.host.getSourceFile(fileName + '.ts', ts.ScriptTarget.Latest);
|
||||||
return this.collector.getMetadata(sourceFile);
|
return this.collector.getMetadata(sourceFile);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
export class CliOptions {
|
export class CliOptions {
|
||||||
public basePath: string;
|
public basePath: string|null;
|
||||||
constructor({basePath = null}: {basePath?: string}) { this.basePath = basePath; }
|
constructor({basePath = null}: {basePath?: string | null}) { this.basePath = basePath; }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class I18nExtractionCliOptions extends CliOptions {
|
export class I18nExtractionCliOptions extends CliOptions {
|
||||||
|
@ -28,18 +28,18 @@ export class I18nExtractionCliOptions extends CliOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NgcCliOptions extends CliOptions {
|
export class NgcCliOptions extends CliOptions {
|
||||||
public i18nFormat: string;
|
public i18nFormat: string|null;
|
||||||
public i18nFile: string;
|
public i18nFile: string|null;
|
||||||
public locale: string;
|
public locale: string|null;
|
||||||
public missingTranslation: string;
|
public missingTranslation: string|null;
|
||||||
|
|
||||||
constructor({i18nFormat = null, i18nFile = null, locale = null, missingTranslation = null,
|
constructor({i18nFormat = null, i18nFile = null, locale = null, missingTranslation = null,
|
||||||
basePath = null}: {
|
basePath = null}: {
|
||||||
i18nFormat?: string,
|
i18nFormat?: string | null,
|
||||||
i18nFile?: string,
|
i18nFile?: string|null,
|
||||||
locale?: string,
|
locale?: string|null,
|
||||||
missingTranslation?: string,
|
missingTranslation?: string|null,
|
||||||
basePath?: string
|
basePath?: string|null
|
||||||
}) {
|
}) {
|
||||||
super({basePath: basePath});
|
super({basePath: basePath});
|
||||||
this.i18nFormat = i18nFormat;
|
this.i18nFormat = i18nFormat;
|
||||||
|
|
|
@ -54,13 +54,13 @@ export class MetadataCollector {
|
||||||
* Returns a JSON.stringify friendly form describing the decorators of the exported classes from
|
* Returns a JSON.stringify friendly form describing the decorators of the exported classes from
|
||||||
* the source file that is expected to correspond to a module.
|
* the source file that is expected to correspond to a module.
|
||||||
*/
|
*/
|
||||||
public getMetadata(sourceFile: ts.SourceFile, strict: boolean = false): ModuleMetadata {
|
public getMetadata(sourceFile: ts.SourceFile, strict: boolean = false): ModuleMetadata|undefined {
|
||||||
const locals = new Symbols(sourceFile);
|
const locals = new Symbols(sourceFile);
|
||||||
const nodeMap =
|
const nodeMap =
|
||||||
new Map<MetadataValue|ClassMetadata|InterfaceMetadata|FunctionMetadata, ts.Node>();
|
new Map<MetadataValue|ClassMetadata|InterfaceMetadata|FunctionMetadata, ts.Node>();
|
||||||
const evaluator = new Evaluator(locals, nodeMap, this.options);
|
const evaluator = new Evaluator(locals, nodeMap, this.options);
|
||||||
let metadata: {[name: string]: MetadataValue | ClassMetadata | FunctionMetadata}|undefined;
|
let metadata: {[name: string]: MetadataValue | ClassMetadata | FunctionMetadata}|undefined;
|
||||||
let exports: ModuleExportMetadata[];
|
let exports: ModuleExportMetadata[]|undefined = undefined;
|
||||||
|
|
||||||
function objFromDecorator(decoratorNode: ts.Decorator): MetadataSymbolicExpression {
|
function objFromDecorator(decoratorNode: ts.Decorator): MetadataSymbolicExpression {
|
||||||
return <MetadataSymbolicExpression>evaluator.evaluateNode(decoratorNode.expression);
|
return <MetadataSymbolicExpression>evaluator.evaluateNode(decoratorNode.expression);
|
||||||
|
@ -79,7 +79,7 @@ export class MetadataCollector {
|
||||||
function maybeGetSimpleFunction(
|
function maybeGetSimpleFunction(
|
||||||
functionDeclaration: ts.FunctionDeclaration |
|
functionDeclaration: ts.FunctionDeclaration |
|
||||||
ts.MethodDeclaration): {func: FunctionMetadata, name: string}|undefined {
|
ts.MethodDeclaration): {func: FunctionMetadata, name: string}|undefined {
|
||||||
if (functionDeclaration.name.kind == ts.SyntaxKind.Identifier) {
|
if (functionDeclaration.name && functionDeclaration.name.kind == ts.SyntaxKind.Identifier) {
|
||||||
const nameNode = <ts.Identifier>functionDeclaration.name;
|
const nameNode = <ts.Identifier>functionDeclaration.name;
|
||||||
const functionName = nameNode.text;
|
const functionName = nameNode.text;
|
||||||
const functionBody = functionDeclaration.body;
|
const functionBody = functionDeclaration.body;
|
||||||
|
@ -107,7 +107,8 @@ export class MetadataCollector {
|
||||||
function classMetadataOf(classDeclaration: ts.ClassDeclaration): ClassMetadata {
|
function classMetadataOf(classDeclaration: ts.ClassDeclaration): ClassMetadata {
|
||||||
const result: ClassMetadata = {__symbolic: 'class'};
|
const result: ClassMetadata = {__symbolic: 'class'};
|
||||||
|
|
||||||
function getDecorators(decorators: ts.Decorator[]): MetadataSymbolicExpression[] {
|
function getDecorators(decorators: ts.Decorator[] | undefined): MetadataSymbolicExpression[]|
|
||||||
|
undefined {
|
||||||
if (decorators && decorators.length)
|
if (decorators && decorators.length)
|
||||||
return decorators.map(decorator => objFromDecorator(decorator));
|
return decorators.map(decorator => objFromDecorator(decorator));
|
||||||
return undefined;
|
return undefined;
|
||||||
|
@ -145,7 +146,7 @@ export class MetadataCollector {
|
||||||
}
|
}
|
||||||
|
|
||||||
// member decorators
|
// member decorators
|
||||||
let members: MetadataMap = null;
|
let members: MetadataMap|null = null;
|
||||||
function recordMember(name: string, metadata: MemberMetadata) {
|
function recordMember(name: string, metadata: MemberMetadata) {
|
||||||
if (!members) members = {};
|
if (!members) members = {};
|
||||||
const data = members.hasOwnProperty(name) ? members[name] : [];
|
const data = members.hasOwnProperty(name) ? members[name] : [];
|
||||||
|
@ -154,7 +155,7 @@ export class MetadataCollector {
|
||||||
}
|
}
|
||||||
|
|
||||||
// static member
|
// static member
|
||||||
let statics: {[name: string]: MetadataValue | FunctionMetadata} = null;
|
let statics: {[name: string]: MetadataValue | FunctionMetadata}|null = null;
|
||||||
function recordStaticMember(name: string, value: MetadataValue | FunctionMetadata) {
|
function recordStaticMember(name: string, value: MetadataValue | FunctionMetadata) {
|
||||||
if (!statics) statics = {};
|
if (!statics) statics = {};
|
||||||
statics[name] = value;
|
statics[name] = value;
|
||||||
|
@ -176,7 +177,8 @@ export class MetadataCollector {
|
||||||
}
|
}
|
||||||
const methodDecorators = getDecorators(method.decorators);
|
const methodDecorators = getDecorators(method.decorators);
|
||||||
const parameters = method.parameters;
|
const parameters = method.parameters;
|
||||||
const parameterDecoratorData: (MetadataSymbolicExpression | MetadataError)[][] = [];
|
const parameterDecoratorData:
|
||||||
|
((MetadataSymbolicExpression | MetadataError)[] | undefined)[] = [];
|
||||||
const parametersData:
|
const parametersData:
|
||||||
(MetadataSymbolicReferenceExpression | MetadataError |
|
(MetadataSymbolicReferenceExpression | MetadataError |
|
||||||
MetadataSymbolicSelectExpression | null)[] = [];
|
MetadataSymbolicSelectExpression | null)[] = [];
|
||||||
|
@ -254,7 +256,8 @@ export class MetadataCollector {
|
||||||
const {moduleSpecifier, exportClause} = exportDeclaration;
|
const {moduleSpecifier, exportClause} = exportDeclaration;
|
||||||
|
|
||||||
if (!moduleSpecifier) {
|
if (!moduleSpecifier) {
|
||||||
exportClause.elements.forEach(spec => {
|
// If there is a module specifier there is also an exportClause
|
||||||
|
exportClause !.elements.forEach(spec => {
|
||||||
const exportedAs = spec.name.text;
|
const exportedAs = spec.name.text;
|
||||||
const name = (spec.propertyName || spec.name).text;
|
const name = (spec.propertyName || spec.name).text;
|
||||||
exportMap.set(name, exportedAs);
|
exportMap.set(name, exportedAs);
|
||||||
|
@ -263,12 +266,13 @@ export class MetadataCollector {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const isExportedIdentifier = (identifier: ts.Identifier) => exportMap.has(identifier.text);
|
const isExportedIdentifier = (identifier?: ts.Identifier) =>
|
||||||
|
identifier && exportMap.has(identifier.text);
|
||||||
const isExported =
|
const isExported =
|
||||||
(node: ts.FunctionDeclaration | ts.ClassDeclaration | ts.InterfaceDeclaration |
|
(node: ts.FunctionDeclaration | ts.ClassDeclaration | ts.InterfaceDeclaration |
|
||||||
ts.EnumDeclaration) => isExport(node) || isExportedIdentifier(node.name);
|
ts.EnumDeclaration) => isExport(node) || isExportedIdentifier(node.name);
|
||||||
const exportedIdentifierName = (identifier: ts.Identifier) =>
|
const exportedIdentifierName = (identifier?: ts.Identifier) =>
|
||||||
exportMap.get(identifier.text) || identifier.text;
|
identifier && (exportMap.get(identifier.text) || identifier.text);
|
||||||
const exportedName =
|
const exportedName =
|
||||||
(node: ts.FunctionDeclaration | ts.ClassDeclaration | ts.InterfaceDeclaration |
|
(node: ts.FunctionDeclaration | ts.ClassDeclaration | ts.InterfaceDeclaration |
|
||||||
ts.EnumDeclaration) => exportedIdentifierName(node.name);
|
ts.EnumDeclaration) => exportedIdentifierName(node.name);
|
||||||
|
@ -358,8 +362,11 @@ export class MetadataCollector {
|
||||||
const classDeclaration = <ts.ClassDeclaration>node;
|
const classDeclaration = <ts.ClassDeclaration>node;
|
||||||
if (classDeclaration.name) {
|
if (classDeclaration.name) {
|
||||||
if (isExported(classDeclaration)) {
|
if (isExported(classDeclaration)) {
|
||||||
if (!metadata) metadata = {};
|
const name = exportedName(classDeclaration);
|
||||||
metadata[exportedName(classDeclaration)] = classMetadataOf(classDeclaration);
|
if (name) {
|
||||||
|
if (!metadata) metadata = {};
|
||||||
|
metadata[name] = classMetadataOf(classDeclaration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Otherwise don't record metadata for the class.
|
// Otherwise don't record metadata for the class.
|
||||||
|
@ -368,8 +375,11 @@ export class MetadataCollector {
|
||||||
case ts.SyntaxKind.InterfaceDeclaration:
|
case ts.SyntaxKind.InterfaceDeclaration:
|
||||||
const interfaceDeclaration = <ts.InterfaceDeclaration>node;
|
const interfaceDeclaration = <ts.InterfaceDeclaration>node;
|
||||||
if (interfaceDeclaration.name && isExported(interfaceDeclaration)) {
|
if (interfaceDeclaration.name && isExported(interfaceDeclaration)) {
|
||||||
if (!metadata) metadata = {};
|
const name = exportedName(interfaceDeclaration);
|
||||||
metadata[exportedName(interfaceDeclaration)] = {__symbolic: 'interface'};
|
if (name) {
|
||||||
|
if (!metadata) metadata = {};
|
||||||
|
metadata[name] = {__symbolic: 'interface'};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -378,11 +388,13 @@ export class MetadataCollector {
|
||||||
// names substitution will be performed by the StaticReflector.
|
// names substitution will be performed by the StaticReflector.
|
||||||
const functionDeclaration = <ts.FunctionDeclaration>node;
|
const functionDeclaration = <ts.FunctionDeclaration>node;
|
||||||
if (isExported(functionDeclaration) && functionDeclaration.name) {
|
if (isExported(functionDeclaration) && functionDeclaration.name) {
|
||||||
if (!metadata) metadata = {};
|
|
||||||
const name = exportedName(functionDeclaration);
|
const name = exportedName(functionDeclaration);
|
||||||
const maybeFunc = maybeGetSimpleFunction(functionDeclaration);
|
const maybeFunc = maybeGetSimpleFunction(functionDeclaration);
|
||||||
metadata[name] =
|
if (name) {
|
||||||
maybeFunc ? recordEntry(maybeFunc.func, node) : {__symbolic: 'function'};
|
if (!metadata) metadata = {};
|
||||||
|
metadata[name] =
|
||||||
|
maybeFunc ? recordEntry(maybeFunc.func, node) : {__symbolic: 'function'};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -400,7 +412,7 @@ export class MetadataCollector {
|
||||||
} else {
|
} else {
|
||||||
enumValue = evaluator.evaluateNode(member.initializer);
|
enumValue = evaluator.evaluateNode(member.initializer);
|
||||||
}
|
}
|
||||||
let name: string = undefined;
|
let name: string|undefined = undefined;
|
||||||
if (member.name.kind == ts.SyntaxKind.Identifier) {
|
if (member.name.kind == ts.SyntaxKind.Identifier) {
|
||||||
const identifier = <ts.Identifier>member.name;
|
const identifier = <ts.Identifier>member.name;
|
||||||
name = identifier.text;
|
name = identifier.text;
|
||||||
|
@ -424,8 +436,10 @@ export class MetadataCollector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (writtenMembers) {
|
if (writtenMembers) {
|
||||||
if (!metadata) metadata = {};
|
if (enumName) {
|
||||||
metadata[enumName] = recordEntry(enumValueHolder, node);
|
if (!metadata) metadata = {};
|
||||||
|
metadata[enumName] = recordEntry(enumValueHolder, node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -444,8 +458,11 @@ export class MetadataCollector {
|
||||||
let exported = false;
|
let exported = false;
|
||||||
if (isExport(variableStatement) || isExport(variableDeclaration) ||
|
if (isExport(variableStatement) || isExport(variableDeclaration) ||
|
||||||
isExportedIdentifier(nameNode)) {
|
isExportedIdentifier(nameNode)) {
|
||||||
if (!metadata) metadata = {};
|
const name = exportedIdentifierName(nameNode);
|
||||||
metadata[exportedIdentifierName(nameNode)] = recordEntry(varValue, node);
|
if (name) {
|
||||||
|
if (!metadata) metadata = {};
|
||||||
|
metadata[name] = recordEntry(varValue, node);
|
||||||
|
}
|
||||||
exported = true;
|
exported = true;
|
||||||
}
|
}
|
||||||
if (typeof varValue == 'string' || typeof varValue == 'number' ||
|
if (typeof varValue == 'string' || typeof varValue == 'number' ||
|
||||||
|
@ -601,11 +618,11 @@ function validateMetadata(
|
||||||
}
|
}
|
||||||
if (classData.members) {
|
if (classData.members) {
|
||||||
Object.getOwnPropertyNames(classData.members)
|
Object.getOwnPropertyNames(classData.members)
|
||||||
.forEach(name => classData.members[name].forEach((m) => validateMember(classData, m)));
|
.forEach(name => classData.members ![name].forEach((m) => validateMember(classData, m)));
|
||||||
}
|
}
|
||||||
if (classData.statics) {
|
if (classData.statics) {
|
||||||
Object.getOwnPropertyNames(classData.statics).forEach(name => {
|
Object.getOwnPropertyNames(classData.statics).forEach(name => {
|
||||||
const staticMember = classData.statics[name];
|
const staticMember = classData.statics ![name];
|
||||||
if (isFunctionMetadata(staticMember)) {
|
if (isFunctionMetadata(staticMember)) {
|
||||||
validateExpression(staticMember.value);
|
validateExpression(staticMember.value);
|
||||||
} else {
|
} else {
|
||||||
|
@ -628,7 +645,7 @@ function validateMetadata(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldReportNode(node: ts.Node) {
|
function shouldReportNode(node: ts.Node | undefined) {
|
||||||
if (node) {
|
if (node) {
|
||||||
const nodeStart = node.getStart();
|
const nodeStart = node.getStart();
|
||||||
return !(
|
return !(
|
||||||
|
|
|
@ -33,10 +33,10 @@ export abstract class DelegatingHost implements ts.CompilerHost {
|
||||||
(fileName: string, languageVersion: ts.ScriptTarget, onError?: (message: string) => void) =>
|
(fileName: string, languageVersion: ts.ScriptTarget, onError?: (message: string) => void) =>
|
||||||
this.delegate.getSourceFile(fileName, languageVersion, onError);
|
this.delegate.getSourceFile(fileName, languageVersion, onError);
|
||||||
|
|
||||||
getCancellationToken = () => this.delegate.getCancellationToken();
|
getCancellationToken = () => this.delegate.getCancellationToken !();
|
||||||
getDefaultLibFileName = (options: ts.CompilerOptions) =>
|
getDefaultLibFileName = (options: ts.CompilerOptions) =>
|
||||||
this.delegate.getDefaultLibFileName(options);
|
this.delegate.getDefaultLibFileName(options);
|
||||||
getDefaultLibLocation = () => this.delegate.getDefaultLibLocation();
|
getDefaultLibLocation = () => this.delegate.getDefaultLibLocation !();
|
||||||
writeFile: ts.WriteFileCallback = this.delegate.writeFile;
|
writeFile: ts.WriteFileCallback = this.delegate.writeFile;
|
||||||
getCurrentDirectory = () => this.delegate.getCurrentDirectory();
|
getCurrentDirectory = () => this.delegate.getCurrentDirectory();
|
||||||
getDirectories = (path: string): string[] =>
|
getDirectories = (path: string): string[] =>
|
||||||
|
@ -46,8 +46,8 @@ export abstract class DelegatingHost implements ts.CompilerHost {
|
||||||
getNewLine = () => this.delegate.getNewLine();
|
getNewLine = () => this.delegate.getNewLine();
|
||||||
fileExists = (fileName: string) => this.delegate.fileExists(fileName);
|
fileExists = (fileName: string) => this.delegate.fileExists(fileName);
|
||||||
readFile = (fileName: string) => this.delegate.readFile(fileName);
|
readFile = (fileName: string) => this.delegate.readFile(fileName);
|
||||||
trace = (s: string) => this.delegate.trace(s);
|
trace = (s: string) => this.delegate.trace !(s);
|
||||||
directoryExists = (directoryName: string) => this.delegate.directoryExists(directoryName);
|
directoryExists = (directoryName: string) => this.delegate.directoryExists !(directoryName);
|
||||||
}
|
}
|
||||||
|
|
||||||
const IGNORED_FILES = /\.ngfactory\.js$|\.ngstyle\.js$/;
|
const IGNORED_FILES = /\.ngfactory\.js$|\.ngstyle\.js$/;
|
||||||
|
@ -79,7 +79,8 @@ export class MetadataWriterHost extends DelegatingHost {
|
||||||
const metadata =
|
const metadata =
|
||||||
this.metadataCollector.getMetadata(collectableFile, !!this.ngOptions.strictMetadataEmit);
|
this.metadataCollector.getMetadata(collectableFile, !!this.ngOptions.strictMetadataEmit);
|
||||||
const metadata1 = this.metadataCollector1.getMetadata(collectableFile, false);
|
const metadata1 = this.metadataCollector1.getMetadata(collectableFile, false);
|
||||||
const metadatas: ModuleMetadata[] = [metadata, metadata1].filter(e => !!e);
|
const metadatas: ModuleMetadata[] =
|
||||||
|
[metadata, metadata1].filter(e => !!e) as ModuleMetadata[];
|
||||||
if (metadatas.length) {
|
if (metadatas.length) {
|
||||||
const metadataText = JSON.stringify(metadatas);
|
const metadataText = JSON.stringify(metadatas);
|
||||||
writeFileSync(path, metadataText, {encoding: 'utf-8'});
|
writeFileSync(path, metadataText, {encoding: 'utf-8'});
|
||||||
|
@ -163,7 +164,7 @@ export class SyntheticIndexHost extends DelegatingHost {
|
||||||
normalize(sourceFiles[0].fileName) == this.normalSyntheticIndexName) {
|
normalize(sourceFiles[0].fileName) == this.normalSyntheticIndexName) {
|
||||||
// If we are writing the synthetic index, write the metadata along side.
|
// If we are writing the synthetic index, write the metadata along side.
|
||||||
const metadataName = fileName.replace(DTS, '.metadata.json');
|
const metadataName = fileName.replace(DTS, '.metadata.json');
|
||||||
writeFileSync(metadataName, this.indexMetadata, 'utf8');
|
writeFileSync(metadataName, this.indexMetadata, {encoding: 'utf8'});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -68,7 +68,7 @@ export interface ImportMetadata {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function getSourceFileOfNode(node: ts.Node): ts.SourceFile {
|
function getSourceFileOfNode(node: ts.Node | undefined): ts.SourceFile {
|
||||||
while (node && node.kind != ts.SyntaxKind.SourceFile) {
|
while (node && node.kind != ts.SyntaxKind.SourceFile) {
|
||||||
node = node.parent;
|
node = node.parent;
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ function getSourceFileOfNode(node: ts.Node): ts.SourceFile {
|
||||||
export function errorSymbol(
|
export function errorSymbol(
|
||||||
message: string, node?: ts.Node, context?: {[name: string]: string},
|
message: string, node?: ts.Node, context?: {[name: string]: string},
|
||||||
sourceFile?: ts.SourceFile): MetadataError {
|
sourceFile?: ts.SourceFile): MetadataError {
|
||||||
let result: MetadataError;
|
let result: MetadataError|undefined = undefined;
|
||||||
if (node) {
|
if (node) {
|
||||||
sourceFile = sourceFile || getSourceFileOfNode(node);
|
sourceFile = sourceFile || getSourceFileOfNode(node);
|
||||||
if (sourceFile) {
|
if (sourceFile) {
|
||||||
|
@ -106,15 +106,16 @@ export class Evaluator {
|
||||||
private symbols: Symbols, private nodeMap: Map<MetadataEntry, ts.Node>,
|
private symbols: Symbols, private nodeMap: Map<MetadataEntry, ts.Node>,
|
||||||
private options: CollectorOptions = {}) {}
|
private options: CollectorOptions = {}) {}
|
||||||
|
|
||||||
nameOf(node: ts.Node): string|MetadataError {
|
nameOf(node: ts.Node|undefined): string|MetadataError {
|
||||||
if (node.kind == ts.SyntaxKind.Identifier) {
|
if (node && node.kind == ts.SyntaxKind.Identifier) {
|
||||||
return (<ts.Identifier>node).text;
|
return (<ts.Identifier>node).text;
|
||||||
}
|
}
|
||||||
const result = this.evaluateNode(node);
|
const result = node && this.evaluateNode(node);
|
||||||
if (isMetadataError(result) || typeof result === 'string') {
|
if (isMetadataError(result) || typeof result === 'string') {
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
return errorSymbol('Name expected', node, {received: node.getText()});
|
return errorSymbol(
|
||||||
|
'Name expected', node, {received: (node && node.getText()) || '<missing>'});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +139,7 @@ export class Evaluator {
|
||||||
return this.isFoldableWorker(node, new Map<ts.Node, boolean>());
|
return this.isFoldableWorker(node, new Map<ts.Node, boolean>());
|
||||||
}
|
}
|
||||||
|
|
||||||
private isFoldableWorker(node: ts.Node, folding: Map<ts.Node, boolean>): boolean {
|
private isFoldableWorker(node: ts.Node|undefined, folding: Map<ts.Node, boolean>): boolean {
|
||||||
if (node) {
|
if (node) {
|
||||||
switch (node.kind) {
|
switch (node.kind) {
|
||||||
case ts.SyntaxKind.ObjectLiteralExpression:
|
case ts.SyntaxKind.ObjectLiteralExpression:
|
||||||
|
@ -518,11 +519,11 @@ export class Evaluator {
|
||||||
if (isDefined(operand) && isPrimitive(operand)) {
|
if (isDefined(operand) && isPrimitive(operand)) {
|
||||||
switch (prefixUnaryExpression.operator) {
|
switch (prefixUnaryExpression.operator) {
|
||||||
case ts.SyntaxKind.PlusToken:
|
case ts.SyntaxKind.PlusToken:
|
||||||
return +operand;
|
return +(operand as any);
|
||||||
case ts.SyntaxKind.MinusToken:
|
case ts.SyntaxKind.MinusToken:
|
||||||
return -operand;
|
return -(operand as any);
|
||||||
case ts.SyntaxKind.TildeToken:
|
case ts.SyntaxKind.TildeToken:
|
||||||
return ~operand;
|
return ~(operand as any);
|
||||||
case ts.SyntaxKind.ExclamationToken:
|
case ts.SyntaxKind.ExclamationToken:
|
||||||
return !operand;
|
return !operand;
|
||||||
}
|
}
|
||||||
|
@ -661,8 +662,8 @@ function isPropertyAssignment(node: ts.Node): node is ts.PropertyAssignment {
|
||||||
return node.kind == ts.SyntaxKind.PropertyAssignment;
|
return node.kind == ts.SyntaxKind.PropertyAssignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
const empty = [] as ts.NodeArray<any>;
|
const empty = ts.createNodeArray<any>();
|
||||||
|
|
||||||
function arrayOrEmpty<T extends ts.Node>(v: ts.NodeArray<T>): ts.NodeArray<T> {
|
function arrayOrEmpty<T extends ts.Node>(v: ts.NodeArray<T>| undefined): ts.NodeArray<T> {
|
||||||
return v || empty;
|
return v || empty;
|
||||||
}
|
}
|
|
@ -41,9 +41,9 @@ export function createBundleIndexHost(
|
||||||
return {
|
return {
|
||||||
host,
|
host,
|
||||||
errors: [{
|
errors: [{
|
||||||
file: null,
|
file: null as any as ts.SourceFile,
|
||||||
start: null,
|
start: null as any as number,
|
||||||
length: null,
|
length: null as any as number,
|
||||||
messageText:
|
messageText:
|
||||||
'Angular compiler option "flatModuleIndex" requires one and only one .ts file in the "files" field.',
|
'Angular compiler option "flatModuleIndex" requires one and only one .ts file in the "files" field.',
|
||||||
category: ts.DiagnosticCategory.Error,
|
category: ts.DiagnosticCategory.Error,
|
||||||
|
@ -58,7 +58,7 @@ export function createBundleIndexHost(
|
||||||
const metadataBundle = bundler.getMetadataBundle();
|
const metadataBundle = bundler.getMetadataBundle();
|
||||||
const metadata = JSON.stringify(metadataBundle.metadata);
|
const metadata = JSON.stringify(metadataBundle.metadata);
|
||||||
const name =
|
const name =
|
||||||
path.join(path.dirname(indexModule), ngOptions.flatModuleOutFile.replace(JS_EXT, '.ts'));
|
path.join(path.dirname(indexModule), ngOptions.flatModuleOutFile !.replace(JS_EXT, '.ts'));
|
||||||
const libraryIndex = `./${path.basename(indexModule)}`;
|
const libraryIndex = `./${path.basename(indexModule)}`;
|
||||||
const content = privateEntriesToIndex(libraryIndex, metadataBundle.privates);
|
const content = privateEntriesToIndex(libraryIndex, metadataBundle.privates);
|
||||||
host = new SyntheticIndexHost(host, {name, content, metadata});
|
host = new SyntheticIndexHost(host, {name, content, metadata});
|
||||||
|
@ -201,7 +201,7 @@ if (require.main === module) {
|
||||||
const project = options.project || '.';
|
const project = options.project || '.';
|
||||||
// TODO(alexeagle): command line should be TSC-compatible, remove "CliOptions" here
|
// TODO(alexeagle): command line should be TSC-compatible, remove "CliOptions" here
|
||||||
const cliOptions = new CliOptions(require('minimist')(args));
|
const cliOptions = new CliOptions(require('minimist')(args));
|
||||||
main(project, cliOptions, null, options)
|
main(project, cliOptions, undefined, options)
|
||||||
.then((exitCode: any) => process.exit(exitCode))
|
.then((exitCode: any) => process.exit(exitCode))
|
||||||
.catch((e: any) => {
|
.catch((e: any) => {
|
||||||
console.error(e.stack);
|
console.error(e.stack);
|
||||||
|
|
|
@ -73,7 +73,7 @@ export function isMemberMetadata(value: any): value is MemberMetadata {
|
||||||
|
|
||||||
export interface MethodMetadata extends MemberMetadata {
|
export interface MethodMetadata extends MemberMetadata {
|
||||||
__symbolic: 'constructor'|'method';
|
__symbolic: 'constructor'|'method';
|
||||||
parameterDecorators?: (MetadataSymbolicExpression|MetadataError)[][];
|
parameterDecorators?: ((MetadataSymbolicExpression | MetadataError)[]|undefined)[];
|
||||||
}
|
}
|
||||||
export function isMethodMetadata(value: any): value is MethodMetadata {
|
export function isMethodMetadata(value: any): value is MethodMetadata {
|
||||||
return value && (value.__symbolic === 'constructor' || value.__symbolic === 'method');
|
return value && (value.__symbolic === 'constructor' || value.__symbolic === 'method');
|
||||||
|
@ -81,7 +81,7 @@ export function isMethodMetadata(value: any): value is MethodMetadata {
|
||||||
|
|
||||||
export interface ConstructorMetadata extends MethodMetadata {
|
export interface ConstructorMetadata extends MethodMetadata {
|
||||||
__symbolic: 'constructor';
|
__symbolic: 'constructor';
|
||||||
parameters?: (MetadataSymbolicExpression|MetadataError|null)[];
|
parameters?: (MetadataSymbolicExpression|MetadataError|null|undefined)[];
|
||||||
}
|
}
|
||||||
export function isConstructorMetadata(value: any): value is ConstructorMetadata {
|
export function isConstructorMetadata(value: any): value is ConstructorMetadata {
|
||||||
return value && value.__symbolic === 'constructor';
|
return value && value.__symbolic === 'constructor';
|
||||||
|
@ -97,8 +97,8 @@ export function isFunctionMetadata(value: any): value is FunctionMetadata {
|
||||||
return value && value.__symbolic === 'function';
|
return value && value.__symbolic === 'function';
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MetadataValue = string | number | boolean | MetadataObject | MetadataArray |
|
export type MetadataValue = string | number | boolean | undefined | null | MetadataObject |
|
||||||
MetadataSymbolicExpression | MetadataError;
|
MetadataArray | MetadataSymbolicExpression | MetadataError;
|
||||||
|
|
||||||
export interface MetadataObject { [name: string]: MetadataValue; }
|
export interface MetadataObject { [name: string]: MetadataValue; }
|
||||||
|
|
||||||
|
|
|
@ -49,23 +49,26 @@ export class Symbols {
|
||||||
ts.SyntaxKind.ExternalModuleReference) {
|
ts.SyntaxKind.ExternalModuleReference) {
|
||||||
const externalReference =
|
const externalReference =
|
||||||
<ts.ExternalModuleReference>importEqualsDeclaration.moduleReference;
|
<ts.ExternalModuleReference>importEqualsDeclaration.moduleReference;
|
||||||
// An `import <identifier> = require(<module-specifier>);
|
if (externalReference.expression) {
|
||||||
if (!externalReference.expression.parent) {
|
// An `import <identifier> = require(<module-specifier>);
|
||||||
// The `parent` field of a node is set by the TypeScript binder (run as
|
if (!externalReference.expression.parent) {
|
||||||
// part of the type checker). Setting it here allows us to call `getText()`
|
// The `parent` field of a node is set by the TypeScript binder (run as
|
||||||
// even if the `SourceFile` was not type checked (which looks for `SourceFile`
|
// part of the type checker). Setting it here allows us to call `getText()`
|
||||||
// in the parent chain). This doesn't damage the node as the binder unconditionally
|
// even if the `SourceFile` was not type checked (which looks for `SourceFile`
|
||||||
// sets the parent.
|
// in the parent chain). This doesn't damage the node as the binder unconditionally
|
||||||
externalReference.expression.parent = externalReference;
|
// sets the parent.
|
||||||
externalReference.parent = this.sourceFile as any;
|
externalReference.expression.parent = externalReference;
|
||||||
|
externalReference.parent = this.sourceFile as any;
|
||||||
|
}
|
||||||
|
const from = stripQuotes(externalReference.expression.getText());
|
||||||
|
symbols.set(
|
||||||
|
importEqualsDeclaration.name.text, {__symbolic: 'reference', module: from});
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
const from = stripQuotes(externalReference.expression.getText());
|
|
||||||
symbols.set(importEqualsDeclaration.name.text, {__symbolic: 'reference', module: from});
|
|
||||||
} else {
|
|
||||||
symbols.set(
|
|
||||||
importEqualsDeclaration.name.text,
|
|
||||||
{__symbolic: 'error', message: `Unsupported import syntax`});
|
|
||||||
}
|
}
|
||||||
|
symbols.set(
|
||||||
|
importEqualsDeclaration.name.text,
|
||||||
|
{__symbolic: 'error', message: `Unsupported import syntax`});
|
||||||
break;
|
break;
|
||||||
case ts.SyntaxKind.ImportDeclaration:
|
case ts.SyntaxKind.ImportDeclaration:
|
||||||
const importDecl = <ts.ImportDeclaration>node;
|
const importDecl = <ts.ImportDeclaration>node;
|
||||||
|
|
|
@ -33,7 +33,7 @@ export class UserError extends Error {
|
||||||
super(message);
|
super(message);
|
||||||
// Required for TS 2.1, see
|
// Required for TS 2.1, see
|
||||||
// https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work
|
// https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work
|
||||||
Object.setPrototypeOf(this, UserError.prototype);
|
(Object as any).setPrototypeOf(this, UserError.prototype);
|
||||||
|
|
||||||
const nativeError = new Error(message) as any as Error;
|
const nativeError = new Error(message) as any as Error;
|
||||||
this._nativeError = nativeError;
|
this._nativeError = nativeError;
|
||||||
|
@ -76,13 +76,14 @@ export function formatDiagnostics(diags: ts.Diagnostic[]): string {
|
||||||
.join('\n');
|
.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function check(diags: ts.Diagnostic[]) {
|
export function check(diags: ts.Diagnostic[] | undefined) {
|
||||||
if (diags && diags.length && diags[0]) {
|
if (diags && diags.length && diags[0]) {
|
||||||
throw new UserError(formatDiagnostics(diags));
|
throw new UserError(formatDiagnostics(diags));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function validateAngularCompilerOptions(options: AngularCompilerOptions): ts.Diagnostic[] {
|
export function validateAngularCompilerOptions(options: AngularCompilerOptions): ts.Diagnostic[]|
|
||||||
|
undefined {
|
||||||
if (options.annotationsAs) {
|
if (options.annotationsAs) {
|
||||||
switch (options.annotationsAs) {
|
switch (options.annotationsAs) {
|
||||||
case 'decorators':
|
case 'decorators':
|
||||||
|
@ -90,9 +91,9 @@ export function validateAngularCompilerOptions(options: AngularCompilerOptions):
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return [{
|
return [{
|
||||||
file: null,
|
file: null as any as ts.SourceFile,
|
||||||
start: null,
|
start: null as any as number,
|
||||||
length: null,
|
length: null as any as number,
|
||||||
messageText:
|
messageText:
|
||||||
'Angular compiler options "annotationsAs" only supports "static fields" and "decorators"',
|
'Angular compiler options "annotationsAs" only supports "static fields" and "decorators"',
|
||||||
category: ts.DiagnosticCategory.Error,
|
category: ts.DiagnosticCategory.Error,
|
||||||
|
@ -136,7 +137,7 @@ export class Tsc implements CompilerInterface {
|
||||||
return ts.readConfigFile(project, this.readFile);
|
return ts.readConfigFile(project, this.readFile);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
check([error]);
|
check([error !]);
|
||||||
|
|
||||||
const parsed =
|
const parsed =
|
||||||
ts.parseJsonConfigFileContent(config, this.parseConfigHost, basePath, existingOptions);
|
ts.parseJsonConfigFileContent(config, this.parseConfigHost, basePath, existingOptions);
|
||||||
|
|
|
@ -29,7 +29,7 @@ describe('metadata bundler', () => {
|
||||||
const originalTwo = './src/two/index';
|
const originalTwo = './src/two/index';
|
||||||
expect(Object.keys(result.metadata.origins)
|
expect(Object.keys(result.metadata.origins)
|
||||||
.sort()
|
.sort()
|
||||||
.map(name => ({name, value: result.metadata.origins[name]})))
|
.map(name => ({name, value: result.metadata.origins ![name]})))
|
||||||
.toEqual([
|
.toEqual([
|
||||||
{name: 'ONE_CLASSES', value: originalOne}, {name: 'One', value: originalOne},
|
{name: 'ONE_CLASSES', value: originalOne}, {name: 'One', value: originalOne},
|
||||||
{name: 'OneMore', value: originalOne}, {name: 'TWO_CLASSES', value: originalTwo},
|
{name: 'OneMore', value: originalOne}, {name: 'TWO_CLASSES', value: originalTwo},
|
||||||
|
@ -190,7 +190,7 @@ describe('metadata bundler', () => {
|
||||||
from: 'external_one'
|
from: 'external_one'
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
expect(result.metadata.origins['E']).toBeUndefined();
|
expect(result.metadata.origins !['E']).toBeUndefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ export class MockStringBundlerHost implements MetadataBundlerHost {
|
||||||
|
|
||||||
constructor(private dirName: string, private directory: Directory) {}
|
constructor(private dirName: string, private directory: Directory) {}
|
||||||
|
|
||||||
getMetadataFor(moduleName: string): ModuleMetadata {
|
getMetadataFor(moduleName: string): ModuleMetadata|undefined {
|
||||||
const fileName = path.join(this.dirName, moduleName) + '.ts';
|
const fileName = path.join(this.dirName, moduleName) + '.ts';
|
||||||
const text = open(this.directory, fileName);
|
const text = open(this.directory, fileName);
|
||||||
if (typeof text == 'string') {
|
if (typeof text == 'string') {
|
||||||
|
|
|
@ -196,13 +196,13 @@ describe('Collector', () => {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
casesFile = program.getSourceFile('/app/cases-data.ts');
|
casesFile = program.getSourceFile('/app/cases-data.ts');
|
||||||
casesMetadata = collector.getMetadata(casesFile);
|
casesMetadata = collector.getMetadata(casesFile) !;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should provide any reference for an any ctor parameter type', () => {
|
it('should provide any reference for an any ctor parameter type', () => {
|
||||||
const casesAny = <ClassMetadata>casesMetadata.metadata['CaseAny'];
|
const casesAny = <ClassMetadata>casesMetadata.metadata['CaseAny'];
|
||||||
expect(casesAny).toBeTruthy();
|
expect(casesAny).toBeTruthy();
|
||||||
const ctorData = casesAny.members['__ctor__'];
|
const ctorData = casesAny.members !['__ctor__'];
|
||||||
expect(ctorData).toEqual(
|
expect(ctorData).toEqual(
|
||||||
[{__symbolic: 'constructor', parameters: [{__symbolic: 'reference', name: 'any'}]}]);
|
[{__symbolic: 'constructor', parameters: [{__symbolic: 'reference', name: 'any'}]}]);
|
||||||
});
|
});
|
||||||
|
@ -265,10 +265,10 @@ describe('Collector', () => {
|
||||||
|
|
||||||
it('should report an error for references to unexpected types', () => {
|
it('should report an error for references to unexpected types', () => {
|
||||||
const unsupported1 = program.getSourceFile('/unsupported-2.ts');
|
const unsupported1 = program.getSourceFile('/unsupported-2.ts');
|
||||||
const metadata = collector.getMetadata(unsupported1);
|
const metadata = collector.getMetadata(unsupported1) !;
|
||||||
const barClass = <ClassMetadata>metadata.metadata['Bar'];
|
const barClass = <ClassMetadata>metadata.metadata['Bar'];
|
||||||
const ctor = <ConstructorMetadata>barClass.members['__ctor__'][0];
|
const ctor = <ConstructorMetadata>barClass.members !['__ctor__'][0];
|
||||||
const parameter = ctor.parameters[0];
|
const parameter = ctor.parameters ![0];
|
||||||
expect(parameter).toEqual({
|
expect(parameter).toEqual({
|
||||||
__symbolic: 'error',
|
__symbolic: 'error',
|
||||||
message: 'Reference to non-exported class',
|
message: 'Reference to non-exported class',
|
||||||
|
@ -280,9 +280,9 @@ describe('Collector', () => {
|
||||||
|
|
||||||
it('should be able to handle import star type references', () => {
|
it('should be able to handle import star type references', () => {
|
||||||
const importStar = program.getSourceFile('/import-star.ts');
|
const importStar = program.getSourceFile('/import-star.ts');
|
||||||
const metadata = collector.getMetadata(importStar);
|
const metadata = collector.getMetadata(importStar) !;
|
||||||
const someClass = <ClassMetadata>metadata.metadata['SomeClass'];
|
const someClass = <ClassMetadata>metadata.metadata['SomeClass'];
|
||||||
const ctor = <ConstructorMetadata>someClass.members['__ctor__'][0];
|
const ctor = <ConstructorMetadata>someClass.members !['__ctor__'][0];
|
||||||
const parameters = ctor.parameters;
|
const parameters = ctor.parameters;
|
||||||
expect(parameters).toEqual([
|
expect(parameters).toEqual([
|
||||||
{__symbolic: 'reference', module: 'angular2/common', name: 'NgFor'}
|
{__symbolic: 'reference', module: 'angular2/common', name: 'NgFor'}
|
||||||
|
@ -365,9 +365,9 @@ describe('Collector', () => {
|
||||||
|
|
||||||
it('should be able to handle import star type references', () => {
|
it('should be able to handle import star type references', () => {
|
||||||
const importStar = program.getSourceFile('/import-star.ts');
|
const importStar = program.getSourceFile('/import-star.ts');
|
||||||
const metadata = collector.getMetadata(importStar);
|
const metadata = collector.getMetadata(importStar) !;
|
||||||
const someClass = <ClassMetadata>metadata.metadata['SomeClass'];
|
const someClass = <ClassMetadata>metadata.metadata['SomeClass'];
|
||||||
const ctor = <ConstructorMetadata>someClass.members['__ctor__'][0];
|
const ctor = <ConstructorMetadata>someClass.members !['__ctor__'][0];
|
||||||
const parameters = ctor.parameters;
|
const parameters = ctor.parameters;
|
||||||
expect(parameters).toEqual([
|
expect(parameters).toEqual([
|
||||||
{__symbolic: 'reference', module: 'angular2/common', name: 'NgFor'}
|
{__symbolic: 'reference', module: 'angular2/common', name: 'NgFor'}
|
||||||
|
@ -376,14 +376,14 @@ describe('Collector', () => {
|
||||||
|
|
||||||
it('should be able to collect the value of an enum', () => {
|
it('should be able to collect the value of an enum', () => {
|
||||||
const enumSource = program.getSourceFile('/exported-enum.ts');
|
const enumSource = program.getSourceFile('/exported-enum.ts');
|
||||||
const metadata = collector.getMetadata(enumSource);
|
const metadata = collector.getMetadata(enumSource) !;
|
||||||
const someEnum: any = metadata.metadata['SomeEnum'];
|
const someEnum: any = metadata.metadata['SomeEnum'];
|
||||||
expect(someEnum).toEqual({A: 0, B: 1, C: 100, D: 101});
|
expect(someEnum).toEqual({A: 0, B: 1, C: 100, D: 101});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should ignore a non-export enum', () => {
|
it('should ignore a non-export enum', () => {
|
||||||
const enumSource = program.getSourceFile('/private-enum.ts');
|
const enumSource = program.getSourceFile('/private-enum.ts');
|
||||||
const metadata = collector.getMetadata(enumSource);
|
const metadata = collector.getMetadata(enumSource) !;
|
||||||
const publicEnum: any = metadata.metadata['PublicEnum'];
|
const publicEnum: any = metadata.metadata['PublicEnum'];
|
||||||
const privateEnum: any = metadata.metadata['PrivateEnum'];
|
const privateEnum: any = metadata.metadata['PrivateEnum'];
|
||||||
expect(publicEnum).toEqual({a: 0, b: 1, c: 2});
|
expect(publicEnum).toEqual({a: 0, b: 1, c: 2});
|
||||||
|
@ -392,7 +392,7 @@ describe('Collector', () => {
|
||||||
|
|
||||||
it('should be able to collect enums initialized from consts', () => {
|
it('should be able to collect enums initialized from consts', () => {
|
||||||
const enumSource = program.getSourceFile('/exported-enum.ts');
|
const enumSource = program.getSourceFile('/exported-enum.ts');
|
||||||
const metadata = collector.getMetadata(enumSource);
|
const metadata = collector.getMetadata(enumSource) !;
|
||||||
const complexEnum: any = metadata.metadata['ComplexEnum'];
|
const complexEnum: any = metadata.metadata['ComplexEnum'];
|
||||||
expect(complexEnum).toEqual({
|
expect(complexEnum).toEqual({
|
||||||
A: 0,
|
A: 0,
|
||||||
|
@ -405,7 +405,7 @@ describe('Collector', () => {
|
||||||
|
|
||||||
it('should be able to collect a simple static method', () => {
|
it('should be able to collect a simple static method', () => {
|
||||||
const staticSource = program.getSourceFile('/static-method.ts');
|
const staticSource = program.getSourceFile('/static-method.ts');
|
||||||
const metadata = collector.getMetadata(staticSource);
|
const metadata = collector.getMetadata(staticSource) !;
|
||||||
expect(metadata).toBeDefined();
|
expect(metadata).toBeDefined();
|
||||||
const classData = <ClassMetadata>metadata.metadata['MyModule'];
|
const classData = <ClassMetadata>metadata.metadata['MyModule'];
|
||||||
expect(classData).toBeDefined();
|
expect(classData).toBeDefined();
|
||||||
|
@ -423,7 +423,7 @@ describe('Collector', () => {
|
||||||
|
|
||||||
it('should be able to collect a call to a static method', () => {
|
it('should be able to collect a call to a static method', () => {
|
||||||
const staticSource = program.getSourceFile('/static-method-call.ts');
|
const staticSource = program.getSourceFile('/static-method-call.ts');
|
||||||
const metadata = collector.getMetadata(staticSource);
|
const metadata = collector.getMetadata(staticSource) !;
|
||||||
expect(metadata).toBeDefined();
|
expect(metadata).toBeDefined();
|
||||||
const classData = <ClassMetadata>metadata.metadata['Foo'];
|
const classData = <ClassMetadata>metadata.metadata['Foo'];
|
||||||
expect(classData).toBeDefined();
|
expect(classData).toBeDefined();
|
||||||
|
@ -446,7 +446,7 @@ describe('Collector', () => {
|
||||||
|
|
||||||
it('should be able to collect a static field', () => {
|
it('should be able to collect a static field', () => {
|
||||||
const staticSource = program.getSourceFile('/static-field.ts');
|
const staticSource = program.getSourceFile('/static-field.ts');
|
||||||
const metadata = collector.getMetadata(staticSource);
|
const metadata = collector.getMetadata(staticSource) !;
|
||||||
expect(metadata).toBeDefined();
|
expect(metadata).toBeDefined();
|
||||||
const classData = <ClassMetadata>metadata.metadata['MyModule'];
|
const classData = <ClassMetadata>metadata.metadata['MyModule'];
|
||||||
expect(classData).toBeDefined();
|
expect(classData).toBeDefined();
|
||||||
|
@ -455,7 +455,7 @@ describe('Collector', () => {
|
||||||
|
|
||||||
it('should be able to collect a reference to a static field', () => {
|
it('should be able to collect a reference to a static field', () => {
|
||||||
const staticSource = program.getSourceFile('/static-field-reference.ts');
|
const staticSource = program.getSourceFile('/static-field-reference.ts');
|
||||||
const metadata = collector.getMetadata(staticSource);
|
const metadata = collector.getMetadata(staticSource) !;
|
||||||
expect(metadata).toBeDefined();
|
expect(metadata).toBeDefined();
|
||||||
const classData = <ClassMetadata>metadata.metadata['Foo'];
|
const classData = <ClassMetadata>metadata.metadata['Foo'];
|
||||||
expect(classData).toBeDefined();
|
expect(classData).toBeDefined();
|
||||||
|
@ -477,7 +477,7 @@ describe('Collector', () => {
|
||||||
|
|
||||||
it('should be able to collect a method with a conditional expression', () => {
|
it('should be able to collect a method with a conditional expression', () => {
|
||||||
const source = program.getSourceFile('/static-method-with-if.ts');
|
const source = program.getSourceFile('/static-method-with-if.ts');
|
||||||
const metadata = collector.getMetadata(source);
|
const metadata = collector.getMetadata(source) !;
|
||||||
expect(metadata).toBeDefined();
|
expect(metadata).toBeDefined();
|
||||||
const classData = <ClassMetadata>metadata.metadata['MyModule'];
|
const classData = <ClassMetadata>metadata.metadata['MyModule'];
|
||||||
expect(classData).toBeDefined();
|
expect(classData).toBeDefined();
|
||||||
|
@ -502,7 +502,7 @@ describe('Collector', () => {
|
||||||
|
|
||||||
it('should be able to collect a method with a default parameter', () => {
|
it('should be able to collect a method with a default parameter', () => {
|
||||||
const source = program.getSourceFile('/static-method-with-default.ts');
|
const source = program.getSourceFile('/static-method-with-default.ts');
|
||||||
const metadata = collector.getMetadata(source);
|
const metadata = collector.getMetadata(source) !;
|
||||||
expect(metadata).toBeDefined();
|
expect(metadata).toBeDefined();
|
||||||
const classData = <ClassMetadata>metadata.metadata['MyModule'];
|
const classData = <ClassMetadata>metadata.metadata['MyModule'];
|
||||||
expect(classData).toBeDefined();
|
expect(classData).toBeDefined();
|
||||||
|
@ -531,7 +531,7 @@ describe('Collector', () => {
|
||||||
|
|
||||||
it('should be able to collect re-exported symbols', () => {
|
it('should be able to collect re-exported symbols', () => {
|
||||||
const source = program.getSourceFile('/re-exports.ts');
|
const source = program.getSourceFile('/re-exports.ts');
|
||||||
const metadata = collector.getMetadata(source);
|
const metadata = collector.getMetadata(source) !;
|
||||||
expect(metadata.exports).toEqual([
|
expect(metadata.exports).toEqual([
|
||||||
{from: './static-field', export: ['MyModule']},
|
{from: './static-field', export: ['MyModule']},
|
||||||
{from: './static-field-reference', export: [{name: 'Foo', as: 'OtherModule'}]},
|
{from: './static-field-reference', export: [{name: 'Foo', as: 'OtherModule'}]},
|
||||||
|
@ -541,13 +541,13 @@ describe('Collector', () => {
|
||||||
|
|
||||||
it('should be able to collect a export as symbol', () => {
|
it('should be able to collect a export as symbol', () => {
|
||||||
const source = program.getSourceFile('export-as.d.ts');
|
const source = program.getSourceFile('export-as.d.ts');
|
||||||
const metadata = collector.getMetadata(source);
|
const metadata = collector.getMetadata(source) !;
|
||||||
expect(metadata.metadata).toEqual({SomeFunction: {__symbolic: 'function'}});
|
expect(metadata.metadata).toEqual({SomeFunction: {__symbolic: 'function'}});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to collect exports with no module specifier', () => {
|
it('should be able to collect exports with no module specifier', () => {
|
||||||
const source = program.getSourceFile('/re-exports-2.ts');
|
const source = program.getSourceFile('/re-exports-2.ts');
|
||||||
const metadata = collector.getMetadata(source);
|
const metadata = collector.getMetadata(source) !;
|
||||||
expect(metadata.metadata).toEqual({
|
expect(metadata.metadata).toEqual({
|
||||||
MyClass: Object({__symbolic: 'class'}),
|
MyClass: Object({__symbolic: 'class'}),
|
||||||
OtherModule: {__symbolic: 'reference', module: './static-field-reference', name: 'Foo'},
|
OtherModule: {__symbolic: 'reference', module: './static-field-reference', name: 'Foo'},
|
||||||
|
@ -557,7 +557,7 @@ describe('Collector', () => {
|
||||||
|
|
||||||
it('should collect an error symbol if collecting a reference to a non-exported symbol', () => {
|
it('should collect an error symbol if collecting a reference to a non-exported symbol', () => {
|
||||||
const source = program.getSourceFile('/local-symbol-ref.ts');
|
const source = program.getSourceFile('/local-symbol-ref.ts');
|
||||||
const metadata = collector.getMetadata(source);
|
const metadata = collector.getMetadata(source) !;
|
||||||
expect(metadata.metadata).toEqual({
|
expect(metadata.metadata).toEqual({
|
||||||
REQUIRED_VALIDATOR: {
|
REQUIRED_VALIDATOR: {
|
||||||
__symbolic: 'error',
|
__symbolic: 'error',
|
||||||
|
@ -579,7 +579,7 @@ describe('Collector', () => {
|
||||||
|
|
||||||
it('should collect an error symbol if collecting a reference to a non-exported function', () => {
|
it('should collect an error symbol if collecting a reference to a non-exported function', () => {
|
||||||
const source = program.getSourceFile('/local-function-ref.ts');
|
const source = program.getSourceFile('/local-function-ref.ts');
|
||||||
const metadata = collector.getMetadata(source);
|
const metadata = collector.getMetadata(source) !;
|
||||||
expect(metadata.metadata).toEqual({
|
expect(metadata.metadata).toEqual({
|
||||||
REQUIRED_VALIDATOR: {
|
REQUIRED_VALIDATOR: {
|
||||||
__symbolic: 'error',
|
__symbolic: 'error',
|
||||||
|
@ -601,7 +601,7 @@ describe('Collector', () => {
|
||||||
|
|
||||||
it('should collect an error for a simple function that references a local variable', () => {
|
it('should collect an error for a simple function that references a local variable', () => {
|
||||||
const source = program.getSourceFile('/local-symbol-ref-func.ts');
|
const source = program.getSourceFile('/local-symbol-ref-func.ts');
|
||||||
const metadata = collector.getMetadata(source);
|
const metadata = collector.getMetadata(source) !;
|
||||||
expect(metadata.metadata).toEqual({
|
expect(metadata.metadata).toEqual({
|
||||||
foo: {
|
foo: {
|
||||||
__symbolic: 'function',
|
__symbolic: 'function',
|
||||||
|
@ -619,7 +619,7 @@ describe('Collector', () => {
|
||||||
|
|
||||||
it('should collect any for interface parameter reference', () => {
|
it('should collect any for interface parameter reference', () => {
|
||||||
const source = program.getSourceFile('/interface-reference.ts');
|
const source = program.getSourceFile('/interface-reference.ts');
|
||||||
const metadata = collector.getMetadata(source);
|
const metadata = collector.getMetadata(source) !;
|
||||||
expect((metadata.metadata['SomeClass'] as ClassMetadata).members).toEqual({
|
expect((metadata.metadata['SomeClass'] as ClassMetadata).members).toEqual({
|
||||||
__ctor__: [{
|
__ctor__: [{
|
||||||
__symbolic: 'constructor',
|
__symbolic: 'constructor',
|
||||||
|
@ -734,7 +734,7 @@ describe('Collector', () => {
|
||||||
toString(): string { return \`InjectionToken ${this._desc}\`; }
|
toString(): string { return \`InjectionToken ${this._desc}\`; }
|
||||||
} as any;`,
|
} as any;`,
|
||||||
ts.ScriptTarget.Latest, true);
|
ts.ScriptTarget.Latest, true);
|
||||||
const metadata = collector.getMetadata(source);
|
const metadata = collector.getMetadata(source) !;
|
||||||
expect(metadata.metadata).toEqual({InjectionToken: {__symbolic: 'class'}});
|
expect(metadata.metadata).toEqual({InjectionToken: {__symbolic: 'class'}});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -781,19 +781,19 @@ describe('Collector', () => {
|
||||||
|
|
||||||
describe('inheritance', () => {
|
describe('inheritance', () => {
|
||||||
it('should record `extends` clauses for declared classes', () => {
|
it('should record `extends` clauses for declared classes', () => {
|
||||||
const metadata = collector.getMetadata(program.getSourceFile('/class-inheritance.ts'));
|
const metadata = collector.getMetadata(program.getSourceFile('/class-inheritance.ts')) !;
|
||||||
expect(metadata.metadata['DeclaredChildClass'])
|
expect(metadata.metadata['DeclaredChildClass'])
|
||||||
.toEqual({__symbolic: 'class', extends: {__symbolic: 'reference', name: 'ParentClass'}});
|
.toEqual({__symbolic: 'class', extends: {__symbolic: 'reference', name: 'ParentClass'}});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should record `extends` clauses for classes in the same file', () => {
|
it('should record `extends` clauses for classes in the same file', () => {
|
||||||
const metadata = collector.getMetadata(program.getSourceFile('/class-inheritance.ts'));
|
const metadata = collector.getMetadata(program.getSourceFile('/class-inheritance.ts')) !;
|
||||||
expect(metadata.metadata['ChildClassSameFile'])
|
expect(metadata.metadata['ChildClassSameFile'])
|
||||||
.toEqual({__symbolic: 'class', extends: {__symbolic: 'reference', name: 'ParentClass'}});
|
.toEqual({__symbolic: 'class', extends: {__symbolic: 'reference', name: 'ParentClass'}});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should record `extends` clauses for classes in a different file', () => {
|
it('should record `extends` clauses for classes in a different file', () => {
|
||||||
const metadata = collector.getMetadata(program.getSourceFile('/class-inheritance.ts'));
|
const metadata = collector.getMetadata(program.getSourceFile('/class-inheritance.ts')) !;
|
||||||
expect(metadata.metadata['ChildClassOtherFile']).toEqual({
|
expect(metadata.metadata['ChildClassOtherFile']).toEqual({
|
||||||
__symbolic: 'class',
|
__symbolic: 'class',
|
||||||
extends: {
|
extends: {
|
||||||
|
@ -811,7 +811,7 @@ describe('Collector', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should collect the correct arity for a class', () => {
|
it('should collect the correct arity for a class', () => {
|
||||||
const metadata = collector.getMetadata(program.getSourceFile('/class-arity.ts'));
|
const metadata = collector.getMetadata(program.getSourceFile('/class-arity.ts')) !;
|
||||||
|
|
||||||
const zero = metadata.metadata['Zero'];
|
const zero = metadata.metadata['Zero'];
|
||||||
if (expectClass(zero)) expect(zero.arity).toBeUndefined();
|
if (expectClass(zero)) expect(zero.arity).toBeUndefined();
|
||||||
|
@ -883,7 +883,7 @@ describe('Collector', () => {
|
||||||
})
|
})
|
||||||
export class MyComponent {}
|
export class MyComponent {}
|
||||||
`);
|
`);
|
||||||
const metadata = collector.getMetadata(source);
|
const metadata = collector.getMetadata(source) !;
|
||||||
expect(metadata.metadata.MyComponent).toEqual({
|
expect(metadata.metadata.MyComponent).toEqual({
|
||||||
__symbolic: 'class',
|
__symbolic: 'class',
|
||||||
decorators: [{
|
decorators: [{
|
||||||
|
@ -947,7 +947,7 @@ describe('Collector', () => {
|
||||||
|
|
||||||
function collectSource(content: string): ModuleMetadata {
|
function collectSource(content: string): ModuleMetadata {
|
||||||
const sourceFile = createSource(content);
|
const sourceFile = createSource(content);
|
||||||
return collector.getMetadata(sourceFile);
|
return collector.getMetadata(sourceFile) !;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import * as ts from 'typescript';
|
||||||
import {Evaluator} from '../src/evaluator';
|
import {Evaluator} from '../src/evaluator';
|
||||||
import {Symbols} from '../src/symbols';
|
import {Symbols} from '../src/symbols';
|
||||||
|
|
||||||
import {Directory, Host, expectNoDiagnostics, findVar} from './typescript.mocks';
|
import {Directory, Host, expectNoDiagnostics, findVar, findVarInitializer} from './typescript.mocks';
|
||||||
|
|
||||||
describe('Evaluator', () => {
|
describe('Evaluator', () => {
|
||||||
const documentRegistry = ts.createDocumentRegistry();
|
const documentRegistry = ts.createDocumentRegistry();
|
||||||
|
@ -31,7 +31,7 @@ describe('Evaluator', () => {
|
||||||
service = ts.createLanguageService(host, documentRegistry);
|
service = ts.createLanguageService(host, documentRegistry);
|
||||||
program = service.getProgram();
|
program = service.getProgram();
|
||||||
typeChecker = program.getTypeChecker();
|
typeChecker = program.getTypeChecker();
|
||||||
symbols = new Symbols(null);
|
symbols = new Symbols(null as any as ts.SourceFile);
|
||||||
evaluator = new Evaluator(symbols, new Map());
|
evaluator = new Evaluator(symbols, new Map());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -48,10 +48,10 @@ describe('Evaluator', () => {
|
||||||
|
|
||||||
it('should be able to fold literal expressions', () => {
|
it('should be able to fold literal expressions', () => {
|
||||||
const consts = program.getSourceFile('consts.ts');
|
const consts = program.getSourceFile('consts.ts');
|
||||||
expect(evaluator.isFoldable(findVar(consts, 'someName').initializer)).toBeTruthy();
|
expect(evaluator.isFoldable(findVarInitializer(consts, 'someName'))).toBeTruthy();
|
||||||
expect(evaluator.isFoldable(findVar(consts, 'someBool').initializer)).toBeTruthy();
|
expect(evaluator.isFoldable(findVarInitializer(consts, 'someBool'))).toBeTruthy();
|
||||||
expect(evaluator.isFoldable(findVar(consts, 'one').initializer)).toBeTruthy();
|
expect(evaluator.isFoldable(findVarInitializer(consts, 'one'))).toBeTruthy();
|
||||||
expect(evaluator.isFoldable(findVar(consts, 'two').initializer)).toBeTruthy();
|
expect(evaluator.isFoldable(findVarInitializer(consts, 'two'))).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to fold expressions with foldable references', () => {
|
it('should be able to fold expressions with foldable references', () => {
|
||||||
|
@ -60,20 +60,20 @@ describe('Evaluator', () => {
|
||||||
symbols.define('someBool', true);
|
symbols.define('someBool', true);
|
||||||
symbols.define('one', 1);
|
symbols.define('one', 1);
|
||||||
symbols.define('two', 2);
|
symbols.define('two', 2);
|
||||||
expect(evaluator.isFoldable(findVar(expressions, 'three').initializer)).toBeTruthy();
|
expect(evaluator.isFoldable(findVarInitializer(expressions, 'three'))).toBeTruthy();
|
||||||
expect(evaluator.isFoldable(findVar(expressions, 'four').initializer)).toBeTruthy();
|
expect(evaluator.isFoldable(findVarInitializer(expressions, 'four'))).toBeTruthy();
|
||||||
symbols.define('three', 3);
|
symbols.define('three', 3);
|
||||||
symbols.define('four', 4);
|
symbols.define('four', 4);
|
||||||
expect(evaluator.isFoldable(findVar(expressions, 'obj').initializer)).toBeTruthy();
|
expect(evaluator.isFoldable(findVarInitializer(expressions, 'obj'))).toBeTruthy();
|
||||||
expect(evaluator.isFoldable(findVar(expressions, 'arr').initializer)).toBeTruthy();
|
expect(evaluator.isFoldable(findVarInitializer(expressions, 'arr'))).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to evaluate literal expressions', () => {
|
it('should be able to evaluate literal expressions', () => {
|
||||||
const consts = program.getSourceFile('consts.ts');
|
const consts = program.getSourceFile('consts.ts');
|
||||||
expect(evaluator.evaluateNode(findVar(consts, 'someName').initializer)).toBe('some-name');
|
expect(evaluator.evaluateNode(findVarInitializer(consts, 'someName'))).toBe('some-name');
|
||||||
expect(evaluator.evaluateNode(findVar(consts, 'someBool').initializer)).toBe(true);
|
expect(evaluator.evaluateNode(findVarInitializer(consts, 'someBool'))).toBe(true);
|
||||||
expect(evaluator.evaluateNode(findVar(consts, 'one').initializer)).toBe(1);
|
expect(evaluator.evaluateNode(findVarInitializer(consts, 'one'))).toBe(1);
|
||||||
expect(evaluator.evaluateNode(findVar(consts, 'two').initializer)).toBe(2);
|
expect(evaluator.evaluateNode(findVarInitializer(consts, 'two'))).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to evaluate expressions', () => {
|
it('should be able to evaluate expressions', () => {
|
||||||
|
@ -82,78 +82,77 @@ describe('Evaluator', () => {
|
||||||
symbols.define('someBool', true);
|
symbols.define('someBool', true);
|
||||||
symbols.define('one', 1);
|
symbols.define('one', 1);
|
||||||
symbols.define('two', 2);
|
symbols.define('two', 2);
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'three').initializer)).toBe(3);
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'three'))).toBe(3);
|
||||||
symbols.define('three', 3);
|
symbols.define('three', 3);
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'four').initializer)).toBe(4);
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'four'))).toBe(4);
|
||||||
symbols.define('four', 4);
|
symbols.define('four', 4);
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'obj').initializer))
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'obj')))
|
||||||
.toEqual({one: 1, two: 2, three: 3, four: 4});
|
.toEqual({one: 1, two: 2, three: 3, four: 4});
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'arr').initializer)).toEqual([1, 2, 3, 4]);
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'arr'))).toEqual([1, 2, 3, 4]);
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'bTrue').initializer)).toEqual(true);
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bTrue'))).toEqual(true);
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'bFalse').initializer)).toEqual(false);
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bFalse'))).toEqual(false);
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'bAnd').initializer)).toEqual(true);
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bAnd'))).toEqual(true);
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'bOr').initializer)).toEqual(true);
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bOr'))).toEqual(true);
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'nDiv').initializer)).toEqual(2);
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'nDiv'))).toEqual(2);
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'nMod').initializer)).toEqual(1);
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'nMod'))).toEqual(1);
|
||||||
|
|
||||||
|
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'bLOr').initializer)).toEqual(false || true);
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bLOr'))).toEqual(false || true);
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'bLAnd').initializer)).toEqual(true && true);
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bLAnd'))).toEqual(true && true);
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'bBOr').initializer)).toEqual(0x11 | 0x22);
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bBOr'))).toEqual(0x11 | 0x22);
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'bBAnd').initializer)).toEqual(0x11 & 0x03);
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bBAnd'))).toEqual(0x11 & 0x03);
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'bXor').initializer)).toEqual(0x11 ^ 0x21);
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bXor'))).toEqual(0x11 ^ 0x21);
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'bEqual').initializer))
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bEqual')))
|
||||||
.toEqual(1 == <any>'1');
|
.toEqual(1 == <any>'1');
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'bNotEqual').initializer))
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bNotEqual')))
|
||||||
.toEqual(1 != <any>'1');
|
.toEqual(1 != <any>'1');
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'bIdentical').initializer))
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bIdentical')))
|
||||||
.toEqual(1 === <any>'1');
|
.toEqual(1 === <any>'1');
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'bNotIdentical').initializer))
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bNotIdentical')))
|
||||||
.toEqual(1 !== <any>'1');
|
.toEqual(1 !== <any>'1');
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'bLessThan').initializer)).toEqual(1 < 2);
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bLessThan'))).toEqual(1 < 2);
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'bGreaterThan').initializer)).toEqual(1 > 2);
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bGreaterThan'))).toEqual(1 > 2);
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'bLessThanEqual').initializer))
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bLessThanEqual')))
|
||||||
.toEqual(1 <= 2);
|
.toEqual(1 <= 2);
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'bGreaterThanEqual').initializer))
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bGreaterThanEqual')))
|
||||||
.toEqual(1 >= 2);
|
.toEqual(1 >= 2);
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'bShiftLeft').initializer)).toEqual(1 << 2);
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bShiftLeft'))).toEqual(1 << 2);
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'bShiftRight').initializer))
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bShiftRight'))).toEqual(-1 >> 2);
|
||||||
.toEqual(-1 >> 2);
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bShiftRightU')))
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'bShiftRightU').initializer))
|
|
||||||
.toEqual(-1 >>> 2);
|
.toEqual(-1 >>> 2);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should report recursive references as symbolic', () => {
|
it('should report recursive references as symbolic', () => {
|
||||||
const expressions = program.getSourceFile('expressions.ts');
|
const expressions = program.getSourceFile('expressions.ts');
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'recursiveA').initializer))
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'recursiveA')))
|
||||||
.toEqual({__symbolic: 'reference', name: 'recursiveB'});
|
.toEqual({__symbolic: 'reference', name: 'recursiveB'});
|
||||||
expect(evaluator.evaluateNode(findVar(expressions, 'recursiveB').initializer))
|
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'recursiveB')))
|
||||||
.toEqual({__symbolic: 'reference', name: 'recursiveA'});
|
.toEqual({__symbolic: 'reference', name: 'recursiveA'});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly handle special cases for CONST_EXPR', () => {
|
it('should correctly handle special cases for CONST_EXPR', () => {
|
||||||
const const_expr = program.getSourceFile('const_expr.ts');
|
const const_expr = program.getSourceFile('const_expr.ts');
|
||||||
expect(evaluator.evaluateNode(findVar(const_expr, 'bTrue').initializer)).toEqual(true);
|
expect(evaluator.evaluateNode(findVarInitializer(const_expr, 'bTrue'))).toEqual(true);
|
||||||
expect(evaluator.evaluateNode(findVar(const_expr, 'bFalse').initializer)).toEqual(false);
|
expect(evaluator.evaluateNode(findVarInitializer(const_expr, 'bFalse'))).toEqual(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should resolve a forwardRef', () => {
|
it('should resolve a forwardRef', () => {
|
||||||
const forwardRef = program.getSourceFile('forwardRef.ts');
|
const forwardRef = program.getSourceFile('forwardRef.ts');
|
||||||
expect(evaluator.evaluateNode(findVar(forwardRef, 'bTrue').initializer)).toEqual(true);
|
expect(evaluator.evaluateNode(findVarInitializer(forwardRef, 'bTrue'))).toEqual(true);
|
||||||
expect(evaluator.evaluateNode(findVar(forwardRef, 'bFalse').initializer)).toEqual(false);
|
expect(evaluator.evaluateNode(findVarInitializer(forwardRef, 'bFalse'))).toEqual(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return new expressions', () => {
|
it('should return new expressions', () => {
|
||||||
symbols.define('Value', {__symbolic: 'reference', module: './classes', name: 'Value'});
|
symbols.define('Value', {__symbolic: 'reference', module: './classes', name: 'Value'});
|
||||||
evaluator = new Evaluator(symbols, new Map());
|
evaluator = new Evaluator(symbols, new Map());
|
||||||
const newExpression = program.getSourceFile('newExpression.ts');
|
const newExpression = program.getSourceFile('newExpression.ts');
|
||||||
expect(evaluator.evaluateNode(findVar(newExpression, 'someValue').initializer)).toEqual({
|
expect(evaluator.evaluateNode(findVarInitializer(newExpression, 'someValue'))).toEqual({
|
||||||
__symbolic: 'new',
|
__symbolic: 'new',
|
||||||
expression: {__symbolic: 'reference', name: 'Value', module: './classes'},
|
expression: {__symbolic: 'reference', name: 'Value', module: './classes'},
|
||||||
arguments: ['name', 12]
|
arguments: ['name', 12]
|
||||||
});
|
});
|
||||||
expect(evaluator.evaluateNode(findVar(newExpression, 'complex').initializer)).toEqual({
|
expect(evaluator.evaluateNode(findVarInitializer(newExpression, 'complex'))).toEqual({
|
||||||
__symbolic: 'new',
|
__symbolic: 'new',
|
||||||
expression: {__symbolic: 'reference', name: 'Value', module: './classes'},
|
expression: {__symbolic: 'reference', name: 'Value', module: './classes'},
|
||||||
arguments: ['name', 12]
|
arguments: ['name', 12]
|
||||||
|
@ -162,8 +161,8 @@ describe('Evaluator', () => {
|
||||||
|
|
||||||
it('should support referene to a declared module type', () => {
|
it('should support referene to a declared module type', () => {
|
||||||
const declared = program.getSourceFile('declared.ts');
|
const declared = program.getSourceFile('declared.ts');
|
||||||
const aDecl = findVar(declared, 'a');
|
const aDecl = findVar(declared, 'a') !;
|
||||||
expect(evaluator.evaluateNode(aDecl.type)).toEqual({
|
expect(evaluator.evaluateNode(aDecl.type !)).toEqual({
|
||||||
__symbolic: 'select',
|
__symbolic: 'select',
|
||||||
expression: {__symbolic: 'reference', name: 'Foo'},
|
expression: {__symbolic: 'reference', name: 'Foo'},
|
||||||
member: 'A'
|
member: 'A'
|
||||||
|
@ -172,28 +171,28 @@ describe('Evaluator', () => {
|
||||||
|
|
||||||
it('should return errors for unsupported expressions', () => {
|
it('should return errors for unsupported expressions', () => {
|
||||||
const errors = program.getSourceFile('errors.ts');
|
const errors = program.getSourceFile('errors.ts');
|
||||||
const fDecl = findVar(errors, 'f');
|
const fDecl = findVar(errors, 'f') !;
|
||||||
expect(evaluator.evaluateNode(fDecl.initializer))
|
expect(evaluator.evaluateNode(fDecl.initializer !))
|
||||||
.toEqual(
|
.toEqual(
|
||||||
{__symbolic: 'error', message: 'Function call not supported', line: 1, character: 12});
|
{__symbolic: 'error', message: 'Function call not supported', line: 1, character: 12});
|
||||||
const eDecl = findVar(errors, 'e');
|
const eDecl = findVar(errors, 'e') !;
|
||||||
expect(evaluator.evaluateNode(eDecl.type)).toEqual({
|
expect(evaluator.evaluateNode(eDecl.type !)).toEqual({
|
||||||
__symbolic: 'error',
|
__symbolic: 'error',
|
||||||
message: 'Could not resolve type',
|
message: 'Could not resolve type',
|
||||||
line: 2,
|
line: 2,
|
||||||
character: 11,
|
character: 11,
|
||||||
context: {typeName: 'NotFound'}
|
context: {typeName: 'NotFound'}
|
||||||
});
|
});
|
||||||
const sDecl = findVar(errors, 's');
|
const sDecl = findVar(errors, 's') !;
|
||||||
expect(evaluator.evaluateNode(sDecl.initializer)).toEqual({
|
expect(evaluator.evaluateNode(sDecl.initializer !)).toEqual({
|
||||||
__symbolic: 'error',
|
__symbolic: 'error',
|
||||||
message: 'Name expected',
|
message: 'Name expected',
|
||||||
line: 3,
|
line: 3,
|
||||||
character: 14,
|
character: 14,
|
||||||
context: {received: '1'}
|
context: {received: '1'}
|
||||||
});
|
});
|
||||||
const tDecl = findVar(errors, 't');
|
const tDecl = findVar(errors, 't') !;
|
||||||
expect(evaluator.evaluateNode(tDecl.initializer)).toEqual({
|
expect(evaluator.evaluateNode(tDecl.initializer !)).toEqual({
|
||||||
__symbolic: 'error',
|
__symbolic: 'error',
|
||||||
message: 'Expression form not supported',
|
message: 'Expression form not supported',
|
||||||
line: 4,
|
line: 4,
|
||||||
|
@ -204,14 +203,14 @@ describe('Evaluator', () => {
|
||||||
it('should be able to fold an array spread', () => {
|
it('should be able to fold an array spread', () => {
|
||||||
const expressions = program.getSourceFile('expressions.ts');
|
const expressions = program.getSourceFile('expressions.ts');
|
||||||
symbols.define('arr', [1, 2, 3, 4]);
|
symbols.define('arr', [1, 2, 3, 4]);
|
||||||
const arrSpread = findVar(expressions, 'arrSpread');
|
const arrSpread = findVar(expressions, 'arrSpread') !;
|
||||||
expect(evaluator.evaluateNode(arrSpread.initializer)).toEqual([0, 1, 2, 3, 4, 5]);
|
expect(evaluator.evaluateNode(arrSpread.initializer !)).toEqual([0, 1, 2, 3, 4, 5]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to produce a spread expression', () => {
|
it('should be able to produce a spread expression', () => {
|
||||||
const expressions = program.getSourceFile('expressions.ts');
|
const expressions = program.getSourceFile('expressions.ts');
|
||||||
const arrSpreadRef = findVar(expressions, 'arrSpreadRef');
|
const arrSpreadRef = findVar(expressions, 'arrSpreadRef') !;
|
||||||
expect(evaluator.evaluateNode(arrSpreadRef.initializer)).toEqual([
|
expect(evaluator.evaluateNode(arrSpreadRef.initializer !)).toEqual([
|
||||||
0, {__symbolic: 'spread', expression: {__symbolic: 'reference', name: 'arrImport'}}, 5
|
0, {__symbolic: 'spread', expression: {__symbolic: 'reference', name: 'arrImport'}}, 5
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
@ -220,8 +219,8 @@ describe('Evaluator', () => {
|
||||||
const source = sourceFileOf(`
|
const source = sourceFileOf(`
|
||||||
export var a = new f;
|
export var a = new f;
|
||||||
`);
|
`);
|
||||||
const expr = findVar(source, 'a');
|
const expr = findVar(source, 'a') !;
|
||||||
expect(evaluator.evaluateNode(expr.initializer))
|
expect(evaluator.evaluateNode(expr.initializer !))
|
||||||
.toEqual({__symbolic: 'new', expression: {__symbolic: 'reference', name: 'f'}});
|
.toEqual({__symbolic: 'new', expression: {__symbolic: 'reference', name: 'f'}});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,7 +17,7 @@ describe('Symbols', () => {
|
||||||
let symbols: Symbols;
|
let symbols: Symbols;
|
||||||
const someValue = 'some-value';
|
const someValue = 'some-value';
|
||||||
|
|
||||||
beforeEach(() => symbols = new Symbols(null));
|
beforeEach(() => symbols = new Symbols(null as any as ts.SourceFile));
|
||||||
|
|
||||||
it('should be able to add a symbol', () => symbols.define('someSymbol', someValue));
|
it('should be able to add a symbol', () => symbols.define('someSymbol', someValue));
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ describe('Symbols', () => {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
ts.forEachChild(core, visit);
|
ts.forEachChild(core !, visit);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ export class Host implements ts.LanguageServiceHost {
|
||||||
|
|
||||||
getScriptVersion(fileName: string): string { return this.version.toString(); }
|
getScriptVersion(fileName: string): string { return this.version.toString(); }
|
||||||
|
|
||||||
getScriptSnapshot(fileName: string): ts.IScriptSnapshot {
|
getScriptSnapshot(fileName: string): ts.IScriptSnapshot|undefined {
|
||||||
const content = this.getFileContent(fileName);
|
const content = this.getFileContent(fileName);
|
||||||
if (content) return ts.ScriptSnapshot.fromString(content);
|
if (content) return ts.ScriptSnapshot.fromString(content);
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ export class Host implements ts.LanguageServiceHost {
|
||||||
this.version++;
|
this.version++;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getFileContent(fileName: string): string {
|
private getFileContent(fileName: string): string|undefined {
|
||||||
if (this.overrides.has(fileName)) {
|
if (this.overrides.has(fileName)) {
|
||||||
return this.overrides.get(fileName);
|
return this.overrides.get(fileName);
|
||||||
}
|
}
|
||||||
|
@ -69,9 +69,9 @@ export class MockNode implements ts.Node {
|
||||||
constructor(
|
constructor(
|
||||||
public kind: ts.SyntaxKind = ts.SyntaxKind.Identifier, public flags: ts.NodeFlags = 0,
|
public kind: ts.SyntaxKind = ts.SyntaxKind.Identifier, public flags: ts.NodeFlags = 0,
|
||||||
public pos: number = 0, public end: number = 0) {}
|
public pos: number = 0, public end: number = 0) {}
|
||||||
getSourceFile(): ts.SourceFile { return null; }
|
getSourceFile(): ts.SourceFile { return null as any as ts.SourceFile; }
|
||||||
getChildCount(sourceFile?: ts.SourceFile): number { return 0 }
|
getChildCount(sourceFile?: ts.SourceFile): number { return 0 }
|
||||||
getChildAt(index: number, sourceFile?: ts.SourceFile): ts.Node { return null; }
|
getChildAt(index: number, sourceFile?: ts.SourceFile): ts.Node { return null as any as ts.Node; }
|
||||||
getChildren(sourceFile?: ts.SourceFile): ts.Node[] { return []; }
|
getChildren(sourceFile?: ts.SourceFile): ts.Node[] { return []; }
|
||||||
getStart(sourceFile?: ts.SourceFile): number { return 0; }
|
getStart(sourceFile?: ts.SourceFile): number { return 0; }
|
||||||
getFullStart(): number { return 0; }
|
getFullStart(): number { return 0; }
|
||||||
|
@ -81,10 +81,10 @@ export class MockNode implements ts.Node {
|
||||||
getLeadingTriviaWidth(sourceFile?: ts.SourceFile): number { return 0; }
|
getLeadingTriviaWidth(sourceFile?: ts.SourceFile): number { return 0; }
|
||||||
getFullText(sourceFile?: ts.SourceFile): string { return ''; }
|
getFullText(sourceFile?: ts.SourceFile): string { return ''; }
|
||||||
getText(sourceFile?: ts.SourceFile): string { return ''; }
|
getText(sourceFile?: ts.SourceFile): string { return ''; }
|
||||||
getFirstToken(sourceFile?: ts.SourceFile): ts.Node { return null; }
|
getFirstToken(sourceFile?: ts.SourceFile): ts.Node { return null as any as ts.Node; }
|
||||||
getLastToken(sourceFile?: ts.SourceFile): ts.Node { return null; }
|
getLastToken(sourceFile?: ts.SourceFile): ts.Node { return null as any as ts.Node; }
|
||||||
forEachChild<T>(cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T): T {
|
forEachChild<T>(cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.Node[]) => T): T {
|
||||||
return null;
|
return null as any as T;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,22 +162,28 @@ export function allChildren<T>(node: ts.Node, cb: (node: ts.Node) => T): T {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function findClass(sourceFile: ts.SourceFile, name: string): ts.ClassDeclaration {
|
export function findClass(sourceFile: ts.SourceFile, name: string): ts.ClassDeclaration|undefined {
|
||||||
return ts.forEachChild(
|
return ts.forEachChild(
|
||||||
sourceFile, node => isClass(node) && isNamed(node.name, name) ? node : undefined);
|
sourceFile, node => isClass(node) && isNamed(node.name, name) ? node : undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function findVar(sourceFile: ts.SourceFile, name: string): ts.VariableDeclaration {
|
export function findVar(sourceFile: ts.SourceFile, name: string): ts.VariableDeclaration|undefined {
|
||||||
return allChildren(
|
return allChildren(
|
||||||
sourceFile, node => isVar(node) && isNamed(node.name, name) ? node : undefined);
|
sourceFile, node => isVar(node) && isNamed(node.name, name) ? node : undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function findVarInitializer(sourceFile: ts.SourceFile, name: string): ts.Expression {
|
||||||
|
const v = findVar(sourceFile, name);
|
||||||
|
expect(v && v.initializer).toBeDefined();
|
||||||
|
return v !.initializer !;
|
||||||
|
}
|
||||||
|
|
||||||
export function isClass(node: ts.Node): node is ts.ClassDeclaration {
|
export function isClass(node: ts.Node): node is ts.ClassDeclaration {
|
||||||
return node.kind === ts.SyntaxKind.ClassDeclaration;
|
return node.kind === ts.SyntaxKind.ClassDeclaration;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isNamed(node: ts.Node, name: string): node is ts.Identifier {
|
export function isNamed(node: ts.Node | undefined, name: string): node is ts.Identifier {
|
||||||
return node.kind === ts.SyntaxKind.Identifier && (<ts.Identifier>node).text === name;
|
return !!node && node.kind === ts.SyntaxKind.Identifier && (<ts.Identifier>node).text === name;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isVar(node: ts.Node): node is ts.VariableDeclaration {
|
export function isVar(node: ts.Node): node is ts.VariableDeclaration {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"outDir": "../../dist/all/@angular/tsc-wrapped",
|
"outDir": "../../dist/all/@angular/tsc-wrapped",
|
||||||
|
"strictNullChecks": true,
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"paths": {
|
"paths": {
|
||||||
|
|
Loading…
Reference in New Issue