fix(compiler): Update types for TypeScript nullability support

This commit is contained in:
Miško Hevery 2017-03-24 09:59:58 -07:00 committed by Hans
parent d8b73e4223
commit 09d9f5fe54
118 changed files with 2086 additions and 1859 deletions

View File

@ -33,7 +33,7 @@ export class CompilerHost implements AotCompilerHost {
private resolverCache = new Map<string, ModuleMetadata[]>(); private resolverCache = new Map<string, ModuleMetadata[]>();
private bundleIndexCache = new Map<string, boolean>(); private bundleIndexCache = new Map<string, boolean>();
private bundleIndexNames = new Set<string>(); private bundleIndexNames = new Set<string>();
private moduleFileNames = new Map<string, string>(); private moduleFileNames = new Map<string, string|null>();
protected resolveModuleNameHost: CompilerHostContext; protected resolveModuleNameHost: CompilerHostContext;
constructor( constructor(
@ -71,7 +71,7 @@ export class CompilerHost implements AotCompilerHost {
moduleNameToFileName(m: string, containingFile: string): string|null { moduleNameToFileName(m: string, containingFile: string): string|null {
const key = m + ':' + (containingFile || ''); const key = m + ':' + (containingFile || '');
let result = this.moduleFileNames.get(key); let result: string|null = this.moduleFileNames.get(key) || null;
if (!result) { if (!result) {
if (!containingFile || !containingFile.length) { if (!containingFile || !containingFile.length) {
if (m.indexOf('.') === 0) { if (m.indexOf('.') === 0) {
@ -183,7 +183,7 @@ export class CompilerHost implements AotCompilerHost {
return sf; return sf;
} }
getMetadataFor(filePath: string): ModuleMetadata[] { getMetadataFor(filePath: string): ModuleMetadata[]|undefined {
if (!this.context.fileExists(filePath)) { if (!this.context.fileExists(filePath)) {
// If the file doesn't exists then we cannot return metadata for the file. // If the file doesn't exists then we cannot return metadata for the file.
// This will occur if the user refernced a declared module for which no file // This will occur if the user refernced a declared module for which no file
@ -263,6 +263,7 @@ export class CompilerHost implements AotCompilerHost {
if (this.context.fileExists(filePath)) { if (this.context.fileExists(filePath)) {
return this.context.readFile(filePath); return this.context.readFile(filePath);
} }
return null;
} }
getOutputFileName(sourceFilePath: string): string { getOutputFileName(sourceFilePath: string): string {
@ -287,7 +288,7 @@ export class CompilerHost implements AotCompilerHost {
calculateEmitPath(filePath: string): string { calculateEmitPath(filePath: string): string {
// Write codegen in a directory structure matching the sources. // Write codegen in a directory structure matching the sources.
let root = this.options.basePath; let root = this.options.basePath !;
for (const eachRootDir of this.options.rootDirs || []) { for (const eachRootDir of this.options.rootDirs || []) {
if (this.options.trace) { if (this.options.trace) {
console.error(`Check if ${filePath} is under rootDirs element ${eachRootDir}`); console.error(`Check if ${filePath} is under rootDirs element ${eachRootDir}`);
@ -373,7 +374,7 @@ export class ModuleResolutionHostAdapter extends CompilerHostContextAdapter impl
constructor(private host: ts.ModuleResolutionHost) { constructor(private host: ts.ModuleResolutionHost) {
super(); super();
if (host.directoryExists) { if (host.directoryExists) {
this.directoryExists = (directoryName: string) => host.directoryExists(directoryName); this.directoryExists = (directoryName: string) => host.directoryExists !(directoryName);
} }
} }

View File

@ -23,7 +23,7 @@ function extract(
ngOptions: tsc.AngularCompilerOptions, cliOptions: tsc.I18nExtractionCliOptions, ngOptions: tsc.AngularCompilerOptions, cliOptions: tsc.I18nExtractionCliOptions,
program: ts.Program, host: ts.CompilerHost): Promise<void> { program: ts.Program, host: ts.CompilerHost): Promise<void> {
return Extractor.create(ngOptions, program, host, cliOptions.locale) return Extractor.create(ngOptions, program, host, cliOptions.locale)
.extract(cliOptions.i18nFormat, cliOptions.outFile); .extract(cliOptions.i18nFormat !, cliOptions.outFile);
} }
// Entry point // Entry point

View File

@ -92,9 +92,9 @@ export class NgTools_InternalApi_NG_2 {
const hostContext: CompilerHostContext = const hostContext: CompilerHostContext =
new CustomLoaderModuleResolutionHostAdapter(options.readResource, options.host); new CustomLoaderModuleResolutionHostAdapter(options.readResource, options.host);
const cliOptions: NgcCliOptions = { const cliOptions: NgcCliOptions = {
i18nFormat: options.i18nFormat, i18nFormat: options.i18nFormat !,
i18nFile: options.i18nFile, i18nFile: options.i18nFile !,
locale: options.locale, locale: options.locale !,
basePath: options.basePath basePath: options.basePath
}; };
@ -148,6 +148,6 @@ export class NgTools_InternalApi_NG_2 {
const extractor = Extractor.create( const extractor = Extractor.create(
options.angularCompilerOptions, options.program, options.host, locale, hostContext); options.angularCompilerOptions, options.program, options.host, locale, hostContext);
return extractor.extract(options.i18nFormat, options.outFile || null); return extractor.extract(options.i18nFormat !, options.outFile || null);
} }
} }

View File

@ -33,7 +33,8 @@ export type LazyRouteMap = {
// A route definition. Normally the short form 'path/to/module#ModuleClassName' is used by // A route definition. Normally the short form 'path/to/module#ModuleClassName' is used by
// the user, and this is a helper class to extract information from it. // the user, and this is a helper class to extract information from it.
export class RouteDef { export class RouteDef {
private constructor(public readonly path: string, public readonly className: string = null) {} private constructor(public readonly path: string, public readonly className: string|null = null) {
}
toString() { toString() {
return (this.className === null || this.className == 'default') ? return (this.className === null || this.className == 'default') ?
@ -58,7 +59,7 @@ export function listLazyRoutesOfModule(
const entryRouteDef = RouteDef.fromString(entryModule); const entryRouteDef = RouteDef.fromString(entryModule);
const containingFile = _resolveModule(entryRouteDef.path, entryRouteDef.path, host); const containingFile = _resolveModule(entryRouteDef.path, entryRouteDef.path, host);
const modulePath = `./${containingFile.replace(/^(.*)\//, '')}`; const modulePath = `./${containingFile.replace(/^(.*)\//, '')}`;
const className = entryRouteDef.className; const className = entryRouteDef.className !;
// List loadChildren of this single module. // List loadChildren of this single module.
const appStaticSymbol = reflector.findDeclaration(modulePath, className, containingFile); const appStaticSymbol = reflector.findDeclaration(modulePath, className, containingFile);

View File

@ -40,7 +40,7 @@ export class PathMappedCompilerHost extends CompilerHost {
return fileName; return fileName;
} }
moduleNameToFileName(m: string, containingFile: string) { moduleNameToFileName(m: string, containingFile: string): string|null {
if (!containingFile || !containingFile.length) { if (!containingFile || !containingFile.length) {
if (m.indexOf('.') === 0) { if (m.indexOf('.') === 0) {
throw new Error('Resolution of relative paths requires a containing file.'); throw new Error('Resolution of relative paths requires a containing file.');
@ -59,6 +59,7 @@ export class PathMappedCompilerHost extends CompilerHost {
return this.getCanonicalFileName(resolved.resolvedFileName); return this.getCanonicalFileName(resolved.resolvedFileName);
} }
} }
return null;
} }
/** /**
@ -90,7 +91,7 @@ export class PathMappedCompilerHost extends CompilerHost {
const importModuleName = importedFile.replace(EXT, ''); const importModuleName = importedFile.replace(EXT, '');
const parts = importModuleName.split(path.sep).filter(p => !!p); const parts = importModuleName.split(path.sep).filter(p => !!p);
let foundRelativeImport: string; let foundRelativeImport: string = undefined !;
for (let index = parts.length - 1; index >= 0; index--) { for (let index = parts.length - 1; index >= 0; index--) {
let candidate = parts.slice(index, parts.length).join(path.sep); let candidate = parts.slice(index, parts.length).join(path.sep);
if (resolvable(candidate)) { if (resolvable(candidate)) {
@ -135,5 +136,6 @@ export class PathMappedCompilerHost extends CompilerHost {
return metadata ? [metadata] : []; return metadata ? [metadata] : [];
} }
} }
return null !;
} }
} }

View File

@ -4,6 +4,7 @@
"declaration": true, "declaration": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"noImplicitAny": true, "noImplicitAny": true,
"strictNullChecks": true,
"module": "commonjs", "module": "commonjs",
"outDir": "../../dist/packages/compiler-cli", "outDir": "../../dist/packages/compiler-cli",
"paths": { "paths": {

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileProviderMetadata, componentFactoryName, createHostComponentMeta, flatten, identifierName, sourceUrl, templateSourceUrl} from '../compile_metadata'; import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileProviderMetadata, CompileTypeSummary, componentFactoryName, createHostComponentMeta, flatten, identifierName, sourceUrl, templateSourceUrl} from '../compile_metadata';
import {CompilerConfig} from '../config'; import {CompilerConfig} from '../config';
import {Identifiers, createIdentifier, createIdentifierToken} from '../identifiers'; import {Identifiers, createIdentifier, createIdentifierToken} from '../identifiers';
import {CompileMetadataResolver} from '../metadata_resolver'; import {CompileMetadataResolver} from '../metadata_resolver';
@ -32,8 +32,8 @@ export class AotCompiler {
private _metadataResolver: CompileMetadataResolver, private _templateParser: TemplateParser, private _metadataResolver: CompileMetadataResolver, private _templateParser: TemplateParser,
private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler, private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler,
private _ngModuleCompiler: NgModuleCompiler, private _outputEmitter: OutputEmitter, private _ngModuleCompiler: NgModuleCompiler, private _outputEmitter: OutputEmitter,
private _summaryResolver: SummaryResolver<StaticSymbol>, private _localeId: string, private _summaryResolver: SummaryResolver<StaticSymbol>, private _localeId: string|null,
private _translationFormat: string, private _genFilePreamble: string, private _translationFormat: string|null, private _genFilePreamble: string|null,
private _symbolResolver: StaticSymbolResolver) {} private _symbolResolver: StaticSymbolResolver) {}
clearCache() { this._metadataResolver.clearCache(); } clearCache() { this._metadataResolver.clearCache(); }
@ -113,11 +113,11 @@ export class AotCompiler {
targetExportedVars: string[]): GeneratedFile { targetExportedVars: string[]): GeneratedFile {
const symbolSummaries = this._symbolResolver.getSymbolsOf(srcFileUrl) const symbolSummaries = this._symbolResolver.getSymbolsOf(srcFileUrl)
.map(symbol => this._symbolResolver.resolveSymbol(symbol)); .map(symbol => this._symbolResolver.resolveSymbol(symbol));
const typeSummaries = [ const typeSummaries: CompileTypeSummary[] = [
...ngModules.map(ref => this._metadataResolver.getNgModuleSummary(ref)), ...ngModules.map(ref => this._metadataResolver.getNgModuleSummary(ref) !),
...directives.map(ref => this._metadataResolver.getDirectiveSummary(ref)), ...directives.map(ref => this._metadataResolver.getDirectiveSummary(ref) !),
...pipes.map(ref => this._metadataResolver.getPipeSummary(ref)), ...pipes.map(ref => this._metadataResolver.getPipeSummary(ref) !),
...injectables.map(ref => this._metadataResolver.getInjectableSummary(ref)) ...injectables.map(ref => this._metadataResolver.getInjectableSummary(ref) !)
]; ];
const {json, exportAs} = serializeSummaries( const {json, exportAs} = serializeSummaries(
this._summaryResolver, this._symbolResolver, symbolSummaries, typeSummaries); this._summaryResolver, this._symbolResolver, symbolSummaries, typeSummaries);
@ -130,7 +130,7 @@ export class AotCompiler {
} }
private _compileModule(ngModuleType: StaticSymbol, targetStatements: o.Statement[]): string { private _compileModule(ngModuleType: StaticSymbol, targetStatements: o.Statement[]): string {
const ngModule = this._metadataResolver.getNgModuleMetadata(ngModuleType); const ngModule = this._metadataResolver.getNgModuleMetadata(ngModuleType) !;
const providers: CompileProviderMetadata[] = []; const providers: CompileProviderMetadata[] = [];
if (this._localeId) { if (this._localeId) {
@ -183,11 +183,11 @@ export class AotCompiler {
o.variable(hostViewFactoryVar), new o.LiteralMapExpr(inputsExprs), o.variable(hostViewFactoryVar), new o.LiteralMapExpr(inputsExprs),
new o.LiteralMapExpr(outputsExprs), new o.LiteralMapExpr(outputsExprs),
o.literalArr( o.literalArr(
compMeta.template.ngContentSelectors.map(selector => o.literal(selector))) compMeta.template !.ngContentSelectors.map(selector => o.literal(selector)))
])) ]))
.toDeclStmt( .toDeclStmt(
o.importType( o.importType(
createIdentifier(Identifiers.ComponentFactory), [o.importType(compMeta.type)], createIdentifier(Identifiers.ComponentFactory), [o.importType(compMeta.type) !],
[o.TypeModifier.Const]), [o.TypeModifier.Const]),
[o.StmtModifier.Final])); [o.StmtModifier.Final]));
return compFactoryVar; return compFactoryVar;
@ -195,7 +195,7 @@ export class AotCompiler {
private _compileComponent( private _compileComponent(
compMeta: CompileDirectiveMetadata, ngModule: CompileNgModuleMetadata, compMeta: CompileDirectiveMetadata, ngModule: CompileNgModuleMetadata,
directiveIdentifiers: CompileIdentifierMetadata[], componentStyles: CompiledStylesheet, directiveIdentifiers: CompileIdentifierMetadata[], componentStyles: CompiledStylesheet|null,
fileSuffix: string, fileSuffix: string,
targetStatements: o.Statement[]): {viewClassVar: string, compRenderTypeVar: string} { targetStatements: o.Statement[]): {viewClassVar: string, compRenderTypeVar: string} {
const directives = const directives =
@ -204,8 +204,8 @@ export class AotCompiler {
pipe => this._metadataResolver.getPipeSummary(pipe.reference)); pipe => this._metadataResolver.getPipeSummary(pipe.reference));
const {template: parsedTemplate, pipes: usedPipes} = this._templateParser.parse( const {template: parsedTemplate, pipes: usedPipes} = this._templateParser.parse(
compMeta, compMeta.template.template, directives, pipes, ngModule.schemas, compMeta, compMeta.template !.template !, directives, pipes, ngModule.schemas,
templateSourceUrl(ngModule.type, compMeta, compMeta.template)); templateSourceUrl(ngModule.type, compMeta, compMeta.template !));
const stylesExpr = componentStyles ? o.variable(componentStyles.stylesVar) : o.literalArr([]); const stylesExpr = componentStyles ? o.variable(componentStyles.stylesVar) : o.literalArr([]);
const viewResult = const viewResult =
this._viewCompiler.compileComponent(compMeta, parsedTemplate, stylesExpr, usedPipes); this._viewCompiler.compileComponent(compMeta, parsedTemplate, stylesExpr, usedPipes);
@ -221,8 +221,9 @@ export class AotCompiler {
fileUrl: string, stylesCompileResult: CompiledStylesheet, fileSuffix: string): GeneratedFile { fileUrl: string, stylesCompileResult: CompiledStylesheet, fileSuffix: string): GeneratedFile {
_resolveStyleStatements(this._symbolResolver, stylesCompileResult, fileSuffix); _resolveStyleStatements(this._symbolResolver, stylesCompileResult, fileSuffix);
return this._codegenSourceModule( return this._codegenSourceModule(
fileUrl, _stylesModuleUrl( fileUrl,
stylesCompileResult.meta.moduleUrl, stylesCompileResult.isShimmed, fileSuffix), _stylesModuleUrl(
stylesCompileResult.meta.moduleUrl !, stylesCompileResult.isShimmed, fileSuffix),
stylesCompileResult.statements, [stylesCompileResult.stylesVar]); stylesCompileResult.statements, [stylesCompileResult.stylesVar]);
} }

View File

@ -70,15 +70,16 @@ export function createAotCompiler(compilerHost: AotCompilerHost, options: AotCom
console, symbolCache, staticReflector); console, symbolCache, staticReflector);
// TODO(vicb): do not pass options.i18nFormat here // TODO(vicb): do not pass options.i18nFormat here
const importResolver = { const importResolver = {
getImportAs: (symbol: StaticSymbol) => symbolResolver.getImportAs(symbol), getImportAs: (symbol: StaticSymbol) => symbolResolver.getImportAs(symbol) !,
fileNameToModuleName: (fileName: string, containingFilePath: string) => fileNameToModuleName: (fileName: string, containingFilePath: string) =>
compilerHost.fileNameToModuleName(fileName, containingFilePath), compilerHost.fileNameToModuleName(fileName, containingFilePath),
getTypeArity: (symbol: StaticSymbol) => symbolResolver.getTypeArity(symbol) getTypeArity: (symbol: StaticSymbol) => symbolResolver.getTypeArity(symbol) !
}; };
const viewCompiler = new ViewCompiler(config, elementSchemaRegistry); const viewCompiler = new ViewCompiler(config, elementSchemaRegistry);
const compiler = new AotCompiler( const compiler = new AotCompiler(
config, compilerHost, resolver, tmplParser, new StyleCompiler(urlResolver), viewCompiler, config, compilerHost, resolver, tmplParser, new StyleCompiler(urlResolver), viewCompiler,
new NgModuleCompiler(), new TypeScriptEmitter(importResolver), summaryResolver, new NgModuleCompiler(), new TypeScriptEmitter(importResolver), summaryResolver,
options.locale, options.i18nFormat, options.genFilePreamble, symbolResolver); options.locale || null, options.i18nFormat || null, options.genFilePreamble || null,
symbolResolver);
return {compiler, reflector: staticReflector}; return {compiler, reflector: staticReflector};
} }

View File

@ -20,8 +20,7 @@ export interface AotCompilerHost extends StaticSymbolResolverHost, AotSummaryRes
* *
* See ImportResolver. * See ImportResolver.
*/ */
fileNameToModuleName(importedFilePath: string, containingFilePath: string): string fileNameToModuleName(importedFilePath: string, containingFilePath: string): string|null;
/*|null*/;
/** /**
* Loads a resource (e.g. html / css) * Loads a resource (e.g. html / css)

View File

@ -41,7 +41,7 @@ export class StaticAndDynamicReflectionCapabilities {
getter(name: string): ɵGetterFn { return this.dynamicDelegate.getter(name); } getter(name: string): ɵGetterFn { return this.dynamicDelegate.getter(name); }
setter(name: string): ɵSetterFn { return this.dynamicDelegate.setter(name); } setter(name: string): ɵSetterFn { return this.dynamicDelegate.setter(name); }
method(name: string): ɵMethodFn { return this.dynamicDelegate.method(name); } method(name: string): ɵMethodFn { return this.dynamicDelegate.method(name); }
importUri(type: any): string { return this.staticDelegate.importUri(type); } importUri(type: any): string { return this.staticDelegate.importUri(type) !; }
resourceUri(type: any): string { return this.staticDelegate.resourceUri(type); } resourceUri(type: any): string { return this.staticDelegate.resourceUri(type); }
resolveIdentifier(name: string, moduleUrl: string, members: string[], runtime: any) { resolveIdentifier(name: string, moduleUrl: string, members: string[], runtime: any) {
return this.staticDelegate.resolveIdentifier(name, moduleUrl, members); return this.staticDelegate.resolveIdentifier(name, moduleUrl, members);

View File

@ -47,7 +47,7 @@ export class StaticReflector implements ɵReflectorReader {
private symbolResolver: StaticSymbolResolver, private symbolResolver: StaticSymbolResolver,
knownMetadataClasses: {name: string, filePath: string, ctor: any}[] = [], knownMetadataClasses: {name: string, filePath: string, ctor: any}[] = [],
knownMetadataFunctions: {name: string, filePath: string, fn: any}[] = [], knownMetadataFunctions: {name: string, filePath: string, fn: any}[] = [],
private errorRecorder?: (error: any, fileName: string) => void) { private errorRecorder?: (error: any, fileName?: string) => void) {
this.initializeConversionMap(); this.initializeConversionMap();
knownMetadataClasses.forEach( knownMetadataClasses.forEach(
(kc) => this._registerDecoratorOrConstructor( (kc) => this._registerDecoratorOrConstructor(
@ -67,7 +67,7 @@ export class StaticReflector implements ɵReflectorReader {
this.annotationNames.set(Injectable, 'Injectable'); this.annotationNames.set(Injectable, 'Injectable');
} }
importUri(typeOrFunc: StaticSymbol): string { importUri(typeOrFunc: StaticSymbol): string|null {
const staticSymbol = this.findSymbolDeclaration(typeOrFunc); const staticSymbol = this.findSymbolDeclaration(typeOrFunc);
return staticSymbol ? staticSymbol.filePath : null; return staticSymbol ? staticSymbol.filePath : null;
} }
@ -129,14 +129,14 @@ export class StaticReflector implements ɵReflectorReader {
const summary = this.summaryResolver.resolveSummary(parentType); const summary = this.summaryResolver.resolveSummary(parentType);
if (summary && summary.type) { if (summary && summary.type) {
const requiredAnnotationTypes = const requiredAnnotationTypes =
this.annotationForParentClassWithSummaryKind.get(summary.type.summaryKind); this.annotationForParentClassWithSummaryKind.get(summary.type.summaryKind !) !;
const typeHasRequiredAnnotation = requiredAnnotationTypes.some( const typeHasRequiredAnnotation = requiredAnnotationTypes.some(
requiredType => ownAnnotations.some(ann => ann instanceof requiredType)); (requiredType: any) => ownAnnotations.some(ann => ann instanceof requiredType));
if (!typeHasRequiredAnnotation) { if (!typeHasRequiredAnnotation) {
this.reportError( this.reportError(
syntaxError( syntaxError(
`Class ${type.name} in ${type.filePath} extends from a ${CompileSummaryKind[summary.type.summaryKind]} in another compilation unit without duplicating the decorator. ` + `Class ${type.name} in ${type.filePath} extends from a ${CompileSummaryKind[summary.type.summaryKind!]} in another compilation unit without duplicating the decorator. ` +
`Please add a ${requiredAnnotationTypes.map(type => this.annotationNames.get(type)).join(' or ')} decorator to the class.`), `Please add a ${requiredAnnotationTypes.map((type: any) => this.annotationNames.get(type)).join(' or ')} decorator to the class.`),
type); type);
} }
} }
@ -155,7 +155,7 @@ export class StaticReflector implements ɵReflectorReader {
if (parentType) { if (parentType) {
const parentPropMetadata = this.propMetadata(parentType); const parentPropMetadata = this.propMetadata(parentType);
Object.keys(parentPropMetadata).forEach((parentProp) => { Object.keys(parentPropMetadata).forEach((parentProp) => {
propMetadata[parentProp] = parentPropMetadata[parentProp]; propMetadata ![parentProp] = parentPropMetadata[parentProp];
}); });
} }
@ -165,10 +165,10 @@ export class StaticReflector implements ɵReflectorReader {
const prop = (<any[]>propData) const prop = (<any[]>propData)
.find(a => a['__symbolic'] == 'property' || a['__symbolic'] == 'method'); .find(a => a['__symbolic'] == 'property' || a['__symbolic'] == 'method');
const decorators: any[] = []; const decorators: any[] = [];
if (propMetadata[propName]) { if (propMetadata ![propName]) {
decorators.push(...propMetadata[propName]); decorators.push(...propMetadata ![propName]);
} }
propMetadata[propName] = decorators; propMetadata ![propName] = decorators;
if (prop && prop['decorators']) { if (prop && prop['decorators']) {
decorators.push(...this.simplify(type, prop['decorators'])); decorators.push(...this.simplify(type, prop['decorators']));
} }
@ -206,7 +206,7 @@ export class StaticReflector implements ɵReflectorReader {
if (decorators) { if (decorators) {
nestedResult.push(...decorators); nestedResult.push(...decorators);
} }
parameters.push(nestedResult); parameters !.push(nestedResult);
}); });
} else if (parentType) { } else if (parentType) {
parameters = this.parameters(parentType); parameters = this.parameters(parentType);
@ -232,7 +232,7 @@ export class StaticReflector implements ɵReflectorReader {
if (parentType) { if (parentType) {
const parentMethodNames = this._methodNames(parentType); const parentMethodNames = this._methodNames(parentType);
Object.keys(parentMethodNames).forEach((parentProp) => { Object.keys(parentMethodNames).forEach((parentProp) => {
methodNames[parentProp] = parentMethodNames[parentProp]; methodNames ![parentProp] = parentMethodNames[parentProp];
}); });
} }
@ -240,14 +240,14 @@ export class StaticReflector implements ɵReflectorReader {
Object.keys(members).forEach((propName) => { Object.keys(members).forEach((propName) => {
const propData = members[propName]; const propData = members[propName];
const isMethod = (<any[]>propData).some(a => a['__symbolic'] == 'method'); const isMethod = (<any[]>propData).some(a => a['__symbolic'] == 'method');
methodNames[propName] = methodNames[propName] || isMethod; methodNames ![propName] = methodNames ![propName] || isMethod;
}); });
this.methodCache.set(type, methodNames); this.methodCache.set(type, methodNames);
} }
return methodNames; return methodNames;
} }
private findParentType(type: StaticSymbol, classMetadata: any): StaticSymbol|null { private findParentType(type: StaticSymbol, classMetadata: any): StaticSymbol|undefined {
const parentType = this.trySimplify(type, classMetadata['extends']); const parentType = this.trySimplify(type, classMetadata['extends']);
if (parentType instanceof StaticSymbol) { if (parentType instanceof StaticSymbol) {
return parentType; return parentType;

View File

@ -31,14 +31,14 @@ export interface StaticSymbolResolverHost {
* @param modulePath is a string identifier for a module as an absolute path. * @param modulePath is a string identifier for a module as an absolute path.
* @returns the metadata for the given module. * @returns the metadata for the given module.
*/ */
getMetadataFor(modulePath: string): {[key: string]: any}[]; getMetadataFor(modulePath: string): {[key: string]: any}[]|undefined;
/** /**
* Converts a module name that is used in an `import` to a file path. * Converts a module name that is used in an `import` to a file path.
* I.e. * I.e.
* `path/to/containingFile.ts` containing `import {...} from 'module-name'`. * `path/to/containingFile.ts` containing `import {...} from 'module-name'`.
*/ */
moduleNameToFileName(moduleName: string, containingFile: string): string /*|null*/; moduleNameToFileName(moduleName: string, containingFile?: string): string|null;
} }
const SUPPORTED_SCHEMA_VERSION = 3; const SUPPORTED_SCHEMA_VERSION = 3;
@ -64,17 +64,17 @@ export class StaticSymbolResolver {
constructor( constructor(
private host: StaticSymbolResolverHost, private staticSymbolCache: StaticSymbolCache, private host: StaticSymbolResolverHost, private staticSymbolCache: StaticSymbolCache,
private summaryResolver: SummaryResolver<StaticSymbol>, private summaryResolver: SummaryResolver<StaticSymbol>,
private errorRecorder?: (error: any, fileName: string) => void) {} private errorRecorder?: (error: any, fileName?: string) => void) {}
resolveSymbol(staticSymbol: StaticSymbol): ResolvedStaticSymbol { resolveSymbol(staticSymbol: StaticSymbol): ResolvedStaticSymbol {
if (staticSymbol.members.length > 0) { if (staticSymbol.members.length > 0) {
return this._resolveSymbolMembers(staticSymbol); return this._resolveSymbolMembers(staticSymbol) !;
} }
let result = this.resolvedSymbols.get(staticSymbol); let result = this.resolvedSymbols.get(staticSymbol);
if (result) { if (result) {
return result; return result;
} }
result = this._resolveSymbolFromSummary(staticSymbol); result = this._resolveSymbolFromSummary(staticSymbol) !;
if (result) { if (result) {
return result; return result;
} }
@ -82,7 +82,7 @@ export class StaticSymbolResolver {
// have summaries, only .d.ts files. So we always need to check both, the summary // have summaries, only .d.ts files. So we always need to check both, the summary
// and metadata. // and metadata.
this._createSymbolsOf(staticSymbol.filePath); this._createSymbolsOf(staticSymbol.filePath);
result = this.resolvedSymbols.get(staticSymbol); result = this.resolvedSymbols.get(staticSymbol) !;
return result; return result;
} }
@ -95,7 +95,7 @@ export class StaticSymbolResolver {
* *
* @param staticSymbol the symbol for which to generate a import symbol * @param staticSymbol the symbol for which to generate a import symbol
*/ */
getImportAs(staticSymbol: StaticSymbol): StaticSymbol { getImportAs(staticSymbol: StaticSymbol): StaticSymbol|null {
if (staticSymbol.members.length) { if (staticSymbol.members.length) {
const baseSymbol = this.getStaticSymbol(staticSymbol.filePath, staticSymbol.name); const baseSymbol = this.getStaticSymbol(staticSymbol.filePath, staticSymbol.name);
const baseImportAs = this.getImportAs(baseSymbol); const baseImportAs = this.getImportAs(baseSymbol);
@ -105,7 +105,7 @@ export class StaticSymbolResolver {
} }
let result = this.summaryResolver.getImportAs(staticSymbol); let result = this.summaryResolver.getImportAs(staticSymbol);
if (!result) { if (!result) {
result = this.importAs.get(staticSymbol); result = this.importAs.get(staticSymbol) !;
} }
return result; return result;
} }
@ -123,7 +123,7 @@ export class StaticSymbolResolver {
* getTypeArity returns the number of generic type parameters the given symbol * getTypeArity returns the number of generic type parameters the given symbol
* has. If the symbol is not a type the result is null. * has. If the symbol is not a type the result is null.
*/ */
getTypeArity(staticSymbol: StaticSymbol): number /*|null*/ { getTypeArity(staticSymbol: StaticSymbol): number|null {
// If the file is a factory file, don't resolve the symbol as doing so would // If the file is a factory file, don't resolve the symbol as doing so would
// cause the metadata for an factory file to be loaded which doesn't exist. // cause the metadata for an factory file to be loaded which doesn't exist.
// All references to generated classes must include the correct arity whenever // All references to generated classes must include the correct arity whenever
@ -163,7 +163,7 @@ export class StaticSymbolResolver {
} }
} }
private _resolveSymbolMembers(staticSymbol: StaticSymbol): ResolvedStaticSymbol { private _resolveSymbolMembers(staticSymbol: StaticSymbol): ResolvedStaticSymbol|null {
const members = staticSymbol.members; const members = staticSymbol.members;
const baseResolvedSymbol = const baseResolvedSymbol =
this.resolveSymbol(this.getStaticSymbol(staticSymbol.filePath, staticSymbol.name)); this.resolveSymbol(this.getStaticSymbol(staticSymbol.filePath, staticSymbol.name));
@ -188,7 +188,7 @@ export class StaticSymbolResolver {
return null; return null;
} }
private _resolveSymbolFromSummary(staticSymbol: StaticSymbol): ResolvedStaticSymbol { private _resolveSymbolFromSummary(staticSymbol: StaticSymbol): ResolvedStaticSymbol|null {
const summary = this.summaryResolver.resolveSummary(staticSymbol); const summary = this.summaryResolver.resolveSummary(staticSymbol);
return summary ? new ResolvedStaticSymbol(staticSymbol, summary.metadata) : null; return summary ? new ResolvedStaticSymbol(staticSymbol, summary.metadata) : null;
} }
@ -252,7 +252,7 @@ export class StaticSymbolResolver {
const originFilePath = this.resolveModule(origin, filePath); const originFilePath = this.resolveModule(origin, filePath);
if (!originFilePath) { if (!originFilePath) {
this.reportError( this.reportError(
new Error(`Couldn't resolve original symbol for ${origin} from ${filePath}`), null); new Error(`Couldn't resolve original symbol for ${origin} from ${filePath}`));
} else { } else {
this.symbolResourcePaths.set(symbol, originFilePath); this.symbolResourcePaths.set(symbol, originFilePath);
} }
@ -337,7 +337,7 @@ export class StaticSymbolResolver {
} }
let filePath: string; let filePath: string;
if (module) { if (module) {
filePath = self.resolveModule(module, sourceSymbol.filePath); filePath = self.resolveModule(module, sourceSymbol.filePath) !;
if (!filePath) { if (!filePath) {
return { return {
__symbolic: 'error', __symbolic: 'error',
@ -381,7 +381,7 @@ export class StaticSymbolResolver {
return new ResolvedStaticSymbol(sourceSymbol, targetSymbol); return new ResolvedStaticSymbol(sourceSymbol, targetSymbol);
} }
private reportError(error: Error, context: StaticSymbol, path?: string) { private reportError(error: Error, context?: StaticSymbol, path?: string) {
if (this.errorRecorder) { if (this.errorRecorder) {
this.errorRecorder(error, (context && context.filePath) || path); this.errorRecorder(error, (context && context.filePath) || path);
} else { } else {
@ -413,7 +413,7 @@ export class StaticSymbolResolver {
const errorMessage = moduleMetadata['version'] == 2 ? const errorMessage = moduleMetadata['version'] == 2 ?
`Unsupported metadata version ${moduleMetadata['version']} for module ${module}. This module should be compiled with a newer version of ngc` : `Unsupported metadata version ${moduleMetadata['version']} for module ${module}. This module should be compiled with a newer version of ngc` :
`Metadata version mismatch for module ${module}, found version ${moduleMetadata['version']}, expected ${SUPPORTED_SCHEMA_VERSION}`; `Metadata version mismatch for module ${module}, found version ${moduleMetadata['version']}, expected ${SUPPORTED_SCHEMA_VERSION}`;
this.reportError(new Error(errorMessage), null); this.reportError(new Error(errorMessage));
} }
this.metadataCache.set(module, moduleMetadata); this.metadataCache.set(module, moduleMetadata);
} }
@ -426,20 +426,20 @@ export class StaticSymbolResolver {
this.reportError( this.reportError(
new Error(`Could not resolve module ${module}${containingFile ? ` relative to $ { new Error(`Could not resolve module ${module}${containingFile ? ` relative to $ {
containingFile containingFile
} `: ''}`), } `: ''}`));
null);
return this.getStaticSymbol(`ERROR:${module}`, symbolName); return this.getStaticSymbol(`ERROR:${module}`, symbolName);
} }
return this.getStaticSymbol(filePath, symbolName); return this.getStaticSymbol(filePath, symbolName);
} }
private resolveModule(module: string, containingFile: string): string { private resolveModule(module: string, containingFile?: string): string|null {
try { try {
return this.host.moduleNameToFileName(module, containingFile); return this.host.moduleNameToFileName(module, containingFile);
} catch (e) { } catch (e) {
console.error(`Could not resolve module '${module}' relative to file ${containingFile}`); console.error(`Could not resolve module '${module}' relative to file ${containingFile}`);
this.reportError(e, null, containingFile); this.reportError(e, undefined, containingFile);
} }
return null;
} }
} }
@ -447,4 +447,4 @@ export class StaticSymbolResolver {
// See https://github.com/Microsoft/TypeScript/blob/master/src/compiler/utilities.ts // See https://github.com/Microsoft/TypeScript/blob/master/src/compiler/utilities.ts
export function unescapeIdentifier(identifier: string): string { export function unescapeIdentifier(identifier: string): string {
return identifier.startsWith('___') ? identifier.substr(1) : identifier; return identifier.startsWith('___') ? identifier.substr(1) : identifier;
} }

View File

@ -16,7 +16,7 @@ export interface AotSummaryResolverHost {
/** /**
* Loads an NgModule/Directive/Pipe summary file * Loads an NgModule/Directive/Pipe summary file
*/ */
loadSummary(filePath: string): string /*|null*/; loadSummary(filePath: string): string|null;
/** /**
* Returns whether a file is a source file or not. * Returns whether a file is a source file or not.
@ -53,7 +53,7 @@ export class AotSummaryResolver implements SummaryResolver<StaticSymbol> {
let summary = this.summaryCache.get(staticSymbol); let summary = this.summaryCache.get(staticSymbol);
if (!summary) { if (!summary) {
this._loadSummaryFile(staticSymbol.filePath); this._loadSummaryFile(staticSymbol.filePath);
summary = this.summaryCache.get(staticSymbol); summary = this.summaryCache.get(staticSymbol) !;
} }
return summary; return summary;
} }
@ -65,7 +65,7 @@ export class AotSummaryResolver implements SummaryResolver<StaticSymbol> {
getImportAs(staticSymbol: StaticSymbol): StaticSymbol { getImportAs(staticSymbol: StaticSymbol): StaticSymbol {
staticSymbol.assertNoMembers(); staticSymbol.assertNoMembers();
return this.importAs.get(staticSymbol); return this.importAs.get(staticSymbol) !;
} }
private _loadSummaryFile(filePath: string) { private _loadSummaryFile(filePath: string) {
@ -75,7 +75,7 @@ export class AotSummaryResolver implements SummaryResolver<StaticSymbol> {
this.loadedFilePaths.add(filePath); this.loadedFilePaths.add(filePath);
if (this.isLibraryFile(filePath)) { if (this.isLibraryFile(filePath)) {
const summaryFilePath = summaryFileName(filePath); const summaryFilePath = summaryFileName(filePath);
let json: string; let json: string|null;
try { try {
json = this.host.loadSummary(summaryFilePath); json = this.host.loadSummary(summaryFilePath);
} catch (e) { } catch (e) {

View File

@ -133,7 +133,7 @@ class Serializer extends ValueTransformer {
summaries: this.processedSummaries, summaries: this.processedSummaries,
symbols: this.symbols.map((symbol, index) => { symbols: this.symbols.map((symbol, index) => {
symbol.assertNoMembers(); symbol.assertNoMembers();
let importAs: string; let importAs: string = undefined !;
if (this.summaryResolver.isLibraryFile(symbol.filePath)) { if (this.summaryResolver.isLibraryFile(symbol.filePath)) {
importAs = `${symbol.name}_${index}`; importAs = `${symbol.name}_${index}`;
exportAs.push({symbol, exportAs: importAs}); exportAs.push({symbol, exportAs: importAs});

View File

@ -22,7 +22,8 @@ const HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))|(\@[-\w]+)$/;
export class CompileAnimationEntryMetadata { export class CompileAnimationEntryMetadata {
constructor( constructor(
public name: string = null, public definitions: CompileAnimationStateMetadata[] = null) {} public name: string|null = null,
public definitions: CompileAnimationStateMetadata[]|null = null) {}
} }
export abstract class CompileAnimationStateMetadata {} export abstract class CompileAnimationStateMetadata {}
@ -49,7 +50,8 @@ export class CompileAnimationKeyframesSequenceMetadata extends CompileAnimationM
export class CompileAnimationStyleMetadata extends CompileAnimationMetadata { export class CompileAnimationStyleMetadata extends CompileAnimationMetadata {
constructor( constructor(
public offset: number, public styles: Array<string|{[key: string]: string | number}> = null) { public offset: number,
public styles: Array<string|{[key: string]: string | number}>|null = null) {
super(); super();
} }
} }
@ -57,21 +59,21 @@ export class CompileAnimationStyleMetadata extends CompileAnimationMetadata {
export class CompileAnimationAnimateMetadata extends CompileAnimationMetadata { export class CompileAnimationAnimateMetadata extends CompileAnimationMetadata {
constructor( constructor(
public timings: string|number = 0, public styles: CompileAnimationStyleMetadata| public timings: string|number = 0, public styles: CompileAnimationStyleMetadata|
CompileAnimationKeyframesSequenceMetadata = null) { CompileAnimationKeyframesSequenceMetadata|null = null) {
super(); super();
} }
} }
export abstract class CompileAnimationWithStepsMetadata extends CompileAnimationMetadata { export abstract class CompileAnimationWithStepsMetadata extends CompileAnimationMetadata {
constructor(public steps: CompileAnimationMetadata[] = null) { super(); } constructor(public steps: CompileAnimationMetadata[]|null = null) { super(); }
} }
export class CompileAnimationSequenceMetadata extends CompileAnimationWithStepsMetadata { export class CompileAnimationSequenceMetadata extends CompileAnimationWithStepsMetadata {
constructor(steps: CompileAnimationMetadata[] = null) { super(steps); } constructor(steps: CompileAnimationMetadata[]|null = null) { super(steps); }
} }
export class CompileAnimationGroupMetadata extends CompileAnimationWithStepsMetadata { export class CompileAnimationGroupMetadata extends CompileAnimationWithStepsMetadata {
constructor(steps: CompileAnimationMetadata[] = null) { super(steps); } constructor(steps: CompileAnimationMetadata[]|null = null) { super(steps); }
} }
@ -81,7 +83,8 @@ function _sanitizeIdentifier(name: string): string {
let _anonymousTypeIndex = 0; let _anonymousTypeIndex = 0;
export function identifierName(compileIdentifier: CompileIdentifierMetadata): string { export function identifierName(compileIdentifier: CompileIdentifierMetadata | null | undefined):
string|null {
if (!compileIdentifier || !compileIdentifier.reference) { if (!compileIdentifier || !compileIdentifier.reference) {
return null; return null;
} }
@ -148,7 +151,7 @@ export enum CompileSummaryKind {
* the directive / module itself. * the directive / module itself.
*/ */
export interface CompileTypeSummary { export interface CompileTypeSummary {
summaryKind: CompileSummaryKind; summaryKind: CompileSummaryKind|null;
type: CompileTypeMetadata; type: CompileTypeMetadata;
} }
@ -216,13 +219,13 @@ export interface CompileQueryMetadata {
* Metadata about a stylesheet * Metadata about a stylesheet
*/ */
export class CompileStylesheetMetadata { export class CompileStylesheetMetadata {
moduleUrl: string; moduleUrl: string|null;
styles: string[]; styles: string[];
styleUrls: string[]; styleUrls: string[];
constructor( constructor(
{moduleUrl, styles, {moduleUrl, styles,
styleUrls}: {moduleUrl?: string, styles?: string[], styleUrls?: string[]} = {}) { styleUrls}: {moduleUrl?: string, styles?: string[], styleUrls?: string[]} = {}) {
this.moduleUrl = moduleUrl; this.moduleUrl = moduleUrl || null;
this.styles = _normalizeArray(styles); this.styles = _normalizeArray(styles);
this.styleUrls = _normalizeArray(styleUrls); this.styleUrls = _normalizeArray(styleUrls);
} }
@ -232,39 +235,38 @@ export class CompileStylesheetMetadata {
* Summary Metadata regarding compilation of a template. * Summary Metadata regarding compilation of a template.
*/ */
export interface CompileTemplateSummary { export interface CompileTemplateSummary {
animations: string[]; animations: string[]|null;
ngContentSelectors: string[]; ngContentSelectors: string[];
encapsulation: ViewEncapsulation; encapsulation: ViewEncapsulation|null;
} }
/** /**
* Metadata regarding compilation of a template. * Metadata regarding compilation of a template.
*/ */
export class CompileTemplateMetadata { export class CompileTemplateMetadata {
encapsulation: ViewEncapsulation; encapsulation: ViewEncapsulation|null;
template: string; template: string|null;
templateUrl: string; templateUrl: string|null;
isInline: boolean; isInline: boolean;
styles: string[]; styles: string[];
styleUrls: string[]; styleUrls: string[];
externalStylesheets: CompileStylesheetMetadata[]; externalStylesheets: CompileStylesheetMetadata[];
animations: any[]; animations: any[];
ngContentSelectors: string[]; ngContentSelectors: string[];
interpolation: [string, string]; interpolation: [string, string]|null;
constructor( constructor({encapsulation, template, templateUrl, styles, styleUrls, externalStylesheets,
{encapsulation, template, templateUrl, styles, styleUrls, externalStylesheets, animations, animations, ngContentSelectors, interpolation, isInline}: {
ngContentSelectors, interpolation, isInline}: { encapsulation: ViewEncapsulation | null,
encapsulation?: ViewEncapsulation, template: string|null,
template?: string, templateUrl: string|null,
templateUrl?: string, styles: string[],
styles?: string[], styleUrls: string[],
styleUrls?: string[], externalStylesheets: CompileStylesheetMetadata[],
externalStylesheets?: CompileStylesheetMetadata[], ngContentSelectors: string[],
ngContentSelectors?: string[], animations: any[],
animations?: any[], interpolation: [string, string]|null,
interpolation?: [string, string], isInline: boolean
isInline?: boolean }) {
} = {}) {
this.encapsulation = encapsulation; this.encapsulation = encapsulation;
this.template = template; this.template = template;
this.templateUrl = templateUrl; this.templateUrl = templateUrl;
@ -299,8 +301,8 @@ export interface CompileEntryComponentMetadata {
export interface CompileDirectiveSummary extends CompileTypeSummary { export interface CompileDirectiveSummary extends CompileTypeSummary {
type: CompileTypeMetadata; type: CompileTypeMetadata;
isComponent: boolean; isComponent: boolean;
selector: string; selector: string|null;
exportAs: string; exportAs: string|null;
inputs: {[key: string]: string}; inputs: {[key: string]: string};
outputs: {[key: string]: string}; outputs: {[key: string]: string};
hostListeners: {[key: string]: string}; hostListeners: {[key: string]: string};
@ -311,40 +313,39 @@ export interface CompileDirectiveSummary extends CompileTypeSummary {
queries: CompileQueryMetadata[]; queries: CompileQueryMetadata[];
viewQueries: CompileQueryMetadata[]; viewQueries: CompileQueryMetadata[];
entryComponents: CompileEntryComponentMetadata[]; entryComponents: CompileEntryComponentMetadata[];
changeDetection: ChangeDetectionStrategy; changeDetection: ChangeDetectionStrategy|null;
template: CompileTemplateSummary; template: CompileTemplateSummary|null;
componentViewType: StaticSymbol|ProxyClass; componentViewType: StaticSymbol|ProxyClass|null;
rendererType: StaticSymbol|RendererType2; rendererType: StaticSymbol|RendererType2|null;
componentFactory: StaticSymbol|ComponentFactory<any>; componentFactory: StaticSymbol|ComponentFactory<any>|null;
} }
/** /**
* Metadata regarding compilation of a directive. * Metadata regarding compilation of a directive.
*/ */
export class CompileDirectiveMetadata { export class CompileDirectiveMetadata {
static create( static create({isHost, type, isComponent, selector, exportAs, changeDetection, inputs, outputs,
{isHost, type, isComponent, selector, exportAs, changeDetection, inputs, outputs, host, host, providers, viewProviders, queries, viewQueries, entryComponents, template,
providers, viewProviders, queries, viewQueries, entryComponents, template, componentViewType, componentViewType, rendererType, componentFactory}: {
rendererType, componentFactory}: { isHost: boolean,
isHost?: boolean, type: CompileTypeMetadata,
type?: CompileTypeMetadata, isComponent: boolean,
isComponent?: boolean, selector: string|null,
selector?: string, exportAs: string|null,
exportAs?: string, changeDetection: ChangeDetectionStrategy|null,
changeDetection?: ChangeDetectionStrategy, inputs: string[],
inputs?: string[], outputs: string[],
outputs?: string[], host: {[key: string]: string},
host?: {[key: string]: string}, providers: CompileProviderMetadata[],
providers?: CompileProviderMetadata[], viewProviders: CompileProviderMetadata[],
viewProviders?: CompileProviderMetadata[], queries: CompileQueryMetadata[],
queries?: CompileQueryMetadata[], viewQueries: CompileQueryMetadata[],
viewQueries?: CompileQueryMetadata[], entryComponents: CompileEntryComponentMetadata[],
entryComponents?: CompileEntryComponentMetadata[], template: CompileTemplateMetadata,
template?: CompileTemplateMetadata, componentViewType: StaticSymbol|ProxyClass|null,
componentViewType?: StaticSymbol|ProxyClass, rendererType: StaticSymbol|RendererType2|null,
rendererType?: StaticSymbol|RendererType2, componentFactory: StaticSymbol|ComponentFactory<any>|null,
componentFactory?: StaticSymbol|ComponentFactory<any>, }): CompileDirectiveMetadata {
} = {}): CompileDirectiveMetadata {
const hostListeners: {[key: string]: string} = {}; const hostListeners: {[key: string]: string} = {};
const hostProperties: {[key: string]: string} = {}; const hostProperties: {[key: string]: string} = {};
const hostAttributes: {[key: string]: string} = {}; const hostAttributes: {[key: string]: string} = {};
@ -403,9 +404,9 @@ export class CompileDirectiveMetadata {
isHost: boolean; isHost: boolean;
type: CompileTypeMetadata; type: CompileTypeMetadata;
isComponent: boolean; isComponent: boolean;
selector: string; selector: string|null;
exportAs: string; exportAs: string|null;
changeDetection: ChangeDetectionStrategy; changeDetection: ChangeDetectionStrategy|null;
inputs: {[key: string]: string}; inputs: {[key: string]: string};
outputs: {[key: string]: string}; outputs: {[key: string]: string};
hostListeners: {[key: string]: string}; hostListeners: {[key: string]: string};
@ -417,37 +418,37 @@ export class CompileDirectiveMetadata {
viewQueries: CompileQueryMetadata[]; viewQueries: CompileQueryMetadata[];
entryComponents: CompileEntryComponentMetadata[]; entryComponents: CompileEntryComponentMetadata[];
template: CompileTemplateMetadata; template: CompileTemplateMetadata|null;
componentViewType: StaticSymbol|ProxyClass; componentViewType: StaticSymbol|ProxyClass|null;
rendererType: StaticSymbol|RendererType2; rendererType: StaticSymbol|RendererType2|null;
componentFactory: StaticSymbol|ComponentFactory<any>; componentFactory: StaticSymbol|ComponentFactory<any>|null;
constructor({isHost, type, isComponent, selector, exportAs, constructor({isHost, type, isComponent, selector, exportAs,
changeDetection, inputs, outputs, hostListeners, hostProperties, changeDetection, inputs, outputs, hostListeners, hostProperties,
hostAttributes, providers, viewProviders, queries, viewQueries, hostAttributes, providers, viewProviders, queries, viewQueries,
entryComponents, template, componentViewType, rendererType, componentFactory}: { entryComponents, template, componentViewType, rendererType, componentFactory}: {
isHost?: boolean, isHost: boolean,
type?: CompileTypeMetadata, type: CompileTypeMetadata,
isComponent?: boolean, isComponent: boolean,
selector?: string, selector: string|null,
exportAs?: string, exportAs: string|null,
changeDetection?: ChangeDetectionStrategy, changeDetection: ChangeDetectionStrategy|null,
inputs?: {[key: string]: string}, inputs: {[key: string]: string},
outputs?: {[key: string]: string}, outputs: {[key: string]: string},
hostListeners?: {[key: string]: string}, hostListeners: {[key: string]: string},
hostProperties?: {[key: string]: string}, hostProperties: {[key: string]: string},
hostAttributes?: {[key: string]: string}, hostAttributes: {[key: string]: string},
providers?: CompileProviderMetadata[], providers: CompileProviderMetadata[],
viewProviders?: CompileProviderMetadata[], viewProviders: CompileProviderMetadata[],
queries?: CompileQueryMetadata[], queries: CompileQueryMetadata[],
viewQueries?: CompileQueryMetadata[], viewQueries: CompileQueryMetadata[],
entryComponents?: CompileEntryComponentMetadata[], entryComponents: CompileEntryComponentMetadata[],
template?: CompileTemplateMetadata, template: CompileTemplateMetadata|null,
componentViewType?: StaticSymbol|ProxyClass, componentViewType: StaticSymbol|ProxyClass|null,
rendererType?: StaticSymbol|RendererType2, rendererType: StaticSymbol|RendererType2|null,
componentFactory?: StaticSymbol|ComponentFactory<any>, componentFactory: StaticSymbol|ComponentFactory<any>|null,
} = {}) { }) {
this.isHost = !!isHost; this.isHost = !!isHost;
this.type = type; this.type = type;
this.isComponent = isComponent; this.isComponent = isComponent;
@ -503,7 +504,7 @@ export class CompileDirectiveMetadata {
export function createHostComponentMeta( export function createHostComponentMeta(
hostTypeReference: any, compMeta: CompileDirectiveMetadata, hostTypeReference: any, compMeta: CompileDirectiveMetadata,
hostViewType: StaticSymbol | ProxyClass): CompileDirectiveMetadata { hostViewType: StaticSymbol | ProxyClass): CompileDirectiveMetadata {
const template = CssSelector.parse(compMeta.selector)[0].getMatchingElementTemplate(); const template = CssSelector.parse(compMeta.selector !)[0].getMatchingElementTemplate();
return CompileDirectiveMetadata.create({ return CompileDirectiveMetadata.create({
isHost: true, isHost: true,
type: {reference: hostTypeReference, diDeps: [], lifecycleHooks: []}, type: {reference: hostTypeReference, diDeps: [], lifecycleHooks: []},
@ -516,7 +517,10 @@ export function createHostComponentMeta(
ngContentSelectors: [], ngContentSelectors: [],
animations: [], animations: [],
isInline: true, isInline: true,
externalStylesheets: [],
interpolation: null
}), }),
exportAs: null,
changeDetection: ChangeDetectionStrategy.Default, changeDetection: ChangeDetectionStrategy.Default,
inputs: [], inputs: [],
outputs: [], outputs: [],
@ -528,7 +532,9 @@ export function createHostComponentMeta(
queries: [], queries: [],
viewQueries: [], viewQueries: [],
componentViewType: hostViewType, componentViewType: hostViewType,
rendererType: {id: '__Host__', encapsulation: ViewEncapsulation.None, styles: [], data: {}} rendererType: {id: '__Host__', encapsulation: ViewEncapsulation.None, styles: [], data: {}},
entryComponents: [],
componentFactory: null
}); });
} }
@ -544,10 +550,10 @@ export class CompilePipeMetadata {
pure: boolean; pure: boolean;
constructor({type, name, pure}: { constructor({type, name, pure}: {
type?: CompileTypeMetadata, type: CompileTypeMetadata,
name?: string, name: string,
pure?: boolean, pure: boolean,
} = {}) { }) {
this.type = type; this.type = type;
this.name = name; this.name = name;
this.pure = !!pure; this.pure = !!pure;
@ -598,29 +604,28 @@ export class CompileNgModuleMetadata {
importedModules: CompileNgModuleSummary[]; importedModules: CompileNgModuleSummary[];
exportedModules: CompileNgModuleSummary[]; exportedModules: CompileNgModuleSummary[];
schemas: SchemaMetadata[]; schemas: SchemaMetadata[];
id: string; id: string|null;
transitiveModule: TransitiveCompileNgModuleMetadata; transitiveModule: TransitiveCompileNgModuleMetadata;
constructor( constructor({type, providers, declaredDirectives, exportedDirectives, declaredPipes,
{type, providers, declaredDirectives, exportedDirectives, declaredPipes, exportedPipes, exportedPipes, entryComponents, bootstrapComponents, importedModules,
entryComponents, bootstrapComponents, importedModules, exportedModules, schemas, exportedModules, schemas, transitiveModule, id}: {
transitiveModule, id}: { type: CompileTypeMetadata,
type?: CompileTypeMetadata, providers: CompileProviderMetadata[],
providers?: CompileProviderMetadata[], declaredDirectives: CompileIdentifierMetadata[],
declaredDirectives?: CompileIdentifierMetadata[], exportedDirectives: CompileIdentifierMetadata[],
exportedDirectives?: CompileIdentifierMetadata[], declaredPipes: CompileIdentifierMetadata[],
declaredPipes?: CompileIdentifierMetadata[], exportedPipes: CompileIdentifierMetadata[],
exportedPipes?: CompileIdentifierMetadata[], entryComponents: CompileEntryComponentMetadata[],
entryComponents?: CompileEntryComponentMetadata[], bootstrapComponents: CompileIdentifierMetadata[],
bootstrapComponents?: CompileIdentifierMetadata[], importedModules: CompileNgModuleSummary[],
importedModules?: CompileNgModuleSummary[], exportedModules: CompileNgModuleSummary[],
exportedModules?: CompileNgModuleSummary[], transitiveModule: TransitiveCompileNgModuleMetadata,
transitiveModule?: TransitiveCompileNgModuleMetadata, schemas: SchemaMetadata[],
schemas?: SchemaMetadata[], id: string|null
id?: string }) {
} = {}) { this.type = type || null;
this.type = type;
this.declaredDirectives = _normalizeArray(declaredDirectives); this.declaredDirectives = _normalizeArray(declaredDirectives);
this.exportedDirectives = _normalizeArray(exportedDirectives); this.exportedDirectives = _normalizeArray(exportedDirectives);
this.declaredPipes = _normalizeArray(declaredPipes); this.declaredPipes = _normalizeArray(declaredPipes);
@ -631,19 +636,20 @@ export class CompileNgModuleMetadata {
this.importedModules = _normalizeArray(importedModules); this.importedModules = _normalizeArray(importedModules);
this.exportedModules = _normalizeArray(exportedModules); this.exportedModules = _normalizeArray(exportedModules);
this.schemas = _normalizeArray(schemas); this.schemas = _normalizeArray(schemas);
this.id = id; this.id = id || null;
this.transitiveModule = transitiveModule; this.transitiveModule = transitiveModule || null;
} }
toSummary(): CompileNgModuleSummary { toSummary(): CompileNgModuleSummary {
const module = this.transitiveModule !;
return { return {
summaryKind: CompileSummaryKind.NgModule, summaryKind: CompileSummaryKind.NgModule,
type: this.type, type: this.type,
entryComponents: this.transitiveModule.entryComponents, entryComponents: module.entryComponents,
providers: this.transitiveModule.providers, providers: module.providers,
modules: this.transitiveModule.modules, modules: module.modules,
exportedDirectives: this.transitiveModule.exportedDirectives, exportedDirectives: module.exportedDirectives,
exportedPipes: this.transitiveModule.exportedPipes exportedPipes: module.exportedPipes
}; };
} }
} }
@ -706,33 +712,33 @@ export class TransitiveCompileNgModuleMetadata {
} }
} }
function _normalizeArray(obj: any[]): any[] { function _normalizeArray(obj: any[] | undefined | null): any[] {
return obj || []; return obj || [];
} }
export class ProviderMeta { export class ProviderMeta {
token: any; token: any;
useClass: Type<any>; useClass: Type<any>|null;
useValue: any; useValue: any;
useExisting: any; useExisting: any;
useFactory: Function; useFactory: Function|null;
dependencies: Object[]; dependencies: Object[]|null;
multi: boolean; multi: boolean;
constructor(token: any, {useClass, useValue, useExisting, useFactory, deps, multi}: { constructor(token: any, {useClass, useValue, useExisting, useFactory, deps, multi}: {
useClass?: Type<any>, useClass?: Type<any>,
useValue?: any, useValue?: any,
useExisting?: any, useExisting?: any,
useFactory?: Function, useFactory?: Function|null,
deps?: Object[], deps?: Object[]|null,
multi?: boolean multi?: boolean
}) { }) {
this.token = token; this.token = token;
this.useClass = useClass; this.useClass = useClass || null;
this.useValue = useValue; this.useValue = useValue;
this.useExisting = useExisting; this.useExisting = useExisting;
this.useFactory = useFactory; this.useFactory = useFactory || null;
this.dependencies = deps; this.dependencies = deps || null;
this.multi = !!multi; this.multi = !!multi;
} }
} }
@ -752,7 +758,7 @@ export function sourceUrl(url: string) {
export function templateSourceUrl( export function templateSourceUrl(
ngModuleType: CompileIdentifierMetadata, compMeta: {type: CompileIdentifierMetadata}, ngModuleType: CompileIdentifierMetadata, compMeta: {type: CompileIdentifierMetadata},
templateMeta: {isInline: boolean, templateUrl: string}) { templateMeta: {isInline: boolean, templateUrl: string | null}) {
let url: string; let url: string;
if (templateMeta.isInline) { if (templateMeta.isInline) {
if (compMeta.type.reference instanceof StaticSymbol) { if (compMeta.type.reference instanceof StaticSymbol) {
@ -763,7 +769,7 @@ export function templateSourceUrl(
url = `${identifierName(ngModuleType)}/${identifierName(compMeta.type)}.html`; url = `${identifierName(ngModuleType)}/${identifierName(compMeta.type)}.html`;
} }
} else { } else {
url = templateMeta.templateUrl; url = templateMeta.templateUrl !;
} }
// always prepend ng:// to make angular resources easy to find and not clobber // always prepend ng:// to make angular resources easy to find and not clobber
// user resources. // user resources.
@ -771,7 +777,7 @@ export function templateSourceUrl(
} }
export function sharedStylesheetJitUrl(meta: CompileStylesheetMetadata, id: number) { export function sharedStylesheetJitUrl(meta: CompileStylesheetMetadata, id: number) {
const pathParts = meta.moduleUrl.split(/\/\\/g); const pathParts = meta.moduleUrl !.split(/\/\\/g);
const baseName = pathParts[pathParts.length - 1]; const baseName = pathParts[pathParts.length - 1];
return sourceUrl(`css/${id}${baseName}.ngstyle.js`); return sourceUrl(`css/${id}${baseName}.ngstyle.js`);
} }

View File

@ -13,7 +13,7 @@ import * as o from '../output/output_ast';
export class EventHandlerVars { static event = o.variable('$event'); } export class EventHandlerVars { static event = o.variable('$event'); }
export interface LocalResolver { getLocal(name: string): o.Expression; } export interface LocalResolver { getLocal(name: string): o.Expression|null; }
export class ConvertActionBindingResult { export class ConvertActionBindingResult {
constructor(public stmts: o.Statement[], public allowDefault: o.ReadVarExpr) {} constructor(public stmts: o.Statement[], public allowDefault: o.ReadVarExpr) {}
@ -24,7 +24,7 @@ export class ConvertActionBindingResult {
* used in an action binding (e.g. an event handler). * used in an action binding (e.g. an event handler).
*/ */
export function convertActionBinding( export function convertActionBinding(
localResolver: LocalResolver, implicitReceiver: o.Expression, action: cdAst.AST, localResolver: LocalResolver | null, implicitReceiver: o.Expression, action: cdAst.AST,
bindingId: string): ConvertActionBindingResult { bindingId: string): ConvertActionBindingResult {
if (!localResolver) { if (!localResolver) {
localResolver = new DefaultLocalResolver(); localResolver = new DefaultLocalResolver();
@ -51,7 +51,7 @@ export function convertActionBinding(
flattenStatements(actionWithoutBuiltins.visit(visitor, _Mode.Statement), actionStmts); flattenStatements(actionWithoutBuiltins.visit(visitor, _Mode.Statement), actionStmts);
prependTemporaryDecls(visitor.temporaryCount, bindingId, actionStmts); prependTemporaryDecls(visitor.temporaryCount, bindingId, actionStmts);
const lastIndex = actionStmts.length - 1; const lastIndex = actionStmts.length - 1;
let preventDefaultVar: o.ReadVarExpr = null; let preventDefaultVar: o.ReadVarExpr = null !;
if (lastIndex >= 0) { if (lastIndex >= 0) {
const lastStatement = actionStmts[lastIndex]; const lastStatement = actionStmts[lastIndex];
const returnExpr = convertStmtIntoExpression(lastStatement); const returnExpr = convertStmtIntoExpression(lastStatement);
@ -90,7 +90,7 @@ export class ConvertPropertyBindingResult {
* `convertPropertyBindingBuiltins`. * `convertPropertyBindingBuiltins`.
*/ */
export function convertPropertyBinding( export function convertPropertyBinding(
localResolver: LocalResolver, implicitReceiver: o.Expression, localResolver: LocalResolver | null, implicitReceiver: o.Expression,
expressionWithoutBuiltins: cdAst.AST, bindingId: string): ConvertPropertyBindingResult { expressionWithoutBuiltins: cdAst.AST, bindingId: string): ConvertPropertyBindingResult {
if (!localResolver) { if (!localResolver) {
localResolver = new DefaultLocalResolver(); localResolver = new DefaultLocalResolver();
@ -266,7 +266,7 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
if (ast instanceof BuiltinFunctionCall) { if (ast instanceof BuiltinFunctionCall) {
fnResult = ast.converter(convertedArgs); fnResult = ast.converter(convertedArgs);
} else { } else {
fnResult = this.visit(ast.target, _Mode.Expression).callFn(convertedArgs); fnResult = this.visit(ast.target !, _Mode.Expression).callFn(convertedArgs);
} }
return convertToStatementIfNeeded(mode, fnResult); return convertToStatementIfNeeded(mode, fnResult);
} }
@ -321,7 +321,7 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
return convertToStatementIfNeeded(mode, o.literal(ast.value)); return convertToStatementIfNeeded(mode, o.literal(ast.value));
} }
private _getLocal(name: string): o.Expression { return this._localResolver.getLocal(name); } private _getLocal(name: string): o.Expression|null { return this._localResolver.getLocal(name); }
visitMethodCall(ast: cdAst.MethodCall, mode: _Mode): any { visitMethodCall(ast: cdAst.MethodCall, mode: _Mode): any {
const leftMostSafe = this.leftMostSafeNode(ast); const leftMostSafe = this.leftMostSafeNode(ast);
@ -439,7 +439,7 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
// which comes in as leftMostSafe to this routine. // which comes in as leftMostSafe to this routine.
let guardedExpression = this.visit(leftMostSafe.receiver, _Mode.Expression); let guardedExpression = this.visit(leftMostSafe.receiver, _Mode.Expression);
let temporary: o.ReadVarExpr; let temporary: o.ReadVarExpr = undefined !;
if (this.needsTemporary(leftMostSafe.receiver)) { if (this.needsTemporary(leftMostSafe.receiver)) {
// If the expression has method calls or pipes then we need to save the result into a // If the expression has method calls or pipes then we need to save the result into a
// temporary variable to avoid calling stateful or impure code more than once. // temporary variable to avoid calling stateful or impure code more than once.
@ -577,7 +577,7 @@ function flattenStatements(arg: any, output: o.Statement[]) {
} }
class DefaultLocalResolver implements LocalResolver { class DefaultLocalResolver implements LocalResolver {
getLocal(name: string): o.Expression { getLocal(name: string): o.Expression|null {
if (name === EventHandlerVars.event.name) { if (name === EventHandlerVars.event.name) {
return EventHandlerVars.event; return EventHandlerVars.event;
} }
@ -593,7 +593,7 @@ function createPreventDefaultVar(bindingId: string): o.ReadVarExpr {
return o.variable(`pd_${bindingId}`); return o.variable(`pd_${bindingId}`);
} }
function convertStmtIntoExpression(stmt: o.Statement): o.Expression { function convertStmtIntoExpression(stmt: o.Statement): o.Expression|null {
if (stmt instanceof o.ExpressionStatement) { if (stmt instanceof o.ExpressionStatement) {
return stmt.expr; return stmt.expr;
} else if (stmt instanceof o.ReturnStatement) { } else if (stmt instanceof o.ReturnStatement) {

View File

@ -13,12 +13,12 @@ import {Identifiers, createIdentifier} from './identifiers';
export class CompilerConfig { export class CompilerConfig {
public defaultEncapsulation: ViewEncapsulation; public defaultEncapsulation: ViewEncapsulation|null;
// Whether to support the `<template>` tag and the `template` attribute to define angular // Whether to support the `<template>` tag and the `template` attribute to define angular
// templates. They have been deprecated in 4.x, `<ng-template>` should be used instead. // templates. They have been deprecated in 4.x, `<ng-template>` should be used instead.
public enableLegacyTemplate: boolean; public enableLegacyTemplate: boolean;
public useJit: boolean; public useJit: boolean;
public missingTranslation: MissingTranslationStrategy; public missingTranslation: MissingTranslationStrategy|null;
constructor( constructor(
{defaultEncapsulation = ViewEncapsulation.Emulated, useJit = true, missingTranslation, {defaultEncapsulation = ViewEncapsulation.Emulated, useJit = true, missingTranslation,
@ -29,8 +29,8 @@ export class CompilerConfig {
enableLegacyTemplate?: boolean, enableLegacyTemplate?: boolean,
} = {}) { } = {}) {
this.defaultEncapsulation = defaultEncapsulation; this.defaultEncapsulation = defaultEncapsulation;
this.useJit = useJit; this.useJit = !!useJit;
this.missingTranslation = missingTranslation; this.missingTranslation = missingTranslation || null;
this.enableLegacyTemplate = enableLegacyTemplate !== false; this.enableLegacyTemplate = enableLegacyTemplate !== false;
} }
} }

View File

@ -65,7 +65,7 @@ export abstract class CssRuleAst extends CssAst {
export class CssBlockRuleAst extends CssRuleAst { export class CssBlockRuleAst extends CssRuleAst {
constructor( constructor(
public location: ParseSourceSpan, public type: BlockType, public block: CssBlockAst, public location: ParseSourceSpan, public type: BlockType, public block: CssBlockAst,
public name: CssToken = null) { public name: CssToken|null = null) {
super(location); super(location);
} }
visit(visitor: CssAstVisitor, context?: any): any { visit(visitor: CssAstVisitor, context?: any): any {

View File

@ -40,7 +40,7 @@ export enum CssLexerMode {
} }
export class LexedCssResult { export class LexedCssResult {
constructor(public error: Error, public token: CssToken) {} constructor(public error: Error|null, public token: CssToken) {}
} }
export function generateErrorMessage( export function generateErrorMessage(
@ -126,7 +126,7 @@ export class CssScanner {
/** @internal */ /** @internal */
_currentMode: CssLexerMode = CssLexerMode.BLOCK; _currentMode: CssLexerMode = CssLexerMode.BLOCK;
/** @internal */ /** @internal */
_currentError: Error = null; _currentError: Error|null = null;
constructor(public input: string, private _trackComments: boolean = false) { constructor(public input: string, private _trackComments: boolean = false) {
this.length = this.input.length; this.length = this.input.length;
@ -188,7 +188,7 @@ export class CssScanner {
} }
} }
consume(type: CssTokenType, value: string = null): LexedCssResult { consume(type: CssTokenType, value: string|null = null): LexedCssResult {
const mode = this._currentMode; const mode = this._currentMode;
this.setMode(_trackWhitespace(mode) ? CssLexerMode.ALL_TRACK_WS : CssLexerMode.ALL); this.setMode(_trackWhitespace(mode) ? CssLexerMode.ALL_TRACK_WS : CssLexerMode.ALL);
@ -197,7 +197,7 @@ export class CssScanner {
const previousLine = this.line; const previousLine = this.line;
const previousColumn = this.column; const previousColumn = this.column;
let next: CssToken; let next: CssToken = undefined !;
const output = this.scan(); const output = this.scan();
if (output != null) { if (output != null) {
// just incase the inner scan method returned an error // just incase the inner scan method returned an error
@ -225,7 +225,7 @@ export class CssScanner {
// mode so that the parser can recover... // mode so that the parser can recover...
this.setMode(mode); this.setMode(mode);
let error: Error = null; let error: Error|null = null;
if (!isMatchingType || (value != null && value != next.strValue)) { if (!isMatchingType || (value != null && value != next.strValue)) {
let errorMessage = let errorMessage =
CssTokenType[next.type] + ' does not match expected ' + CssTokenType[type] + ' value'; CssTokenType[next.type] + ' does not match expected ' + CssTokenType[type] + ' value';
@ -244,7 +244,7 @@ export class CssScanner {
} }
scan(): LexedCssResult { scan(): LexedCssResult|null {
const trackWS = _trackWhitespace(this._currentMode); const trackWS = _trackWhitespace(this._currentMode);
if (this.index == 0 && !trackWS) { // first scan if (this.index == 0 && !trackWS) { // first scan
this.consumeWhitespace(); this.consumeWhitespace();
@ -253,7 +253,7 @@ export class CssScanner {
const token = this._scan(); const token = this._scan();
if (token == null) return null; if (token == null) return null;
const error = this._currentError; const error = this._currentError !;
this._currentError = null; this._currentError = null;
if (!trackWS) { if (!trackWS) {
@ -263,7 +263,7 @@ export class CssScanner {
} }
/** @internal */ /** @internal */
_scan(): CssToken { _scan(): CssToken|null {
let peek = this.peek; let peek = this.peek;
let peekPeek = this.peekPeek; let peekPeek = this.peekPeek;
if (peek == chars.$EOF) return null; if (peek == chars.$EOF) return null;
@ -317,7 +317,7 @@ export class CssScanner {
return this.error(`Unexpected character [${String.fromCharCode(peek)}]`); return this.error(`Unexpected character [${String.fromCharCode(peek)}]`);
} }
scanComment(): CssToken { scanComment(): CssToken|null {
if (this.assertCondition( if (this.assertCondition(
isCommentStart(this.peek, this.peekPeek), 'Expected comment start value')) { isCommentStart(this.peek, this.peekPeek), 'Expected comment start value')) {
return null; return null;
@ -355,7 +355,7 @@ export class CssScanner {
return new CssToken(start, startingColumn, startingLine, CssTokenType.Whitespace, str); return new CssToken(start, startingColumn, startingLine, CssTokenType.Whitespace, str);
} }
scanString(): CssToken { scanString(): CssToken|null {
if (this.assertCondition( if (this.assertCondition(
isStringStart(this.peek, this.peekPeek), 'Unexpected non-string starting value')) { isStringStart(this.peek, this.peekPeek), 'Unexpected non-string starting value')) {
return null; return null;
@ -405,7 +405,7 @@ export class CssScanner {
return new CssToken(start, startingColumn, this.line, CssTokenType.Number, strValue); return new CssToken(start, startingColumn, this.line, CssTokenType.Number, strValue);
} }
scanIdentifier(): CssToken { scanIdentifier(): CssToken|null {
if (this.assertCondition( if (this.assertCondition(
isIdentifierStart(this.peek, this.peekPeek), 'Expected identifier starting value')) { isIdentifierStart(this.peek, this.peekPeek), 'Expected identifier starting value')) {
return null; return null;
@ -436,7 +436,7 @@ export class CssScanner {
return new CssToken(start, startingColumn, this.line, CssTokenType.Identifier, strValue); return new CssToken(start, startingColumn, this.line, CssTokenType.Identifier, strValue);
} }
scanCharacter(): CssToken { scanCharacter(): CssToken|null {
const start = this.index; const start = this.index;
const startingColumn = this.column; const startingColumn = this.column;
if (this.assertCondition( if (this.assertCondition(
@ -451,7 +451,7 @@ export class CssScanner {
return new CssToken(start, startingColumn, this.line, CssTokenType.Character, c); return new CssToken(start, startingColumn, this.line, CssTokenType.Character, c);
} }
scanAtExpression(): CssToken { scanAtExpression(): CssToken|null {
if (this.assertCondition(this.peek == chars.$AT, 'Expected @ value')) { if (this.assertCondition(this.peek == chars.$AT, 'Expected @ value')) {
return null; return null;
} }
@ -460,7 +460,7 @@ export class CssScanner {
const startingColumn = this.column; const startingColumn = this.column;
this.advance(); this.advance();
if (isIdentifierStart(this.peek, this.peekPeek)) { if (isIdentifierStart(this.peek, this.peekPeek)) {
const ident = this.scanIdentifier(); const ident = this.scanIdentifier() !;
const strValue = '@' + ident.strValue; const strValue = '@' + ident.strValue;
return new CssToken(start, startingColumn, this.line, CssTokenType.AtKeyword, strValue); return new CssToken(start, startingColumn, this.line, CssTokenType.AtKeyword, strValue);
} else { } else {
@ -476,7 +476,8 @@ export class CssScanner {
return false; return false;
} }
error(message: string, errorTokenValue: string = null, doNotAdvance: boolean = false): CssToken { error(message: string, errorTokenValue: string|null = null, doNotAdvance: boolean = false):
CssToken {
const index: number = this.index; const index: number = this.index;
const column: number = this.column; const column: number = this.column;
const line: number = this.line; const line: number = this.line;

View File

@ -102,8 +102,8 @@ export class CssParser {
this._errors = []; this._errors = [];
const result = new ParsedCssResult(errors, ast); const result = new ParsedCssResult(errors, ast);
this._file = null; this._file = null as any;
this._scanner = null; this._scanner = null as any;
return result; return result;
} }
@ -115,14 +115,14 @@ export class CssParser {
this._scanner.setMode(CssLexerMode.BLOCK); this._scanner.setMode(CssLexerMode.BLOCK);
results.push(this._parseRule(delimiters)); results.push(this._parseRule(delimiters));
} }
let span: ParseSourceSpan = null; let span: ParseSourceSpan|null = null;
if (results.length > 0) { if (results.length > 0) {
const firstRule = results[0]; const firstRule = results[0];
// we collect the last token like so incase there was an // we collect the last token like so incase there was an
// EOF token that was emitted sometime during the lexing // EOF token that was emitted sometime during the lexing
span = this._generateSourceSpan(firstRule, this._lastToken); span = this._generateSourceSpan(firstRule, this._lastToken);
} }
return new CssStyleSheetAst(span, results); return new CssStyleSheetAst(span !, results);
} }
/** @internal */ /** @internal */
@ -134,7 +134,7 @@ export class CssParser {
} }
/** @internal */ /** @internal */
_generateSourceSpan(start: CssToken|CssAst, end: CssToken|CssAst = null): ParseSourceSpan { _generateSourceSpan(start: CssToken|CssAst, end: CssToken|CssAst|null = null): ParseSourceSpan {
let startLoc: ParseLocation; let startLoc: ParseLocation;
if (start instanceof CssAst) { if (start instanceof CssAst) {
startLoc = start.location.start; startLoc = start.location.start;
@ -152,13 +152,13 @@ export class CssParser {
end = this._lastToken; end = this._lastToken;
} }
let endLine: number; let endLine: number = -1;
let endColumn: number; let endColumn: number = -1;
let endIndex: number; let endIndex: number = -1;
if (end instanceof CssAst) { if (end instanceof CssAst) {
endLine = end.location.end.line; endLine = end.location.end.line !;
endColumn = end.location.end.col; endColumn = end.location.end.col !;
endIndex = end.location.end.offset; endIndex = end.location.end.offset !;
} else if (end instanceof CssToken) { } else if (end instanceof CssToken) {
endLine = end.line; endLine = end.line;
endColumn = end.column; endColumn = end.column;
@ -250,7 +250,7 @@ export class CssParser {
case BlockType.Viewport: case BlockType.Viewport:
case BlockType.FontFace: case BlockType.FontFace:
block = this._parseStyleBlock(delimiters); block = this._parseStyleBlock(delimiters) !;
span = this._generateSourceSpan(startToken, block); span = this._generateSourceSpan(startToken, block);
return new CssBlockRuleAst(span, type, block); return new CssBlockRuleAst(span, type, block);
@ -290,7 +290,7 @@ export class CssParser {
span = this._generateSourceSpan(startToken, tokens[tokens.length - 1]); span = this._generateSourceSpan(startToken, tokens[tokens.length - 1]);
query = new CssAtRulePredicateAst(span, strValue, tokens); query = new CssAtRulePredicateAst(span, strValue, tokens);
block = this._parseBlock(delimiters); block = this._parseBlock(delimiters);
strValue = this._extractSourceContent(start, block.end.offset); strValue = this._extractSourceContent(start, block.end.offset !);
span = this._generateSourceSpan(startToken, block); span = this._generateSourceSpan(startToken, block);
return new CssBlockDefinitionRuleAst(span, strValue, type, query, block); return new CssBlockDefinitionRuleAst(span, strValue, type, query, block);
@ -373,7 +373,7 @@ export class CssParser {
/** @internal */ /** @internal */
_scan(): CssToken { _scan(): CssToken {
const output = this._scanner.scan(); const output = this._scanner.scan() !;
const token = output.token; const token = output.token;
const error = output.error; const error = output.error;
if (error != null) { if (error != null) {
@ -387,7 +387,7 @@ export class CssParser {
_getScannerIndex(): number { return this._scanner.index; } _getScannerIndex(): number { return this._scanner.index; }
/** @internal */ /** @internal */
_consume(type: CssTokenType, value: string = null): CssToken { _consume(type: CssTokenType, value: string|null = null): CssToken {
const output = this._scanner.consume(type, value); const output = this._scanner.consume(type, value);
const token = output.token; const token = output.token;
const error = output.error; const error = output.error;
@ -429,7 +429,7 @@ export class CssParser {
} }
const stylesBlock = this._parseStyleBlock(delimiters | RBRACE_DELIM_FLAG); const stylesBlock = this._parseStyleBlock(delimiters | RBRACE_DELIM_FLAG);
const span = this._generateSourceSpan(stepTokens[0], stylesBlock); const span = this._generateSourceSpan(stepTokens[0], stylesBlock);
const ast = new CssKeyframeDefinitionAst(span, stepTokens, stylesBlock); const ast = new CssKeyframeDefinitionAst(span, stepTokens, stylesBlock !);
this._scanner.setMode(CssLexerMode.BLOCK); this._scanner.setMode(CssLexerMode.BLOCK);
return ast; return ast;
@ -520,7 +520,7 @@ export class CssParser {
const selectorCssTokens: CssToken[] = []; const selectorCssTokens: CssToken[] = [];
const pseudoSelectors: CssPseudoSelectorAst[] = []; const pseudoSelectors: CssPseudoSelectorAst[] = [];
let previousToken: CssToken; let previousToken: CssToken = undefined !;
const selectorPartDelimiters = delimiters | SPACE_DELIM_FLAG; const selectorPartDelimiters = delimiters | SPACE_DELIM_FLAG;
let loopOverSelector = !characterContainsDelimiter(this._scanner.peek, selectorPartDelimiters); let loopOverSelector = !characterContainsDelimiter(this._scanner.peek, selectorPartDelimiters);
@ -581,9 +581,9 @@ export class CssParser {
// this happens if the selector is not directly followed by // this happens if the selector is not directly followed by
// a comma or curly brace without a space in between // a comma or curly brace without a space in between
let operator: CssToken = null; let operator: CssToken|null = null;
let operatorScanCount = 0; let operatorScanCount = 0;
let lastOperatorToken: CssToken = null; let lastOperatorToken: CssToken|null = null;
if (!characterContainsDelimiter(this._scanner.peek, delimiters)) { if (!characterContainsDelimiter(this._scanner.peek, delimiters)) {
while (operator == null && !characterContainsDelimiter(this._scanner.peek, delimiters) && while (operator == null && !characterContainsDelimiter(this._scanner.peek, delimiters) &&
isSelectorOperatorCharacter(this._scanner.peek)) { isSelectorOperatorCharacter(this._scanner.peek)) {
@ -653,8 +653,8 @@ export class CssParser {
// please note that `endToken` is reassigned multiple times below // please note that `endToken` is reassigned multiple times below
// so please do not optimize the if statements into if/elseif // so please do not optimize the if statements into if/elseif
let startTokenOrAst: CssToken|CssAst = null; let startTokenOrAst: CssToken|CssAst|null = null;
let endTokenOrAst: CssToken|CssAst = null; let endTokenOrAst: CssToken|CssAst|null = null;
if (selectorCssTokens.length > 0) { if (selectorCssTokens.length > 0) {
startTokenOrAst = startTokenOrAst || selectorCssTokens[0]; startTokenOrAst = startTokenOrAst || selectorCssTokens[0];
endTokenOrAst = selectorCssTokens[selectorCssTokens.length - 1]; endTokenOrAst = selectorCssTokens[selectorCssTokens.length - 1];
@ -668,8 +668,8 @@ export class CssParser {
endTokenOrAst = operator; endTokenOrAst = operator;
} }
const span = this._generateSourceSpan(startTokenOrAst, endTokenOrAst); const span = this._generateSourceSpan(startTokenOrAst !, endTokenOrAst);
return new CssSimpleSelectorAst(span, selectorCssTokens, strValue, pseudoSelectors, operator); return new CssSimpleSelectorAst(span, selectorCssTokens, strValue, pseudoSelectors, operator !);
} }
/** @internal */ /** @internal */
@ -698,7 +698,7 @@ export class CssParser {
const tokens: CssToken[] = []; const tokens: CssToken[] = [];
let wsStr = ''; let wsStr = '';
let previous: CssToken; let previous: CssToken = undefined !;
while (!characterContainsDelimiter(this._scanner.peek, delimiters)) { while (!characterContainsDelimiter(this._scanner.peek, delimiters)) {
let token: CssToken; let token: CssToken;
if (previous != null && previous.type == CssTokenType.Identifier && if (previous != null && previous.type == CssTokenType.Identifier &&
@ -749,7 +749,7 @@ export class CssParser {
} }
/** @internal */ /** @internal */
_collectUntilDelim(delimiters: number, assertType: CssTokenType = null): CssToken[] { _collectUntilDelim(delimiters: number, assertType: CssTokenType|null = null): CssToken[] {
const tokens: CssToken[] = []; const tokens: CssToken[] = [];
while (!characterContainsDelimiter(this._scanner.peek, delimiters)) { while (!characterContainsDelimiter(this._scanner.peek, delimiters)) {
const val = assertType != null ? this._consume(assertType) : this._scan(); const val = assertType != null ? this._consume(assertType) : this._scan();
@ -782,7 +782,7 @@ export class CssParser {
} }
/** @internal */ /** @internal */
_parseStyleBlock(delimiters: number): CssStylesBlockAst { _parseStyleBlock(delimiters: number): CssStylesBlockAst|null {
delimiters |= RBRACE_DELIM_FLAG | LBRACE_DELIM_FLAG; delimiters |= RBRACE_DELIM_FLAG | LBRACE_DELIM_FLAG;
this._scanner.setMode(CssLexerMode.STYLE_BLOCK); this._scanner.setMode(CssLexerMode.STYLE_BLOCK);
@ -815,7 +815,7 @@ export class CssParser {
let prop = this._consume(CssTokenType.Identifier); let prop = this._consume(CssTokenType.Identifier);
let parseValue: boolean = false; let parseValue: boolean = false;
let value: CssStyleValueAst = null; let value: CssStyleValueAst|null = null;
let endToken: CssToken|CssStyleValueAst = prop; let endToken: CssToken|CssStyleValueAst = prop;
// the colon value separates the prop from the style. // the colon value separates the prop from the style.
@ -865,7 +865,7 @@ export class CssParser {
} }
const span = this._generateSourceSpan(prop, endToken); const span = this._generateSourceSpan(prop, endToken);
return new CssDefinitionAst(span, prop, value); return new CssDefinitionAst(span, prop, value !);
} }
/** @internal */ /** @internal */

View File

@ -7,6 +7,7 @@
*/ */
import {ViewEncapsulation, ɵstringify as stringify} from '@angular/core'; import {ViewEncapsulation, ɵstringify as stringify} from '@angular/core';
import {CompileAnimationEntryMetadata, CompileDirectiveMetadata, CompileStylesheetMetadata, CompileTemplateMetadata, templateSourceUrl} from './compile_metadata'; import {CompileAnimationEntryMetadata, CompileDirectiveMetadata, CompileStylesheetMetadata, CompileTemplateMetadata, templateSourceUrl} from './compile_metadata';
import {CompilerConfig} from './config'; import {CompilerConfig} from './config';
import {CompilerInjectable} from './injectable'; import {CompilerInjectable} from './injectable';
@ -17,19 +18,19 @@ import {ResourceLoader} from './resource_loader';
import {extractStyleUrls, isStyleUrlResolvable} from './style_url_resolver'; import {extractStyleUrls, isStyleUrlResolvable} from './style_url_resolver';
import {PreparsedElementType, preparseElement} from './template_parser/template_preparser'; import {PreparsedElementType, preparseElement} from './template_parser/template_preparser';
import {UrlResolver} from './url_resolver'; import {UrlResolver} from './url_resolver';
import {SyncAsyncResult, syntaxError} from './util'; import {SyncAsyncResult, isDefined, syntaxError} from './util';
export interface PrenormalizedTemplateMetadata { export interface PrenormalizedTemplateMetadata {
ngModuleType: any; ngModuleType: any;
componentType: any; componentType: any;
moduleUrl: string; moduleUrl: string;
template?: string; template: string|null;
templateUrl?: string; templateUrl: string|null;
styles?: string[]; styles: string[];
styleUrls?: string[]; styleUrls: string[];
interpolation?: [string, string]; interpolation: [string, string]|null;
encapsulation?: ViewEncapsulation; encapsulation: ViewEncapsulation|null;
animations?: CompileAnimationEntryMetadata[]; animations: CompileAnimationEntryMetadata[];
} }
@CompilerInjectable() @CompilerInjectable()
@ -46,15 +47,16 @@ export class DirectiveNormalizer {
if (!normalizedDirective.isComponent) { if (!normalizedDirective.isComponent) {
return; return;
} }
this._resourceLoaderCache.delete(normalizedDirective.template.templateUrl); const template = normalizedDirective.template !;
normalizedDirective.template.externalStylesheets.forEach( this._resourceLoaderCache.delete(template.templateUrl !);
(stylesheet) => { this._resourceLoaderCache.delete(stylesheet.moduleUrl); }); template.externalStylesheets.forEach(
(stylesheet) => { this._resourceLoaderCache.delete(stylesheet.moduleUrl !); });
} }
private _fetch(url: string): Promise<string> { private _fetch(url: string): Promise<string> {
let result = this._resourceLoaderCache.get(url); let result = this._resourceLoaderCache.get(url);
if (!result) { if (!result) {
result = this._resourceLoader.get(url); result = this._resourceLoader.get(url) !;
this._resourceLoaderCache.set(url, result); this._resourceLoaderCache.set(url, result);
} }
return result; return result;
@ -62,10 +64,10 @@ export class DirectiveNormalizer {
normalizeTemplate(prenormData: PrenormalizedTemplateMetadata): normalizeTemplate(prenormData: PrenormalizedTemplateMetadata):
SyncAsyncResult<CompileTemplateMetadata> { SyncAsyncResult<CompileTemplateMetadata> {
let normalizedTemplateSync: CompileTemplateMetadata = null; let normalizedTemplateSync: CompileTemplateMetadata = null !;
let normalizedTemplateAsync: Promise<CompileTemplateMetadata>; let normalizedTemplateAsync: Promise<CompileTemplateMetadata> = undefined !;
if (prenormData.template != null) { if (isDefined(prenormData.template)) {
if (prenormData.templateUrl != null) { if (isDefined(prenormData.templateUrl)) {
throw syntaxError( throw syntaxError(
`'${stringify(prenormData.componentType)}' component cannot define both template and templateUrl`); `'${stringify(prenormData.componentType)}' component cannot define both template and templateUrl`);
} }
@ -74,8 +76,8 @@ export class DirectiveNormalizer {
`The template specified for component ${stringify(prenormData.componentType)} is not a string`); `The template specified for component ${stringify(prenormData.componentType)} is not a string`);
} }
normalizedTemplateSync = this.normalizeTemplateSync(prenormData); normalizedTemplateSync = this.normalizeTemplateSync(prenormData);
normalizedTemplateAsync = Promise.resolve(normalizedTemplateSync); normalizedTemplateAsync = Promise.resolve(normalizedTemplateSync !);
} else if (prenormData.templateUrl) { } else if (isDefined(prenormData.templateUrl)) {
if (typeof prenormData.templateUrl !== 'string') { if (typeof prenormData.templateUrl !== 'string') {
throw syntaxError( throw syntaxError(
`The templateUrl specified for component ${stringify(prenormData.componentType)} is not a string`); `The templateUrl specified for component ${stringify(prenormData.componentType)} is not a string`);
@ -98,12 +100,12 @@ export class DirectiveNormalizer {
} }
normalizeTemplateSync(prenomData: PrenormalizedTemplateMetadata): CompileTemplateMetadata { normalizeTemplateSync(prenomData: PrenormalizedTemplateMetadata): CompileTemplateMetadata {
return this.normalizeLoadedTemplate(prenomData, prenomData.template, prenomData.moduleUrl); return this.normalizeLoadedTemplate(prenomData, prenomData.template !, prenomData.moduleUrl);
} }
normalizeTemplateAsync(prenomData: PrenormalizedTemplateMetadata): normalizeTemplateAsync(prenomData: PrenormalizedTemplateMetadata):
Promise<CompileTemplateMetadata> { Promise<CompileTemplateMetadata> {
const templateUrl = this._urlResolver.resolve(prenomData.moduleUrl, prenomData.templateUrl); const templateUrl = this._urlResolver.resolve(prenomData.moduleUrl, prenomData.templateUrl !);
return this._fetch(templateUrl) return this._fetch(templateUrl)
.then((value) => this.normalizeLoadedTemplate(prenomData, value, templateUrl)); .then((value) => this.normalizeLoadedTemplate(prenomData, value, templateUrl));
} }
@ -112,7 +114,7 @@ export class DirectiveNormalizer {
prenormData: PrenormalizedTemplateMetadata, template: string, prenormData: PrenormalizedTemplateMetadata, template: string,
templateAbsUrl: string): CompileTemplateMetadata { templateAbsUrl: string): CompileTemplateMetadata {
const isInline = !!prenormData.template; const isInline = !!prenormData.template;
const interpolationConfig = InterpolationConfig.fromArray(prenormData.interpolation); const interpolationConfig = InterpolationConfig.fromArray(prenormData.interpolation !);
const rootNodesAndErrors = this._htmlParser.parse( const rootNodesAndErrors = this._htmlParser.parse(
template, template,
templateSourceUrl( templateSourceUrl(
@ -154,7 +156,8 @@ export class DirectiveNormalizer {
templateUrl: templateAbsUrl, styles, styleUrls, templateUrl: templateAbsUrl, styles, styleUrls,
ngContentSelectors: visitor.ngContentSelectors, ngContentSelectors: visitor.ngContentSelectors,
animations: prenormData.animations, animations: prenormData.animations,
interpolation: prenormData.interpolation, isInline interpolation: prenormData.interpolation, isInline,
externalStylesheets: []
}); });
} }
@ -193,17 +196,18 @@ export class DirectiveNormalizer {
} }
normalizeStylesheet(stylesheet: CompileStylesheetMetadata): CompileStylesheetMetadata { normalizeStylesheet(stylesheet: CompileStylesheetMetadata): CompileStylesheetMetadata {
const moduleUrl = stylesheet.moduleUrl !;
const allStyleUrls = stylesheet.styleUrls.filter(isStyleUrlResolvable) const allStyleUrls = stylesheet.styleUrls.filter(isStyleUrlResolvable)
.map(url => this._urlResolver.resolve(stylesheet.moduleUrl, url)); .map(url => this._urlResolver.resolve(moduleUrl, url));
const allStyles = stylesheet.styles.map(style => { const allStyles = stylesheet.styles.map(style => {
const styleWithImports = extractStyleUrls(this._urlResolver, stylesheet.moduleUrl, style); const styleWithImports = extractStyleUrls(this._urlResolver, moduleUrl, style);
allStyleUrls.push(...styleWithImports.styleUrls); allStyleUrls.push(...styleWithImports.styleUrls);
return styleWithImports.style; return styleWithImports.style;
}); });
return new CompileStylesheetMetadata( return new CompileStylesheetMetadata(
{styles: allStyles, styleUrls: allStyleUrls, moduleUrl: stylesheet.moduleUrl}); {styles: allStyles, styleUrls: allStyleUrls, moduleUrl: moduleUrl});
} }
} }

View File

@ -30,7 +30,10 @@ export class DirectiveResolver {
/** /**
* Return {@link Directive} for a given `Type`. * Return {@link Directive} for a given `Type`.
*/ */
resolve(type: Type<any>, throwIfNotFound = true): Directive { resolve(type: Type<any>): Directive;
resolve(type: Type<any>, throwIfNotFound: true): Directive;
resolve(type: Type<any>, throwIfNotFound: boolean): Directive|null;
resolve(type: Type<any>, throwIfNotFound = true): Directive|null {
const typeMetadata = this._reflector.annotations(resolveForwardRef(type)); const typeMetadata = this._reflector.annotations(resolveForwardRef(type));
if (typeMetadata) { if (typeMetadata) {
const metadata = findLast(typeMetadata, isDirectiveMetadata); const metadata = findLast(typeMetadata, isDirectiveMetadata);
@ -100,7 +103,7 @@ export class DirectiveResolver {
return this._merge(dm, inputs, outputs, host, queries, directiveType); return this._merge(dm, inputs, outputs, host, queries, directiveType);
} }
private _extractPublicName(def: string) { return splitAtColon(def, [null, def])[1].trim(); } private _extractPublicName(def: string) { return splitAtColon(def, [null !, def])[1].trim(); }
private _dedupeBindings(bindings: string[]): string[] { private _dedupeBindings(bindings: string[]): string[] {
const names = new Set<string>(); const names = new Set<string>();
@ -166,7 +169,7 @@ function isDirectiveMetadata(type: any): type is Directive {
return type instanceof Directive; return type instanceof Directive;
} }
export function findLast<T>(arr: T[], condition: (value: T) => boolean): T { export function findLast<T>(arr: T[], condition: (value: T) => boolean): T|null {
for (let i = arr.length - 1; i >= 0; i--) { for (let i = arr.length - 1; i >= 0; i--) {
if (condition(arr[i])) { if (condition(arr[i])) {
return arr[i]; return arr[i];

View File

@ -185,7 +185,7 @@ export class SafeMethodCall extends AST {
} }
export class FunctionCall extends AST { export class FunctionCall extends AST {
constructor(span: ParseSpan, public target: AST, public args: any[]) { super(span); } constructor(span: ParseSpan, public target: AST|null, public args: any[]) { super(span); }
visit(visitor: AstVisitor, context: any = null): any { visit(visitor: AstVisitor, context: any = null): any {
return visitor.visitFunctionCall(this, context); return visitor.visitFunctionCall(this, context);
} }
@ -193,7 +193,7 @@ export class FunctionCall extends AST {
export class ASTWithSource extends AST { export class ASTWithSource extends AST {
constructor( constructor(
public ast: AST, public source: string, public location: string, public ast: AST, public source: string|null, public location: string,
public errors: ParserError[]) { public errors: ParserError[]) {
super(new ParseSpan(0, source == null ? 0 : source.length)); super(new ParseSpan(0, source == null ? 0 : source.length));
} }
@ -248,7 +248,7 @@ export class RecursiveAstVisitor implements AstVisitor {
return null; return null;
} }
visitFunctionCall(ast: FunctionCall, context: any): any { visitFunctionCall(ast: FunctionCall, context: any): any {
ast.target.visit(this); ast.target !.visit(this);
this.visitAll(ast.args, context); this.visitAll(ast.args, context);
return null; return null;
} }
@ -337,7 +337,7 @@ export class AstTransformer implements AstVisitor {
} }
visitFunctionCall(ast: FunctionCall, context: any): AST { visitFunctionCall(ast: FunctionCall, context: any): AST {
return new FunctionCall(ast.span, ast.target.visit(this), this.visitAll(ast.args)); return new FunctionCall(ast.span, ast.target !.visit(this), this.visitAll(ast.args));
} }
visitLiteralArray(ast: LiteralArray, context: any): AST { visitLiteralArray(ast: LiteralArray, context: any): AST {

View File

@ -76,7 +76,7 @@ export class Token {
toNumber(): number { return this.type == TokenType.Number ? this.numValue : -1; } toNumber(): number { return this.type == TokenType.Number ? this.numValue : -1; }
toString(): string { toString(): string|null {
switch (this.type) { switch (this.type) {
case TokenType.Character: case TokenType.Character:
case TokenType.Identifier: case TokenType.Identifier:
@ -137,7 +137,7 @@ class _Scanner {
this.peek = ++this.index >= this.length ? chars.$EOF : this.input.charCodeAt(this.index); this.peek = ++this.index >= this.length ? chars.$EOF : this.input.charCodeAt(this.index);
} }
scanToken(): Token { scanToken(): Token|null {
const input = this.input, length = this.length; const input = this.input, length = this.length;
let peek = this.peek, index = this.index; let peek = this.peek, index = this.index;

View File

@ -90,7 +90,7 @@ export class Parser {
.parseChain(); .parseChain();
} }
private _parseQuote(input: string, location: any): AST { private _parseQuote(input: string|null, location: any): AST|null {
if (input == null) return null; if (input == null) return null;
const prefixSeparatorIndex = input.indexOf(':'); const prefixSeparatorIndex = input.indexOf(':');
if (prefixSeparatorIndex == -1) return null; if (prefixSeparatorIndex == -1) return null;
@ -100,7 +100,7 @@ export class Parser {
return new Quote(new ParseSpan(0, input.length), prefix, uninterpretedExpression, location); return new Quote(new ParseSpan(0, input.length), prefix, uninterpretedExpression, location);
} }
parseTemplateBindings(prefixToken: string, input: string, location: any): parseTemplateBindings(prefixToken: string|null, input: string, location: any):
TemplateBindingParseResult { TemplateBindingParseResult {
const tokens = this._lexer.tokenize(input); const tokens = this._lexer.tokenize(input);
if (prefixToken) { if (prefixToken) {
@ -117,7 +117,7 @@ export class Parser {
parseInterpolation( parseInterpolation(
input: string, location: any, input: string, location: any,
interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG): ASTWithSource { interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG): ASTWithSource|null {
const split = this.splitInterpolation(input, location, interpolationConfig); const split = this.splitInterpolation(input, location, interpolationConfig);
if (split == null) return null; if (split == null) return null;
@ -142,7 +142,8 @@ export class Parser {
splitInterpolation( splitInterpolation(
input: string, location: string, input: string, location: string,
interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG): SplitInterpolation { interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG): SplitInterpolation
|null {
const regexp = _createInterpolateRegExp(interpolationConfig); const regexp = _createInterpolateRegExp(interpolationConfig);
const parts = input.split(regexp); const parts = input.split(regexp);
if (parts.length <= 1) { if (parts.length <= 1) {
@ -175,7 +176,7 @@ export class Parser {
return new SplitInterpolation(strings, expressions, offsets); return new SplitInterpolation(strings, expressions, offsets);
} }
wrapLiteralPrimitive(input: string, location: any): ASTWithSource { wrapLiteralPrimitive(input: string|null, location: any): ASTWithSource {
return new ASTWithSource( return new ASTWithSource(
new LiteralPrimitive(new ParseSpan(0, input == null ? 0 : input.length), input), input, new LiteralPrimitive(new ParseSpan(0, input == null ? 0 : input.length), input), input,
location, this.errors); location, this.errors);
@ -186,8 +187,8 @@ export class Parser {
return i != null ? input.substring(0, i).trim() : input; return i != null ? input.substring(0, i).trim() : input;
} }
private _commentStart(input: string): number { private _commentStart(input: string): number|null {
let outerQuote: number = null; let outerQuote: number|null = null;
for (let i = 0; i < input.length - 1; i++) { for (let i = 0; i < input.length - 1; i++) {
const char = input.charCodeAt(i); const char = input.charCodeAt(i);
const nextChar = input.charCodeAt(i + 1); const nextChar = input.charCodeAt(i + 1);
@ -288,7 +289,7 @@ export class _ParseAST {
this.error(`Missing expected operator ${operator}`); this.error(`Missing expected operator ${operator}`);
} }
expectIdentifierOrKeyword(): string { expectIdentifierOrKeyword(): string|null {
const n = this.next; const n = this.next;
if (!n.isIdentifier() && !n.isKeyword()) { if (!n.isIdentifier() && !n.isKeyword()) {
this.error(`Unexpected token ${n}, expected identifier or keyword`); this.error(`Unexpected token ${n}, expected identifier or keyword`);
@ -298,7 +299,7 @@ export class _ParseAST {
return n.toString(); return n.toString();
} }
expectIdentifierOrKeywordOrString(): string { expectIdentifierOrKeywordOrString(): string|null {
const n = this.next; const n = this.next;
if (!n.isIdentifier() && !n.isKeyword() && !n.isString()) { if (!n.isIdentifier() && !n.isKeyword() && !n.isString()) {
this.error(`Unexpected token ${n}, expected identifier, keyword, or string`); this.error(`Unexpected token ${n}, expected identifier, keyword, or string`);
@ -338,7 +339,7 @@ export class _ParseAST {
} }
do { do {
const name = this.expectIdentifierOrKeyword(); const name = this.expectIdentifierOrKeyword() !;
const args: AST[] = []; const args: AST[] = [];
while (this.optionalCharacter(chars.$COLON)) { while (this.optionalCharacter(chars.$COLON)) {
args.push(this.parseExpression()); args.push(this.parseExpression());
@ -607,7 +608,7 @@ export class _ParseAST {
if (!this.optionalCharacter(chars.$RBRACE)) { if (!this.optionalCharacter(chars.$RBRACE)) {
this.rbracesExpected++; this.rbracesExpected++;
do { do {
const key = this.expectIdentifierOrKeywordOrString(); const key = this.expectIdentifierOrKeywordOrString() !;
keys.push(key); keys.push(key);
this.expectCharacter(chars.$COLON); this.expectCharacter(chars.$COLON);
values.push(this.parsePipe()); values.push(this.parsePipe());
@ -620,7 +621,7 @@ export class _ParseAST {
parseAccessMemberOrMethodCall(receiver: AST, isSafe: boolean = false): AST { parseAccessMemberOrMethodCall(receiver: AST, isSafe: boolean = false): AST {
const start = receiver.span.start; const start = receiver.span.start;
const id = this.expectIdentifierOrKeyword(); const id = this.expectIdentifierOrKeyword() !;
if (this.optionalCharacter(chars.$LPAREN)) { if (this.optionalCharacter(chars.$LPAREN)) {
this.rparensExpected++; this.rparensExpected++;
@ -683,7 +684,7 @@ export class _ParseAST {
parseTemplateBindings(): TemplateBindingParseResult { parseTemplateBindings(): TemplateBindingParseResult {
const bindings: TemplateBinding[] = []; const bindings: TemplateBinding[] = [];
let prefix: string = null; let prefix: string = null !;
const warnings: string[] = []; const warnings: string[] = [];
while (this.index < this.tokens.length) { while (this.index < this.tokens.length) {
const start = this.inputIndex; const start = this.inputIndex;
@ -701,8 +702,8 @@ export class _ParseAST {
} }
} }
this.optionalCharacter(chars.$COLON); this.optionalCharacter(chars.$COLON);
let name: string = null; let name: string = null !;
let expression: ASTWithSource = null; let expression: ASTWithSource = null !;
if (keyIsVar) { if (keyIsVar) {
if (this.optionalOperator('=')) { if (this.optionalOperator('=')) {
name = this.expectTemplateBindingKey(); name = this.expectTemplateBindingKey();
@ -726,7 +727,7 @@ export class _ParseAST {
const letStart = this.inputIndex; const letStart = this.inputIndex;
this.advance(); // consume `as` this.advance(); // consume `as`
const letName = this.expectTemplateBindingKey(); // read local var name const letName = this.expectTemplateBindingKey(); // read local var name
bindings.push(new TemplateBinding(this.span(letStart), letName, true, key, null)); bindings.push(new TemplateBinding(this.span(letStart), letName, true, key, null !));
} }
if (!this.optionalCharacter(chars.$SEMICOLON)) { if (!this.optionalCharacter(chars.$SEMICOLON)) {
this.optionalCharacter(chars.$COMMA); this.optionalCharacter(chars.$COMMA);
@ -735,12 +736,12 @@ export class _ParseAST {
return new TemplateBindingParseResult(bindings, warnings, this.errors); return new TemplateBindingParseResult(bindings, warnings, this.errors);
} }
error(message: string, index: number = null) { error(message: string, index: number|null = null) {
this.errors.push(new ParserError(message, this.input, this.locationText(index), this.location)); this.errors.push(new ParserError(message, this.input, this.locationText(index), this.location));
this.skip(); this.skip();
} }
private locationText(index: number = null) { private locationText(index: number|null = null) {
if (index == null) index = this.index; if (index == null) index = this.index;
return (index < this.tokens.length) ? `at column ${this.tokens[index].index + 1} in` : return (index < this.tokens.length) ? `at column ${this.tokens[index].index + 1} in` :
`at the end of the expression`; `at the end of the expression`;
@ -766,8 +767,8 @@ export class _ParseAST {
(this.rbracesExpected <= 0 || !n.isCharacter(chars.$RBRACE)) && (this.rbracesExpected <= 0 || !n.isCharacter(chars.$RBRACE)) &&
(this.rbracketsExpected <= 0 || !n.isCharacter(chars.$RBRACKET))) { (this.rbracketsExpected <= 0 || !n.isCharacter(chars.$RBRACKET))) {
if (this.next.isError()) { if (this.next.isError()) {
this.errors.push( this.errors.push(new ParserError(
new ParserError(this.next.toString(), this.input, this.locationText(), this.location)); this.next.toString() !, this.input, this.locationText(), this.location));
} }
this.advance(); this.advance();
n = this.next; n = this.next;

View File

@ -70,11 +70,11 @@ export class Extractor {
} }
}); });
compMetas.forEach(compMeta => { compMetas.forEach(compMeta => {
const html = compMeta.template.template; const html = compMeta.template !.template !;
const interpolationConfig = const interpolationConfig =
InterpolationConfig.fromArray(compMeta.template.interpolation); InterpolationConfig.fromArray(compMeta.template !.interpolation);
errors.push( errors.push(...this.messageBundle.updateFromTemplate(
...this.messageBundle.updateFromTemplate(html, file.srcUrl, interpolationConfig)); html, file.srcUrl, interpolationConfig) !);
}); });
}); });

View File

@ -71,7 +71,7 @@ class _Visitor implements html.Visitor {
private _inIcu: boolean; private _inIcu: boolean;
// set to void 0 when not in a section // set to void 0 when not in a section
private _msgCountAtSectionStart: number; private _msgCountAtSectionStart: number|undefined;
private _errors: I18nError[]; private _errors: I18nError[];
private _mode: _VisitorMode; private _mode: _VisitorMode;
@ -111,7 +111,7 @@ class _Visitor implements html.Visitor {
this._translations = translations; this._translations = translations;
// Construct a single fake root element // Construct a single fake root element
const wrapper = new html.Element('wrapper', [], nodes, null, null, null); const wrapper = new html.Element('wrapper', [], nodes, undefined, undefined, undefined);
const translatedNode = wrapper.visit(this, null); const translatedNode = wrapper.visit(this, null);
@ -179,7 +179,8 @@ class _Visitor implements html.Visitor {
this._inI18nBlock = true; this._inI18nBlock = true;
this._blockStartDepth = this._depth; this._blockStartDepth = this._depth;
this._blockChildren = []; this._blockChildren = [];
this._blockMeaningAndDesc = comment.value.replace(_I18N_COMMENT_PREFIX_REGEXP, '').trim(); this._blockMeaningAndDesc =
comment.value !.replace(_I18N_COMMENT_PREFIX_REGEXP, '').trim();
this._openTranslatableSection(comment); this._openTranslatableSection(comment);
} }
} else { } else {
@ -187,7 +188,7 @@ class _Visitor implements html.Visitor {
if (this._depth == this._blockStartDepth) { if (this._depth == this._blockStartDepth) {
this._closeTranslatableSection(comment, this._blockChildren); this._closeTranslatableSection(comment, this._blockChildren);
this._inI18nBlock = false; this._inI18nBlock = false;
const message = this._addMessage(this._blockChildren, this._blockMeaningAndDesc); const message = this._addMessage(this._blockChildren, this._blockMeaningAndDesc) !;
// merge attributes in sections // merge attributes in sections
const nodes = this._translateMessage(comment, message); const nodes = this._translateMessage(comment, message);
return html.visitAll(this, nodes); return html.visitAll(this, nodes);
@ -207,13 +208,13 @@ class _Visitor implements html.Visitor {
return text; return text;
} }
visitElement(el: html.Element, context: any): html.Element { visitElement(el: html.Element, context: any): html.Element|null {
this._mayBeAddBlockChildren(el); this._mayBeAddBlockChildren(el);
this._depth++; this._depth++;
const wasInI18nNode = this._inI18nNode; const wasInI18nNode = this._inI18nNode;
const wasInImplicitNode = this._inImplicitNode; const wasInImplicitNode = this._inImplicitNode;
let childNodes: html.Node[] = []; let childNodes: html.Node[] = [];
let translatedChildNodes: html.Node[]; let translatedChildNodes: html.Node[] = undefined !;
// Extract: // Extract:
// - top level nodes with the (implicit) "i18n" attribute if not already in a section // - top level nodes with the (implicit) "i18n" attribute if not already in a section
@ -228,7 +229,7 @@ class _Visitor implements html.Visitor {
if (!this._isInTranslatableSection && !this._inIcu) { if (!this._isInTranslatableSection && !this._inIcu) {
if (i18nAttr || isTopLevelImplicit) { if (i18nAttr || isTopLevelImplicit) {
this._inI18nNode = true; this._inI18nNode = true;
const message = this._addMessage(el.children, i18nMeta); const message = this._addMessage(el.children, i18nMeta) !;
translatedChildNodes = this._translateMessage(el, message); translatedChildNodes = this._translateMessage(el, message);
} }
@ -274,6 +275,7 @@ class _Visitor implements html.Visitor {
el.name, translatedAttrs, childNodes, el.sourceSpan, el.startSourceSpan, el.name, translatedAttrs, childNodes, el.sourceSpan, el.startSourceSpan,
el.endSourceSpan); el.endSourceSpan);
} }
return null;
} }
visitAttribute(attribute: html.Attribute, context: any): any { visitAttribute(attribute: html.Attribute, context: any): any {
@ -286,7 +288,7 @@ class _Visitor implements html.Visitor {
this._inI18nNode = false; this._inI18nNode = false;
this._depth = 0; this._depth = 0;
this._inIcu = false; this._inIcu = false;
this._msgCountAtSectionStart = void 0; this._msgCountAtSectionStart = undefined;
this._errors = []; this._errors = [];
this._messages = []; this._messages = [];
this._inImplicitNode = false; this._inImplicitNode = false;
@ -313,11 +315,11 @@ class _Visitor implements html.Visitor {
} }
// add a translatable message // add a translatable message
private _addMessage(ast: html.Node[], msgMeta?: string): i18n.Message { private _addMessage(ast: html.Node[], msgMeta?: string): i18n.Message|null {
if (ast.length == 0 || if (ast.length == 0 ||
ast.length == 1 && ast[0] instanceof html.Attribute && !(<html.Attribute>ast[0]).value) { ast.length == 1 && ast[0] instanceof html.Attribute && !(<html.Attribute>ast[0]).value) {
// Do not create empty messages // Do not create empty messages
return; return null;
} }
const {meaning, description, id} = _parseMessageMeta(msgMeta); const {meaning, description, id} = _parseMessageMeta(msgMeta);
@ -463,27 +465,27 @@ class _Visitor implements html.Visitor {
} }
} }
this._msgCountAtSectionStart = void 0; this._msgCountAtSectionStart = undefined;
} }
private _reportError(node: html.Node, msg: string): void { private _reportError(node: html.Node, msg: string): void {
this._errors.push(new I18nError(node.sourceSpan, msg)); this._errors.push(new I18nError(node.sourceSpan !, msg));
} }
} }
function _isOpeningComment(n: html.Node): boolean { function _isOpeningComment(n: html.Node): boolean {
return n instanceof html.Comment && n.value && n.value.startsWith('i18n'); return !!(n instanceof html.Comment && n.value && n.value.startsWith('i18n'));
} }
function _isClosingComment(n: html.Node): boolean { function _isClosingComment(n: html.Node): boolean {
return n instanceof html.Comment && n.value && n.value === '/i18n'; return !!(n instanceof html.Comment && n.value && n.value === '/i18n');
} }
function _getI18nAttr(p: html.Element): html.Attribute { function _getI18nAttr(p: html.Element): html.Attribute|null {
return p.attrs.find(attr => attr.name === _I18N_ATTR) || null; return p.attrs.find(attr => attr.name === _I18N_ATTR) || null;
} }
function _parseMessageMeta(i18n: string): {meaning: string, description: string, id: string} { function _parseMessageMeta(i18n?: string): {meaning: string, description: string, id: string} {
if (!i18n) return {meaning: '', description: '', id: ''}; if (!i18n) return {meaning: '', description: '', id: ''};
const idIndex = i18n.indexOf(ID_SEPARATOR); const idIndex = i18n.indexOf(ID_SEPARATOR);

View File

@ -65,7 +65,7 @@ class _I18nVisitor implements html.Visitor {
const isVoid: boolean = getHtmlTagDefinition(el.name).isVoid; const isVoid: boolean = getHtmlTagDefinition(el.name).isVoid;
const startPhName = const startPhName =
this._placeholderRegistry.getStartTagPlaceholderName(el.name, attrs, isVoid); this._placeholderRegistry.getStartTagPlaceholderName(el.name, attrs, isVoid);
this._placeholderToContent[startPhName] = el.sourceSpan.toString(); this._placeholderToContent[startPhName] = el.sourceSpan !.toString();
let closePhName = ''; let closePhName = '';
@ -75,7 +75,7 @@ class _I18nVisitor implements html.Visitor {
} }
return new i18n.TagPlaceholder( return new i18n.TagPlaceholder(
el.name, attrs, startPhName, closePhName, children, isVoid, el.sourceSpan); el.name, attrs, startPhName, closePhName, children, isVoid, el.sourceSpan !);
} }
visitAttribute(attribute: html.Attribute, context: any): i18n.Node { visitAttribute(attribute: html.Attribute, context: any): i18n.Node {
@ -83,10 +83,10 @@ class _I18nVisitor implements html.Visitor {
} }
visitText(text: html.Text, context: any): i18n.Node { visitText(text: html.Text, context: any): i18n.Node {
return this._visitTextWithInterpolation(text.value, text.sourceSpan); return this._visitTextWithInterpolation(text.value, text.sourceSpan !);
} }
visitComment(comment: html.Comment, context: any): i18n.Node { return null; } visitComment(comment: html.Comment, context: any): i18n.Node|null { return null; }
visitExpansion(icu: html.Expansion, context: any): i18n.Node { visitExpansion(icu: html.Expansion, context: any): i18n.Node {
this._icuDepth++; this._icuDepth++;

View File

@ -26,7 +26,7 @@ export class MessageBundle {
private _implicitAttrs: {[k: string]: string[]}, private _locale: string|null = null) {} private _implicitAttrs: {[k: string]: string[]}, private _locale: string|null = null) {}
updateFromTemplate(html: string, url: string, interpolationConfig: InterpolationConfig): updateFromTemplate(html: string, url: string, interpolationConfig: InterpolationConfig):
ParseError[] { ParseError[]|null {
const htmlParserResult = this._htmlParser.parse(html, url, true, interpolationConfig); const htmlParserResult = this._htmlParser.parse(html, url, true, interpolationConfig);
if (htmlParserResult.errors.length) { if (htmlParserResult.errors.length) {
@ -41,6 +41,7 @@ export class MessageBundle {
} }
this._messages.push(...i18nParserResult.messages); this._messages.push(...i18nParserResult.messages);
return null;
} }
// Return the message in the internal format // Return the message in the internal format
@ -78,18 +79,18 @@ class MapPlaceholderNames extends i18n.CloneVisitor {
} }
visitTagPlaceholder(ph: i18n.TagPlaceholder, mapper: PlaceholderMapper): i18n.TagPlaceholder { visitTagPlaceholder(ph: i18n.TagPlaceholder, mapper: PlaceholderMapper): i18n.TagPlaceholder {
const startName = mapper.toPublicName(ph.startName); const startName = mapper.toPublicName(ph.startName) !;
const closeName = ph.closeName ? mapper.toPublicName(ph.closeName) : ph.closeName; const closeName = ph.closeName ? mapper.toPublicName(ph.closeName) ! : ph.closeName;
const children = ph.children.map(n => n.visit(this, mapper)); const children = ph.children.map(n => n.visit(this, mapper));
return new i18n.TagPlaceholder( return new i18n.TagPlaceholder(
ph.tag, ph.attrs, startName, closeName, children, ph.isVoid, ph.sourceSpan); ph.tag, ph.attrs, startName, closeName, children, ph.isVoid, ph.sourceSpan);
} }
visitPlaceholder(ph: i18n.Placeholder, mapper: PlaceholderMapper): i18n.Placeholder { visitPlaceholder(ph: i18n.Placeholder, mapper: PlaceholderMapper): i18n.Placeholder {
return new i18n.Placeholder(ph.value, mapper.toPublicName(ph.name), ph.sourceSpan); return new i18n.Placeholder(ph.value, mapper.toPublicName(ph.name) !, ph.sourceSpan);
} }
visitIcuPlaceholder(ph: i18n.IcuPlaceholder, mapper: PlaceholderMapper): i18n.IcuPlaceholder { visitIcuPlaceholder(ph: i18n.IcuPlaceholder, mapper: PlaceholderMapper): i18n.IcuPlaceholder {
return new i18n.IcuPlaceholder(ph.value, mapper.toPublicName(ph.name), ph.sourceSpan); return new i18n.IcuPlaceholder(ph.value, mapper.toPublicName(ph.name) !, ph.sourceSpan);
} }
} }

View File

@ -21,7 +21,7 @@ export abstract class Serializer {
// Creates a name mapper, see `PlaceholderMapper` // Creates a name mapper, see `PlaceholderMapper`
// Returning `null` means that no name mapping is used. // Returning `null` means that no name mapping is used.
createNameMapper(message: i18n.Message): PlaceholderMapper { return null; } createNameMapper(message: i18n.Message): PlaceholderMapper|null { return null; }
} }
/** /**
@ -31,9 +31,9 @@ export abstract class Serializer {
* It should be used for serialization format that put constraints on the placeholder names. * It should be used for serialization format that put constraints on the placeholder names.
*/ */
export interface PlaceholderMapper { export interface PlaceholderMapper {
toPublicName(internalName: string): string; toPublicName(internalName: string): string|null;
toInternalName(publicName: string): string; toInternalName(publicName: string): string|null;
} }
/** /**
@ -50,13 +50,13 @@ export class SimplePlaceholderMapper extends i18n.RecurseVisitor implements Plac
message.nodes.forEach(node => node.visit(this)); message.nodes.forEach(node => node.visit(this));
} }
toPublicName(internalName: string): string { toPublicName(internalName: string): string|null {
return this.internalToPublic.hasOwnProperty(internalName) ? return this.internalToPublic.hasOwnProperty(internalName) ?
this.internalToPublic[internalName] : this.internalToPublic[internalName] :
null; null;
} }
toInternalName(publicName: string): string { toInternalName(publicName: string): string|null {
return this.publicToInternal.hasOwnProperty(publicName) ? this.publicToInternal[publicName] : return this.publicToInternal.hasOwnProperty(publicName) ? this.publicToInternal[publicName] :
null; null;
} }

View File

@ -93,7 +93,7 @@ export class Xliff extends Serializer {
throw new Error(`xliff parse errors:\n${errors.join('\n')}`); throw new Error(`xliff parse errors:\n${errors.join('\n')}`);
} }
return {locale, i18nNodesByMsgId}; return {locale: locale !, i18nNodesByMsgId};
} }
digest(message: i18n.Message): string { return digest(message); } digest(message: i18n.Message): string { return digest(message); }
@ -150,7 +150,7 @@ class _WriteVisitor implements i18n.Visitor {
// TODO(vicb): add error management (structure) // TODO(vicb): add error management (structure)
// Extract messages as xml nodes from the xliff file // Extract messages as xml nodes from the xliff file
class XliffParser implements ml.Visitor { class XliffParser implements ml.Visitor {
private _unitMlString: string; private _unitMlString: string|null;
private _errors: I18nError[]; private _errors: I18nError[];
private _msgIdToHtml: {[msgId: string]: string}; private _msgIdToHtml: {[msgId: string]: string};
private _locale: string|null = null; private _locale: string|null = null;
@ -174,7 +174,7 @@ class XliffParser implements ml.Visitor {
visitElement(element: ml.Element, context: any): any { visitElement(element: ml.Element, context: any): any {
switch (element.name) { switch (element.name) {
case _UNIT_TAG: case _UNIT_TAG:
this._unitMlString = null; this._unitMlString = null !;
const idAttr = element.attrs.find((attr) => attr.name === 'id'); const idAttr = element.attrs.find((attr) => attr.name === 'id');
if (!idAttr) { if (!idAttr) {
this._addError(element, `<${_UNIT_TAG}> misses the "id" attribute`); this._addError(element, `<${_UNIT_TAG}> misses the "id" attribute`);
@ -198,9 +198,9 @@ class XliffParser implements ml.Visitor {
break; break;
case _TARGET_TAG: case _TARGET_TAG:
const innerTextStart = element.startSourceSpan.end.offset; const innerTextStart = element.startSourceSpan !.end.offset;
const innerTextEnd = element.endSourceSpan.start.offset; const innerTextEnd = element.endSourceSpan !.start.offset;
const content = element.startSourceSpan.start.file.content; const content = element.startSourceSpan !.start.file.content;
const innerText = content.slice(innerTextStart, innerTextEnd); const innerText = content.slice(innerTextStart, innerTextEnd);
this._unitMlString = innerText; this._unitMlString = innerText;
break; break;
@ -231,7 +231,7 @@ class XliffParser implements ml.Visitor {
visitExpansionCase(expansionCase: ml.ExpansionCase, context: any): any {} visitExpansionCase(expansionCase: ml.ExpansionCase, context: any): any {}
private _addError(node: ml.Node, message: string): void { private _addError(node: ml.Node, message: string): void {
this._errors.push(new I18nError(node.sourceSpan, message)); this._errors.push(new I18nError(node.sourceSpan !, message));
} }
} }
@ -253,19 +253,20 @@ class XmlToI18n implements ml.Visitor {
}; };
} }
visitText(text: ml.Text, context: any) { return new i18n.Text(text.value, text.sourceSpan); } visitText(text: ml.Text, context: any) { return new i18n.Text(text.value, text.sourceSpan !); }
visitElement(el: ml.Element, context: any): i18n.Placeholder { visitElement(el: ml.Element, context: any): i18n.Placeholder|null {
if (el.name === _PLACEHOLDER_TAG) { if (el.name === _PLACEHOLDER_TAG) {
const nameAttr = el.attrs.find((attr) => attr.name === 'id'); const nameAttr = el.attrs.find((attr) => attr.name === 'id');
if (nameAttr) { if (nameAttr) {
return new i18n.Placeholder('', nameAttr.value, el.sourceSpan); return new i18n.Placeholder('', nameAttr.value, el.sourceSpan !);
} }
this._addError(el, `<${_PLACEHOLDER_TAG}> misses the "id" attribute`); this._addError(el, `<${_PLACEHOLDER_TAG}> misses the "id" attribute`);
} else { } else {
this._addError(el, `Unexpected tag`); this._addError(el, `Unexpected tag`);
} }
return null;
} }
visitExpansion(icu: ml.Expansion, context: any) { visitExpansion(icu: ml.Expansion, context: any) {
@ -290,7 +291,7 @@ class XmlToI18n implements ml.Visitor {
visitAttribute(attribute: ml.Attribute, context: any) {} visitAttribute(attribute: ml.Attribute, context: any) {}
private _addError(node: ml.Node, message: string): void { private _addError(node: ml.Node, message: string): void {
this._errors.push(new I18nError(node.sourceSpan, message)); this._errors.push(new I18nError(node.sourceSpan !, message));
} }
} }

View File

@ -49,7 +49,7 @@ export class Xtb extends Serializer {
throw new Error(`xtb parse errors:\n${errors.join('\n')}`); throw new Error(`xtb parse errors:\n${errors.join('\n')}`);
} }
return {locale, i18nNodesByMsgId}; return {locale: locale !, i18nNodesByMsgId};
} }
digest(message: i18n.Message): string { return digest(message); } digest(message: i18n.Message): string { return digest(message); }
@ -121,10 +121,10 @@ class XtbParser implements ml.Visitor {
if (this._msgIdToHtml.hasOwnProperty(id)) { if (this._msgIdToHtml.hasOwnProperty(id)) {
this._addError(element, `Duplicated translations for msg ${id}`); this._addError(element, `Duplicated translations for msg ${id}`);
} else { } else {
const innerTextStart = element.startSourceSpan.end.offset; const innerTextStart = element.startSourceSpan !.end.offset;
const innerTextEnd = element.endSourceSpan.start.offset; const innerTextEnd = element.endSourceSpan !.start.offset;
const content = element.startSourceSpan.start.file.content; const content = element.startSourceSpan !.start.file.content;
const innerText = content.slice(innerTextStart, innerTextEnd); const innerText = content.slice(innerTextStart !, innerTextEnd !);
this._msgIdToHtml[id] = innerText; this._msgIdToHtml[id] = innerText;
} }
} }
@ -146,7 +146,7 @@ class XtbParser implements ml.Visitor {
visitExpansionCase(expansionCase: ml.ExpansionCase, context: any): any {} visitExpansionCase(expansionCase: ml.ExpansionCase, context: any): any {}
private _addError(node: ml.Node, message: string): void { private _addError(node: ml.Node, message: string): void {
this._errors.push(new I18nError(node.sourceSpan, message)); this._errors.push(new I18nError(node.sourceSpan !, message));
} }
} }
@ -168,7 +168,7 @@ class XmlToI18n implements ml.Visitor {
}; };
} }
visitText(text: ml.Text, context: any) { return new i18n.Text(text.value, text.sourceSpan); } visitText(text: ml.Text, context: any) { return new i18n.Text(text.value, text.sourceSpan !); }
visitExpansion(icu: ml.Expansion, context: any) { visitExpansion(icu: ml.Expansion, context: any) {
const caseMap: {[value: string]: i18n.Node} = {}; const caseMap: {[value: string]: i18n.Node} = {};
@ -187,17 +187,18 @@ class XmlToI18n implements ml.Visitor {
}; };
} }
visitElement(el: ml.Element, context: any): i18n.Placeholder { visitElement(el: ml.Element, context: any): i18n.Placeholder|null {
if (el.name === _PLACEHOLDER_TAG) { if (el.name === _PLACEHOLDER_TAG) {
const nameAttr = el.attrs.find((attr) => attr.name === 'name'); const nameAttr = el.attrs.find((attr) => attr.name === 'name');
if (nameAttr) { if (nameAttr) {
return new i18n.Placeholder('', nameAttr.value, el.sourceSpan); return new i18n.Placeholder('', nameAttr.value, el.sourceSpan !);
} }
this._addError(el, `<${_PLACEHOLDER_TAG}> misses the "name" attribute`); this._addError(el, `<${_PLACEHOLDER_TAG}> misses the "name" attribute`);
} else { } else {
this._addError(el, `Unexpected tag`); this._addError(el, `Unexpected tag`);
} }
return null;
} }
visitComment(comment: ml.Comment, context: any) {} visitComment(comment: ml.Comment, context: any) {}
@ -205,6 +206,6 @@ class XmlToI18n implements ml.Visitor {
visitAttribute(attribute: ml.Attribute, context: any) {} visitAttribute(attribute: ml.Attribute, context: any) {}
private _addError(node: ml.Node, message: string): void { private _addError(node: ml.Node, message: string): void {
this._errors.push(new I18nError(node.sourceSpan, message)); this._errors.push(new I18nError(node.sourceSpan !, message));
} }
} }

View File

@ -26,7 +26,7 @@ export class TranslationBundle {
missingTranslationStrategy: MissingTranslationStrategy = MissingTranslationStrategy.Warning, missingTranslationStrategy: MissingTranslationStrategy = MissingTranslationStrategy.Warning,
console?: Console) { console?: Console) {
this._i18nToHtml = new I18nToHtmlVisitor( this._i18nToHtml = new I18nToHtmlVisitor(
_i18nNodesByMsgId, locale, digest, mapperFactory, missingTranslationStrategy, console); _i18nNodesByMsgId, locale, digest, mapperFactory !, missingTranslationStrategy, console);
} }
// Creates a `TranslationBundle` by parsing the given `content` with the `serializer`. // Creates a `TranslationBundle` by parsing the given `content` with the `serializer`.
@ -36,7 +36,7 @@ export class TranslationBundle {
console?: Console): TranslationBundle { console?: Console): TranslationBundle {
const {locale, i18nNodesByMsgId} = serializer.load(content, url); const {locale, i18nNodesByMsgId} = serializer.load(content, url);
const digestFn = (m: i18n.Message) => serializer.digest(m); const digestFn = (m: i18n.Message) => serializer.digest(m);
const mapperFactory = (m: i18n.Message) => serializer.createNameMapper(m); const mapperFactory = (m: i18n.Message) => serializer.createNameMapper(m) !;
return new TranslationBundle( return new TranslationBundle(
i18nNodesByMsgId, locale, digestFn, mapperFactory, missingTranslationStrategy, console); i18nNodesByMsgId, locale, digestFn, mapperFactory, missingTranslationStrategy, console);
} }
@ -156,7 +156,7 @@ class I18nToHtmlVisitor implements i18n.Visitor {
// When there is a translation use its nodes as the source // When there is a translation use its nodes as the source
// And create a mapper to convert serialized placeholder names to internal names // And create a mapper to convert serialized placeholder names to internal names
nodes = this._i18nNodesByMsgId[id]; nodes = this._i18nNodesByMsgId[id];
this._mapper = (name: string) => mapper ? mapper.toInternalName(name) : name; this._mapper = (name: string) => mapper ? mapper.toInternalName(name) ! : name;
} else { } else {
// When no translation has been found // When no translation has been found
// - report an error / a warning / nothing, // - report an error / a warning / nothing,
@ -175,7 +175,7 @@ class I18nToHtmlVisitor implements i18n.Visitor {
this._mapper = (name: string) => name; this._mapper = (name: string) => name;
} }
const text = nodes.map(node => node.visit(this)).join(''); const text = nodes.map(node => node.visit(this)).join('');
const context = this._contextStack.pop(); const context = this._contextStack.pop() !;
this._srcMsg = context.msg; this._srcMsg = context.msg;
this._mapper = context.mapper; this._mapper = context.mapper;
return text; return text;

View File

@ -112,7 +112,7 @@ export class Identifiers {
static createComponentFactory: IdentifierSpec = {name: 'ɵccf', moduleUrl: CORE, runtime: ɵccf}; static createComponentFactory: IdentifierSpec = {name: 'ɵccf', moduleUrl: CORE, runtime: ɵccf};
} }
export function assetUrl(pkg: string, path: string = null, type: string = 'src'): string { export function assetUrl(pkg: string, path: string | null = null, type: string = 'src'): string {
if (path == null) { if (path == null) {
return `@angular/${pkg}`; return `@angular/${pkg}`;
} else { } else {

View File

@ -49,20 +49,20 @@ export class JitCompiler implements Compiler {
get injector(): Injector { return this._injector; } get injector(): Injector { return this._injector; }
compileModuleSync<T>(moduleType: Type<T>): NgModuleFactory<T> { compileModuleSync<T>(moduleType: Type<T>): NgModuleFactory<T> {
return this._compileModuleAndComponents(moduleType, true).syncResult; return this._compileModuleAndComponents(moduleType, true).syncResult !;
} }
compileModuleAsync<T>(moduleType: Type<T>): Promise<NgModuleFactory<T>> { compileModuleAsync<T>(moduleType: Type<T>): Promise<NgModuleFactory<T>> {
return this._compileModuleAndComponents(moduleType, false).asyncResult; return this._compileModuleAndComponents(moduleType, false).asyncResult !;
} }
compileModuleAndAllComponentsSync<T>(moduleType: Type<T>): ModuleWithComponentFactories<T> { compileModuleAndAllComponentsSync<T>(moduleType: Type<T>): ModuleWithComponentFactories<T> {
return this._compileModuleAndAllComponents(moduleType, true).syncResult; return this._compileModuleAndAllComponents(moduleType, true).syncResult !;
} }
compileModuleAndAllComponentsAsync<T>(moduleType: Type<T>): compileModuleAndAllComponentsAsync<T>(moduleType: Type<T>):
Promise<ModuleWithComponentFactories<T>> { Promise<ModuleWithComponentFactories<T>> {
return this._compileModuleAndAllComponents(moduleType, false).asyncResult; return this._compileModuleAndAllComponents(moduleType, false).asyncResult !;
} }
getNgContentSelectors(component: Type<any>): string[] { getNgContentSelectors(component: Type<any>): string[] {
@ -72,7 +72,7 @@ export class JitCompiler implements Compiler {
if (!template) { if (!template) {
throw new Error(`The component ${stringify(component)} is not yet compiled!`); throw new Error(`The component ${stringify(component)} is not yet compiled!`);
} }
return template.compMeta.template.ngContentSelectors; return template.compMeta.template !.ngContentSelectors;
} }
private _compileModuleAndComponents<T>(moduleType: Type<T>, isSync: boolean): private _compileModuleAndComponents<T>(moduleType: Type<T>, isSync: boolean):
@ -106,7 +106,7 @@ export class JitCompiler implements Compiler {
private _loadModules(mainModule: any, isSync: boolean): Promise<any> { private _loadModules(mainModule: any, isSync: boolean): Promise<any> {
const loadingPromises: Promise<any>[] = []; const loadingPromises: Promise<any>[] = [];
const ngModule = this._metadataResolver.getNgModuleMetadata(mainModule); const ngModule = this._metadataResolver.getNgModuleMetadata(mainModule) !;
// Note: the loadingPromise for a module only includes the loading of the exported directives // Note: the loadingPromise for a module only includes the loading of the exported directives
// of imported modules. // of imported modules.
// However, for runtime compilation, we want to transitively compile all modules, // However, for runtime compilation, we want to transitively compile all modules,
@ -119,9 +119,9 @@ export class JitCompiler implements Compiler {
} }
private _compileModule<T>(moduleType: Type<T>): NgModuleFactory<T> { private _compileModule<T>(moduleType: Type<T>): NgModuleFactory<T> {
let ngModuleFactory = this._compiledNgModuleCache.get(moduleType); let ngModuleFactory = this._compiledNgModuleCache.get(moduleType) !;
if (!ngModuleFactory) { if (!ngModuleFactory) {
const moduleMeta = this._metadataResolver.getNgModuleMetadata(moduleType); const moduleMeta = this._metadataResolver.getNgModuleMetadata(moduleType) !;
// Always provide a bound Compiler // Always provide a bound Compiler
const extraProviders = [this._metadataResolver.getProviderMetadata(new ProviderMeta( const extraProviders = [this._metadataResolver.getProviderMetadata(new ProviderMeta(
Compiler, {useFactory: () => new ModuleBoundCompiler(this, moduleMeta.type.reference)}))]; Compiler, {useFactory: () => new ModuleBoundCompiler(this, moduleMeta.type.reference)}))];
@ -142,14 +142,14 @@ export class JitCompiler implements Compiler {
/** /**
* @internal * @internal
*/ */
_compileComponents(mainModule: Type<any>, allComponentFactories: ComponentFactory<any>[]) { _compileComponents(mainModule: Type<any>, allComponentFactories: ComponentFactory<any>[]|null) {
const ngModule = this._metadataResolver.getNgModuleMetadata(mainModule); const ngModule = this._metadataResolver.getNgModuleMetadata(mainModule) !;
const moduleByDirective = new Map<any, CompileNgModuleMetadata>(); const moduleByDirective = new Map<any, CompileNgModuleMetadata>();
const templates = new Set<CompiledTemplate>(); const templates = new Set<CompiledTemplate>();
ngModule.transitiveModule.modules.forEach((localModuleSummary) => { ngModule.transitiveModule.modules.forEach((localModuleSummary) => {
const localModuleMeta = const localModuleMeta =
this._metadataResolver.getNgModuleMetadata(localModuleSummary.reference); this._metadataResolver.getNgModuleMetadata(localModuleSummary.reference) !;
localModuleMeta.declaredDirectives.forEach((dirIdentifier) => { localModuleMeta.declaredDirectives.forEach((dirIdentifier) => {
moduleByDirective.set(dirIdentifier.reference, localModuleMeta); moduleByDirective.set(dirIdentifier.reference, localModuleMeta);
const dirMeta = this._metadataResolver.getDirectiveMetadata(dirIdentifier.reference); const dirMeta = this._metadataResolver.getDirectiveMetadata(dirIdentifier.reference);
@ -166,19 +166,19 @@ export class JitCompiler implements Compiler {
}); });
ngModule.transitiveModule.modules.forEach((localModuleSummary) => { ngModule.transitiveModule.modules.forEach((localModuleSummary) => {
const localModuleMeta = const localModuleMeta =
this._metadataResolver.getNgModuleMetadata(localModuleSummary.reference); this._metadataResolver.getNgModuleMetadata(localModuleSummary.reference) !;
localModuleMeta.declaredDirectives.forEach((dirIdentifier) => { localModuleMeta.declaredDirectives.forEach((dirIdentifier) => {
const dirMeta = this._metadataResolver.getDirectiveMetadata(dirIdentifier.reference); const dirMeta = this._metadataResolver.getDirectiveMetadata(dirIdentifier.reference);
if (dirMeta.isComponent) { if (dirMeta.isComponent) {
dirMeta.entryComponents.forEach((entryComponentType) => { dirMeta.entryComponents.forEach((entryComponentType) => {
const moduleMeta = moduleByDirective.get(entryComponentType.componentType); const moduleMeta = moduleByDirective.get(entryComponentType.componentType) !;
templates.add( templates.add(
this._createCompiledHostTemplate(entryComponentType.componentType, moduleMeta)); this._createCompiledHostTemplate(entryComponentType.componentType, moduleMeta));
}); });
} }
}); });
localModuleMeta.entryComponents.forEach((entryComponentType) => { localModuleMeta.entryComponents.forEach((entryComponentType) => {
const moduleMeta = moduleByDirective.get(entryComponentType.componentType); const moduleMeta = moduleByDirective.get(entryComponentType.componentType) !;
templates.add( templates.add(
this._createCompiledHostTemplate(entryComponentType.componentType, moduleMeta)); this._createCompiledHostTemplate(entryComponentType.componentType, moduleMeta));
}); });
@ -245,7 +245,7 @@ export class JitCompiler implements Compiler {
const externalStylesheetsByModuleUrl = new Map<string, CompiledStylesheet>(); const externalStylesheetsByModuleUrl = new Map<string, CompiledStylesheet>();
const stylesCompileResult = this._styleCompiler.compileComponent(compMeta); const stylesCompileResult = this._styleCompiler.compileComponent(compMeta);
stylesCompileResult.externalStylesheets.forEach( stylesCompileResult.externalStylesheets.forEach(
(r) => { externalStylesheetsByModuleUrl.set(r.meta.moduleUrl, r); }); (r) => { externalStylesheetsByModuleUrl.set(r.meta.moduleUrl !, r); });
this._resolveStylesCompileResult( this._resolveStylesCompileResult(
stylesCompileResult.componentStylesheet, externalStylesheetsByModuleUrl); stylesCompileResult.componentStylesheet, externalStylesheetsByModuleUrl);
const directives = const directives =
@ -253,8 +253,8 @@ export class JitCompiler implements Compiler {
const pipes = template.ngModule.transitiveModule.pipes.map( const pipes = template.ngModule.transitiveModule.pipes.map(
pipe => this._metadataResolver.getPipeSummary(pipe.reference)); pipe => this._metadataResolver.getPipeSummary(pipe.reference));
const {template: parsedTemplate, pipes: usedPipes} = this._templateParser.parse( const {template: parsedTemplate, pipes: usedPipes} = this._templateParser.parse(
compMeta, compMeta.template.template, directives, pipes, template.ngModule.schemas, compMeta, compMeta.template !.template !, directives, pipes, template.ngModule.schemas,
templateSourceUrl(template.ngModule.type, template.compMeta, template.compMeta.template)); templateSourceUrl(template.ngModule.type, template.compMeta, template.compMeta.template !));
const compileResult = this._viewCompiler.compileComponent( const compileResult = this._viewCompiler.compileComponent(
compMeta, parsedTemplate, ir.variable(stylesCompileResult.componentStylesheet.stylesVar), compMeta, parsedTemplate, ir.variable(stylesCompileResult.componentStylesheet.stylesVar),
usedPipes); usedPipes);
@ -278,7 +278,7 @@ export class JitCompiler implements Compiler {
private _resolveStylesCompileResult( private _resolveStylesCompileResult(
result: CompiledStylesheet, externalStylesheetsByModuleUrl: Map<string, CompiledStylesheet>) { result: CompiledStylesheet, externalStylesheetsByModuleUrl: Map<string, CompiledStylesheet>) {
result.dependencies.forEach((dep, i) => { result.dependencies.forEach((dep, i) => {
const nestedCompileResult = externalStylesheetsByModuleUrl.get(dep.moduleUrl); const nestedCompileResult = externalStylesheetsByModuleUrl.get(dep.moduleUrl) !;
const nestedStylesArr = this._resolveAndEvalStylesCompileResult( const nestedStylesArr = this._resolveAndEvalStylesCompileResult(
nestedCompileResult, externalStylesheetsByModuleUrl); nestedCompileResult, externalStylesheetsByModuleUrl);
dep.valuePlaceholder.reference = nestedStylesArr; dep.valuePlaceholder.reference = nestedStylesArr;
@ -300,7 +300,7 @@ export class JitCompiler implements Compiler {
} }
class CompiledTemplate { class CompiledTemplate {
private _viewClass: Function = null; private _viewClass: Function = null !;
isCompiled = false; isCompiled = false;
constructor( constructor(

View File

@ -59,7 +59,7 @@ export const COMPILER_PROVIDERS: Array<any|Type<any>|{[k: string]: any}|any[]> =
useFactory: (parser: HtmlParser, translations: string, format: string, config: CompilerConfig, useFactory: (parser: HtmlParser, translations: string, format: string, config: CompilerConfig,
console: Console) => console: Console) =>
new i18n.I18NHtmlParser( new i18n.I18NHtmlParser(
parser, translations, format, config.missingTranslation, console), parser, translations, format, config.missingTranslation !, console),
deps: [ deps: [
baseHtmlParser, baseHtmlParser,
[new Optional(), new Inject(TRANSLATIONS)], [new Optional(), new Inject(TRANSLATIONS)],
@ -123,7 +123,7 @@ export class JitCompilerFactory implements CompilerFactory {
}, },
deps: [] deps: []
}, },
opts.providers opts.providers !
]); ]);
return injector.get(Compiler); return injector.get(Compiler);
} }
@ -148,12 +148,12 @@ function _mergeOptions(optionsArr: CompilerOptions[]): CompilerOptions {
return { return {
useJit: _lastDefined(optionsArr.map(options => options.useJit)), useJit: _lastDefined(optionsArr.map(options => options.useJit)),
defaultEncapsulation: _lastDefined(optionsArr.map(options => options.defaultEncapsulation)), defaultEncapsulation: _lastDefined(optionsArr.map(options => options.defaultEncapsulation)),
providers: _mergeArrays(optionsArr.map(options => options.providers)), providers: _mergeArrays(optionsArr.map(options => options.providers !)),
missingTranslation: _lastDefined(optionsArr.map(options => options.missingTranslation)), missingTranslation: _lastDefined(optionsArr.map(options => options.missingTranslation)),
}; };
} }
function _lastDefined<T>(args: T[]): T { function _lastDefined<T>(args: T[]): T|undefined {
for (let i = args.length - 1; i >= 0; i--) { for (let i = args.length - 1; i >= 0; i--) {
if (args[i] !== undefined) { if (args[i] !== undefined) {
return args[i]; return args[i];

View File

@ -23,7 +23,7 @@ import {PipeResolver} from './pipe_resolver';
import {ElementSchemaRegistry} from './schema/element_schema_registry'; import {ElementSchemaRegistry} from './schema/element_schema_registry';
import {SummaryResolver} from './summary_resolver'; import {SummaryResolver} from './summary_resolver';
import {getUrlScheme} from './url_resolver'; import {getUrlScheme} from './url_resolver';
import {MODULE_SUFFIX, ValueTransformer, syntaxError, visitValue} from './util'; import {MODULE_SUFFIX, ValueTransformer, noUndefined, syntaxError, visitValue} from './util';
export type ErrorCollector = (error: any, type?: any) => void; export type ErrorCollector = (error: any, type?: any) => void;
export const ERROR_COLLECTOR_TOKEN = new InjectionToken('ErrorCollector'); export const ERROR_COLLECTOR_TOKEN = new InjectionToken('ErrorCollector');
@ -40,7 +40,7 @@ export class CompileMetadataResolver {
private _nonNormalizedDirectiveCache = private _nonNormalizedDirectiveCache =
new Map<Type<any>, {annotation: Directive, metadata: cpl.CompileDirectiveMetadata}>(); new Map<Type<any>, {annotation: Directive, metadata: cpl.CompileDirectiveMetadata}>();
private _directiveCache = new Map<Type<any>, cpl.CompileDirectiveMetadata>(); private _directiveCache = new Map<Type<any>, cpl.CompileDirectiveMetadata>();
private _summaryCache = new Map<Type<any>, cpl.CompileTypeSummary>(); private _summaryCache = new Map<Type<any>, cpl.CompileTypeSummary|null>();
private _pipeCache = new Map<Type<any>, cpl.CompilePipeMetadata>(); private _pipeCache = new Map<Type<any>, cpl.CompilePipeMetadata>();
private _ngModuleCache = new Map<Type<any>, cpl.CompileNgModuleMetadata>(); private _ngModuleCache = new Map<Type<any>, cpl.CompileNgModuleMetadata>();
private _ngModuleOfTypes = new Map<Type<any>, Type<any>>(); private _ngModuleOfTypes = new Map<Type<any>, Type<any>>();
@ -137,7 +137,7 @@ export class CompileMetadataResolver {
} }
private getComponentFactory( private getComponentFactory(
selector: string, dirType: any, inputs: {[key: string]: string}, selector: string, dirType: any, inputs: {[key: string]: string}|null,
outputs: {[key: string]: string}): StaticSymbol|ComponentFactory<any> { outputs: {[key: string]: string}): StaticSymbol|ComponentFactory<any> {
if (dirType instanceof StaticSymbol) { if (dirType instanceof StaticSymbol) {
return this._staticSymbolCache.get( return this._staticSymbolCache.get(
@ -157,26 +157,27 @@ export class CompileMetadataResolver {
} }
} }
private _loadSummary(type: any, kind: cpl.CompileSummaryKind): cpl.CompileTypeSummary { private _loadSummary(type: any, kind: cpl.CompileSummaryKind): cpl.CompileTypeSummary|null {
let typeSummary = this._summaryCache.get(type); let typeSummary = this._summaryCache.get(type);
if (!typeSummary) { if (!typeSummary) {
const summary = this._summaryResolver.resolveSummary(type); const summary = this._summaryResolver.resolveSummary(type);
typeSummary = summary ? summary.type : null; typeSummary = summary ? summary.type : null;
this._summaryCache.set(type, typeSummary); this._summaryCache.set(type, typeSummary || null);
} }
return typeSummary && typeSummary.summaryKind === kind ? typeSummary : null; return typeSummary && typeSummary.summaryKind === kind ? typeSummary : null;
} }
private _loadDirectiveMetadata(ngModuleType: any, directiveType: any, isSync: boolean): private _loadDirectiveMetadata(ngModuleType: any, directiveType: any, isSync: boolean):
Promise<any> { Promise<any>|null {
if (this._directiveCache.has(directiveType)) { if (this._directiveCache.has(directiveType)) {
return; return null;
} }
directiveType = resolveForwardRef(directiveType); directiveType = resolveForwardRef(directiveType);
const {annotation, metadata} = this.getNonNormalizedDirectiveMetadata(directiveType); const {annotation, metadata} = this.getNonNormalizedDirectiveMetadata(directiveType) !;
const createDirectiveMetadata = (templateMetadata: cpl.CompileTemplateMetadata) => { const createDirectiveMetadata = (templateMetadata: cpl.CompileTemplateMetadata | null) => {
const normalizedDirMeta = new cpl.CompileDirectiveMetadata({ const normalizedDirMeta = new cpl.CompileDirectiveMetadata({
isHost: false,
type: metadata.type, type: metadata.type,
isComponent: metadata.isComponent, isComponent: metadata.isComponent,
selector: metadata.selector, selector: metadata.selector,
@ -198,7 +199,7 @@ export class CompileMetadataResolver {
template: templateMetadata template: templateMetadata
}); });
if (templateMetadata) { if (templateMetadata) {
this.initComponentFactory(metadata.componentFactory, templateMetadata.ngContentSelectors); this.initComponentFactory(metadata.componentFactory !, templateMetadata.ngContentSelectors);
} }
this._directiveCache.set(directiveType, normalizedDirMeta); this._directiveCache.set(directiveType, normalizedDirMeta);
this._summaryCache.set(directiveType, normalizedDirMeta.toSummary()); this._summaryCache.set(directiveType, normalizedDirMeta.toSummary());
@ -206,17 +207,18 @@ export class CompileMetadataResolver {
}; };
if (metadata.isComponent) { if (metadata.isComponent) {
const template = metadata.template !;
const templateMeta = this._directiveNormalizer.normalizeTemplate({ const templateMeta = this._directiveNormalizer.normalizeTemplate({
ngModuleType, ngModuleType,
componentType: directiveType, componentType: directiveType,
moduleUrl: componentModuleUrl(this._reflector, directiveType, annotation), moduleUrl: componentModuleUrl(this._reflector, directiveType, annotation),
encapsulation: metadata.template.encapsulation, encapsulation: template.encapsulation,
template: metadata.template.template, template: template.template,
templateUrl: metadata.template.templateUrl, templateUrl: template.templateUrl,
styles: metadata.template.styles, styles: template.styles,
styleUrls: metadata.template.styleUrls, styleUrls: template.styleUrls,
animations: metadata.template.animations, animations: template.animations,
interpolation: metadata.template.interpolation interpolation: template.interpolation
}); });
if (templateMeta.syncResult) { if (templateMeta.syncResult) {
createDirectiveMetadata(templateMeta.syncResult); createDirectiveMetadata(templateMeta.syncResult);
@ -226,7 +228,7 @@ export class CompileMetadataResolver {
this._reportError(componentStillLoadingError(directiveType), directiveType); this._reportError(componentStillLoadingError(directiveType), directiveType);
return null; return null;
} }
return templateMeta.asyncResult.then(createDirectiveMetadata); return templateMeta.asyncResult !.then(createDirectiveMetadata);
} }
} else { } else {
// directive // directive
@ -236,7 +238,7 @@ export class CompileMetadataResolver {
} }
getNonNormalizedDirectiveMetadata(directiveType: any): getNonNormalizedDirectiveMetadata(directiveType: any):
{annotation: Directive, metadata: cpl.CompileDirectiveMetadata} { {annotation: Directive, metadata: cpl.CompileDirectiveMetadata}|null {
directiveType = resolveForwardRef(directiveType); directiveType = resolveForwardRef(directiveType);
if (!directiveType) { if (!directiveType) {
return null; return null;
@ -249,7 +251,7 @@ export class CompileMetadataResolver {
if (!dirMeta) { if (!dirMeta) {
return null; return null;
} }
let nonNormalizedTemplateMetadata: cpl.CompileTemplateMetadata; let nonNormalizedTemplateMetadata: cpl.CompileTemplateMetadata = undefined !;
if (dirMeta instanceof Component) { if (dirMeta instanceof Component) {
// component // component
@ -260,25 +262,27 @@ export class CompileMetadataResolver {
const animations = dirMeta.animations; const animations = dirMeta.animations;
nonNormalizedTemplateMetadata = new cpl.CompileTemplateMetadata({ nonNormalizedTemplateMetadata = new cpl.CompileTemplateMetadata({
encapsulation: dirMeta.encapsulation, encapsulation: noUndefined(dirMeta.encapsulation),
template: dirMeta.template, template: noUndefined(dirMeta.template),
templateUrl: dirMeta.templateUrl, templateUrl: noUndefined(dirMeta.templateUrl),
styles: dirMeta.styles, styles: dirMeta.styles || [],
styleUrls: dirMeta.styleUrls, styleUrls: dirMeta.styleUrls || [],
animations: animations, animations: animations || [],
interpolation: dirMeta.interpolation, interpolation: noUndefined(dirMeta.interpolation),
isInline: !!dirMeta.template isInline: !!dirMeta.template,
externalStylesheets: [],
ngContentSelectors: []
}); });
} }
let changeDetectionStrategy: ChangeDetectionStrategy = null; let changeDetectionStrategy: ChangeDetectionStrategy = null !;
let viewProviders: cpl.CompileProviderMetadata[] = []; let viewProviders: cpl.CompileProviderMetadata[] = [];
let entryComponentMetadata: cpl.CompileEntryComponentMetadata[] = []; let entryComponentMetadata: cpl.CompileEntryComponentMetadata[] = [];
let selector = dirMeta.selector; let selector = dirMeta.selector;
if (dirMeta instanceof Component) { if (dirMeta instanceof Component) {
// Component // Component
changeDetectionStrategy = dirMeta.changeDetection; changeDetectionStrategy = dirMeta.changeDetection !;
if (dirMeta.viewProviders) { if (dirMeta.viewProviders) {
viewProviders = this._getProvidersMetadata( viewProviders = this._getProvidersMetadata(
dirMeta.viewProviders, entryComponentMetadata, dirMeta.viewProviders, entryComponentMetadata,
@ -286,7 +290,7 @@ export class CompileMetadataResolver {
} }
if (dirMeta.entryComponents) { if (dirMeta.entryComponents) {
entryComponentMetadata = flattenAndDedupeArray(dirMeta.entryComponents) entryComponentMetadata = flattenAndDedupeArray(dirMeta.entryComponents)
.map((type) => this._getEntryComponentMetadata(type)) .map((type) => this._getEntryComponentMetadata(type) !)
.concat(entryComponentMetadata); .concat(entryComponentMetadata);
} }
if (!selector) { if (!selector) {
@ -317,24 +321,25 @@ export class CompileMetadataResolver {
} }
const metadata = cpl.CompileDirectiveMetadata.create({ const metadata = cpl.CompileDirectiveMetadata.create({
isHost: false,
selector: selector, selector: selector,
exportAs: dirMeta.exportAs, exportAs: noUndefined(dirMeta.exportAs),
isComponent: !!nonNormalizedTemplateMetadata, isComponent: !!nonNormalizedTemplateMetadata,
type: this._getTypeMetadata(directiveType), type: this._getTypeMetadata(directiveType),
template: nonNormalizedTemplateMetadata, template: nonNormalizedTemplateMetadata,
changeDetection: changeDetectionStrategy, changeDetection: changeDetectionStrategy,
inputs: dirMeta.inputs, inputs: dirMeta.inputs || [],
outputs: dirMeta.outputs, outputs: dirMeta.outputs || [],
host: dirMeta.host, host: dirMeta.host || {},
providers: providers, providers: providers || [],
viewProviders: viewProviders, viewProviders: viewProviders || [],
queries: queries, queries: queries || [],
viewQueries: viewQueries, viewQueries: viewQueries || [],
entryComponents: entryComponentMetadata, entryComponents: entryComponentMetadata,
componentViewType: nonNormalizedTemplateMetadata ? this.getComponentViewClass(directiveType) : componentViewType: nonNormalizedTemplateMetadata ? this.getComponentViewClass(directiveType) :
undefined, null,
rendererType: nonNormalizedTemplateMetadata ? this.getRendererType(directiveType) : undefined, rendererType: nonNormalizedTemplateMetadata ? this.getRendererType(directiveType) : null,
componentFactory: undefined componentFactory: null
}); });
if (nonNormalizedTemplateMetadata) { if (nonNormalizedTemplateMetadata) {
metadata.componentFactory = metadata.componentFactory =
@ -350,7 +355,7 @@ export class CompileMetadataResolver {
* This assumes `loadNgModuleDirectiveAndPipeMetadata` has been called first. * This assumes `loadNgModuleDirectiveAndPipeMetadata` has been called first.
*/ */
getDirectiveMetadata(directiveType: any): cpl.CompileDirectiveMetadata { getDirectiveMetadata(directiveType: any): cpl.CompileDirectiveMetadata {
const dirMeta = this._directiveCache.get(directiveType); const dirMeta = this._directiveCache.get(directiveType) !;
if (!dirMeta) { if (!dirMeta) {
this._reportError( this._reportError(
syntaxError( syntaxError(
@ -376,8 +381,8 @@ export class CompileMetadataResolver {
isPipe(type: any) { return this._pipeResolver.isPipe(type); } isPipe(type: any) { return this._pipeResolver.isPipe(type); }
getNgModuleSummary(moduleType: any): cpl.CompileNgModuleSummary { getNgModuleSummary(moduleType: any): cpl.CompileNgModuleSummary|null {
let moduleSummary = let moduleSummary: cpl.CompileNgModuleSummary|null =
<cpl.CompileNgModuleSummary>this._loadSummary(moduleType, cpl.CompileSummaryKind.NgModule); <cpl.CompileNgModuleSummary>this._loadSummary(moduleType, cpl.CompileSummaryKind.NgModule);
if (!moduleSummary) { if (!moduleSummary) {
const moduleMeta = this.getNgModuleMetadata(moduleType, false); const moduleMeta = this.getNgModuleMetadata(moduleType, false);
@ -408,7 +413,7 @@ export class CompileMetadataResolver {
return Promise.all(loading); return Promise.all(loading);
} }
getNgModuleMetadata(moduleType: any, throwIfNotFound = true): cpl.CompileNgModuleMetadata { getNgModuleMetadata(moduleType: any, throwIfNotFound = true): cpl.CompileNgModuleMetadata|null {
moduleType = resolveForwardRef(moduleType); moduleType = resolveForwardRef(moduleType);
let compileMeta = this._ngModuleCache.get(moduleType); let compileMeta = this._ngModuleCache.get(moduleType);
if (compileMeta) { if (compileMeta) {
@ -430,7 +435,7 @@ export class CompileMetadataResolver {
if (meta.imports) { if (meta.imports) {
flattenAndDedupeArray(meta.imports).forEach((importedType) => { flattenAndDedupeArray(meta.imports).forEach((importedType) => {
let importedModuleType: Type<any>; let importedModuleType: Type<any> = undefined !;
if (isValidType(importedType)) { if (isValidType(importedType)) {
importedModuleType = importedType; importedModuleType = importedType;
} else if (importedType && importedType.ngModule) { } else if (importedType && importedType.ngModule) {
@ -543,7 +548,7 @@ export class CompileMetadataResolver {
if (meta.entryComponents) { if (meta.entryComponents) {
entryComponents.push(...flattenAndDedupeArray(meta.entryComponents) entryComponents.push(...flattenAndDedupeArray(meta.entryComponents)
.map(type => this._getEntryComponentMetadata(type))); .map(type => this._getEntryComponentMetadata(type) !));
} }
if (meta.bootstrap) { if (meta.bootstrap) {
@ -560,7 +565,7 @@ export class CompileMetadataResolver {
} }
entryComponents.push( entryComponents.push(
...bootstrapComponents.map(type => this._getEntryComponentMetadata(type.reference))); ...bootstrapComponents.map(type => this._getEntryComponentMetadata(type.reference) !));
if (meta.schemas) { if (meta.schemas) {
schemas.push(...flattenAndDedupeArray(meta.schemas)); schemas.push(...flattenAndDedupeArray(meta.schemas));
@ -579,11 +584,11 @@ export class CompileMetadataResolver {
importedModules, importedModules,
exportedModules, exportedModules,
transitiveModule, transitiveModule,
id: meta.id, id: meta.id || null,
}); });
entryComponents.forEach((id) => transitiveModule.addEntryComponent(id)); entryComponents.forEach((id) => transitiveModule.addEntryComponent(id));
providers.forEach((provider) => transitiveModule.addProvider(provider, compileMeta.type)); providers.forEach((provider) => transitiveModule.addProvider(provider, compileMeta !.type));
transitiveModule.addModule(compileMeta.type); transitiveModule.addModule(compileMeta.type);
this._ngModuleCache.set(moduleType, compileMeta); this._ngModuleCache.set(moduleType, compileMeta);
return compileMeta; return compileMeta;
@ -690,7 +695,7 @@ export class CompileMetadataResolver {
}; };
} }
private _getInjectableMetadata(type: Type<any>, dependencies: any[] = null): private _getInjectableMetadata(type: Type<any>, dependencies: any[]|null = null):
cpl.CompileTypeMetadata { cpl.CompileTypeMetadata {
const typeSummary = this._loadSummary(type, cpl.CompileSummaryKind.Injectable); const typeSummary = this._loadSummary(type, cpl.CompileSummaryKind.Injectable);
if (typeSummary) { if (typeSummary) {
@ -699,8 +704,9 @@ export class CompileMetadataResolver {
return this._getTypeMetadata(type, dependencies); return this._getTypeMetadata(type, dependencies);
} }
private _getTypeMetadata(type: Type<any>, dependencies: any[] = null, throwOnUnknownDeps = true): private _getTypeMetadata(
cpl.CompileTypeMetadata { type: Type<any>, dependencies: any[]|null = null,
throwOnUnknownDeps = true): cpl.CompileTypeMetadata {
const identifier = this._getIdentifierMetadata(type); const identifier = this._getIdentifierMetadata(type);
return { return {
reference: identifier.reference, reference: identifier.reference,
@ -710,7 +716,7 @@ export class CompileMetadataResolver {
}; };
} }
private _getFactoryMetadata(factory: Function, dependencies: any[] = null): private _getFactoryMetadata(factory: Function, dependencies: any[]|null = null):
cpl.CompileFactoryMetadata { cpl.CompileFactoryMetadata {
factory = resolveForwardRef(factory); factory = resolveForwardRef(factory);
return {reference: factory, diDeps: this._getDependenciesMetadata(factory, dependencies)}; return {reference: factory, diDeps: this._getDependenciesMetadata(factory, dependencies)};
@ -720,7 +726,7 @@ export class CompileMetadataResolver {
* Gets the metadata for the given pipe. * Gets the metadata for the given pipe.
* This assumes `loadNgModuleDirectiveAndPipeMetadata` has been called first. * This assumes `loadNgModuleDirectiveAndPipeMetadata` has been called first.
*/ */
getPipeMetadata(pipeType: any): cpl.CompilePipeMetadata { getPipeMetadata(pipeType: any): cpl.CompilePipeMetadata|null {
const pipeMeta = this._pipeCache.get(pipeType); const pipeMeta = this._pipeCache.get(pipeType);
if (!pipeMeta) { if (!pipeMeta) {
this._reportError( this._reportError(
@ -728,7 +734,7 @@ export class CompileMetadataResolver {
`Illegal state: getPipeMetadata can only be called after loadNgModuleDirectiveAndPipeMetadata for a module that declares it. Pipe ${stringifyType(pipeType)}.`), `Illegal state: getPipeMetadata can only be called after loadNgModuleDirectiveAndPipeMetadata for a module that declares it. Pipe ${stringifyType(pipeType)}.`),
pipeType); pipeType);
} }
return pipeMeta; return pipeMeta || null;
} }
getPipeSummary(pipeType: any): cpl.CompilePipeSummary { getPipeSummary(pipeType: any): cpl.CompilePipeSummary {
@ -753,12 +759,12 @@ export class CompileMetadataResolver {
private _loadPipeMetadata(pipeType: any): cpl.CompilePipeMetadata { private _loadPipeMetadata(pipeType: any): cpl.CompilePipeMetadata {
pipeType = resolveForwardRef(pipeType); pipeType = resolveForwardRef(pipeType);
const pipeAnnotation = this._pipeResolver.resolve(pipeType); const pipeAnnotation = this._pipeResolver.resolve(pipeType) !;
const pipeMeta = new cpl.CompilePipeMetadata({ const pipeMeta = new cpl.CompilePipeMetadata({
type: this._getTypeMetadata(pipeType), type: this._getTypeMetadata(pipeType),
name: pipeAnnotation.name, name: pipeAnnotation.name,
pure: pipeAnnotation.pure pure: !!pipeAnnotation.pure
}); });
this._pipeCache.set(pipeType, pipeMeta); this._pipeCache.set(pipeType, pipeMeta);
this._summaryCache.set(pipeType, pipeMeta.toSummary()); this._summaryCache.set(pipeType, pipeMeta.toSummary());
@ -766,7 +772,7 @@ export class CompileMetadataResolver {
} }
private _getDependenciesMetadata( private _getDependenciesMetadata(
typeOrFunc: Type<any>|Function, dependencies: any[], typeOrFunc: Type<any>|Function, dependencies: any[]|null,
throwOnUnknownDeps = true): cpl.CompileDiDependencyMetadata[] { throwOnUnknownDeps = true): cpl.CompileDiDependencyMetadata[] {
let hasUnknownDeps = false; let hasUnknownDeps = false;
const params = dependencies || this._reflector.parameters(typeOrFunc) || []; const params = dependencies || this._reflector.parameters(typeOrFunc) || [];
@ -804,7 +810,7 @@ export class CompileMetadataResolver {
} }
if (token == null) { if (token == null) {
hasUnknownDeps = true; hasUnknownDeps = true;
return null; return null !;
} }
return { return {
@ -853,7 +859,7 @@ export class CompileMetadataResolver {
this._getProvidersMetadata(provider, targetEntryComponents, debugInfo, compileProviders); this._getProvidersMetadata(provider, targetEntryComponents, debugInfo, compileProviders);
} else { } else {
provider = resolveForwardRef(provider); provider = resolveForwardRef(provider);
let providerMeta: cpl.ProviderMeta; let providerMeta: cpl.ProviderMeta = undefined !;
if (provider && typeof provider === 'object' && provider.hasOwnProperty('provide')) { if (provider && typeof provider === 'object' && provider.hasOwnProperty('provide')) {
this._validateProvider(provider); this._validateProvider(provider);
providerMeta = new cpl.ProviderMeta(provider.provide, provider); providerMeta = new cpl.ProviderMeta(provider.provide, provider);
@ -933,25 +939,26 @@ export class CompileMetadataResolver {
} }
private _getEntryComponentMetadata(dirType: any, throwIfNotFound = true): private _getEntryComponentMetadata(dirType: any, throwIfNotFound = true):
cpl.CompileEntryComponentMetadata { cpl.CompileEntryComponentMetadata|null {
const dirMeta = this.getNonNormalizedDirectiveMetadata(dirType); const dirMeta = this.getNonNormalizedDirectiveMetadata(dirType);
if (dirMeta && dirMeta.metadata.isComponent) { if (dirMeta && dirMeta.metadata.isComponent) {
return {componentType: dirType, componentFactory: dirMeta.metadata.componentFactory}; return {componentType: dirType, componentFactory: dirMeta.metadata.componentFactory !};
} }
const dirSummary = const dirSummary =
<cpl.CompileDirectiveSummary>this._loadSummary(dirType, cpl.CompileSummaryKind.Directive); <cpl.CompileDirectiveSummary>this._loadSummary(dirType, cpl.CompileSummaryKind.Directive);
if (dirSummary && dirSummary.isComponent) { if (dirSummary && dirSummary.isComponent) {
return {componentType: dirType, componentFactory: dirSummary.componentFactory}; return {componentType: dirType, componentFactory: dirSummary.componentFactory !};
} }
if (throwIfNotFound) { if (throwIfNotFound) {
throw syntaxError(`${dirType.name} cannot be used as an entry component.`); throw syntaxError(`${dirType.name} cannot be used as an entry component.`);
} }
return null;
} }
getProviderMetadata(provider: cpl.ProviderMeta): cpl.CompileProviderMetadata { getProviderMetadata(provider: cpl.ProviderMeta): cpl.CompileProviderMetadata {
let compileDeps: cpl.CompileDiDependencyMetadata[]; let compileDeps: cpl.CompileDiDependencyMetadata[] = undefined !;
let compileTypeMetadata: cpl.CompileTypeMetadata = null; let compileTypeMetadata: cpl.CompileTypeMetadata = null !;
let compileFactoryMetadata: cpl.CompileFactoryMetadata = null; let compileFactoryMetadata: cpl.CompileFactoryMetadata = null !;
let token: cpl.CompileTokenMetadata = this._getTokenMetadata(provider.token); let token: cpl.CompileTokenMetadata = this._getTokenMetadata(provider.token);
if (provider.useClass) { if (provider.useClass) {
@ -971,7 +978,7 @@ export class CompileMetadataResolver {
useClass: compileTypeMetadata, useClass: compileTypeMetadata,
useValue: provider.useValue, useValue: provider.useValue,
useFactory: compileFactoryMetadata, useFactory: compileFactoryMetadata,
useExisting: provider.useExisting ? this._getTokenMetadata(provider.useExisting) : null, useExisting: provider.useExisting ? this._getTokenMetadata(provider.useExisting) : undefined,
deps: compileDeps, deps: compileDeps,
multi: provider.multi multi: provider.multi
}; };
@ -1016,7 +1023,7 @@ export class CompileMetadataResolver {
selectors, selectors,
first: q.first, first: q.first,
descendants: q.descendants, propertyName, descendants: q.descendants, propertyName,
read: q.read ? this._getTokenMetadata(q.read) : null read: q.read ? this._getTokenMetadata(q.read) : null !
}; };
} }
@ -1078,7 +1085,7 @@ export function componentModuleUrl(
`If you're using Webpack you should inline the template and the styles, see https://goo.gl/X2J8zc.`); `If you're using Webpack you should inline the template and the styles, see https://goo.gl/X2J8zc.`);
} }
return reflector.importUri(type); return reflector.importUri(type) !;
} }
function extractIdentifiers(value: any, targetIdentifiers: cpl.CompileIdentifierMetadata[]) { function extractIdentifiers(value: any, targetIdentifiers: cpl.CompileIdentifierMetadata[]) {

View File

@ -9,12 +9,12 @@
import {ParseSourceSpan} from '../parse_util'; import {ParseSourceSpan} from '../parse_util';
export interface Node { export interface Node {
sourceSpan: ParseSourceSpan; sourceSpan: ParseSourceSpan|null;
visit(visitor: Visitor, context: any): any; visit(visitor: Visitor, context: any): any;
} }
export class Text implements Node { export class Text implements Node {
constructor(public value: string, public sourceSpan: ParseSourceSpan) {} constructor(public value: string, public sourceSpan: ParseSourceSpan|null) {}
visit(visitor: Visitor, context: any): any { return visitor.visitText(this, context); } visit(visitor: Visitor, context: any): any { return visitor.visitText(this, context); }
} }
@ -43,13 +43,14 @@ export class Attribute implements Node {
export class Element implements Node { export class Element implements Node {
constructor( constructor(
public name: string, public attrs: Attribute[], public children: Node[], public name: string, public attrs: Attribute[], public children: Node[],
public sourceSpan: ParseSourceSpan, public startSourceSpan: ParseSourceSpan, public sourceSpan: ParseSourceSpan|null = null,
public endSourceSpan: ParseSourceSpan) {} public startSourceSpan: ParseSourceSpan|null = null,
public endSourceSpan: ParseSourceSpan|null = null) {}
visit(visitor: Visitor, context: any): any { return visitor.visitElement(this, context); } visit(visitor: Visitor, context: any): any { return visitor.visitElement(this, context); }
} }
export class Comment implements Node { export class Comment implements Node {
constructor(public value: string, public sourceSpan: ParseSourceSpan) {} constructor(public value: string|null, public sourceSpan: ParseSourceSpan) {}
visit(visitor: Visitor, context: any): any { return visitor.visitComment(this, context); } visit(visitor: Visitor, context: any): any { return visitor.visitComment(this, context); }
} }
@ -70,7 +71,7 @@ export function visitAll(visitor: Visitor, nodes: Node[], context: any = null):
const result: any[] = []; const result: any[] = [];
const visit = visitor.visit ? const visit = visitor.visit ?
(ast: Node) => visitor.visit(ast, context) || ast.visit(visitor, context) : (ast: Node) => visitor.visit !(ast, context) || ast.visit(visitor, context) :
(ast: Node) => ast.visit(visitor, context); (ast: Node) => ast.visit(visitor, context);
nodes.forEach(ast => { nodes.forEach(ast => {
const astResult = visit(ast); const astResult = visit(ast);

View File

@ -14,7 +14,7 @@ export class HtmlTagDefinition implements TagDefinition {
closedByParent: boolean = false; closedByParent: boolean = false;
requiredParents: {[key: string]: boolean}; requiredParents: {[key: string]: boolean};
parentToAdd: string; parentToAdd: string;
implicitNamespacePrefix: string; implicitNamespacePrefix: string|null;
contentType: TagContentType; contentType: TagContentType;
isVoid: boolean; isVoid: boolean;
ignoreFirstLf: boolean; ignoreFirstLf: boolean;
@ -43,7 +43,7 @@ export class HtmlTagDefinition implements TagDefinition {
this.parentToAdd = requiredParents[0]; this.parentToAdd = requiredParents[0];
requiredParents.forEach(tagName => this.requiredParents[tagName] = true); requiredParents.forEach(tagName => this.requiredParents[tagName] = true);
} }
this.implicitNamespacePrefix = implicitNamespacePrefix; this.implicitNamespacePrefix = implicitNamespacePrefix || null;
this.contentType = contentType; this.contentType = contentType;
this.ignoreFirstLf = ignoreFirstLf; this.ignoreFirstLf = ignoreFirstLf;
} }

View File

@ -9,7 +9,7 @@
import {assertInterpolationSymbols} from '../assertions'; import {assertInterpolationSymbols} from '../assertions';
export class InterpolationConfig { export class InterpolationConfig {
static fromArray(markers: [string, string]): InterpolationConfig { static fromArray(markers: [string, string]|null): InterpolationConfig {
if (!markers) { if (!markers) {
return DEFAULT_INTERPOLATION_CONFIG; return DEFAULT_INTERPOLATION_CONFIG;
} }

View File

@ -198,8 +198,8 @@ class _Tokenizer {
const token = const token =
new Token(this._currentTokenType, parts, new ParseSourceSpan(this._currentTokenStart, end)); new Token(this._currentTokenType, parts, new ParseSourceSpan(this._currentTokenStart, end));
this.tokens.push(token); this.tokens.push(token);
this._currentTokenStart = null; this._currentTokenStart = null !;
this._currentTokenType = null; this._currentTokenType = null !;
return token; return token;
} }
@ -208,8 +208,8 @@ class _Tokenizer {
msg += ` (Do you have an unescaped "{" in your template? Use "{{ '{' }}") to escape it.)`; msg += ` (Do you have an unescaped "{" in your template? Use "{{ '{' }}") to escape it.)`;
} }
const error = new TokenError(msg, this._currentTokenType, span); const error = new TokenError(msg, this._currentTokenType, span);
this._currentTokenStart = null; this._currentTokenStart = null !;
this._currentTokenType = null; this._currentTokenType = null !;
return new _ControlFlowError(error); return new _ControlFlowError(error);
} }
@ -402,7 +402,7 @@ class _Tokenizer {
private _consumePrefixAndName(): string[] { private _consumePrefixAndName(): string[] {
const nameOrPrefixStart = this._index; const nameOrPrefixStart = this._index;
let prefix: string = null; let prefix: string = null !;
while (this._peek !== chars.$COLON && !isPrefixEnd(this._peek)) { while (this._peek !== chars.$COLON && !isPrefixEnd(this._peek)) {
this._advance(); this._advance();
} }
@ -473,7 +473,7 @@ class _Tokenizer {
return this._attemptCharCode(chars.$GT); return this._attemptCharCode(chars.$GT);
}); });
this._beginToken(TokenType.TAG_CLOSE, textToken.sourceSpan.end); this._beginToken(TokenType.TAG_CLOSE, textToken.sourceSpan.end);
this._endToken([null, lowercaseTagName]); this._endToken([null !, lowercaseTagName]);
} }
private _consumeTagOpenStart(start: ParseLocation) { private _consumeTagOpenStart(start: ParseLocation) {
@ -697,7 +697,7 @@ function toUpperCaseCharCode(code: number): number {
function mergeTextTokens(srcTokens: Token[]): Token[] { function mergeTextTokens(srcTokens: Token[]): Token[] {
const dstTokens: Token[] = []; const dstTokens: Token[] = [];
let lastDstToken: Token; let lastDstToken: Token|undefined = undefined;
for (let i = 0; i < srcTokens.length; i++) { for (let i = 0; i < srcTokens.length; i++) {
const token = srcTokens[i]; const token = srcTokens[i];
if (lastDstToken && lastDstToken.type == TokenType.TEXT && token.type == TokenType.TEXT) { if (lastDstToken && lastDstToken.type == TokenType.TEXT && token.type == TokenType.TEXT) {

View File

@ -14,11 +14,13 @@ import * as lex from './lexer';
import {TagDefinition, getNsPrefix, mergeNsAndName} from './tags'; import {TagDefinition, getNsPrefix, mergeNsAndName} from './tags';
export class TreeError extends ParseError { export class TreeError extends ParseError {
static create(elementName: string, span: ParseSourceSpan, msg: string): TreeError { static create(elementName: string|null, span: ParseSourceSpan, msg: string): TreeError {
return new TreeError(elementName, span, msg); return new TreeError(elementName, span, msg);
} }
constructor(public elementName: string, span: ParseSourceSpan, msg: string) { super(span, msg); } constructor(public elementName: string|null, span: ParseSourceSpan, msg: string) {
super(span, msg);
}
} }
export class ParseTreeResult { export class ParseTreeResult {
@ -93,7 +95,7 @@ class _TreeBuilder {
return prev; return prev;
} }
private _advanceIf(type: lex.TokenType): lex.Token { private _advanceIf(type: lex.TokenType): lex.Token|null {
if (this._peek.type === type) { if (this._peek.type === type) {
return this._advance(); return this._advance();
} }
@ -138,7 +140,7 @@ class _TreeBuilder {
this._advance(); this._advance();
} }
private _parseExpansionCase(): html.ExpansionCase { private _parseExpansionCase(): html.ExpansionCase|null {
const value = this._advance(); const value = this._advance();
// read { // read {
@ -170,7 +172,7 @@ class _TreeBuilder {
value.parts[0], parsedExp.rootNodes, sourceSpan, value.sourceSpan, expSourceSpan); value.parts[0], parsedExp.rootNodes, sourceSpan, value.sourceSpan, expSourceSpan);
} }
private _collectExpansionExpTokens(start: lex.Token): lex.Token[] { private _collectExpansionExpTokens(start: lex.Token): lex.Token[]|null {
const exp: lex.Token[] = []; const exp: lex.Token[] = [];
const expansionFormStack = [lex.TokenType.EXPANSION_CASE_EXP_START]; const expansionFormStack = [lex.TokenType.EXPANSION_CASE_EXP_START];
@ -263,7 +265,7 @@ class _TreeBuilder {
} }
const end = this._peek.sourceSpan.start; const end = this._peek.sourceSpan.start;
const span = new ParseSourceSpan(startTagToken.sourceSpan.start, end); const span = new ParseSourceSpan(startTagToken.sourceSpan.start, end);
const el = new html.Element(fullName, attrs, [], span, span, null); const el = new html.Element(fullName, attrs, [], span, span, undefined);
this._pushElement(el); this._pushElement(el);
if (selfClosing) { if (selfClosing) {
this._popElement(fullName); this._popElement(fullName);
@ -297,7 +299,7 @@ class _TreeBuilder {
endTagToken.parts[0], endTagToken.parts[1], this._getParentElement()); endTagToken.parts[0], endTagToken.parts[1], this._getParentElement());
if (this._getParentElement()) { if (this._getParentElement()) {
this._getParentElement().endSourceSpan = endTagToken.sourceSpan; this._getParentElement() !.endSourceSpan = endTagToken.sourceSpan;
} }
if (this.getTagDefinition(fullName).isVoid) { if (this.getTagDefinition(fullName).isVoid) {
@ -330,7 +332,7 @@ class _TreeBuilder {
const fullName = mergeNsAndName(attrName.parts[0], attrName.parts[1]); const fullName = mergeNsAndName(attrName.parts[0], attrName.parts[1]);
let end = attrName.sourceSpan.end; let end = attrName.sourceSpan.end;
let value = ''; let value = '';
let valueSpan: ParseSourceSpan; let valueSpan: ParseSourceSpan = undefined !;
if (this._peek.type === lex.TokenType.ATTR_VALUE) { if (this._peek.type === lex.TokenType.ATTR_VALUE) {
const valueToken = this._advance(); const valueToken = this._advance();
value = valueToken.parts[0]; value = valueToken.parts[0];
@ -341,7 +343,7 @@ class _TreeBuilder {
fullName, value, new ParseSourceSpan(attrName.sourceSpan.start, end), valueSpan); fullName, value, new ParseSourceSpan(attrName.sourceSpan.start, end), valueSpan);
} }
private _getParentElement(): html.Element { private _getParentElement(): html.Element|null {
return this._elementStack.length > 0 ? this._elementStack[this._elementStack.length - 1] : null; return this._elementStack.length > 0 ? this._elementStack[this._elementStack.length - 1] : null;
} }
@ -351,7 +353,7 @@ class _TreeBuilder {
* `<ng-container>` elements are skipped as they are not rendered as DOM element. * `<ng-container>` elements are skipped as they are not rendered as DOM element.
*/ */
private _getParentElementSkippingContainers(): {parent: html.Element, container: html.Element} { private _getParentElementSkippingContainers(): {parent: html.Element, container: html.Element} {
let container: html.Element = null; let container: html.Element = null !;
for (let i = this._elementStack.length - 1; i >= 0; i--) { for (let i = this._elementStack.length - 1; i >= 0; i--) {
if (this._elementStack[i].name !== 'ng-container') { if (this._elementStack[i].name !== 'ng-container') {
@ -397,10 +399,10 @@ class _TreeBuilder {
} }
} }
private _getElementFullName(prefix: string, localName: string, parentElement: html.Element): private _getElementFullName(prefix: string, localName: string, parentElement: html.Element|null):
string { string {
if (prefix == null) { if (prefix == null) {
prefix = this.getTagDefinition(localName).implicitNamespacePrefix; prefix = this.getTagDefinition(localName).implicitNamespacePrefix !;
if (prefix == null && parentElement != null) { if (prefix == null && parentElement != null) {
prefix = getNsPrefix(parentElement.name); prefix = getNsPrefix(parentElement.name);
} }

View File

@ -17,7 +17,7 @@ export interface TagDefinition {
closedByParent: boolean; closedByParent: boolean;
requiredParents: {[key: string]: boolean}; requiredParents: {[key: string]: boolean};
parentToAdd: string; parentToAdd: string;
implicitNamespacePrefix: string; implicitNamespacePrefix: string|null;
contentType: TagContentType; contentType: TagContentType;
isVoid: boolean; isVoid: boolean;
ignoreFirstLf: boolean; ignoreFirstLf: boolean;
@ -28,7 +28,7 @@ export interface TagDefinition {
isClosedByChild(name: string): boolean; isClosedByChild(name: string): boolean;
} }
export function splitNsName(elementName: string): [string, string] { export function splitNsName(elementName: string): [string | null, string] {
if (elementName[0] != ':') { if (elementName[0] != ':') {
return [null, elementName]; return [null, elementName];
} }
@ -42,269 +42,274 @@ export function splitNsName(elementName: string): [string, string] {
return [elementName.slice(1, colonIndex), elementName.slice(colonIndex + 1)]; return [elementName.slice(1, colonIndex), elementName.slice(colonIndex + 1)];
} }
export function getNsPrefix(fullName: string): string { export function getNsPrefix(fullName: string): string
return fullName === null ? null : splitNsName(fullName)[0]; export function getNsPrefix(fullName: null): null;
} export function getNsPrefix(fullName: string | null): string |
null {
return fullName === null ? null : splitNsName(fullName)[0];
}
export function mergeNsAndName(prefix: string, localName: string): string { export function mergeNsAndName(prefix: string, localName: string):
return prefix ? `:${prefix}:${localName}` : localName; string {
} return prefix ? `:${prefix}:${localName}` : localName;
}
// see http://www.w3.org/TR/html51/syntax.html#named-character-references // see http://www.w3.org/TR/html51/syntax.html#named-character-references
// see https://html.spec.whatwg.org/multipage/entities.json // see https://html.spec.whatwg.org/multipage/entities.json
// This list is not exhaustive to keep the compiler footprint low. // This list is not exhaustive to keep the compiler footprint low.
// The `&#123;` / `&#x1ab;` syntax should be used when the named character reference does not exist. // The `&#123;` / `&#x1ab;` syntax should be used when the named character reference does not
export const NAMED_ENTITIES: {[k: string]: string} = { // exist.
'Aacute': '\u00C1', export const NAMED_ENTITIES: {[k: string]: string} = {
'aacute': '\u00E1', 'Aacute': '\u00C1',
'Acirc': '\u00C2', 'aacute': '\u00E1',
'acirc': '\u00E2', 'Acirc': '\u00C2',
'acute': '\u00B4', 'acirc': '\u00E2',
'AElig': '\u00C6', 'acute': '\u00B4',
'aelig': '\u00E6', 'AElig': '\u00C6',
'Agrave': '\u00C0', 'aelig': '\u00E6',
'agrave': '\u00E0', 'Agrave': '\u00C0',
'alefsym': '\u2135', 'agrave': '\u00E0',
'Alpha': '\u0391', 'alefsym': '\u2135',
'alpha': '\u03B1', 'Alpha': '\u0391',
'amp': '&', 'alpha': '\u03B1',
'and': '\u2227', 'amp': '&',
'ang': '\u2220', 'and': '\u2227',
'apos': '\u0027', 'ang': '\u2220',
'Aring': '\u00C5', 'apos': '\u0027',
'aring': '\u00E5', 'Aring': '\u00C5',
'asymp': '\u2248', 'aring': '\u00E5',
'Atilde': '\u00C3', 'asymp': '\u2248',
'atilde': '\u00E3', 'Atilde': '\u00C3',
'Auml': '\u00C4', 'atilde': '\u00E3',
'auml': '\u00E4', 'Auml': '\u00C4',
'bdquo': '\u201E', 'auml': '\u00E4',
'Beta': '\u0392', 'bdquo': '\u201E',
'beta': '\u03B2', 'Beta': '\u0392',
'brvbar': '\u00A6', 'beta': '\u03B2',
'bull': '\u2022', 'brvbar': '\u00A6',
'cap': '\u2229', 'bull': '\u2022',
'Ccedil': '\u00C7', 'cap': '\u2229',
'ccedil': '\u00E7', 'Ccedil': '\u00C7',
'cedil': '\u00B8', 'ccedil': '\u00E7',
'cent': '\u00A2', 'cedil': '\u00B8',
'Chi': '\u03A7', 'cent': '\u00A2',
'chi': '\u03C7', 'Chi': '\u03A7',
'circ': '\u02C6', 'chi': '\u03C7',
'clubs': '\u2663', 'circ': '\u02C6',
'cong': '\u2245', 'clubs': '\u2663',
'copy': '\u00A9', 'cong': '\u2245',
'crarr': '\u21B5', 'copy': '\u00A9',
'cup': '\u222A', 'crarr': '\u21B5',
'curren': '\u00A4', 'cup': '\u222A',
'dagger': '\u2020', 'curren': '\u00A4',
'Dagger': '\u2021', 'dagger': '\u2020',
'darr': '\u2193', 'Dagger': '\u2021',
'dArr': '\u21D3', 'darr': '\u2193',
'deg': '\u00B0', 'dArr': '\u21D3',
'Delta': '\u0394', 'deg': '\u00B0',
'delta': '\u03B4', 'Delta': '\u0394',
'diams': '\u2666', 'delta': '\u03B4',
'divide': '\u00F7', 'diams': '\u2666',
'Eacute': '\u00C9', 'divide': '\u00F7',
'eacute': '\u00E9', 'Eacute': '\u00C9',
'Ecirc': '\u00CA', 'eacute': '\u00E9',
'ecirc': '\u00EA', 'Ecirc': '\u00CA',
'Egrave': '\u00C8', 'ecirc': '\u00EA',
'egrave': '\u00E8', 'Egrave': '\u00C8',
'empty': '\u2205', 'egrave': '\u00E8',
'emsp': '\u2003', 'empty': '\u2205',
'ensp': '\u2002', 'emsp': '\u2003',
'Epsilon': '\u0395', 'ensp': '\u2002',
'epsilon': '\u03B5', 'Epsilon': '\u0395',
'equiv': '\u2261', 'epsilon': '\u03B5',
'Eta': '\u0397', 'equiv': '\u2261',
'eta': '\u03B7', 'Eta': '\u0397',
'ETH': '\u00D0', 'eta': '\u03B7',
'eth': '\u00F0', 'ETH': '\u00D0',
'Euml': '\u00CB', 'eth': '\u00F0',
'euml': '\u00EB', 'Euml': '\u00CB',
'euro': '\u20AC', 'euml': '\u00EB',
'exist': '\u2203', 'euro': '\u20AC',
'fnof': '\u0192', 'exist': '\u2203',
'forall': '\u2200', 'fnof': '\u0192',
'frac12': '\u00BD', 'forall': '\u2200',
'frac14': '\u00BC', 'frac12': '\u00BD',
'frac34': '\u00BE', 'frac14': '\u00BC',
'frasl': '\u2044', 'frac34': '\u00BE',
'Gamma': '\u0393', 'frasl': '\u2044',
'gamma': '\u03B3', 'Gamma': '\u0393',
'ge': '\u2265', 'gamma': '\u03B3',
'gt': '>', 'ge': '\u2265',
'harr': '\u2194', 'gt': '>',
'hArr': '\u21D4', 'harr': '\u2194',
'hearts': '\u2665', 'hArr': '\u21D4',
'hellip': '\u2026', 'hearts': '\u2665',
'Iacute': '\u00CD', 'hellip': '\u2026',
'iacute': '\u00ED', 'Iacute': '\u00CD',
'Icirc': '\u00CE', 'iacute': '\u00ED',
'icirc': '\u00EE', 'Icirc': '\u00CE',
'iexcl': '\u00A1', 'icirc': '\u00EE',
'Igrave': '\u00CC', 'iexcl': '\u00A1',
'igrave': '\u00EC', 'Igrave': '\u00CC',
'image': '\u2111', 'igrave': '\u00EC',
'infin': '\u221E', 'image': '\u2111',
'int': '\u222B', 'infin': '\u221E',
'Iota': '\u0399', 'int': '\u222B',
'iota': '\u03B9', 'Iota': '\u0399',
'iquest': '\u00BF', 'iota': '\u03B9',
'isin': '\u2208', 'iquest': '\u00BF',
'Iuml': '\u00CF', 'isin': '\u2208',
'iuml': '\u00EF', 'Iuml': '\u00CF',
'Kappa': '\u039A', 'iuml': '\u00EF',
'kappa': '\u03BA', 'Kappa': '\u039A',
'Lambda': '\u039B', 'kappa': '\u03BA',
'lambda': '\u03BB', 'Lambda': '\u039B',
'lang': '\u27E8', 'lambda': '\u03BB',
'laquo': '\u00AB', 'lang': '\u27E8',
'larr': '\u2190', 'laquo': '\u00AB',
'lArr': '\u21D0', 'larr': '\u2190',
'lceil': '\u2308', 'lArr': '\u21D0',
'ldquo': '\u201C', 'lceil': '\u2308',
'le': '\u2264', 'ldquo': '\u201C',
'lfloor': '\u230A', 'le': '\u2264',
'lowast': '\u2217', 'lfloor': '\u230A',
'loz': '\u25CA', 'lowast': '\u2217',
'lrm': '\u200E', 'loz': '\u25CA',
'lsaquo': '\u2039', 'lrm': '\u200E',
'lsquo': '\u2018', 'lsaquo': '\u2039',
'lt': '<', 'lsquo': '\u2018',
'macr': '\u00AF', 'lt': '<',
'mdash': '\u2014', 'macr': '\u00AF',
'micro': '\u00B5', 'mdash': '\u2014',
'middot': '\u00B7', 'micro': '\u00B5',
'minus': '\u2212', 'middot': '\u00B7',
'Mu': '\u039C', 'minus': '\u2212',
'mu': '\u03BC', 'Mu': '\u039C',
'nabla': '\u2207', 'mu': '\u03BC',
'nbsp': '\u00A0', 'nabla': '\u2207',
'ndash': '\u2013', 'nbsp': '\u00A0',
'ne': '\u2260', 'ndash': '\u2013',
'ni': '\u220B', 'ne': '\u2260',
'not': '\u00AC', 'ni': '\u220B',
'notin': '\u2209', 'not': '\u00AC',
'nsub': '\u2284', 'notin': '\u2209',
'Ntilde': '\u00D1', 'nsub': '\u2284',
'ntilde': '\u00F1', 'Ntilde': '\u00D1',
'Nu': '\u039D', 'ntilde': '\u00F1',
'nu': '\u03BD', 'Nu': '\u039D',
'Oacute': '\u00D3', 'nu': '\u03BD',
'oacute': '\u00F3', 'Oacute': '\u00D3',
'Ocirc': '\u00D4', 'oacute': '\u00F3',
'ocirc': '\u00F4', 'Ocirc': '\u00D4',
'OElig': '\u0152', 'ocirc': '\u00F4',
'oelig': '\u0153', 'OElig': '\u0152',
'Ograve': '\u00D2', 'oelig': '\u0153',
'ograve': '\u00F2', 'Ograve': '\u00D2',
'oline': '\u203E', 'ograve': '\u00F2',
'Omega': '\u03A9', 'oline': '\u203E',
'omega': '\u03C9', 'Omega': '\u03A9',
'Omicron': '\u039F', 'omega': '\u03C9',
'omicron': '\u03BF', 'Omicron': '\u039F',
'oplus': '\u2295', 'omicron': '\u03BF',
'or': '\u2228', 'oplus': '\u2295',
'ordf': '\u00AA', 'or': '\u2228',
'ordm': '\u00BA', 'ordf': '\u00AA',
'Oslash': '\u00D8', 'ordm': '\u00BA',
'oslash': '\u00F8', 'Oslash': '\u00D8',
'Otilde': '\u00D5', 'oslash': '\u00F8',
'otilde': '\u00F5', 'Otilde': '\u00D5',
'otimes': '\u2297', 'otilde': '\u00F5',
'Ouml': '\u00D6', 'otimes': '\u2297',
'ouml': '\u00F6', 'Ouml': '\u00D6',
'para': '\u00B6', 'ouml': '\u00F6',
'permil': '\u2030', 'para': '\u00B6',
'perp': '\u22A5', 'permil': '\u2030',
'Phi': '\u03A6', 'perp': '\u22A5',
'phi': '\u03C6', 'Phi': '\u03A6',
'Pi': '\u03A0', 'phi': '\u03C6',
'pi': '\u03C0', 'Pi': '\u03A0',
'piv': '\u03D6', 'pi': '\u03C0',
'plusmn': '\u00B1', 'piv': '\u03D6',
'pound': '\u00A3', 'plusmn': '\u00B1',
'prime': '\u2032', 'pound': '\u00A3',
'Prime': '\u2033', 'prime': '\u2032',
'prod': '\u220F', 'Prime': '\u2033',
'prop': '\u221D', 'prod': '\u220F',
'Psi': '\u03A8', 'prop': '\u221D',
'psi': '\u03C8', 'Psi': '\u03A8',
'quot': '\u0022', 'psi': '\u03C8',
'radic': '\u221A', 'quot': '\u0022',
'rang': '\u27E9', 'radic': '\u221A',
'raquo': '\u00BB', 'rang': '\u27E9',
'rarr': '\u2192', 'raquo': '\u00BB',
'rArr': '\u21D2', 'rarr': '\u2192',
'rceil': '\u2309', 'rArr': '\u21D2',
'rdquo': '\u201D', 'rceil': '\u2309',
'real': '\u211C', 'rdquo': '\u201D',
'reg': '\u00AE', 'real': '\u211C',
'rfloor': '\u230B', 'reg': '\u00AE',
'Rho': '\u03A1', 'rfloor': '\u230B',
'rho': '\u03C1', 'Rho': '\u03A1',
'rlm': '\u200F', 'rho': '\u03C1',
'rsaquo': '\u203A', 'rlm': '\u200F',
'rsquo': '\u2019', 'rsaquo': '\u203A',
'sbquo': '\u201A', 'rsquo': '\u2019',
'Scaron': '\u0160', 'sbquo': '\u201A',
'scaron': '\u0161', 'Scaron': '\u0160',
'sdot': '\u22C5', 'scaron': '\u0161',
'sect': '\u00A7', 'sdot': '\u22C5',
'shy': '\u00AD', 'sect': '\u00A7',
'Sigma': '\u03A3', 'shy': '\u00AD',
'sigma': '\u03C3', 'Sigma': '\u03A3',
'sigmaf': '\u03C2', 'sigma': '\u03C3',
'sim': '\u223C', 'sigmaf': '\u03C2',
'spades': '\u2660', 'sim': '\u223C',
'sub': '\u2282', 'spades': '\u2660',
'sube': '\u2286', 'sub': '\u2282',
'sum': '\u2211', 'sube': '\u2286',
'sup': '\u2283', 'sum': '\u2211',
'sup1': '\u00B9', 'sup': '\u2283',
'sup2': '\u00B2', 'sup1': '\u00B9',
'sup3': '\u00B3', 'sup2': '\u00B2',
'supe': '\u2287', 'sup3': '\u00B3',
'szlig': '\u00DF', 'supe': '\u2287',
'Tau': '\u03A4', 'szlig': '\u00DF',
'tau': '\u03C4', 'Tau': '\u03A4',
'there4': '\u2234', 'tau': '\u03C4',
'Theta': '\u0398', 'there4': '\u2234',
'theta': '\u03B8', 'Theta': '\u0398',
'thetasym': '\u03D1', 'theta': '\u03B8',
'thinsp': '\u2009', 'thetasym': '\u03D1',
'THORN': '\u00DE', 'thinsp': '\u2009',
'thorn': '\u00FE', 'THORN': '\u00DE',
'tilde': '\u02DC', 'thorn': '\u00FE',
'times': '\u00D7', 'tilde': '\u02DC',
'trade': '\u2122', 'times': '\u00D7',
'Uacute': '\u00DA', 'trade': '\u2122',
'uacute': '\u00FA', 'Uacute': '\u00DA',
'uarr': '\u2191', 'uacute': '\u00FA',
'uArr': '\u21D1', 'uarr': '\u2191',
'Ucirc': '\u00DB', 'uArr': '\u21D1',
'ucirc': '\u00FB', 'Ucirc': '\u00DB',
'Ugrave': '\u00D9', 'ucirc': '\u00FB',
'ugrave': '\u00F9', 'Ugrave': '\u00D9',
'uml': '\u00A8', 'ugrave': '\u00F9',
'upsih': '\u03D2', 'uml': '\u00A8',
'Upsilon': '\u03A5', 'upsih': '\u03D2',
'upsilon': '\u03C5', 'Upsilon': '\u03A5',
'Uuml': '\u00DC', 'upsilon': '\u03C5',
'uuml': '\u00FC', 'Uuml': '\u00DC',
'weierp': '\u2118', 'uuml': '\u00FC',
'Xi': '\u039E', 'weierp': '\u2118',
'xi': '\u03BE', 'Xi': '\u039E',
'Yacute': '\u00DD', 'xi': '\u03BE',
'yacute': '\u00FD', 'Yacute': '\u00DD',
'yen': '\u00A5', 'yacute': '\u00FD',
'yuml': '\u00FF', 'yen': '\u00A5',
'Yuml': '\u0178', 'yuml': '\u00FF',
'Zeta': '\u0396', 'Yuml': '\u0178',
'zeta': '\u03B6', 'Zeta': '\u0396',
'zwj': '\u200D', 'zeta': '\u03B6',
'zwnj': '\u200C', 'zwj': '\u200D',
}; 'zwnj': '\u200C',
};

View File

@ -15,6 +15,6 @@ export class XmlParser extends Parser {
constructor() { super(getXmlTagDefinition); } constructor() { super(getXmlTagDefinition); }
parse(source: string, url: string, parseExpansionForms: boolean = false): ParseTreeResult { parse(source: string, url: string, parseExpansionForms: boolean = false): ParseTreeResult {
return super.parse(source, url, parseExpansionForms, null); return super.parse(source, url, parseExpansionForms);
} }
} }

View File

@ -63,7 +63,7 @@ export class NgModuleCompiler {
[o.variable(injectorClass.name), o.importExpr(ngModuleMeta.type)], [o.variable(injectorClass.name), o.importExpr(ngModuleMeta.type)],
o.importType( o.importType(
createIdentifier(Identifiers.NgModuleFactory), createIdentifier(Identifiers.NgModuleFactory),
[o.importType(ngModuleMeta.type)], [o.TypeModifier.Const]))) [o.importType(ngModuleMeta.type) !], [o.TypeModifier.Const])))
.toDeclStmt(null, [o.StmtModifier.Final]); .toDeclStmt(null, [o.StmtModifier.Final]);
const stmts: o.Statement[] = [injectorClass, ngModuleFactoryStmt]; const stmts: o.Statement[] = [injectorClass, ngModuleFactoryStmt];
@ -106,7 +106,7 @@ class _InjectorBuilder implements ClassBuilder {
if (resolvedProvider.lifecycleHooks.indexOf(ɵLifecycleHooks.OnDestroy) !== -1) { if (resolvedProvider.lifecycleHooks.indexOf(ɵLifecycleHooks.OnDestroy) !== -1) {
let callNgOnDestroy: o.Expression = instance.callMethod('ngOnDestroy', []); let callNgOnDestroy: o.Expression = instance.callMethod('ngOnDestroy', []);
if (!resolvedProvider.eager) { if (!resolvedProvider.eager) {
callNgOnDestroy = this._lazyProps.get(instance.name).and(callNgOnDestroy); callNgOnDestroy = this._lazyProps.get(instance.name) !.and(callNgOnDestroy);
} }
this._destroyStmts.push(callNgOnDestroy.toStmt()); this._destroyStmts.push(callNgOnDestroy.toStmt());
} }
@ -116,7 +116,7 @@ class _InjectorBuilder implements ClassBuilder {
build(): o.ClassStmt { build(): o.ClassStmt {
const getMethodStmts: o.Statement[] = this._tokens.map((token) => { const getMethodStmts: o.Statement[] = this._tokens.map((token) => {
const providerExpr = this._instances.get(tokenReference(token)); const providerExpr = this._instances.get(tokenReference(token)) !;
return new o.IfStmt( return new o.IfStmt(
InjectMethodVars.token.identical(createDiTokenExpression(token)), InjectMethodVars.token.identical(createDiTokenExpression(token)),
[new o.ReturnStatement(providerExpr)]); [new o.ReturnStatement(providerExpr)]);
@ -124,13 +124,13 @@ class _InjectorBuilder implements ClassBuilder {
const methods = [ const methods = [
new o.ClassMethod( new o.ClassMethod(
'createInternal', [], this._createStmts.concat(new o.ReturnStatement( 'createInternal', [], this._createStmts.concat(new o.ReturnStatement(
this._instances.get(this._ngModuleMeta.type.reference))), this._instances.get(this._ngModuleMeta.type.reference) !)),
o.importType(this._ngModuleMeta.type)), o.importType(this._ngModuleMeta.type)),
new o.ClassMethod( new o.ClassMethod(
'getInternal', 'getInternal',
[ [
new o.FnParam(InjectMethodVars.token.name, o.DYNAMIC_TYPE), new o.FnParam(InjectMethodVars.token.name !, o.DYNAMIC_TYPE),
new o.FnParam(InjectMethodVars.notFoundResult.name, o.DYNAMIC_TYPE) new o.FnParam(InjectMethodVars.notFoundResult.name !, o.DYNAMIC_TYPE)
], ],
getMethodStmts.concat([new o.ReturnStatement(InjectMethodVars.notFoundResult)]), getMethodStmts.concat([new o.ReturnStatement(InjectMethodVars.notFoundResult)]),
o.DYNAMIC_TYPE), o.DYNAMIC_TYPE),
@ -150,7 +150,8 @@ class _InjectorBuilder implements ClassBuilder {
ctorParams: [new o.FnParam( ctorParams: [new o.FnParam(
InjectorProps.parent.name, o.importType(createIdentifier(Identifiers.Injector)))], InjectorProps.parent.name, o.importType(createIdentifier(Identifiers.Injector)))],
parent: o.importExpr( parent: o.importExpr(
createIdentifier(Identifiers.NgModuleInjector), [o.importType(this._ngModuleMeta.type)]), createIdentifier(Identifiers.NgModuleInjector),
[o.importType(this._ngModuleMeta.type) !]),
parentArgs: parentArgs, parentArgs: parentArgs,
builders: [{methods}, this] builders: [{methods}, this]
}); });
@ -186,7 +187,7 @@ class _InjectorBuilder implements ClassBuilder {
type = new o.ArrayType(o.DYNAMIC_TYPE); type = new o.ArrayType(o.DYNAMIC_TYPE);
} else { } else {
resolvedProviderValueExpr = providerValueExpressions[0]; resolvedProviderValueExpr = providerValueExpressions[0];
type = providerValueExpressions[0].type; type = providerValueExpressions[0].type !;
} }
if (!type) { if (!type) {
type = o.DYNAMIC_TYPE; type = o.DYNAMIC_TYPE;
@ -211,7 +212,7 @@ class _InjectorBuilder implements ClassBuilder {
} }
private _getDependency(dep: CompileDiDependencyMetadata): o.Expression { private _getDependency(dep: CompileDiDependencyMetadata): o.Expression {
let result: o.Expression = null; let result: o.Expression = null !;
if (dep.isValue) { if (dep.isValue) {
result = o.literal(dep.value); result = o.literal(dep.value);
} }
@ -226,11 +227,11 @@ class _InjectorBuilder implements ClassBuilder {
} }
if (!result) { if (!result) {
result = this._instances.get(tokenReference(dep.token)); result = this._instances.get(tokenReference(dep.token !)) !;
} }
} }
if (!result) { if (!result) {
const args = [createDiTokenExpression(dep.token)]; const args = [createDiTokenExpression(dep.token !)];
if (dep.isOptional) { if (dep.isOptional) {
args.push(o.NULL_EXPR); args.push(o.NULL_EXPR);
} }
@ -244,7 +245,7 @@ function createDiTokenExpression(token: CompileTokenMetadata): o.Expression {
if (token.value != null) { if (token.value != null) {
return o.literal(token.value); return o.literal(token.value);
} else { } else {
return o.importExpr(token.identifier); return o.importExpr(token.identifier !);
} }
} }

View File

@ -23,7 +23,7 @@ export class NgModuleResolver {
isNgModule(type: any) { return this._reflector.annotations(type).some(_isNgModuleMetadata); } isNgModule(type: any) { return this._reflector.annotations(type).some(_isNgModuleMetadata); }
resolve(type: Type<any>, throwIfNotFound = true): NgModule { resolve(type: Type<any>, throwIfNotFound = true): NgModule|null {
const ngModuleMeta: NgModule = findLast(this._reflector.annotations(type), _isNgModuleMetadata); const ngModuleMeta: NgModule = findLast(this._reflector.annotations(type), _isNgModuleMetadata);
if (ngModuleMeta) { if (ngModuleMeta) {

View File

@ -14,18 +14,18 @@ import {SourceMapGenerator} from './source_map';
const _SINGLE_QUOTE_ESCAPE_STRING_RE = /'|\\|\n|\r|\$/g; const _SINGLE_QUOTE_ESCAPE_STRING_RE = /'|\\|\n|\r|\$/g;
const _LEGAL_IDENTIFIER_RE = /^[$A-Z_][0-9A-Z_$]*$/i; const _LEGAL_IDENTIFIER_RE = /^[$A-Z_][0-9A-Z_$]*$/i;
const _INDENT_WITH = ' '; const _INDENT_WITH = ' ';
export const CATCH_ERROR_VAR = o.variable('error'); export const CATCH_ERROR_VAR = o.variable('error', null, null);
export const CATCH_STACK_VAR = o.variable('stack'); export const CATCH_STACK_VAR = o.variable('stack', null, null);
export abstract class OutputEmitter { export abstract class OutputEmitter {
abstract emitStatements( abstract emitStatements(
srcFilePath: string, genFilePath: string, stmts: o.Statement[], exportedVars: string[], srcFilePath: string, genFilePath: string, stmts: o.Statement[], exportedVars: string[],
preamble?: string): string; preamble?: string|null): string;
} }
class _EmittedLine { class _EmittedLine {
parts: string[] = []; parts: string[] = [];
srcSpans: ParseSourceSpan[] = []; srcSpans: (ParseSourceSpan|null)[] = [];
constructor(public indent: number) {} constructor(public indent: number) {}
} }
@ -45,13 +45,13 @@ export class EmitterVisitorContext {
isExportedVar(varName: string): boolean { return this._exportedVars.indexOf(varName) !== -1; } isExportedVar(varName: string): boolean { return this._exportedVars.indexOf(varName) !== -1; }
println(from?: {sourceSpan?: ParseSourceSpan}|null, lastPart: string = ''): void { println(from?: {sourceSpan: ParseSourceSpan | null}|null, lastPart: string = ''): void {
this.print(from, lastPart, true); this.print(from || null, lastPart, true);
} }
lineIsEmpty(): boolean { return this._currentLine.parts.length === 0; } lineIsEmpty(): boolean { return this._currentLine.parts.length === 0; }
print(from: {sourceSpan?: ParseSourceSpan}|null, part: string, newLine: boolean = false) { print(from: {sourceSpan: ParseSourceSpan | null}|null, part: string, newLine: boolean = false) {
if (part.length > 0) { if (part.length > 0) {
this._currentLine.parts.push(part); this._currentLine.parts.push(part);
this._currentLine.srcSpans.push(from && from.sourceSpan || null); this._currentLine.srcSpans.push(from && from.sourceSpan || null);
@ -79,9 +79,9 @@ export class EmitterVisitorContext {
pushClass(clazz: o.ClassStmt) { this._classes.push(clazz); } pushClass(clazz: o.ClassStmt) { this._classes.push(clazz); }
popClass(): o.ClassStmt { return this._classes.pop(); } popClass(): o.ClassStmt { return this._classes.pop() !; }
get currentClass(): o.ClassStmt { get currentClass(): o.ClassStmt|null {
return this._classes.length > 0 ? this._classes[this._classes.length - 1] : null; return this._classes.length > 0 ? this._classes[this._classes.length - 1] : null;
} }
@ -130,7 +130,7 @@ export class EmitterVisitorContext {
} }
while (spanIdx < spans.length) { while (spanIdx < spans.length) {
const span = spans[spanIdx]; const span = spans[spanIdx] !;
const source = span.start.file; const source = span.start.file;
const sourceLine = span.start.line; const sourceLine = span.start.line;
const sourceCol = span.start.col; const sourceCol = span.start.col;
@ -286,7 +286,7 @@ export abstract class AbstractEmitterVisitor implements o.StatementVisitor, o.Ex
return null; return null;
} }
visitReadVarExpr(ast: o.ReadVarExpr, ctx: EmitterVisitorContext): any { visitReadVarExpr(ast: o.ReadVarExpr, ctx: EmitterVisitorContext): any {
let varName = ast.name; let varName = ast.name !;
if (ast.builtin != null) { if (ast.builtin != null) {
switch (ast.builtin) { switch (ast.builtin) {
case o.BuiltinVar.Super: case o.BuiltinVar.Super:
@ -296,10 +296,10 @@ export abstract class AbstractEmitterVisitor implements o.StatementVisitor, o.Ex
varName = 'this'; varName = 'this';
break; break;
case o.BuiltinVar.CatchError: case o.BuiltinVar.CatchError:
varName = CATCH_ERROR_VAR.name; varName = CATCH_ERROR_VAR.name !;
break; break;
case o.BuiltinVar.CatchStack: case o.BuiltinVar.CatchStack:
varName = CATCH_STACK_VAR.name; varName = CATCH_STACK_VAR.name !;
break; break;
default: default:
throw new Error(`Unknown builtin variable ${ast.builtin}`); throw new Error(`Unknown builtin variable ${ast.builtin}`);
@ -335,7 +335,7 @@ export abstract class AbstractEmitterVisitor implements o.StatementVisitor, o.Ex
ctx.print(ast, '? '); ctx.print(ast, '? ');
ast.trueCase.visitExpression(this, ctx); ast.trueCase.visitExpression(this, ctx);
ctx.print(ast, ': '); ctx.print(ast, ': ');
ast.falseCase.visitExpression(this, ctx); ast.falseCase !.visitExpression(this, ctx);
ctx.print(ast, `)`); ctx.print(ast, `)`);
return null; return null;
} }

View File

@ -70,7 +70,7 @@ export abstract class AbstractJsEmitterVisitor extends AbstractEmitterVisitor {
ctx.println(stmt, `};`); ctx.println(stmt, `};`);
} }
visitReadVarExpr(ast: o.ReadVarExpr, ctx: EmitterVisitorContext): string { visitReadVarExpr(ast: o.ReadVarExpr, ctx: EmitterVisitorContext): string|null {
if (ast.builtin === o.BuiltinVar.This) { if (ast.builtin === o.BuiltinVar.This) {
ctx.print(ast, 'self'); ctx.print(ast, 'self');
} else if (ast.builtin === o.BuiltinVar.Super) { } else if (ast.builtin === o.BuiltinVar.Super) {
@ -91,10 +91,10 @@ export abstract class AbstractJsEmitterVisitor extends AbstractEmitterVisitor {
ast.value.visitExpression(this, ctx); ast.value.visitExpression(this, ctx);
return null; return null;
} }
visitInvokeFunctionExpr(expr: o.InvokeFunctionExpr, ctx: EmitterVisitorContext): string { visitInvokeFunctionExpr(expr: o.InvokeFunctionExpr, ctx: EmitterVisitorContext): string|null {
const fnExpr = expr.fn; const fnExpr = expr.fn;
if (fnExpr instanceof o.ReadVarExpr && fnExpr.builtin === o.BuiltinVar.Super) { if (fnExpr instanceof o.ReadVarExpr && fnExpr.builtin === o.BuiltinVar.Super) {
ctx.currentClass.parent.visitExpression(this, ctx); ctx.currentClass !.parent !.visitExpression(this, ctx);
ctx.print(expr, `.call(this`); ctx.print(expr, `.call(this`);
if (expr.args.length > 0) { if (expr.args.length > 0) {
ctx.print(expr, `, `); ctx.print(expr, `, `);

View File

@ -31,16 +31,16 @@ export function createClassStmt(config: {
new o.ClassMethod(null, config.ctorParams || [], superCtorStmts.concat(builder.ctorStmts)); new o.ClassMethod(null, config.ctorParams || [], superCtorStmts.concat(builder.ctorStmts));
return new o.ClassStmt( return new o.ClassStmt(
config.name, config.parent, builder.fields, builder.getters, ctor, builder.methods, config.name, config.parent || null, builder.fields, builder.getters, ctor, builder.methods,
config.modifiers || [], config.sourceSpan); config.modifiers || [], config.sourceSpan);
} }
function concatClassBuilderParts(builders: ClassBuilderPart[]) { function concatClassBuilderParts(builders: ClassBuilderPart[]) {
return { return {
fields: [].concat(...builders.map(builder => builder.fields || [])), fields: [].concat(...(builders.map((builder => builder.fields || [])) as any)),
methods: [].concat(...builders.map(builder => builder.methods || [])), methods: [].concat(...(builders.map(builder => builder.methods || []) as any)),
getters: [].concat(...builders.map(builder => builder.getters || [])), getters: [].concat(...(builders.map(builder => builder.getters || []) as any)),
ctorStmts: [].concat(...builders.map(builder => builder.ctorStmts || [])), ctorStmts: [].concat(...(builders.map(builder => builder.ctorStmts || []) as any)),
}; };
} }

View File

@ -16,14 +16,14 @@ export enum TypeModifier {
} }
export abstract class Type { export abstract class Type {
constructor(public modifiers: TypeModifier[] = null) { constructor(public modifiers: TypeModifier[]|null = null) {
if (!modifiers) { if (!modifiers) {
this.modifiers = []; this.modifiers = [];
} }
} }
abstract visitType(visitor: TypeVisitor, context: any): any; abstract visitType(visitor: TypeVisitor, context: any): any;
hasModifier(modifier: TypeModifier): boolean { return this.modifiers.indexOf(modifier) !== -1; } hasModifier(modifier: TypeModifier): boolean { return this.modifiers !.indexOf(modifier) !== -1; }
} }
export enum BuiltinTypeName { export enum BuiltinTypeName {
@ -37,14 +37,16 @@ export enum BuiltinTypeName {
} }
export class BuiltinType extends Type { export class BuiltinType extends Type {
constructor(public name: BuiltinTypeName, modifiers: TypeModifier[] = null) { super(modifiers); } constructor(public name: BuiltinTypeName, modifiers: TypeModifier[]|null = null) {
super(modifiers);
}
visitType(visitor: TypeVisitor, context: any): any { visitType(visitor: TypeVisitor, context: any): any {
return visitor.visitBuiltintType(this, context); return visitor.visitBuiltintType(this, context);
} }
} }
export class ExpressionType extends Type { export class ExpressionType extends Type {
constructor(public value: Expression, modifiers: TypeModifier[] = null) { super(modifiers); } constructor(public value: Expression, modifiers: TypeModifier[]|null = null) { super(modifiers); }
visitType(visitor: TypeVisitor, context: any): any { visitType(visitor: TypeVisitor, context: any): any {
return visitor.visitExpressionType(this, context); return visitor.visitExpressionType(this, context);
} }
@ -52,7 +54,7 @@ export class ExpressionType extends Type {
export class ArrayType extends Type { export class ArrayType extends Type {
constructor(public of : Type, modifiers: TypeModifier[] = null) { super(modifiers); } constructor(public of : Type, modifiers: TypeModifier[]|null = null) { super(modifiers); }
visitType(visitor: TypeVisitor, context: any): any { visitType(visitor: TypeVisitor, context: any): any {
return visitor.visitArrayType(this, context); return visitor.visitArrayType(this, context);
} }
@ -60,7 +62,11 @@ export class ArrayType extends Type {
export class MapType extends Type { export class MapType extends Type {
constructor(public valueType: Type, modifiers: TypeModifier[] = null) { super(modifiers); } public valueType: Type|null;
constructor(valueType: Type|null|undefined, modifiers: TypeModifier[]|null = null) {
super(modifiers);
this.valueType = valueType || null;
}
visitType(visitor: TypeVisitor, context: any): any { return visitor.visitMapType(this, context); } visitType(visitor: TypeVisitor, context: any): any { return visitor.visitMapType(this, context); }
} }
@ -101,92 +107,99 @@ export enum BinaryOperator {
export abstract class Expression { export abstract class Expression {
constructor(public type: Type, public sourceSpan?: ParseSourceSpan) {} public type: Type|null;
public sourceSpan: ParseSourceSpan|null;
constructor(type: Type|null|undefined, sourceSpan?: ParseSourceSpan|null) {
this.type = type || null;
this.sourceSpan = sourceSpan || null;
}
abstract visitExpression(visitor: ExpressionVisitor, context: any): any; abstract visitExpression(visitor: ExpressionVisitor, context: any): any;
prop(name: string, sourceSpan?: ParseSourceSpan): ReadPropExpr { prop(name: string, sourceSpan?: ParseSourceSpan|null): ReadPropExpr {
return new ReadPropExpr(this, name, null, sourceSpan); return new ReadPropExpr(this, name, null, sourceSpan);
} }
key(index: Expression, type: Type = null, sourceSpan?: ParseSourceSpan): ReadKeyExpr { key(index: Expression, type?: Type|null, sourceSpan?: ParseSourceSpan|null): ReadKeyExpr {
return new ReadKeyExpr(this, index, type, sourceSpan); return new ReadKeyExpr(this, index, type, sourceSpan);
} }
callMethod(name: string|BuiltinMethod, params: Expression[], sourceSpan?: ParseSourceSpan): callMethod(name: string|BuiltinMethod, params: Expression[], sourceSpan?: ParseSourceSpan|null):
InvokeMethodExpr { InvokeMethodExpr {
return new InvokeMethodExpr(this, name, params, null, sourceSpan); return new InvokeMethodExpr(this, name, params, null, sourceSpan);
} }
callFn(params: Expression[], sourceSpan?: ParseSourceSpan): InvokeFunctionExpr { callFn(params: Expression[], sourceSpan?: ParseSourceSpan|null): InvokeFunctionExpr {
return new InvokeFunctionExpr(this, params, null, sourceSpan); return new InvokeFunctionExpr(this, params, null, sourceSpan);
} }
instantiate(params: Expression[], type: Type = null, sourceSpan?: ParseSourceSpan): instantiate(params: Expression[], type?: Type|null, sourceSpan?: ParseSourceSpan|null):
InstantiateExpr { InstantiateExpr {
return new InstantiateExpr(this, params, type, sourceSpan); return new InstantiateExpr(this, params, type, sourceSpan);
} }
conditional(trueCase: Expression, falseCase: Expression = null, sourceSpan?: ParseSourceSpan): conditional(
ConditionalExpr { trueCase: Expression, falseCase: Expression|null = null,
sourceSpan?: ParseSourceSpan|null): ConditionalExpr {
return new ConditionalExpr(this, trueCase, falseCase, null, sourceSpan); return new ConditionalExpr(this, trueCase, falseCase, null, sourceSpan);
} }
equals(rhs: Expression, sourceSpan?: ParseSourceSpan): BinaryOperatorExpr { equals(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {
return new BinaryOperatorExpr(BinaryOperator.Equals, this, rhs, null, sourceSpan); return new BinaryOperatorExpr(BinaryOperator.Equals, this, rhs, null, sourceSpan);
} }
notEquals(rhs: Expression, sourceSpan?: ParseSourceSpan): BinaryOperatorExpr { notEquals(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {
return new BinaryOperatorExpr(BinaryOperator.NotEquals, this, rhs, null, sourceSpan); return new BinaryOperatorExpr(BinaryOperator.NotEquals, this, rhs, null, sourceSpan);
} }
identical(rhs: Expression, sourceSpan?: ParseSourceSpan): BinaryOperatorExpr { identical(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {
return new BinaryOperatorExpr(BinaryOperator.Identical, this, rhs, null, sourceSpan); return new BinaryOperatorExpr(BinaryOperator.Identical, this, rhs, null, sourceSpan);
} }
notIdentical(rhs: Expression, sourceSpan?: ParseSourceSpan): BinaryOperatorExpr { notIdentical(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {
return new BinaryOperatorExpr(BinaryOperator.NotIdentical, this, rhs, null, sourceSpan); return new BinaryOperatorExpr(BinaryOperator.NotIdentical, this, rhs, null, sourceSpan);
} }
minus(rhs: Expression, sourceSpan?: ParseSourceSpan): BinaryOperatorExpr { minus(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {
return new BinaryOperatorExpr(BinaryOperator.Minus, this, rhs, null, sourceSpan); return new BinaryOperatorExpr(BinaryOperator.Minus, this, rhs, null, sourceSpan);
} }
plus(rhs: Expression, sourceSpan?: ParseSourceSpan): BinaryOperatorExpr { plus(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {
return new BinaryOperatorExpr(BinaryOperator.Plus, this, rhs, null, sourceSpan); return new BinaryOperatorExpr(BinaryOperator.Plus, this, rhs, null, sourceSpan);
} }
divide(rhs: Expression, sourceSpan?: ParseSourceSpan): BinaryOperatorExpr { divide(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {
return new BinaryOperatorExpr(BinaryOperator.Divide, this, rhs, null, sourceSpan); return new BinaryOperatorExpr(BinaryOperator.Divide, this, rhs, null, sourceSpan);
} }
multiply(rhs: Expression, sourceSpan?: ParseSourceSpan): BinaryOperatorExpr { multiply(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {
return new BinaryOperatorExpr(BinaryOperator.Multiply, this, rhs, null, sourceSpan); return new BinaryOperatorExpr(BinaryOperator.Multiply, this, rhs, null, sourceSpan);
} }
modulo(rhs: Expression, sourceSpan?: ParseSourceSpan): BinaryOperatorExpr { modulo(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {
return new BinaryOperatorExpr(BinaryOperator.Modulo, this, rhs, null, sourceSpan); return new BinaryOperatorExpr(BinaryOperator.Modulo, this, rhs, null, sourceSpan);
} }
and(rhs: Expression, sourceSpan?: ParseSourceSpan): BinaryOperatorExpr { and(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {
return new BinaryOperatorExpr(BinaryOperator.And, this, rhs, null, sourceSpan); return new BinaryOperatorExpr(BinaryOperator.And, this, rhs, null, sourceSpan);
} }
or(rhs: Expression, sourceSpan?: ParseSourceSpan): BinaryOperatorExpr { or(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {
return new BinaryOperatorExpr(BinaryOperator.Or, this, rhs, null, sourceSpan); return new BinaryOperatorExpr(BinaryOperator.Or, this, rhs, null, sourceSpan);
} }
lower(rhs: Expression, sourceSpan?: ParseSourceSpan): BinaryOperatorExpr { lower(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {
return new BinaryOperatorExpr(BinaryOperator.Lower, this, rhs, null, sourceSpan); return new BinaryOperatorExpr(BinaryOperator.Lower, this, rhs, null, sourceSpan);
} }
lowerEquals(rhs: Expression, sourceSpan?: ParseSourceSpan): BinaryOperatorExpr { lowerEquals(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {
return new BinaryOperatorExpr(BinaryOperator.LowerEquals, this, rhs, null, sourceSpan); return new BinaryOperatorExpr(BinaryOperator.LowerEquals, this, rhs, null, sourceSpan);
} }
bigger(rhs: Expression, sourceSpan?: ParseSourceSpan): BinaryOperatorExpr { bigger(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {
return new BinaryOperatorExpr(BinaryOperator.Bigger, this, rhs, null, sourceSpan); return new BinaryOperatorExpr(BinaryOperator.Bigger, this, rhs, null, sourceSpan);
} }
biggerEquals(rhs: Expression, sourceSpan?: ParseSourceSpan): BinaryOperatorExpr { biggerEquals(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {
return new BinaryOperatorExpr(BinaryOperator.BiggerEquals, this, rhs, null, sourceSpan); return new BinaryOperatorExpr(BinaryOperator.BiggerEquals, this, rhs, null, sourceSpan);
} }
isBlank(sourceSpan?: ParseSourceSpan): Expression { isBlank(sourceSpan?: ParseSourceSpan|null): Expression {
// Note: We use equals by purpose here to compare to null and undefined in JS. // Note: We use equals by purpose here to compare to null and undefined in JS.
// We use the typed null to allow strictNullChecks to narrow types. // We use the typed null to allow strictNullChecks to narrow types.
return this.equals(TYPED_NULL_EXPR, sourceSpan); return this.equals(TYPED_NULL_EXPR, sourceSpan);
} }
cast(type: Type, sourceSpan?: ParseSourceSpan): Expression { cast(type: Type, sourceSpan?: ParseSourceSpan|null): Expression {
return new CastExpr(this, type, sourceSpan); return new CastExpr(this, type, sourceSpan);
} }
toStmt(): Statement { return new ExpressionStatement(this); } toStmt(): Statement { return new ExpressionStatement(this, null); }
} }
export enum BuiltinVar { export enum BuiltinVar {
@ -197,10 +210,10 @@ export enum BuiltinVar {
} }
export class ReadVarExpr extends Expression { export class ReadVarExpr extends Expression {
public name: string; public name: string|null;
public builtin: BuiltinVar; public builtin: BuiltinVar|null;
constructor(name: string|BuiltinVar, type: Type = null, sourceSpan?: ParseSourceSpan) { constructor(name: string|BuiltinVar, type?: Type|null, sourceSpan?: ParseSourceSpan|null) {
super(type, sourceSpan); super(type, sourceSpan);
if (typeof name === 'string') { if (typeof name === 'string') {
this.name = name; this.name = name;
@ -215,6 +228,9 @@ export class ReadVarExpr extends Expression {
} }
set(value: Expression): WriteVarExpr { set(value: Expression): WriteVarExpr {
if (!this.name) {
throw new Error(`Built in variable ${this.builtin} can not be assigned to.`)
}
return new WriteVarExpr(this.name, value, null, this.sourceSpan); return new WriteVarExpr(this.name, value, null, this.sourceSpan);
} }
} }
@ -223,7 +239,7 @@ export class ReadVarExpr extends Expression {
export class WriteVarExpr extends Expression { export class WriteVarExpr extends Expression {
public value: Expression; public value: Expression;
constructor( constructor(
public name: string, value: Expression, type: Type = null, sourceSpan?: ParseSourceSpan) { public name: string, value: Expression, type?: Type|null, sourceSpan?: ParseSourceSpan|null) {
super(type || value.type, sourceSpan); super(type || value.type, sourceSpan);
this.value = value; this.value = value;
} }
@ -232,7 +248,7 @@ export class WriteVarExpr extends Expression {
return visitor.visitWriteVarExpr(this, context); return visitor.visitWriteVarExpr(this, context);
} }
toDeclStmt(type: Type = null, modifiers: StmtModifier[] = null): DeclareVarStmt { toDeclStmt(type?: Type|null, modifiers?: StmtModifier[]|null): DeclareVarStmt {
return new DeclareVarStmt(this.name, this.value, type, modifiers, this.sourceSpan); return new DeclareVarStmt(this.name, this.value, type, modifiers, this.sourceSpan);
} }
} }
@ -241,8 +257,8 @@ export class WriteVarExpr extends Expression {
export class WriteKeyExpr extends Expression { export class WriteKeyExpr extends Expression {
public value: Expression; public value: Expression;
constructor( constructor(
public receiver: Expression, public index: Expression, value: Expression, type: Type = null, public receiver: Expression, public index: Expression, value: Expression, type?: Type|null,
sourceSpan?: ParseSourceSpan) { sourceSpan?: ParseSourceSpan|null) {
super(type || value.type, sourceSpan); super(type || value.type, sourceSpan);
this.value = value; this.value = value;
} }
@ -255,8 +271,8 @@ export class WriteKeyExpr extends Expression {
export class WritePropExpr extends Expression { export class WritePropExpr extends Expression {
public value: Expression; public value: Expression;
constructor( constructor(
public receiver: Expression, public name: string, value: Expression, type: Type = null, public receiver: Expression, public name: string, value: Expression, type?: Type|null,
sourceSpan?: ParseSourceSpan) { sourceSpan?: ParseSourceSpan|null) {
super(type || value.type, sourceSpan); super(type || value.type, sourceSpan);
this.value = value; this.value = value;
} }
@ -272,11 +288,11 @@ export enum BuiltinMethod {
} }
export class InvokeMethodExpr extends Expression { export class InvokeMethodExpr extends Expression {
public name: string; public name: string|null;
public builtin: BuiltinMethod; public builtin: BuiltinMethod|null;
constructor( constructor(
public receiver: Expression, method: string|BuiltinMethod, public args: Expression[], public receiver: Expression, method: string|BuiltinMethod, public args: Expression[],
type: Type = null, sourceSpan?: ParseSourceSpan) { type?: Type|null, sourceSpan?: ParseSourceSpan|null) {
super(type, sourceSpan); super(type, sourceSpan);
if (typeof method === 'string') { if (typeof method === 'string') {
this.name = method; this.name = method;
@ -294,8 +310,8 @@ export class InvokeMethodExpr extends Expression {
export class InvokeFunctionExpr extends Expression { export class InvokeFunctionExpr extends Expression {
constructor( constructor(
public fn: Expression, public args: Expression[], type: Type = null, public fn: Expression, public args: Expression[], type?: Type|null,
sourceSpan?: ParseSourceSpan) { sourceSpan?: ParseSourceSpan|null) {
super(type, sourceSpan); super(type, sourceSpan);
} }
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
@ -306,8 +322,8 @@ export class InvokeFunctionExpr extends Expression {
export class InstantiateExpr extends Expression { export class InstantiateExpr extends Expression {
constructor( constructor(
public classExpr: Expression, public args: Expression[], type?: Type, public classExpr: Expression, public args: Expression[], type?: Type|null,
sourceSpan?: ParseSourceSpan) { sourceSpan?: ParseSourceSpan|null) {
super(type, sourceSpan); super(type, sourceSpan);
} }
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
@ -317,7 +333,7 @@ export class InstantiateExpr extends Expression {
export class LiteralExpr extends Expression { export class LiteralExpr extends Expression {
constructor(public value: any, type: Type = null, sourceSpan?: ParseSourceSpan) { constructor(public value: any, type?: Type|null, sourceSpan?: ParseSourceSpan|null) {
super(type, sourceSpan); super(type, sourceSpan);
} }
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
@ -328,8 +344,8 @@ export class LiteralExpr extends Expression {
export class ExternalExpr extends Expression { export class ExternalExpr extends Expression {
constructor( constructor(
public value: CompileIdentifierMetadata, type: Type = null, public typeParams: Type[] = null, public value: CompileIdentifierMetadata, type?: Type|null,
sourceSpan?: ParseSourceSpan) { public typeParams: Type[]|null = null, sourceSpan?: ParseSourceSpan|null) {
super(type, sourceSpan); super(type, sourceSpan);
} }
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
@ -341,8 +357,8 @@ export class ExternalExpr extends Expression {
export class ConditionalExpr extends Expression { export class ConditionalExpr extends Expression {
public trueCase: Expression; public trueCase: Expression;
constructor( constructor(
public condition: Expression, trueCase: Expression, public falseCase: Expression = null, public condition: Expression, trueCase: Expression, public falseCase: Expression|null = null,
type: Type = null, sourceSpan?: ParseSourceSpan) { type?: Type|null, sourceSpan?: ParseSourceSpan|null) {
super(type || trueCase.type, sourceSpan); super(type || trueCase.type, sourceSpan);
this.trueCase = trueCase; this.trueCase = trueCase;
} }
@ -353,7 +369,7 @@ export class ConditionalExpr extends Expression {
export class NotExpr extends Expression { export class NotExpr extends Expression {
constructor(public condition: Expression, sourceSpan?: ParseSourceSpan) { constructor(public condition: Expression, sourceSpan?: ParseSourceSpan|null) {
super(BOOL_TYPE, sourceSpan); super(BOOL_TYPE, sourceSpan);
} }
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
@ -362,7 +378,7 @@ export class NotExpr extends Expression {
} }
export class CastExpr extends Expression { export class CastExpr extends Expression {
constructor(public value: Expression, type: Type, sourceSpan?: ParseSourceSpan) { constructor(public value: Expression, type?: Type|null, sourceSpan?: ParseSourceSpan|null) {
super(type, sourceSpan); super(type, sourceSpan);
} }
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
@ -372,21 +388,21 @@ export class CastExpr extends Expression {
export class FnParam { export class FnParam {
constructor(public name: string, public type: Type = null) {} constructor(public name: string, public type: Type|null = null) {}
} }
export class FunctionExpr extends Expression { export class FunctionExpr extends Expression {
constructor( constructor(
public params: FnParam[], public statements: Statement[], type: Type = null, public params: FnParam[], public statements: Statement[], type?: Type|null,
sourceSpan?: ParseSourceSpan) { sourceSpan?: ParseSourceSpan|null) {
super(type, sourceSpan); super(type, sourceSpan);
} }
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitFunctionExpr(this, context); return visitor.visitFunctionExpr(this, context);
} }
toDeclStmt(name: string, modifiers: StmtModifier[] = null): DeclareFunctionStmt { toDeclStmt(name: string, modifiers: StmtModifier[]|null = null): DeclareFunctionStmt {
return new DeclareFunctionStmt( return new DeclareFunctionStmt(
name, this.params, this.statements, this.type, modifiers, this.sourceSpan); name, this.params, this.statements, this.type, modifiers, this.sourceSpan);
} }
@ -396,8 +412,8 @@ export class FunctionExpr extends Expression {
export class BinaryOperatorExpr extends Expression { export class BinaryOperatorExpr extends Expression {
public lhs: Expression; public lhs: Expression;
constructor( constructor(
public operator: BinaryOperator, lhs: Expression, public rhs: Expression, type: Type = null, public operator: BinaryOperator, lhs: Expression, public rhs: Expression, type?: Type|null,
sourceSpan?: ParseSourceSpan) { sourceSpan?: ParseSourceSpan|null) {
super(type || lhs.type, sourceSpan); super(type || lhs.type, sourceSpan);
this.lhs = lhs; this.lhs = lhs;
} }
@ -409,8 +425,8 @@ export class BinaryOperatorExpr extends Expression {
export class ReadPropExpr extends Expression { export class ReadPropExpr extends Expression {
constructor( constructor(
public receiver: Expression, public name: string, type: Type = null, public receiver: Expression, public name: string, type?: Type|null,
sourceSpan?: ParseSourceSpan) { sourceSpan?: ParseSourceSpan|null) {
super(type, sourceSpan); super(type, sourceSpan);
} }
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
@ -424,8 +440,8 @@ export class ReadPropExpr extends Expression {
export class ReadKeyExpr extends Expression { export class ReadKeyExpr extends Expression {
constructor( constructor(
public receiver: Expression, public index: Expression, type: Type = null, public receiver: Expression, public index: Expression, type?: Type|null,
sourceSpan?: ParseSourceSpan) { sourceSpan?: ParseSourceSpan|null) {
super(type, sourceSpan); super(type, sourceSpan);
} }
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
@ -439,7 +455,7 @@ export class ReadKeyExpr extends Expression {
export class LiteralArrayExpr extends Expression { export class LiteralArrayExpr extends Expression {
public entries: Expression[]; public entries: Expression[];
constructor(entries: Expression[], type: Type = null, sourceSpan?: ParseSourceSpan) { constructor(entries: Expression[], type?: Type|null, sourceSpan?: ParseSourceSpan|null) {
super(type, sourceSpan); super(type, sourceSpan);
this.entries = entries; this.entries = entries;
} }
@ -453,9 +469,9 @@ export class LiteralMapEntry {
} }
export class LiteralMapExpr extends Expression { export class LiteralMapExpr extends Expression {
public valueType: Type = null; public valueType: Type|null = null;
constructor( constructor(
public entries: LiteralMapEntry[], type: MapType = null, sourceSpan?: ParseSourceSpan) { public entries: LiteralMapEntry[], type?: MapType|null, sourceSpan?: ParseSourceSpan|null) {
super(type, sourceSpan); super(type, sourceSpan);
if (type) { if (type) {
this.valueType = type.valueType; this.valueType = type.valueType;
@ -467,7 +483,7 @@ export class LiteralMapExpr extends Expression {
} }
export class CommaExpr extends Expression { export class CommaExpr extends Expression {
constructor(public parts: Expression[], sourceSpan?: ParseSourceSpan) { constructor(public parts: Expression[], sourceSpan?: ParseSourceSpan|null) {
super(parts[parts.length - 1].type, sourceSpan); super(parts[parts.length - 1].type, sourceSpan);
} }
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
@ -497,12 +513,12 @@ export interface ExpressionVisitor {
visitCommaExpr(ast: CommaExpr, context: any): any; visitCommaExpr(ast: CommaExpr, context: any): any;
} }
export const THIS_EXPR = new ReadVarExpr(BuiltinVar.This); export const THIS_EXPR = new ReadVarExpr(BuiltinVar.This, null, null);
export const SUPER_EXPR = new ReadVarExpr(BuiltinVar.Super); export const SUPER_EXPR = new ReadVarExpr(BuiltinVar.Super, null, null);
export const CATCH_ERROR_VAR = new ReadVarExpr(BuiltinVar.CatchError); export const CATCH_ERROR_VAR = new ReadVarExpr(BuiltinVar.CatchError, null, null);
export const CATCH_STACK_VAR = new ReadVarExpr(BuiltinVar.CatchStack); export const CATCH_STACK_VAR = new ReadVarExpr(BuiltinVar.CatchStack, null, null);
export const NULL_EXPR = new LiteralExpr(null, null); export const NULL_EXPR = new LiteralExpr(null, null, null);
export const TYPED_NULL_EXPR = new LiteralExpr(null, INFERRED_TYPE); export const TYPED_NULL_EXPR = new LiteralExpr(null, INFERRED_TYPE, null);
//// Statements //// Statements
export enum StmtModifier { export enum StmtModifier {
@ -511,23 +527,24 @@ export enum StmtModifier {
} }
export abstract class Statement { export abstract class Statement {
constructor(public modifiers: StmtModifier[] = null, public sourceSpan?: ParseSourceSpan) { public modifiers: StmtModifier[];
if (!modifiers) { public sourceSpan: ParseSourceSpan|null;
this.modifiers = []; constructor(modifiers?: StmtModifier[]|null, sourceSpan?: ParseSourceSpan|null) {
} this.modifiers = modifiers || [];
this.sourceSpan = sourceSpan || null;
} }
abstract visitStatement(visitor: StatementVisitor, context: any): any; abstract visitStatement(visitor: StatementVisitor, context: any): any;
hasModifier(modifier: StmtModifier): boolean { return this.modifiers.indexOf(modifier) !== -1; } hasModifier(modifier: StmtModifier): boolean { return this.modifiers !.indexOf(modifier) !== -1; }
} }
export class DeclareVarStmt extends Statement { export class DeclareVarStmt extends Statement {
public type: Type; public type: Type|null;
constructor( constructor(
public name: string, public value: Expression, type: Type = null, public name: string, public value: Expression, type?: Type|null,
modifiers: StmtModifier[] = null, sourceSpan?: ParseSourceSpan) { modifiers: StmtModifier[]|null = null, sourceSpan?: ParseSourceSpan|null) {
super(modifiers, sourceSpan); super(modifiers, sourceSpan);
this.type = type || value.type; this.type = type || value.type;
} }
@ -538,10 +555,12 @@ export class DeclareVarStmt extends Statement {
} }
export class DeclareFunctionStmt extends Statement { export class DeclareFunctionStmt extends Statement {
public type: Type|null;
constructor( constructor(
public name: string, public params: FnParam[], public statements: Statement[], public name: string, public params: FnParam[], public statements: Statement[],
public type: Type = null, modifiers: StmtModifier[] = null, sourceSpan?: ParseSourceSpan) { type?: Type|null, modifiers: StmtModifier[]|null = null, sourceSpan?: ParseSourceSpan|null) {
super(modifiers, sourceSpan); super(modifiers, sourceSpan);
this.type = type || null;
} }
visitStatement(visitor: StatementVisitor, context: any): any { visitStatement(visitor: StatementVisitor, context: any): any {
@ -550,7 +569,9 @@ export class DeclareFunctionStmt extends Statement {
} }
export class ExpressionStatement extends Statement { export class ExpressionStatement extends Statement {
constructor(public expr: Expression, sourceSpan?: ParseSourceSpan) { super(null, sourceSpan); } constructor(public expr: Expression, sourceSpan?: ParseSourceSpan|null) {
super(null, sourceSpan);
}
visitStatement(visitor: StatementVisitor, context: any): any { visitStatement(visitor: StatementVisitor, context: any): any {
return visitor.visitExpressionStmt(this, context); return visitor.visitExpressionStmt(this, context);
@ -559,23 +580,27 @@ export class ExpressionStatement extends Statement {
export class ReturnStatement extends Statement { export class ReturnStatement extends Statement {
constructor(public value: Expression, sourceSpan?: ParseSourceSpan) { super(null, sourceSpan); } constructor(public value: Expression, sourceSpan?: ParseSourceSpan|null) {
super(null, sourceSpan);
}
visitStatement(visitor: StatementVisitor, context: any): any { visitStatement(visitor: StatementVisitor, context: any): any {
return visitor.visitReturnStmt(this, context); return visitor.visitReturnStmt(this, context);
} }
} }
export class AbstractClassPart { export class AbstractClassPart {
constructor(public type: Type = null, public modifiers: StmtModifier[]) { public type: Type|null;
constructor(type: Type|null|undefined, public modifiers: StmtModifier[]|null) {
if (!modifiers) { if (!modifiers) {
this.modifiers = []; this.modifiers = [];
} }
this.type = type || null;
} }
hasModifier(modifier: StmtModifier): boolean { return this.modifiers.indexOf(modifier) !== -1; } hasModifier(modifier: StmtModifier): boolean { return this.modifiers !.indexOf(modifier) !== -1; }
} }
export class ClassField extends AbstractClassPart { export class ClassField extends AbstractClassPart {
constructor(public name: string, type: Type = null, modifiers: StmtModifier[] = null) { constructor(public name: string, type?: Type|null, modifiers: StmtModifier[]|null = null) {
super(type, modifiers); super(type, modifiers);
} }
} }
@ -583,8 +608,8 @@ export class ClassField extends AbstractClassPart {
export class ClassMethod extends AbstractClassPart { export class ClassMethod extends AbstractClassPart {
constructor( constructor(
public name: string, public params: FnParam[], public body: Statement[], type: Type = null, public name: string|null, public params: FnParam[], public body: Statement[],
modifiers: StmtModifier[] = null) { type?: Type|null, modifiers: StmtModifier[]|null = null) {
super(type, modifiers); super(type, modifiers);
} }
} }
@ -592,8 +617,8 @@ export class ClassMethod extends AbstractClassPart {
export class ClassGetter extends AbstractClassPart { export class ClassGetter extends AbstractClassPart {
constructor( constructor(
public name: string, public body: Statement[], type: Type = null, public name: string, public body: Statement[], type?: Type|null,
modifiers: StmtModifier[] = null) { modifiers: StmtModifier[]|null = null) {
super(type, modifiers); super(type, modifiers);
} }
} }
@ -601,10 +626,10 @@ export class ClassGetter extends AbstractClassPart {
export class ClassStmt extends Statement { export class ClassStmt extends Statement {
constructor( constructor(
public name: string, public parent: Expression, public fields: ClassField[], public name: string, public parent: Expression|null, public fields: ClassField[],
public getters: ClassGetter[], public constructorMethod: ClassMethod, public getters: ClassGetter[], public constructorMethod: ClassMethod,
public methods: ClassMethod[], modifiers: StmtModifier[] = null, public methods: ClassMethod[], modifiers: StmtModifier[]|null = null,
sourceSpan?: ParseSourceSpan) { sourceSpan?: ParseSourceSpan|null) {
super(modifiers, sourceSpan); super(modifiers, sourceSpan);
} }
visitStatement(visitor: StatementVisitor, context: any): any { visitStatement(visitor: StatementVisitor, context: any): any {
@ -616,7 +641,7 @@ export class ClassStmt extends Statement {
export class IfStmt extends Statement { export class IfStmt extends Statement {
constructor( constructor(
public condition: Expression, public trueCase: Statement[], public condition: Expression, public trueCase: Statement[],
public falseCase: Statement[] = [], sourceSpan?: ParseSourceSpan) { public falseCase: Statement[] = [], sourceSpan?: ParseSourceSpan|null) {
super(null, sourceSpan); super(null, sourceSpan);
} }
visitStatement(visitor: StatementVisitor, context: any): any { visitStatement(visitor: StatementVisitor, context: any): any {
@ -626,7 +651,9 @@ export class IfStmt extends Statement {
export class CommentStmt extends Statement { export class CommentStmt extends Statement {
constructor(public comment: string, sourceSpan?: ParseSourceSpan) { super(null, sourceSpan); } constructor(public comment: string, sourceSpan?: ParseSourceSpan|null) {
super(null, sourceSpan);
}
visitStatement(visitor: StatementVisitor, context: any): any { visitStatement(visitor: StatementVisitor, context: any): any {
return visitor.visitCommentStmt(this, context); return visitor.visitCommentStmt(this, context);
} }
@ -635,7 +662,8 @@ export class CommentStmt extends Statement {
export class TryCatchStmt extends Statement { export class TryCatchStmt extends Statement {
constructor( constructor(
public bodyStmts: Statement[], public catchStmts: Statement[], sourceSpan?: ParseSourceSpan) { public bodyStmts: Statement[], public catchStmts: Statement[],
sourceSpan?: ParseSourceSpan|null) {
super(null, sourceSpan); super(null, sourceSpan);
} }
visitStatement(visitor: StatementVisitor, context: any): any { visitStatement(visitor: StatementVisitor, context: any): any {
@ -645,7 +673,9 @@ export class TryCatchStmt extends Statement {
export class ThrowStmt extends Statement { export class ThrowStmt extends Statement {
constructor(public error: Expression, sourceSpan?: ParseSourceSpan) { super(null, sourceSpan); } constructor(public error: Expression, sourceSpan?: ParseSourceSpan|null) {
super(null, sourceSpan);
}
visitStatement(visitor: StatementVisitor, context: any): any { visitStatement(visitor: StatementVisitor, context: any): any {
return visitor.visitThrowStmt(this, context); return visitor.visitThrowStmt(this, context);
} }
@ -697,7 +727,7 @@ export class AstTransformer implements StatementVisitor, ExpressionVisitor {
const method = ast.builtin || ast.name; const method = ast.builtin || ast.name;
return this.transformExpr( return this.transformExpr(
new InvokeMethodExpr( new InvokeMethodExpr(
ast.receiver.visitExpression(this, context), method, ast.receiver.visitExpression(this, context), method !,
this.visitAllExpressions(ast.args, context), ast.type, ast.sourceSpan), this.visitAllExpressions(ast.args, context), ast.type, ast.sourceSpan),
context); context);
} }
@ -729,7 +759,7 @@ export class AstTransformer implements StatementVisitor, ExpressionVisitor {
new ConditionalExpr( new ConditionalExpr(
ast.condition.visitExpression(this, context), ast.condition.visitExpression(this, context),
ast.trueCase.visitExpression(this, context), ast.trueCase.visitExpression(this, context),
ast.falseCase.visitExpression(this, context), ast.type, ast.sourceSpan), ast.falseCase !.visitExpression(this, context), ast.type, ast.sourceSpan),
context); context);
} }
@ -784,7 +814,7 @@ export class AstTransformer implements StatementVisitor, ExpressionVisitor {
const entries = ast.entries.map( const entries = ast.entries.map(
(entry): LiteralMapEntry => new LiteralMapEntry( (entry): LiteralMapEntry => new LiteralMapEntry(
entry.key, entry.value.visitExpression(this, context), entry.quoted, )); entry.key, entry.value.visitExpression(this, context), entry.quoted, ));
const mapType = new MapType(ast.valueType); const mapType = new MapType(ast.valueType, null);
return this.transformExpr(new LiteralMapExpr(entries, mapType, ast.sourceSpan), context); return this.transformExpr(new LiteralMapExpr(entries, mapType, ast.sourceSpan), context);
} }
visitCommaExpr(ast: CommaExpr, context: any): any { visitCommaExpr(ast: CommaExpr, context: any): any {
@ -822,7 +852,7 @@ export class AstTransformer implements StatementVisitor, ExpressionVisitor {
} }
visitDeclareClassStmt(stmt: ClassStmt, context: any): any { visitDeclareClassStmt(stmt: ClassStmt, context: any): any {
const parent = stmt.parent.visitExpression(this, context); const parent = stmt.parent !.visitExpression(this, context);
const getters = stmt.getters.map( const getters = stmt.getters.map(
getter => new ClassGetter( getter => new ClassGetter(
getter.name, this.visitAllStatements(getter.body, context), getter.type, getter.name, this.visitAllStatements(getter.body, context), getter.type,
@ -911,7 +941,7 @@ export class RecursiveAstVisitor implements StatementVisitor, ExpressionVisitor
visitConditionalExpr(ast: ConditionalExpr, context: any): any { visitConditionalExpr(ast: ConditionalExpr, context: any): any {
ast.condition.visitExpression(this, context); ast.condition.visitExpression(this, context);
ast.trueCase.visitExpression(this, context); ast.trueCase.visitExpression(this, context);
ast.falseCase.visitExpression(this, context); ast.falseCase !.visitExpression(this, context);
return ast; return ast;
} }
visitNotExpr(ast: NotExpr, context: any): any { visitNotExpr(ast: NotExpr, context: any): any {
@ -972,7 +1002,7 @@ export class RecursiveAstVisitor implements StatementVisitor, ExpressionVisitor
return stmt; return stmt;
} }
visitDeclareClassStmt(stmt: ClassStmt, context: any): any { visitDeclareClassStmt(stmt: ClassStmt, context: any): any {
stmt.parent.visitExpression(this, context); stmt.parent !.visitExpression(this, context);
stmt.getters.forEach(getter => this.visitAllStatements(getter.body, context)); stmt.getters.forEach(getter => this.visitAllStatements(getter.body, context));
if (stmt.constructorMethod) { if (stmt.constructorMethod) {
this.visitAllStatements(stmt.constructorMethod.body, context); this.visitAllStatements(stmt.constructorMethod.body, context);
@ -1018,13 +1048,15 @@ class _ReadVarVisitor extends RecursiveAstVisitor {
return stmt; return stmt;
} }
visitReadVarExpr(ast: ReadVarExpr, context: any): any { visitReadVarExpr(ast: ReadVarExpr, context: any): any {
this.varNames.add(ast.name); if (ast.name) {
this.varNames.add(ast.name);
}
return null; return null;
} }
} }
export function applySourceSpanToStatementIfNeeded( export function applySourceSpanToStatementIfNeeded(
stmt: Statement, sourceSpan: ParseSourceSpan): Statement { stmt: Statement, sourceSpan: ParseSourceSpan | null): Statement {
if (!sourceSpan) { if (!sourceSpan) {
return stmt; return stmt;
} }
@ -1033,7 +1065,7 @@ export function applySourceSpanToStatementIfNeeded(
} }
export function applySourceSpanToExpressionIfNeeded( export function applySourceSpanToExpressionIfNeeded(
expr: Expression, sourceSpan: ParseSourceSpan): Expression { expr: Expression, sourceSpan: ParseSourceSpan | null): Expression {
if (!sourceSpan) { if (!sourceSpan) {
return expr; return expr;
} }
@ -1069,48 +1101,51 @@ class _ApplySourceSpanTransformer extends AstTransformer {
} }
export function variable( export function variable(
name: string, type: Type = null, sourceSpan?: ParseSourceSpan): ReadVarExpr { name: string, type?: Type | null, sourceSpan?: ParseSourceSpan | null): ReadVarExpr {
return new ReadVarExpr(name, type, sourceSpan); return new ReadVarExpr(name, type, sourceSpan);
} }
export function importExpr( export function importExpr(
id: CompileIdentifierMetadata, typeParams: Type[] = null, id: CompileIdentifierMetadata, typeParams: Type[] | null = null,
sourceSpan?: ParseSourceSpan): ExternalExpr { sourceSpan?: ParseSourceSpan | null): ExternalExpr {
return new ExternalExpr(id, null, typeParams, sourceSpan); return new ExternalExpr(id, null, typeParams, sourceSpan);
} }
export function importType( export function importType(
id: CompileIdentifierMetadata, typeParams: Type[] = null, id: CompileIdentifierMetadata, typeParams: Type[] | null = null,
typeModifiers: TypeModifier[] = null): ExpressionType { typeModifiers: TypeModifier[] | null = null): ExpressionType|null {
return id != null ? expressionType(importExpr(id, typeParams), typeModifiers) : null; return id != null ? expressionType(importExpr(id, typeParams, null), typeModifiers) : null;
} }
export function expressionType( export function expressionType(
expr: Expression, typeModifiers: TypeModifier[] = null): ExpressionType { expr: Expression, typeModifiers: TypeModifier[] | null = null): ExpressionType|null {
return expr != null ? new ExpressionType(expr, typeModifiers) : null; return expr != null ? new ExpressionType(expr, typeModifiers) ! : null;
} }
export function literalArr( export function literalArr(
values: Expression[], type: Type = null, sourceSpan?: ParseSourceSpan): LiteralArrayExpr { values: Expression[], type?: Type | null,
sourceSpan?: ParseSourceSpan | null): LiteralArrayExpr {
return new LiteralArrayExpr(values, type, sourceSpan); return new LiteralArrayExpr(values, type, sourceSpan);
} }
export function literalMap( export function literalMap(
values: [string, Expression][], type: MapType = null, quoted: boolean = false): LiteralMapExpr { values: [string, Expression][], type: MapType | null = null,
quoted: boolean = false): LiteralMapExpr {
return new LiteralMapExpr( return new LiteralMapExpr(
values.map(entry => new LiteralMapEntry(entry[0], entry[1], quoted)), type); values.map(entry => new LiteralMapEntry(entry[0], entry[1], quoted)), type, null);
} }
export function not(expr: Expression, sourceSpan?: ParseSourceSpan): NotExpr { export function not(expr: Expression, sourceSpan?: ParseSourceSpan | null): NotExpr {
return new NotExpr(expr, sourceSpan); return new NotExpr(expr, sourceSpan);
} }
export function fn( export function fn(
params: FnParam[], body: Statement[], type: Type = null, params: FnParam[], body: Statement[], type?: Type | null,
sourceSpan?: ParseSourceSpan): FunctionExpr { sourceSpan?: ParseSourceSpan | null): FunctionExpr {
return new FunctionExpr(params, body, type, sourceSpan); return new FunctionExpr(params, body, type, sourceSpan);
} }
export function literal(value: any, type: Type = null, sourceSpan?: ParseSourceSpan): LiteralExpr { export function literal(
value: any, type?: Type | null, sourceSpan?: ParseSourceSpan | null): LiteralExpr {
return new LiteralExpr(value, type, sourceSpan); return new LiteralExpr(value, type, sourceSpan);
} }

View File

@ -33,7 +33,7 @@ function _executeFunctionStatements(
class _ExecutionContext { class _ExecutionContext {
constructor( constructor(
public parent: _ExecutionContext, public instance: any, public className: string, public parent: _ExecutionContext|null, public instance: any, public className: string|null,
public vars: Map<string, any>) {} public vars: Map<string, any>) {}
createChildWihtLocalVars(): _ExecutionContext { createChildWihtLocalVars(): _ExecutionContext {
@ -62,7 +62,7 @@ function createDynamicClass(
_classStmt.methods.forEach(function(method: o.ClassMethod) { _classStmt.methods.forEach(function(method: o.ClassMethod) {
const paramNames = method.params.map(param => param.name); const paramNames = method.params.map(param => param.name);
// Note: use `function` instead of arrow function to capture `this` // Note: use `function` instead of arrow function to capture `this`
propertyDescriptors[method.name] = { propertyDescriptors[method.name !] = {
writable: false, writable: false,
configurable: false, configurable: false,
value: function(...args: any[]) { value: function(...args: any[]) {
@ -100,12 +100,12 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
currCtx.vars.set(expr.name, value); currCtx.vars.set(expr.name, value);
return value; return value;
} }
currCtx = currCtx.parent; currCtx = currCtx.parent !;
} }
throw new Error(`Not declared variable ${expr.name}`); throw new Error(`Not declared variable ${expr.name}`);
} }
visitReadVarExpr(ast: o.ReadVarExpr, ctx: _ExecutionContext): any { visitReadVarExpr(ast: o.ReadVarExpr, ctx: _ExecutionContext): any {
let varName = ast.name; let varName = ast.name !;
if (ast.builtin != null) { if (ast.builtin != null) {
switch (ast.builtin) { switch (ast.builtin) {
case o.BuiltinVar.Super: case o.BuiltinVar.Super:
@ -127,7 +127,7 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
if (currCtx.vars.has(varName)) { if (currCtx.vars.has(varName)) {
return currCtx.vars.get(varName); return currCtx.vars.get(varName);
} }
currCtx = currCtx.parent; currCtx = currCtx.parent !;
} }
throw new Error(`Not declared variable ${varName}`); throw new Error(`Not declared variable ${varName}`);
} }
@ -164,7 +164,7 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
throw new Error(`Unknown builtin method ${expr.builtin}`); throw new Error(`Unknown builtin method ${expr.builtin}`);
} }
} else { } else {
result = receiver[expr.name].apply(receiver, args); result = receiver[expr.name !].apply(receiver, args);
} }
return result; return result;
} }
@ -312,7 +312,7 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
return expressions.map((expr) => expr.visitExpression(this, ctx)); return expressions.map((expr) => expr.visitExpression(this, ctx));
} }
visitAllStatements(statements: o.Statement[], ctx: _ExecutionContext): ReturnValue { visitAllStatements(statements: o.Statement[], ctx: _ExecutionContext): ReturnValue|null {
for (let i = 0; i < statements.length; i++) { for (let i = 0; i < statements.length; i++) {
const stmt = statements[i]; const stmt = statements[i];
const val = stmt.visitStatement(this, ctx); const val = stmt.visitStatement(this, ctx);

View File

@ -16,17 +16,16 @@ export abstract class ImportResolver {
* Converts a file path to a module name that can be used as an `import. * Converts a file path to a module name that can be used as an `import.
* I.e. `path/to/importedFile.ts` should be imported by `path/to/containingFile.ts`. * I.e. `path/to/importedFile.ts` should be imported by `path/to/containingFile.ts`.
*/ */
abstract fileNameToModuleName(importedFilePath: string, containingFilePath: string): string abstract fileNameToModuleName(importedFilePath: string, containingFilePath: string): string|null;
/*|null*/;
/** /**
* Converts the given StaticSymbol into another StaticSymbol that should be used * Converts the given StaticSymbol into another StaticSymbol that should be used
* to generate the import from. * to generate the import from.
*/ */
abstract getImportAs(symbol: StaticSymbol): StaticSymbol /*|null*/; abstract getImportAs(symbol: StaticSymbol): StaticSymbol|null;
/** /**
* Determine the arity of a type. * Determine the arity of a type.
*/ */
abstract getTypeArity(symbol: StaticSymbol): number /*|null*/; abstract getTypeArity(symbol: StaticSymbol): number|null;
} }

View File

@ -25,12 +25,12 @@ export type SourceMap = {
file?: string, file?: string,
sourceRoot: string, sourceRoot: string,
sources: string[], sources: string[],
sourcesContent: string[], sourcesContent: (string | null)[],
mappings: string, mappings: string,
}; };
export class SourceMapGenerator { export class SourceMapGenerator {
private sourcesContent: Map<string, string> = new Map(); private sourcesContent: Map<string, string|null> = new Map();
private lines: Segment[][] = []; private lines: Segment[][] = [];
private lastCol0: number = 0; private lastCol0: number = 0;
private hasMappings = false; private hasMappings = false;
@ -83,7 +83,7 @@ export class SourceMapGenerator {
const sourcesIndex = new Map<string, number>(); const sourcesIndex = new Map<string, number>();
const sources: string[] = []; const sources: string[] = [];
const sourcesContent: string[] = []; const sourcesContent: (string | null)[] = [];
Array.from(this.sourcesContent.keys()).forEach((url: string, i: number) => { Array.from(this.sourcesContent.keys()).forEach((url: string, i: number) => {
sourcesIndex.set(url, i); sourcesIndex.set(url, i);
@ -109,14 +109,14 @@ export class SourceMapGenerator {
if (segment.sourceUrl != null) { if (segment.sourceUrl != null) {
// zero-based index into the “sources” list // zero-based index into the “sources” list
segAsStr += segAsStr +=
toBase64VLQ(sourcesIndex.get(segment.sourceUrl) - lastSourceIndex); toBase64VLQ(sourcesIndex.get(segment.sourceUrl) ! - lastSourceIndex);
lastSourceIndex = sourcesIndex.get(segment.sourceUrl); lastSourceIndex = sourcesIndex.get(segment.sourceUrl) !;
// the zero-based starting line in the original source // the zero-based starting line in the original source
segAsStr += toBase64VLQ(segment.sourceLine0 - lastSourceLine0); segAsStr += toBase64VLQ(segment.sourceLine0 ! - lastSourceLine0);
lastSourceLine0 = segment.sourceLine0; lastSourceLine0 = segment.sourceLine0 !;
// the zero-based starting column in the original source // the zero-based starting column in the original source
segAsStr += toBase64VLQ(segment.sourceCol0 - lastSourceCol0); segAsStr += toBase64VLQ(segment.sourceCol0 ! - lastSourceCol0);
lastSourceCol0 = segment.sourceCol0; lastSourceCol0 = segment.sourceCol0 !;
} }
return segAsStr; return segAsStr;

View File

@ -20,7 +20,7 @@ export function debugOutputAstAsTypeScript(ast: o.Statement | o.Expression | o.T
string { string {
const converter = new _TsEmitterVisitor(_debugFilePath, { const converter = new _TsEmitterVisitor(_debugFilePath, {
fileNameToModuleName(filePath: string, containingFilePath: string) { return filePath; }, fileNameToModuleName(filePath: string, containingFilePath: string) { return filePath; },
getImportAs(symbol: StaticSymbol) { return null; }, getImportAs(symbol: StaticSymbol | null) { return null; },
getTypeArity: symbol => null getTypeArity: symbol => null
}); });
const ctx = EmitterVisitorContext.createRoot([]); const ctx = EmitterVisitorContext.createRoot([]);
@ -89,8 +89,8 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
importsWithPrefixes = new Map<string, string>(); importsWithPrefixes = new Map<string, string>();
reexports = new Map<string, {name: string, as: string}[]>(); reexports = new Map<string, {name: string, as: string}[]>();
visitType(t: o.Type, ctx: EmitterVisitorContext, defaultType: string = 'any') { visitType(t: o.Type|null, ctx: EmitterVisitorContext, defaultType: string = 'any') {
if (t != null) { if (t) {
this.typeExpression++; this.typeExpression++;
t.visitType(this, ctx); t.visitType(this, ctx);
this.typeExpression--; this.typeExpression--;
@ -133,7 +133,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
if (ctx.isExportedVar(stmt.name) && stmt.value instanceof o.ExternalExpr && !stmt.type) { if (ctx.isExportedVar(stmt.name) && stmt.value instanceof o.ExternalExpr && !stmt.type) {
// check for a reexport // check for a reexport
const {name, filePath, members} = this._resolveStaticSymbol(stmt.value.value); const {name, filePath, members} = this._resolveStaticSymbol(stmt.value.value);
if (members.length === 0 && filePath !== this._genFilePath) { if (members !.length === 0 && filePath !== this._genFilePath) {
let reexports = this.reexports.get(filePath); let reexports = this.reexports.get(filePath);
if (!reexports) { if (!reexports) {
reexports = []; reexports = [];
@ -161,7 +161,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
visitCastExpr(ast: o.CastExpr, ctx: EmitterVisitorContext): any { visitCastExpr(ast: o.CastExpr, ctx: EmitterVisitorContext): any {
ctx.print(ast, `(<`); ctx.print(ast, `(<`);
ast.type.visitType(this, ctx); ast.type !.visitType(this, ctx);
ctx.print(ast, `>`); ctx.print(ast, `>`);
ast.value.visitExpression(this, ctx); ast.value.visitExpression(this, ctx);
ctx.print(ast, `)`); ctx.print(ast, `)`);
@ -290,7 +290,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
ctx.println(stmt, `} catch (${CATCH_ERROR_VAR.name}) {`); ctx.println(stmt, `} catch (${CATCH_ERROR_VAR.name}) {`);
ctx.incIndent(); ctx.incIndent();
const catchStmts = const catchStmts =
[<o.Statement>CATCH_STACK_VAR.set(CATCH_ERROR_VAR.prop('stack')).toDeclStmt(null, [ [<o.Statement>CATCH_STACK_VAR.set(CATCH_ERROR_VAR.prop('stack', null)).toDeclStmt(null, [
o.StmtModifier.Final o.StmtModifier.Final
])].concat(stmt.catchStmts); ])].concat(stmt.catchStmts);
this.visitAllStatements(catchStmts, ctx); this.visitAllStatements(catchStmts, ctx);
@ -386,7 +386,8 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
} }
private _visitIdentifier( private _visitIdentifier(
value: CompileIdentifierMetadata, typeParams: o.Type[], ctx: EmitterVisitorContext): void { value: CompileIdentifierMetadata, typeParams: o.Type[]|null,
ctx: EmitterVisitorContext): void {
const {name, filePath, members, arity} = this._resolveStaticSymbol(value); const {name, filePath, members, arity} = this._resolveStaticSymbol(value);
if (filePath != this._genFilePath) { if (filePath != this._genFilePath) {
let prefix = this.importsWithPrefixes.get(filePath); let prefix = this.importsWithPrefixes.get(filePath);
@ -396,10 +397,10 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
} }
ctx.print(null, `${prefix}.`); ctx.print(null, `${prefix}.`);
} }
if (members.length) { if (members !.length) {
ctx.print(null, name); ctx.print(null, name);
ctx.print(null, '.'); ctx.print(null, '.');
ctx.print(null, members.join('.')); ctx.print(null, members !.join('.'));
} else { } else {
ctx.print(null, name); ctx.print(null, name);
} }
@ -415,7 +416,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
if (suppliedParameters > 0 || additionalParameters > 0) { if (suppliedParameters > 0 || additionalParameters > 0) {
ctx.print(null, `<`); ctx.print(null, `<`);
if (suppliedParameters > 0) { if (suppliedParameters > 0) {
this.visitAllObjects(type => type.visitType(this, ctx), typeParams, ctx, ','); this.visitAllObjects(type => type.visitType(this, ctx), typeParams !, ctx, ',');
} }
if (additionalParameters > 0) { if (additionalParameters > 0) {
for (let i = 0; i < additionalParameters; i++) { for (let i = 0; i < additionalParameters; i++) {
@ -428,7 +429,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
} }
} }
private _printColonType(type: o.Type, ctx: EmitterVisitorContext, defaultType?: string) { private _printColonType(type: o.Type|null, ctx: EmitterVisitorContext, defaultType?: string) {
if (type !== o.INFERRED_TYPE) { if (type !== o.INFERRED_TYPE) {
ctx.print(null, ':'); ctx.print(null, ':');
this.visitType(type, ctx, defaultType); this.visitType(type, ctx, defaultType);

View File

@ -13,7 +13,7 @@ import * as o from './output_ast';
export const QUOTED_KEYS = '$quoted$'; export const QUOTED_KEYS = '$quoted$';
export function convertValueToOutputAst(value: any, type: o.Type = null): o.Expression { export function convertValueToOutputAst(value: any, type: o.Type | null = null): o.Expression {
return visitValue(value, new _ValueOutputAstTransformer(), type); return visitValue(value, new _ValueOutputAstTransformer(), type);
} }

View File

@ -51,7 +51,7 @@ export class ParseLocation {
// Return the source around the location // Return the source around the location
// Up to `maxChars` or `maxLines` on each side of the location // Up to `maxChars` or `maxLines` on each side of the location
getContext(maxChars: number, maxLines: number): {before: string, after: string} { getContext(maxChars: number, maxLines: number): {before: string, after: string}|null {
const content = this.file.content; const content = this.file.content;
let startOffset = this.offset; let startOffset = this.offset;
@ -101,7 +101,7 @@ export class ParseSourceFile {
export class ParseSourceSpan { export class ParseSourceSpan {
constructor( constructor(
public start: ParseLocation, public end: ParseLocation, public details: string = null) {} public start: ParseLocation, public end: ParseLocation, public details: string|null = null) {}
toString(): string { toString(): string {
return this.start.file.content.substring(this.start.offset, this.end.offset); return this.start.file.content.substring(this.start.offset, this.end.offset);
@ -133,6 +133,5 @@ export function typeSourceSpan(kind: string, type: CompileIdentifierMetadata): P
`in ${kind} ${identifierName(type)}`; `in ${kind} ${identifierName(type)}`;
const sourceFile = new ParseSourceFile('', sourceFileName); const sourceFile = new ParseSourceFile('', sourceFileName);
return new ParseSourceSpan( return new ParseSourceSpan(
new ParseLocation(sourceFile, null, null, null), new ParseLocation(sourceFile, -1, -1, -1), new ParseLocation(sourceFile, -1, -1, -1));
new ParseLocation(sourceFile, null, null, null));
} }

View File

@ -33,7 +33,7 @@ export class PipeResolver {
/** /**
* Return {@link Pipe} for a given `Type`. * Return {@link Pipe} for a given `Type`.
*/ */
resolve(type: Type<any>, throwIfNotFound = true): Pipe { resolve(type: Type<any>, throwIfNotFound = true): Pipe|null {
const metas = this._reflector.annotations(resolveForwardRef(type)); const metas = this._reflector.annotations(resolveForwardRef(type));
if (metas) { if (metas) {
const annotation = findLast(metas, _isPipeMetadata); const annotation = findLast(metas, _isPipeMetadata);

View File

@ -135,7 +135,7 @@ export class ProviderElementContext {
const result: QueryWithId[] = []; const result: QueryWithId[] = [];
let currentEl: ProviderElementContext = this; let currentEl: ProviderElementContext = this;
let distance = 0; let distance = 0;
let queries: QueryWithId[]; let queries: QueryWithId[]|undefined;
while (currentEl !== null) { while (currentEl !== null) {
queries = currentEl._contentQueries.get(tokenReference(token)); queries = currentEl._contentQueries.get(tokenReference(token));
if (queries) { if (queries) {
@ -156,7 +156,7 @@ export class ProviderElementContext {
private _getOrCreateLocalProvider( private _getOrCreateLocalProvider(
requestingProviderType: ProviderAstType, token: CompileTokenMetadata, requestingProviderType: ProviderAstType, token: CompileTokenMetadata,
eager: boolean): ProviderAst { eager: boolean): ProviderAst|null {
const resolvedProvider = this._allProviders.get(tokenReference(token)); const resolvedProvider = this._allProviders.get(tokenReference(token));
if (!resolvedProvider || ((requestingProviderType === ProviderAstType.Directive || if (!resolvedProvider || ((requestingProviderType === ProviderAstType.Directive ||
requestingProviderType === ProviderAstType.PublicService) && requestingProviderType === ProviderAstType.PublicService) &&
@ -178,25 +178,25 @@ export class ProviderElementContext {
this._seenProviders.set(tokenReference(token), true); this._seenProviders.set(tokenReference(token), true);
const transformedProviders = resolvedProvider.providers.map((provider) => { const transformedProviders = resolvedProvider.providers.map((provider) => {
let transformedUseValue = provider.useValue; let transformedUseValue = provider.useValue;
let transformedUseExisting = provider.useExisting; let transformedUseExisting = provider.useExisting !;
let transformedDeps: CompileDiDependencyMetadata[]; let transformedDeps: CompileDiDependencyMetadata[] = undefined !;
if (provider.useExisting != null) { if (provider.useExisting != null) {
const existingDiDep = this._getDependency( const existingDiDep = this._getDependency(
resolvedProvider.providerType, {token: provider.useExisting}, eager); resolvedProvider.providerType, {token: provider.useExisting}, eager) !;
if (existingDiDep.token != null) { if (existingDiDep.token != null) {
transformedUseExisting = existingDiDep.token; transformedUseExisting = existingDiDep.token;
} else { } else {
transformedUseExisting = null; transformedUseExisting = null !;
transformedUseValue = existingDiDep.value; transformedUseValue = existingDiDep.value;
} }
} else if (provider.useFactory) { } else if (provider.useFactory) {
const deps = provider.deps || provider.useFactory.diDeps; const deps = provider.deps || provider.useFactory.diDeps;
transformedDeps = transformedDeps =
deps.map((dep) => this._getDependency(resolvedProvider.providerType, dep, eager)); deps.map((dep) => this._getDependency(resolvedProvider.providerType, dep, eager) !);
} else if (provider.useClass) { } else if (provider.useClass) {
const deps = provider.deps || provider.useClass.diDeps; const deps = provider.deps || provider.useClass.diDeps;
transformedDeps = transformedDeps =
deps.map((dep) => this._getDependency(resolvedProvider.providerType, dep, eager)); deps.map((dep) => this._getDependency(resolvedProvider.providerType, dep, eager) !);
} }
return _transformProvider(provider, { return _transformProvider(provider, {
useExisting: transformedUseExisting, useExisting: transformedUseExisting,
@ -212,9 +212,9 @@ export class ProviderElementContext {
private _getLocalDependency( private _getLocalDependency(
requestingProviderType: ProviderAstType, dep: CompileDiDependencyMetadata, requestingProviderType: ProviderAstType, dep: CompileDiDependencyMetadata,
eager: boolean = null): CompileDiDependencyMetadata { eager: boolean = false): CompileDiDependencyMetadata|null {
if (dep.isAttribute) { if (dep.isAttribute) {
const attrValue = this._attrs[dep.token.value]; const attrValue = this._attrs[dep.token !.value];
return {isValue: true, value: attrValue == null ? null : attrValue}; return {isValue: true, value: attrValue == null ? null : attrValue};
} }
@ -246,10 +246,10 @@ export class ProviderElementContext {
private _getDependency( private _getDependency(
requestingProviderType: ProviderAstType, dep: CompileDiDependencyMetadata, requestingProviderType: ProviderAstType, dep: CompileDiDependencyMetadata,
eager: boolean = null): CompileDiDependencyMetadata { eager: boolean = false): CompileDiDependencyMetadata|null {
let currElement: ProviderElementContext = this; let currElement: ProviderElementContext = this;
let currEager: boolean = eager; let currEager: boolean = eager;
let result: CompileDiDependencyMetadata = null; let result: CompileDiDependencyMetadata|null = null;
if (!dep.isSkipSelf) { if (!dep.isSkipSelf) {
result = this._getLocalDependency(requestingProviderType, dep, eager); result = this._getLocalDependency(requestingProviderType, dep, eager);
} }
@ -270,8 +270,8 @@ export class ProviderElementContext {
// check @Host restriction // check @Host restriction
if (!result) { if (!result) {
if (!dep.isHost || this.viewContext.component.isHost || if (!dep.isHost || this.viewContext.component.isHost ||
this.viewContext.component.type.reference === tokenReference(dep.token) || this.viewContext.component.type.reference === tokenReference(dep.token !) ||
this.viewContext.viewProviders.get(tokenReference(dep.token)) != null) { this.viewContext.viewProviders.get(tokenReference(dep.token !)) != null) {
result = dep; result = dep;
} else { } else {
result = dep.isOptional ? result = {isValue: true, value: null} : null; result = dep.isOptional ? result = {isValue: true, value: null} : null;
@ -280,7 +280,7 @@ export class ProviderElementContext {
} }
if (!result) { if (!result) {
this.viewContext.errors.push( this.viewContext.errors.push(
new ProviderError(`No provider for ${tokenName(dep.token)}`, this._sourceSpan)); new ProviderError(`No provider for ${tokenName(dep.token!)}`, this._sourceSpan));
} }
return result; return result;
} }
@ -319,7 +319,7 @@ export class NgModuleProviderAnalyzer {
return Array.from(this._transformedProviders.values()); return Array.from(this._transformedProviders.values());
} }
private _getOrCreateLocalProvider(token: CompileTokenMetadata, eager: boolean): ProviderAst { private _getOrCreateLocalProvider(token: CompileTokenMetadata, eager: boolean): ProviderAst|null {
const resolvedProvider = this._allProviders.get(tokenReference(token)); const resolvedProvider = this._allProviders.get(tokenReference(token));
if (!resolvedProvider) { if (!resolvedProvider) {
return null; return null;
@ -337,15 +337,15 @@ export class NgModuleProviderAnalyzer {
this._seenProviders.set(tokenReference(token), true); this._seenProviders.set(tokenReference(token), true);
const transformedProviders = resolvedProvider.providers.map((provider) => { const transformedProviders = resolvedProvider.providers.map((provider) => {
let transformedUseValue = provider.useValue; let transformedUseValue = provider.useValue;
let transformedUseExisting = provider.useExisting; let transformedUseExisting = provider.useExisting !;
let transformedDeps: CompileDiDependencyMetadata[]; let transformedDeps: CompileDiDependencyMetadata[] = undefined !;
if (provider.useExisting != null) { if (provider.useExisting != null) {
const existingDiDep = const existingDiDep =
this._getDependency({token: provider.useExisting}, eager, resolvedProvider.sourceSpan); this._getDependency({token: provider.useExisting}, eager, resolvedProvider.sourceSpan);
if (existingDiDep.token != null) { if (existingDiDep.token != null) {
transformedUseExisting = existingDiDep.token; transformedUseExisting = existingDiDep.token;
} else { } else {
transformedUseExisting = null; transformedUseExisting = null !;
transformedUseValue = existingDiDep.value; transformedUseValue = existingDiDep.value;
} }
} else if (provider.useFactory) { } else if (provider.useFactory) {
@ -370,7 +370,7 @@ export class NgModuleProviderAnalyzer {
} }
private _getDependency( private _getDependency(
dep: CompileDiDependencyMetadata, eager: boolean = null, dep: CompileDiDependencyMetadata, eager: boolean = false,
requestorSourceSpan: ParseSourceSpan): CompileDiDependencyMetadata { requestorSourceSpan: ParseSourceSpan): CompileDiDependencyMetadata {
let foundLocal = false; let foundLocal = false;
if (!dep.isSkipSelf && dep.token != null) { if (!dep.isSkipSelf && dep.token != null) {
@ -389,7 +389,7 @@ export class NgModuleProviderAnalyzer {
result = {isValue: true, value: null}; result = {isValue: true, value: null};
} else { } else {
this._errors.push( this._errors.push(
new ProviderError(`No provider for ${tokenName(dep.token)}`, requestorSourceSpan)); new ProviderError(`No provider for ${tokenName(dep.token!)}`, requestorSourceSpan));
} }
} }
return result; return result;
@ -464,7 +464,7 @@ function _resolveProviders(
[]; [];
const isUseValue = !(provider.useClass || provider.useExisting || provider.useFactory); const isUseValue = !(provider.useClass || provider.useExisting || provider.useFactory);
resolvedProvider = new ProviderAst( resolvedProvider = new ProviderAst(
provider.token, provider.multi, eager || isUseValue, [provider], providerType, provider.token, !!provider.multi, eager || isUseValue, [provider], providerType,
lifecycleHooks, sourceSpan); lifecycleHooks, sourceSpan);
targetProvidersByToken.set(tokenReference(provider.token), resolvedProvider); targetProvidersByToken.set(tokenReference(provider.token), resolvedProvider);
} else { } else {

View File

@ -11,5 +11,5 @@
* to load templates. * to load templates.
*/ */
export class ResourceLoader { export class ResourceLoader {
get(url: string): Promise<string> { return null; } get(url: string): Promise<string>|null { return null; }
} }

View File

@ -386,7 +386,7 @@ export class DomElementSchemaRegistry extends ElementSchemaRegistry {
{error: string, value: string} { {error: string, value: string} {
let unit: string = ''; let unit: string = '';
const strVal = val.toString().trim(); const strVal = val.toString().trim();
let errorMsg: string = null; let errorMsg: string = null !;
if (_isPixelDimensionStyle(camelCaseProp) && val !== 0 && val !== '0') { if (_isPixelDimensionStyle(camelCaseProp) && val !== 0 && val !== '0') {
if (typeof val === 'number') { if (typeof val === 'number') {

View File

@ -26,7 +26,7 @@ const _SELECTOR_REGEXP = new RegExp(
* of selecting subsets out of them. * of selecting subsets out of them.
*/ */
export class CssSelector { export class CssSelector {
element: string = null; element: string|null = null;
classNames: string[] = []; classNames: string[] = [];
attrs: string[] = []; attrs: string[] = [];
notSelectors: CssSelector[] = []; notSelectors: CssSelector[] = [];
@ -41,7 +41,7 @@ export class CssSelector {
res.push(cssSel); res.push(cssSel);
}; };
let cssSelector = new CssSelector(); let cssSelector = new CssSelector();
let match: string[]; let match: string[]|null;
let current = cssSelector; let current = cssSelector;
let inNot = false; let inNot = false;
_SELECTOR_REGEXP.lastIndex = 0; _SELECTOR_REGEXP.lastIndex = 0;
@ -86,7 +86,7 @@ export class CssSelector {
hasElementSelector(): boolean { return !!this.element; } hasElementSelector(): boolean { return !!this.element; }
setElement(element: string = null) { this.element = element; } setElement(element: string|null = null) { this.element = element; }
/** Gets a template string for an element that matches the selector. */ /** Gets a template string for an element that matches the selector. */
getMatchingElementTemplate(): string { getMatchingElementTemplate(): string {
@ -147,7 +147,7 @@ export class SelectorMatcher {
private _listContexts: SelectorListContext[] = []; private _listContexts: SelectorListContext[] = [];
addSelectables(cssSelectors: CssSelector[], callbackCtxt?: any) { addSelectables(cssSelectors: CssSelector[], callbackCtxt?: any) {
let listContext: SelectorListContext = null; let listContext: SelectorListContext = null !;
if (cssSelectors.length > 1) { if (cssSelectors.length > 1) {
listContext = new SelectorListContext(cssSelectors); listContext = new SelectorListContext(cssSelectors);
this._listContexts.push(listContext); this._listContexts.push(listContext);
@ -243,9 +243,10 @@ export class SelectorMatcher {
* @param matchedCallback This callback will be called with the object handed into `addSelectable` * @param matchedCallback This callback will be called with the object handed into `addSelectable`
* @return boolean true if a match was found * @return boolean true if a match was found
*/ */
match(cssSelector: CssSelector, matchedCallback: (c: CssSelector, a: any) => void): boolean { match(cssSelector: CssSelector, matchedCallback: ((c: CssSelector, a: any) => void)|null):
boolean {
let result = false; let result = false;
const element = cssSelector.element; const element = cssSelector.element !;
const classNames = cssSelector.classNames; const classNames = cssSelector.classNames;
const attrs = cssSelector.attrs; const attrs = cssSelector.attrs;
@ -273,7 +274,7 @@ export class SelectorMatcher {
const name = attrs[i]; const name = attrs[i];
const value = attrs[i + 1]; const value = attrs[i + 1];
const terminalValuesMap = this._attrValueMap.get(name); const terminalValuesMap = this._attrValueMap.get(name) !;
if (value) { if (value) {
result = result =
this._matchTerminal(terminalValuesMap, '', cssSelector, matchedCallback) || result; this._matchTerminal(terminalValuesMap, '', cssSelector, matchedCallback) || result;
@ -281,7 +282,7 @@ export class SelectorMatcher {
result = result =
this._matchTerminal(terminalValuesMap, value, cssSelector, matchedCallback) || result; this._matchTerminal(terminalValuesMap, value, cssSelector, matchedCallback) || result;
const partialValuesMap = this._attrValuePartialMap.get(name); const partialValuesMap = this._attrValuePartialMap.get(name) !;
if (value) { if (value) {
result = this._matchPartial(partialValuesMap, '', cssSelector, matchedCallback) || result; result = this._matchPartial(partialValuesMap, '', cssSelector, matchedCallback) || result;
} }
@ -295,13 +296,13 @@ export class SelectorMatcher {
/** @internal */ /** @internal */
_matchTerminal( _matchTerminal(
map: Map<string, SelectorContext[]>, name: string, cssSelector: CssSelector, map: Map<string, SelectorContext[]>, name: string, cssSelector: CssSelector,
matchedCallback: (c: CssSelector, a: any) => void): boolean { matchedCallback: ((c: CssSelector, a: any) => void)|null): boolean {
if (!map || typeof name !== 'string') { if (!map || typeof name !== 'string') {
return false; return false;
} }
let selectables: SelectorContext[] = map.get(name) || []; let selectables: SelectorContext[] = map.get(name) || [];
const starSelectables: SelectorContext[] = map.get('*'); const starSelectables: SelectorContext[] = map.get('*') !;
if (starSelectables) { if (starSelectables) {
selectables = selectables.concat(starSelectables); selectables = selectables.concat(starSelectables);
} }
@ -320,7 +321,7 @@ export class SelectorMatcher {
/** @internal */ /** @internal */
_matchPartial( _matchPartial(
map: Map<string, SelectorMatcher>, name: string, cssSelector: CssSelector, map: Map<string, SelectorMatcher>, name: string, cssSelector: CssSelector,
matchedCallback: (c: CssSelector, a: any) => void): boolean { matchedCallback: ((c: CssSelector, a: any) => void)|null): boolean {
if (!map || typeof name !== 'string') { if (!map || typeof name !== 'string') {
return false; return false;
} }
@ -353,7 +354,7 @@ export class SelectorContext {
this.notSelectors = selector.notSelectors; this.notSelectors = selector.notSelectors;
} }
finalize(cssSelector: CssSelector, callback: (c: CssSelector, a: any) => void): boolean { finalize(cssSelector: CssSelector, callback: ((c: CssSelector, a: any) => void)|null): boolean {
let result = true; let result = true;
if (this.notSelectors.length > 0 && (!this.listContext || !this.listContext.alreadyMatched)) { if (this.notSelectors.length > 0 && (!this.listContext || !this.listContext.alreadyMatched)) {
const notMatcher = SelectorMatcher.createNotMatcher(this.notSelectors); const notMatcher = SelectorMatcher.createNotMatcher(this.notSelectors);

View File

@ -240,7 +240,7 @@ export class ShadowCss {
private _extractUnscopedRulesFromCssText(cssText: string): string { private _extractUnscopedRulesFromCssText(cssText: string): string {
// Difference with webcomponents.js: does not handle comments // Difference with webcomponents.js: does not handle comments
let r = ''; let r = '';
let m: RegExpExecArray; let m: RegExpExecArray|null;
_cssContentUnscopedRuleRe.lastIndex = 0; _cssContentUnscopedRuleRe.lastIndex = 0;
while ((m = _cssContentUnscopedRuleRe.exec(cssText)) !== null) { while ((m = _cssContentUnscopedRuleRe.exec(cssText)) !== null) {
const rule = m[0].replace(m[2], '').replace(m[1], m[4]); const rule = m[0].replace(m[2], '').replace(m[1], m[4]);
@ -433,7 +433,7 @@ export class ShadowCss {
let scopedSelector = ''; let scopedSelector = '';
let startIndex = 0; let startIndex = 0;
let res: RegExpExecArray; let res: RegExpExecArray|null;
const sep = /( |>|\+|~(?!=))\s*/g; const sep = /( |>|\+|~(?!=))\s*/g;
const scopeAfter = selector.indexOf(_polyfillHostNoCombinator); const scopeAfter = selector.indexOf(_polyfillHostNoCombinator);

View File

@ -44,15 +44,16 @@ export class StyleCompiler {
constructor(private _urlResolver: UrlResolver) {} constructor(private _urlResolver: UrlResolver) {}
compileComponent(comp: CompileDirectiveMetadata): StylesCompileResult { compileComponent(comp: CompileDirectiveMetadata): StylesCompileResult {
const template = comp.template !;
const externalStylesheets: CompiledStylesheet[] = []; const externalStylesheets: CompiledStylesheet[] = [];
const componentStylesheet: CompiledStylesheet = this._compileStyles( const componentStylesheet: CompiledStylesheet = this._compileStyles(
comp, new CompileStylesheetMetadata({ comp, new CompileStylesheetMetadata({
styles: comp.template.styles, styles: template.styles,
styleUrls: comp.template.styleUrls, styleUrls: template.styleUrls,
moduleUrl: identifierModuleUrl(comp.type) moduleUrl: identifierModuleUrl(comp.type)
}), }),
true); true);
comp.template.externalStylesheets.forEach((stylesheetMeta) => { template.externalStylesheets.forEach((stylesheetMeta) => {
const compiledStylesheet = this._compileStyles(comp, stylesheetMeta, false); const compiledStylesheet = this._compileStyles(comp, stylesheetMeta, false);
externalStylesheets.push(compiledStylesheet); externalStylesheets.push(compiledStylesheet);
}); });
@ -62,7 +63,7 @@ export class StyleCompiler {
private _compileStyles( private _compileStyles(
comp: CompileDirectiveMetadata, stylesheet: CompileStylesheetMetadata, comp: CompileDirectiveMetadata, stylesheet: CompileStylesheetMetadata,
isComponentStylesheet: boolean): CompiledStylesheet { isComponentStylesheet: boolean): CompiledStylesheet {
const shim = comp.template.encapsulation === ViewEncapsulation.Emulated; const shim = comp.template !.encapsulation === ViewEncapsulation.Emulated;
const styleExpressions = const styleExpressions =
stylesheet.styles.map(plainStyle => o.literal(this._shimIfNeeded(plainStyle, shim))); stylesheet.styles.map(plainStyle => o.literal(this._shimIfNeeded(plainStyle, shim)));
const dependencies: StylesCompileDependency[] = []; const dependencies: StylesCompileDependency[] = [];
@ -87,7 +88,7 @@ export class StyleCompiler {
} }
} }
function getStylesVarName(component: CompileDirectiveMetadata): string { function getStylesVarName(component: CompileDirectiveMetadata | null): string {
let result = `styles`; let result = `styles`;
if (component) { if (component) {
result += `_${identifierName(component.type)}`; result += `_${identifierName(component.type)}`;

View File

@ -17,8 +17,8 @@ export interface Summary<T> {
@CompilerInjectable() @CompilerInjectable()
export class SummaryResolver<T> { export class SummaryResolver<T> {
isLibraryFile(fileName: string): boolean { return false; }; isLibraryFile(fileName: string): boolean { return false; };
getLibraryFileName(fileName: string): string { return null; } getLibraryFileName(fileName: string): string|null { return null; }
resolveSummary(reference: T): Summary<T> { return null; }; resolveSummary(reference: T): Summary<T>|null { return null; };
getSymbolsOf(filePath: string): T[] { return []; } getSymbolsOf(filePath: string): T[] { return []; }
getImportAs(reference: T): T { return reference; } getImportAs(reference: T): T { return reference; }
} }

View File

@ -64,7 +64,7 @@ export class BindingParser {
createDirectiveHostPropertyAsts( createDirectiveHostPropertyAsts(
dirMeta: CompileDirectiveSummary, elementSelector: string, dirMeta: CompileDirectiveSummary, elementSelector: string,
sourceSpan: ParseSourceSpan): BoundElementPropertyAst[] { sourceSpan: ParseSourceSpan): BoundElementPropertyAst[]|null {
if (dirMeta.hostProperties) { if (dirMeta.hostProperties) {
const boundProps: BoundProperty[] = []; const boundProps: BoundProperty[] = [];
Object.keys(dirMeta.hostProperties).forEach(propName => { Object.keys(dirMeta.hostProperties).forEach(propName => {
@ -79,10 +79,11 @@ export class BindingParser {
}); });
return boundProps.map((prop) => this.createElementPropertyAst(elementSelector, prop)); return boundProps.map((prop) => this.createElementPropertyAst(elementSelector, prop));
} }
return null;
} }
createDirectiveHostEventAsts(dirMeta: CompileDirectiveSummary, sourceSpan: ParseSourceSpan): createDirectiveHostEventAsts(dirMeta: CompileDirectiveSummary, sourceSpan: ParseSourceSpan):
BoundEventAst[] { BoundEventAst[]|null {
if (dirMeta.hostListeners) { if (dirMeta.hostListeners) {
const targetEventAsts: BoundEventAst[] = []; const targetEventAsts: BoundEventAst[] = [];
Object.keys(dirMeta.hostListeners).forEach(propName => { Object.keys(dirMeta.hostListeners).forEach(propName => {
@ -97,13 +98,15 @@ export class BindingParser {
}); });
return targetEventAsts; return targetEventAsts;
} }
return null;
} }
parseInterpolation(value: string, sourceSpan: ParseSourceSpan): ASTWithSource { parseInterpolation(value: string, sourceSpan: ParseSourceSpan): ASTWithSource {
const sourceInfo = sourceSpan.start.toString(); const sourceInfo = sourceSpan.start.toString();
try { try {
const ast = this._exprParser.parseInterpolation(value, sourceInfo, this._interpolationConfig); const ast =
this._exprParser.parseInterpolation(value, sourceInfo, this._interpolationConfig) !;
if (ast) this._reportExpressionParserErrors(ast.errors, sourceSpan); if (ast) this._reportExpressionParserErrors(ast.errors, sourceSpan);
this._checkPipes(ast, sourceSpan); this._checkPipes(ast, sourceSpan);
return ast; return ast;
@ -153,8 +156,8 @@ export class BindingParser {
} }
parseLiteralAttr( parseLiteralAttr(
name: string, value: string, sourceSpan: ParseSourceSpan, targetMatchableAttrs: string[][], name: string, value: string|null, sourceSpan: ParseSourceSpan,
targetProps: BoundProperty[]) { targetMatchableAttrs: string[][], targetProps: BoundProperty[]) {
if (_isAnimationLabel(name)) { if (_isAnimationLabel(name)) {
name = name.substring(1); name = name.substring(1);
if (value) { if (value) {
@ -206,18 +209,18 @@ export class BindingParser {
private _parsePropertyAst( private _parsePropertyAst(
name: string, ast: ASTWithSource, sourceSpan: ParseSourceSpan, name: string, ast: ASTWithSource, sourceSpan: ParseSourceSpan,
targetMatchableAttrs: string[][], targetProps: BoundProperty[]) { targetMatchableAttrs: string[][], targetProps: BoundProperty[]) {
targetMatchableAttrs.push([name, ast.source]); targetMatchableAttrs.push([name, ast.source !]);
targetProps.push(new BoundProperty(name, ast, BoundPropertyType.DEFAULT, sourceSpan)); targetProps.push(new BoundProperty(name, ast, BoundPropertyType.DEFAULT, sourceSpan));
} }
private _parseAnimation( private _parseAnimation(
name: string, expression: string, sourceSpan: ParseSourceSpan, name: string, expression: string|null, sourceSpan: ParseSourceSpan,
targetMatchableAttrs: string[][], targetProps: BoundProperty[]) { targetMatchableAttrs: string[][], targetProps: BoundProperty[]) {
// This will occur when a @trigger is not paired with an expression. // This will occur when a @trigger is not paired with an expression.
// For animations it is valid to not have an expression since */void // For animations it is valid to not have an expression since */void
// states will be applied by angular when the element is attached/detached // states will be applied by angular when the element is attached/detached
const ast = this._parseBinding(expression || 'null', false, sourceSpan); const ast = this._parseBinding(expression || 'null', false, sourceSpan);
targetMatchableAttrs.push([name, ast.source]); targetMatchableAttrs.push([name, ast.source !]);
targetProps.push(new BoundProperty(name, ast, BoundPropertyType.ANIMATION, sourceSpan)); targetProps.push(new BoundProperty(name, ast, BoundPropertyType.ANIMATION, sourceSpan));
} }
@ -246,11 +249,11 @@ export class BindingParser {
null, boundProp.sourceSpan); null, boundProp.sourceSpan);
} }
let unit: string = null; let unit: string|null = null;
let bindingType: PropertyBindingType; let bindingType: PropertyBindingType = undefined !;
let boundPropertyName: string = null; let boundPropertyName: string|null = null;
const parts = boundProp.name.split(PROPERTY_PARTS_SEPARATOR); const parts = boundProp.name.split(PROPERTY_PARTS_SEPARATOR);
let securityContexts: SecurityContext[]; let securityContexts: SecurityContext[] = undefined !;
// Check check for special cases (prefix style, attr, class) // Check check for special cases (prefix style, attr, class)
if (parts.length > 1) { if (parts.length > 1) {
@ -336,9 +339,9 @@ export class BindingParser {
name: string, expression: string, sourceSpan: ParseSourceSpan, name: string, expression: string, sourceSpan: ParseSourceSpan,
targetMatchableAttrs: string[][], targetEvents: BoundEventAst[]) { targetMatchableAttrs: string[][], targetEvents: BoundEventAst[]) {
// long format: 'target: eventName' // long format: 'target: eventName'
const [target, eventName] = splitAtColon(name, [null, name]); const [target, eventName] = splitAtColon(name, [null !, name]);
const ast = this._parseAction(expression, sourceSpan); const ast = this._parseAction(expression, sourceSpan);
targetMatchableAttrs.push([name, ast.source]); targetMatchableAttrs.push([name !, ast.source !]);
targetEvents.push(new BoundEventAst(eventName, target, null, ast, sourceSpan)); targetEvents.push(new BoundEventAst(eventName, target, null, ast, sourceSpan));
// Don't detect directives for event names for now, // Don't detect directives for event names for now,
// so don't add the event name to the matchableAttrs // so don't add the event name to the matchableAttrs
@ -405,7 +408,7 @@ export class BindingParser {
const report = isAttr ? this._schemaRegistry.validateAttribute(propName) : const report = isAttr ? this._schemaRegistry.validateAttribute(propName) :
this._schemaRegistry.validateProperty(propName); this._schemaRegistry.validateProperty(propName);
if (report.error) { if (report.error) {
this._reportError(report.msg, sourceSpan, ParseErrorLevel.ERROR); this._reportError(report.msg !, sourceSpan, ParseErrorLevel.ERROR);
} }
} }
} }

View File

@ -19,7 +19,7 @@ export interface TemplateAst {
/** /**
* The source span from which this node was parsed. * The source span from which this node was parsed.
*/ */
sourceSpan: ParseSourceSpan; sourceSpan: ParseSourceSpan|null;
/** /**
* Visit this node and possibly transform it. * Visit this node and possibly transform it.
@ -62,7 +62,7 @@ export class AttrAst implements TemplateAst {
export class BoundElementPropertyAst implements TemplateAst { export class BoundElementPropertyAst implements TemplateAst {
constructor( constructor(
public name: string, public type: PropertyBindingType, public name: string, public type: PropertyBindingType,
public securityContext: SecurityContext, public value: AST, public unit: string, public securityContext: SecurityContext, public value: AST, public unit: string|null,
public sourceSpan: ParseSourceSpan) {} public sourceSpan: ParseSourceSpan) {}
visit(visitor: TemplateAstVisitor, context: any): any { visit(visitor: TemplateAstVisitor, context: any): any {
return visitor.visitElementProperty(this, context); return visitor.visitElementProperty(this, context);
@ -75,7 +75,7 @@ export class BoundElementPropertyAst implements TemplateAst {
* `(@trigger.phase)="callback($event)"`). * `(@trigger.phase)="callback($event)"`).
*/ */
export class BoundEventAst implements TemplateAst { export class BoundEventAst implements TemplateAst {
static calcFullName(name: string, target: string, phase: string): string { static calcFullName(name: string, target: string|null, phase: string|null): string {
if (target) { if (target) {
return `${target}:${name}`; return `${target}:${name}`;
} else if (phase) { } else if (phase) {
@ -86,8 +86,8 @@ export class BoundEventAst implements TemplateAst {
} }
constructor( constructor(
public name: string, public target: string, public phase: string, public handler: AST, public name: string, public target: string|null, public phase: string|null,
public sourceSpan: ParseSourceSpan) {} public handler: AST, public sourceSpan: ParseSourceSpan) {}
visit(visitor: TemplateAstVisitor, context: any): any { visit(visitor: TemplateAstVisitor, context: any): any {
return visitor.visitEvent(this, context); return visitor.visitEvent(this, context);
} }
@ -126,8 +126,8 @@ export class ElementAst implements TemplateAst {
public outputs: BoundEventAst[], public references: ReferenceAst[], public outputs: BoundEventAst[], public references: ReferenceAst[],
public directives: DirectiveAst[], public providers: ProviderAst[], public directives: DirectiveAst[], public providers: ProviderAst[],
public hasViewContainer: boolean, public queryMatches: QueryMatch[], public hasViewContainer: boolean, public queryMatches: QueryMatch[],
public children: TemplateAst[], public ngContentIndex: number, public children: TemplateAst[], public ngContentIndex: number|null,
public sourceSpan: ParseSourceSpan, public endSourceSpan: ParseSourceSpan) {} public sourceSpan: ParseSourceSpan|null, public endSourceSpan: ParseSourceSpan|null) {}
visit(visitor: TemplateAstVisitor, context: any): any { visit(visitor: TemplateAstVisitor, context: any): any {
return visitor.visitElement(this, context); return visitor.visitElement(this, context);
@ -275,7 +275,7 @@ export function templateVisitAll(
visitor: TemplateAstVisitor, asts: TemplateAst[], context: any = null): any[] { visitor: TemplateAstVisitor, asts: TemplateAst[], context: any = null): any[] {
const result: any[] = []; const result: any[] = [];
const visit = visitor.visit ? const visit = visitor.visit ?
(ast: TemplateAst) => visitor.visit(ast, context) || ast.visit(visitor, context) : (ast: TemplateAst) => visitor.visit !(ast, context) || ast.visit(visitor, context) :
(ast: TemplateAst) => ast.visit(visitor, context); (ast: TemplateAst) => ast.visit(visitor, context);
asts.forEach(ast => { asts.forEach(ast => {
const astResult = visit(ast); const astResult = visit(ast);

View File

@ -115,11 +115,11 @@ export class TemplateParser {
templateUrl: string): {template: TemplateAst[], pipes: CompilePipeSummary[]} { templateUrl: string): {template: TemplateAst[], pipes: CompilePipeSummary[]} {
const result = this.tryParse(component, template, directives, pipes, schemas, templateUrl); const result = this.tryParse(component, template, directives, pipes, schemas, templateUrl);
const warnings = const warnings =
result.errors.filter(error => error.level === ParseErrorLevel.WARNING).filter(warnOnlyOnce([ result.errors !.filter(error => error.level === ParseErrorLevel.WARNING)
TEMPLATE_ATTR_DEPRECATION_WARNING, TEMPLATE_ELEMENT_DEPRECATION_WARNING .filter(warnOnlyOnce(
])); [TEMPLATE_ATTR_DEPRECATION_WARNING, TEMPLATE_ELEMENT_DEPRECATION_WARNING]));
const errors = result.errors.filter(error => error.level === ParseErrorLevel.ERROR); const errors = result.errors !.filter(error => error.level === ParseErrorLevel.ERROR);
if (warnings.length > 0) { if (warnings.length > 0) {
this._console.warn(`Template parse warnings:\n${warnings.join('\n')}`); this._console.warn(`Template parse warnings:\n${warnings.join('\n')}`);
@ -130,7 +130,7 @@ export class TemplateParser {
throw syntaxError(`Template parse errors:\n${errorString}`); throw syntaxError(`Template parse errors:\n${errorString}`);
} }
return {template: result.templateAst, pipes: result.usedPipes}; return {template: result.templateAst !, pipes: result.usedPipes !};
} }
tryParse( tryParse(
@ -138,7 +138,7 @@ export class TemplateParser {
pipes: CompilePipeSummary[], schemas: SchemaMetadata[], pipes: CompilePipeSummary[], schemas: SchemaMetadata[],
templateUrl: string): TemplateParseResult { templateUrl: string): TemplateParseResult {
return this.tryParseHtml( return this.tryParseHtml(
this.expandHtml(this._htmlParser.parse( this.expandHtml(this._htmlParser !.parse(
template, templateUrl, true, this.getInterpolationConfig(component))), template, templateUrl, true, this.getInterpolationConfig(component))),
component, template, directives, pipes, schemas, templateUrl); component, template, directives, pipes, schemas, templateUrl);
} }
@ -154,7 +154,7 @@ export class TemplateParser {
const uniqDirectives = removeSummaryDuplicates(directives); const uniqDirectives = removeSummaryDuplicates(directives);
const uniqPipes = removeSummaryDuplicates(pipes); const uniqPipes = removeSummaryDuplicates(pipes);
const providerViewContext = new ProviderViewContext(component); const providerViewContext = new ProviderViewContext(component);
let interpolationConfig: InterpolationConfig; let interpolationConfig: InterpolationConfig = undefined !;
if (component.template && component.template.interpolation) { if (component.template && component.template.interpolation) {
interpolationConfig = { interpolationConfig = {
start: component.template.interpolation[0], start: component.template.interpolation[0],
@ -162,7 +162,7 @@ export class TemplateParser {
}; };
} }
const bindingParser = new BindingParser( const bindingParser = new BindingParser(
this._exprParser, interpolationConfig, this._schemaRegistry, uniqPipes, errors); this._exprParser, interpolationConfig !, this._schemaRegistry, uniqPipes, errors);
const parseVisitor = new TemplateParseVisitor( const parseVisitor = new TemplateParseVisitor(
this._config, providerViewContext, uniqDirectives, bindingParser, this._schemaRegistry, this._config, providerViewContext, uniqDirectives, bindingParser, this._schemaRegistry,
schemas, errors); schemas, errors);
@ -198,10 +198,11 @@ export class TemplateParser {
return htmlAstWithErrors; return htmlAstWithErrors;
} }
getInterpolationConfig(component: CompileDirectiveMetadata): InterpolationConfig { getInterpolationConfig(component: CompileDirectiveMetadata): InterpolationConfig|undefined {
if (component.template) { if (component.template) {
return InterpolationConfig.fromArray(component.template.interpolation); return InterpolationConfig.fromArray(component.template.interpolation);
} }
return undefined;
} }
/** @internal */ /** @internal */
@ -238,7 +239,7 @@ class TemplateParseVisitor implements html.Visitor {
// Note: queries start with id 1 so we can use the number in a Bloom filter! // Note: queries start with id 1 so we can use the number in a Bloom filter!
this.contentQueryStartId = providerViewContext.component.viewQueries.length + 1; this.contentQueryStartId = providerViewContext.component.viewQueries.length + 1;
directives.forEach((directive, index) => { directives.forEach((directive, index) => {
const selector = CssSelector.parse(directive.selector); const selector = CssSelector.parse(directive.selector !);
this.selectorMatcher.addSelectables(selector, directive); this.selectorMatcher.addSelectables(selector, directive);
this.directivesIndex.set(directive, index); this.directivesIndex.set(directive, index);
}); });
@ -249,10 +250,10 @@ class TemplateParseVisitor implements html.Visitor {
visitExpansionCase(expansionCase: html.ExpansionCase, context: any): any { return null; } visitExpansionCase(expansionCase: html.ExpansionCase, context: any): any { return null; }
visitText(text: html.Text, parent: ElementContext): any { visitText(text: html.Text, parent: ElementContext): any {
const ngContentIndex = parent.findNgContentIndex(TEXT_CSS_SELECTOR); const ngContentIndex = parent.findNgContentIndex(TEXT_CSS_SELECTOR) !;
const expr = this._bindingParser.parseInterpolation(text.value, text.sourceSpan); const expr = this._bindingParser.parseInterpolation(text.value, text.sourceSpan !);
return expr ? new BoundTextAst(expr, ngContentIndex, text.sourceSpan) : return expr ? new BoundTextAst(expr, ngContentIndex, text.sourceSpan !) :
new TextAst(text.value, ngContentIndex, text.sourceSpan); new TextAst(text.value, ngContentIndex, text.sourceSpan !);
} }
visitAttribute(attribute: html.Attribute, context: any): any { visitAttribute(attribute: html.Attribute, context: any): any {
@ -322,7 +323,7 @@ class TemplateParseVisitor implements html.Visitor {
} }
hasInlineTemplates = true; hasInlineTemplates = true;
this._bindingParser.parseInlineTemplateBinding( this._bindingParser.parseInlineTemplateBinding(
prefixToken, templateBindingsSource, attr.sourceSpan, templateMatchableAttrs, prefixToken !, templateBindingsSource !, attr.sourceSpan, templateMatchableAttrs,
templateElementOrDirectiveProps, templateElementVars); templateElementOrDirectiveProps, templateElementVars);
} }
@ -340,48 +341,49 @@ class TemplateParseVisitor implements html.Visitor {
const boundDirectivePropNames = new Set<string>(); const boundDirectivePropNames = new Set<string>();
const directiveAsts = this._createDirectiveAsts( const directiveAsts = this._createDirectiveAsts(
isTemplateElement, element.name, directiveMetas, elementOrDirectiveProps, isTemplateElement, element.name, directiveMetas, elementOrDirectiveProps,
elementOrDirectiveRefs, element.sourceSpan, references, boundDirectivePropNames); elementOrDirectiveRefs, element.sourceSpan !, references, boundDirectivePropNames);
const elementProps: BoundElementPropertyAst[] = this._createElementPropertyAsts( const elementProps: BoundElementPropertyAst[] = this._createElementPropertyAsts(
element.name, elementOrDirectiveProps, boundDirectivePropNames); element.name, elementOrDirectiveProps, boundDirectivePropNames);
const isViewRoot = parent.isTemplateElement || hasInlineTemplates; const isViewRoot = parent.isTemplateElement || hasInlineTemplates;
const providerContext = new ProviderElementContext( const providerContext = new ProviderElementContext(
this.providerViewContext, parent.providerContext, isViewRoot, directiveAsts, attrs, this.providerViewContext, parent.providerContext !, isViewRoot, directiveAsts, attrs,
references, isTemplateElement, queryStartIndex, element.sourceSpan); references, isTemplateElement, queryStartIndex, element.sourceSpan !);
const children: TemplateAst[] = html.visitAll( const children: TemplateAst[] = html.visitAll(
preparsedElement.nonBindable ? NON_BINDABLE_VISITOR : this, element.children, preparsedElement.nonBindable ? NON_BINDABLE_VISITOR : this, element.children,
ElementContext.create( ElementContext.create(
isTemplateElement, directiveAsts, isTemplateElement, directiveAsts,
isTemplateElement ? parent.providerContext : providerContext)); isTemplateElement ? parent.providerContext ! : providerContext));
providerContext.afterElement(); providerContext.afterElement();
// Override the actual selector when the `ngProjectAs` attribute is provided // Override the actual selector when the `ngProjectAs` attribute is provided
const projectionSelector = preparsedElement.projectAs != null ? const projectionSelector = preparsedElement.projectAs != null ?
CssSelector.parse(preparsedElement.projectAs)[0] : CssSelector.parse(preparsedElement.projectAs)[0] :
elementCssSelector; elementCssSelector;
const ngContentIndex = parent.findNgContentIndex(projectionSelector); const ngContentIndex = parent.findNgContentIndex(projectionSelector) !;
let parsedElement: TemplateAst; let parsedElement: TemplateAst;
if (preparsedElement.type === PreparsedElementType.NG_CONTENT) { if (preparsedElement.type === PreparsedElementType.NG_CONTENT) {
if (element.children && !element.children.every(_isEmptyTextNode)) { if (element.children && !element.children.every(_isEmptyTextNode)) {
this._reportError(`<ng-content> element cannot have content.`, element.sourceSpan); this._reportError(`<ng-content> element cannot have content.`, element.sourceSpan !);
} }
parsedElement = new NgContentAst( parsedElement = new NgContentAst(
this.ngContentCount++, hasInlineTemplates ? null : ngContentIndex, element.sourceSpan); this.ngContentCount++, hasInlineTemplates ? null ! : ngContentIndex,
element.sourceSpan !);
} else if (isTemplateElement) { } else if (isTemplateElement) {
this._assertAllEventsPublishedByDirectives(directiveAsts, events); this._assertAllEventsPublishedByDirectives(directiveAsts, events);
this._assertNoComponentsNorElementBindingsOnTemplate( this._assertNoComponentsNorElementBindingsOnTemplate(
directiveAsts, elementProps, element.sourceSpan); directiveAsts, elementProps, element.sourceSpan !);
parsedElement = new EmbeddedTemplateAst( parsedElement = new EmbeddedTemplateAst(
attrs, events, references, elementVars, providerContext.transformedDirectiveAsts, attrs, events, references, elementVars, providerContext.transformedDirectiveAsts,
providerContext.transformProviders, providerContext.transformedHasViewContainer, providerContext.transformProviders, providerContext.transformedHasViewContainer,
providerContext.queryMatches, children, hasInlineTemplates ? null : ngContentIndex, providerContext.queryMatches, children, hasInlineTemplates ? null ! : ngContentIndex,
element.sourceSpan); element.sourceSpan !);
} else { } else {
this._assertElementExists(matchElement, element); this._assertElementExists(matchElement, element);
this._assertOnlyOneComponent(directiveAsts, element.sourceSpan); this._assertOnlyOneComponent(directiveAsts, element.sourceSpan !);
const ngContentIndex = const ngContentIndex =
hasInlineTemplates ? null : parent.findNgContentIndex(projectionSelector); hasInlineTemplates ? null : parent.findNgContentIndex(projectionSelector);
@ -389,7 +391,8 @@ class TemplateParseVisitor implements html.Visitor {
nodeName, attrs, elementProps, events, references, nodeName, attrs, elementProps, events, references,
providerContext.transformedDirectiveAsts, providerContext.transformProviders, providerContext.transformedDirectiveAsts, providerContext.transformProviders,
providerContext.transformedHasViewContainer, providerContext.queryMatches, children, providerContext.transformedHasViewContainer, providerContext.queryMatches, children,
hasInlineTemplates ? null : ngContentIndex, element.sourceSpan, element.endSourceSpan); hasInlineTemplates ? null : ngContentIndex, element.sourceSpan || null,
element.endSourceSpan || null);
} }
if (hasInlineTemplates) { if (hasInlineTemplates) {
@ -400,21 +403,21 @@ class TemplateParseVisitor implements html.Visitor {
const templateBoundDirectivePropNames = new Set<string>(); const templateBoundDirectivePropNames = new Set<string>();
const templateDirectiveAsts = this._createDirectiveAsts( const templateDirectiveAsts = this._createDirectiveAsts(
true, element.name, templateDirectiveMetas, templateElementOrDirectiveProps, [], true, element.name, templateDirectiveMetas, templateElementOrDirectiveProps, [],
element.sourceSpan, [], templateBoundDirectivePropNames); element.sourceSpan !, [], templateBoundDirectivePropNames);
const templateElementProps: BoundElementPropertyAst[] = this._createElementPropertyAsts( const templateElementProps: BoundElementPropertyAst[] = this._createElementPropertyAsts(
element.name, templateElementOrDirectiveProps, templateBoundDirectivePropNames); element.name, templateElementOrDirectiveProps, templateBoundDirectivePropNames);
this._assertNoComponentsNorElementBindingsOnTemplate( this._assertNoComponentsNorElementBindingsOnTemplate(
templateDirectiveAsts, templateElementProps, element.sourceSpan); templateDirectiveAsts, templateElementProps, element.sourceSpan !);
const templateProviderContext = new ProviderElementContext( const templateProviderContext = new ProviderElementContext(
this.providerViewContext, parent.providerContext, parent.isTemplateElement, this.providerViewContext, parent.providerContext !, parent.isTemplateElement,
templateDirectiveAsts, [], [], true, templateQueryStartIndex, element.sourceSpan); templateDirectiveAsts, [], [], true, templateQueryStartIndex, element.sourceSpan !);
templateProviderContext.afterElement(); templateProviderContext.afterElement();
parsedElement = new EmbeddedTemplateAst( parsedElement = new EmbeddedTemplateAst(
[], [], [], templateElementVars, templateProviderContext.transformedDirectiveAsts, [], [], [], templateElementVars, templateProviderContext.transformedDirectiveAsts,
templateProviderContext.transformProviders, templateProviderContext.transformProviders,
templateProviderContext.transformedHasViewContainer, templateProviderContext.queryMatches, templateProviderContext.transformedHasViewContainer, templateProviderContext.queryMatches,
[parsedElement], ngContentIndex, element.sourceSpan); [parsedElement], ngContentIndex, element.sourceSpan !);
} }
return parsedElement; return parsedElement;
@ -531,7 +534,7 @@ class TemplateParseVisitor implements html.Visitor {
let matchElement = false; let matchElement = false;
selectorMatcher.match(elementCssSelector, (selector, directive) => { selectorMatcher.match(elementCssSelector, (selector, directive) => {
directives[this.directivesIndex.get(directive)] = directive; directives[this.directivesIndex.get(directive) !] = directive;
matchElement = matchElement || selector.hasElementSelector(); matchElement = matchElement || selector.hasElementSelector();
}); });
@ -547,7 +550,7 @@ class TemplateParseVisitor implements html.Visitor {
elementSourceSpan: ParseSourceSpan, targetReferences: ReferenceAst[], elementSourceSpan: ParseSourceSpan, targetReferences: ReferenceAst[],
targetBoundDirectivePropNames: Set<string>): DirectiveAst[] { targetBoundDirectivePropNames: Set<string>): DirectiveAst[] {
const matchedReferences = new Set<string>(); const matchedReferences = new Set<string>();
let component: CompileDirectiveSummary = null; let component: CompileDirectiveSummary = null !;
const directiveAsts = directives.map((directive) => { const directiveAsts = directives.map((directive) => {
const sourceSpan = new ParseSourceSpan( const sourceSpan = new ParseSourceSpan(
@ -559,11 +562,11 @@ class TemplateParseVisitor implements html.Visitor {
} }
const directiveProperties: BoundDirectivePropertyAst[] = []; const directiveProperties: BoundDirectivePropertyAst[] = [];
let hostProperties = let hostProperties =
this._bindingParser.createDirectiveHostPropertyAsts(directive, elementName, sourceSpan); this._bindingParser.createDirectiveHostPropertyAsts(directive, elementName, sourceSpan) !;
// Note: We need to check the host properties here as well, // Note: We need to check the host properties here as well,
// as we don't know the element name in the DirectiveWrapperCompiler yet. // as we don't know the element name in the DirectiveWrapperCompiler yet.
hostProperties = this._checkPropertiesInSchema(elementName, hostProperties); hostProperties = this._checkPropertiesInSchema(elementName, hostProperties);
const hostEvents = this._bindingParser.createDirectiveHostEventAsts(directive, sourceSpan); const hostEvents = this._bindingParser.createDirectiveHostEventAsts(directive, sourceSpan) !;
this._createDirectivePropertyAsts( this._createDirectivePropertyAsts(
directive.inputs, props, directiveProperties, targetBoundDirectivePropNames); directive.inputs, props, directiveProperties, targetBoundDirectivePropNames);
elementOrDirectiveRefs.forEach((elOrDirRef) => { elementOrDirectiveRefs.forEach((elOrDirRef) => {
@ -589,7 +592,7 @@ class TemplateParseVisitor implements html.Visitor {
elOrDirRef.sourceSpan); elOrDirRef.sourceSpan);
} }
} else if (!component) { } else if (!component) {
let refToken: CompileTokenMetadata = null; let refToken: CompileTokenMetadata = null !;
if (isTemplateElement) { if (isTemplateElement) {
refToken = createIdentifierToken(Identifiers.TemplateRef); refToken = createIdentifierToken(Identifiers.TemplateRef);
} }
@ -648,7 +651,7 @@ class TemplateParseVisitor implements html.Visitor {
private _findComponentDirectiveNames(directives: DirectiveAst[]): string[] { private _findComponentDirectiveNames(directives: DirectiveAst[]): string[] {
return this._findComponentDirectives(directives) return this._findComponentDirectives(directives)
.map(directive => identifierName(directive.directive.type)); .map(directive => identifierName(directive.directive.type) !);
} }
private _assertOnlyOneComponent(directives: DirectiveAst[], sourceSpan: ParseSourceSpan) { private _assertOnlyOneComponent(directives: DirectiveAst[], sourceSpan: ParseSourceSpan) {
@ -685,7 +688,7 @@ class TemplateParseVisitor implements html.Visitor {
errorMsg += errorMsg +=
`2. To allow any element add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component.`; `2. To allow any element add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component.`;
} }
this._reportError(errorMsg, element.sourceSpan); this._reportError(errorMsg, element.sourceSpan !);
} }
} }
@ -757,7 +760,7 @@ class TemplateParseVisitor implements html.Visitor {
} }
class NonBindableVisitor implements html.Visitor { class NonBindableVisitor implements html.Visitor {
visitElement(ast: html.Element, parent: ElementContext): ElementAst { visitElement(ast: html.Element, parent: ElementContext): ElementAst|null {
const preparsedElement = preparseElement(ast); const preparsedElement = preparseElement(ast);
if (preparsedElement.type === PreparsedElementType.SCRIPT || if (preparsedElement.type === PreparsedElementType.SCRIPT ||
preparsedElement.type === PreparsedElementType.STYLE || preparsedElement.type === PreparsedElementType.STYLE ||
@ -783,8 +786,8 @@ class NonBindableVisitor implements html.Visitor {
} }
visitText(text: html.Text, parent: ElementContext): TextAst { visitText(text: html.Text, parent: ElementContext): TextAst {
const ngContentIndex = parent.findNgContentIndex(TEXT_CSS_SELECTOR); const ngContentIndex = parent.findNgContentIndex(TEXT_CSS_SELECTOR) !;
return new TextAst(text.value, ngContentIndex, text.sourceSpan); return new TextAst(text.value, ngContentIndex, text.sourceSpan !);
} }
visitExpansion(expansion: html.Expansion, context: any): any { return expansion; } visitExpansion(expansion: html.Expansion, context: any): any { return expansion; }
@ -805,10 +808,10 @@ class ElementContext {
isTemplateElement: boolean, directives: DirectiveAst[], isTemplateElement: boolean, directives: DirectiveAst[],
providerContext: ProviderElementContext): ElementContext { providerContext: ProviderElementContext): ElementContext {
const matcher = new SelectorMatcher(); const matcher = new SelectorMatcher();
let wildcardNgContentIndex: number = null; let wildcardNgContentIndex: number = null !;
const component = directives.find(directive => directive.directive.isComponent); const component = directives.find(directive => directive.directive.isComponent);
if (component) { if (component) {
const ngContentSelectors = component.directive.template.ngContentSelectors; const ngContentSelectors = component.directive.template !.ngContentSelectors;
for (let i = 0; i < ngContentSelectors.length; i++) { for (let i = 0; i < ngContentSelectors.length; i++) {
const selector = ngContentSelectors[i]; const selector = ngContentSelectors[i];
if (selector === '*') { if (selector === '*') {
@ -822,9 +825,10 @@ class ElementContext {
} }
constructor( constructor(
public isTemplateElement: boolean, private _ngContentIndexMatcher: SelectorMatcher, public isTemplateElement: boolean, private _ngContentIndexMatcher: SelectorMatcher,
private _wildcardNgContentIndex: number, public providerContext: ProviderElementContext) {} private _wildcardNgContentIndex: number|null,
public providerContext: ProviderElementContext|null) {}
findNgContentIndex(selector: CssSelector): number { findNgContentIndex(selector: CssSelector): number|null {
const ngContentIndices: number[] = []; const ngContentIndices: number[] = [];
this._ngContentIndexMatcher.match( this._ngContentIndexMatcher.match(
selector, (selector, ngContentIndex) => { ngContentIndices.push(ngContentIndex); }); selector, (selector, ngContentIndex) => { ngContentIndices.push(ngContentIndex); });
@ -893,10 +897,9 @@ function isTemplate(
// `<template>` is HTML and case insensitive // `<template>` is HTML and case insensitive
if (tagNoNs.toLowerCase() === TEMPLATE_ELEMENT) { if (tagNoNs.toLowerCase() === TEMPLATE_ELEMENT) {
if (enableLegacyTemplate && tagNoNs.toLowerCase() === TEMPLATE_ELEMENT) { if (enableLegacyTemplate && tagNoNs.toLowerCase() === TEMPLATE_ELEMENT) {
reportDeprecation(TEMPLATE_ELEMENT_DEPRECATION_WARNING, el.sourceSpan); reportDeprecation(TEMPLATE_ELEMENT_DEPRECATION_WARNING, el.sourceSpan !);
return true; return true;
} }
return false;
} }
return false;
} }

View File

@ -21,11 +21,11 @@ const NG_NON_BINDABLE_ATTR = 'ngNonBindable';
const NG_PROJECT_AS = 'ngProjectAs'; const NG_PROJECT_AS = 'ngProjectAs';
export function preparseElement(ast: html.Element): PreparsedElement { export function preparseElement(ast: html.Element): PreparsedElement {
let selectAttr: string = null; let selectAttr: string = null !;
let hrefAttr: string = null; let hrefAttr: string = null !;
let relAttr: string = null; let relAttr: string = null !;
let nonBindable = false; let nonBindable = false;
let projectAs: string = null; let projectAs: string = null !;
ast.attrs.forEach(attr => { ast.attrs.forEach(attr => {
const lcAttrName = attr.name.toLowerCase(); const lcAttrName = attr.name.toLowerCase();
if (lcAttrName == NG_CONTENT_SELECT_ATTR) { if (lcAttrName == NG_CONTENT_SELECT_ATTR) {

View File

@ -49,7 +49,7 @@ export const DEFAULT_PACKAGE_URL_PROVIDER = {
*/ */
@CompilerInjectable() @CompilerInjectable()
export class UrlResolver { export class UrlResolver {
constructor(@Inject(PACKAGE_ROOT_URL) private _packagePrefix: string = null) {} constructor(@Inject(PACKAGE_ROOT_URL) private _packagePrefix: string|null = null) {}
/** /**
* Resolves the `url` given the `baseUrl`: * Resolves the `url` given the `baseUrl`:
@ -254,7 +254,7 @@ enum _ComponentIndex {
* arbitrary strings may still look like path names. * arbitrary strings may still look like path names.
*/ */
function _split(uri: string): Array<string|any> { function _split(uri: string): Array<string|any> {
return uri.match(_splitRe); return uri.match(_splitRe) !;
} }
/** /**

View File

@ -50,6 +50,14 @@ export function visitValue(value: any, visitor: ValueVisitor, context: any): any
return visitor.visitOther(value, context); return visitor.visitOther(value, context);
} }
export function isDefined(val: any): boolean {
return val !== null && val !== undefined;
}
export function noUndefined<T>(val: T | undefined): T {
return val === undefined ? null ! : val;
}
export interface ValueVisitor { export interface ValueVisitor {
visitArray(arr: any[], context: any): any; visitArray(arr: any[], context: any): any;
visitStringMap(map: {[key: string]: any}, context: any): any; visitStringMap(map: {[key: string]: any}, context: any): any;
@ -71,7 +79,7 @@ export class ValueTransformer implements ValueVisitor {
} }
export class SyncAsyncResult<T> { export class SyncAsyncResult<T> {
constructor(public syncResult: T, public asyncResult: Promise<T> = null) { constructor(public syncResult: T|null, public asyncResult: Promise<T>|null = null) {
if (!asyncResult) { if (!asyncResult) {
this.asyncResult = Promise.resolve(syncResult); this.asyncResult = Promise.resolve(syncResult);
} }

View File

@ -44,22 +44,22 @@ export class ViewCompiler {
const statements: o.Statement[] = []; const statements: o.Statement[] = [];
let renderComponentVarName: string; let renderComponentVarName: string = undefined !;
if (!component.isHost) { if (!component.isHost) {
const template = component.template !;
const customRenderData: o.LiteralMapEntry[] = []; const customRenderData: o.LiteralMapEntry[] = [];
if (component.template.animations && component.template.animations.length) { if (template.animations && template.animations.length) {
customRenderData.push(new o.LiteralMapEntry( customRenderData.push(
'animation', convertValueToOutputAst(component.template.animations), true)); new o.LiteralMapEntry('animation', convertValueToOutputAst(template.animations), true));
} }
const renderComponentVar = o.variable(rendererTypeName(component.type.reference)); const renderComponentVar = o.variable(rendererTypeName(component.type.reference));
renderComponentVarName = renderComponentVar.name; renderComponentVarName = renderComponentVar.name !;
statements.push( statements.push(
renderComponentVar renderComponentVar
.set(o.importExpr(createIdentifier(Identifiers.createRendererType2)) .set(o.importExpr(createIdentifier(Identifiers.createRendererType2))
.callFn([new o.LiteralMapExpr([ .callFn([new o.LiteralMapExpr([
new o.LiteralMapEntry( new o.LiteralMapEntry('encapsulation', o.literal(template.encapsulation)),
'encapsulation', o.literal(component.template.encapsulation)),
new o.LiteralMapEntry('styles', styles), new o.LiteralMapEntry('styles', styles),
new o.LiteralMapEntry('data', new o.LiteralMapExpr(customRenderData)) new o.LiteralMapEntry('data', new o.LiteralMapExpr(customRenderData))
])])) ])]))
@ -68,7 +68,7 @@ export class ViewCompiler {
[o.StmtModifier.Final])); [o.StmtModifier.Final]));
} }
const viewBuilderFactory = (parent: ViewBuilder): ViewBuilder => { const viewBuilderFactory = (parent: ViewBuilder | null): ViewBuilder => {
const embeddedViewIndex = embeddedViewCount++; const embeddedViewIndex = embeddedViewCount++;
return new ViewBuilder( return new ViewBuilder(
parent, component, embeddedViewIndex, usedPipes, staticQueryIds, viewBuilderFactory); parent, component, embeddedViewIndex, usedPipes, staticQueryIds, viewBuilderFactory);
@ -105,7 +105,7 @@ const ALLOW_DEFAULT_VAR = o.variable(`ad`);
class ViewBuilder implements TemplateAstVisitor, LocalResolver { class ViewBuilder implements TemplateAstVisitor, LocalResolver {
private compType: o.Type; private compType: o.Type;
private nodes: (() => { private nodes: (() => {
sourceSpan: ParseSourceSpan, sourceSpan: ParseSourceSpan | null,
nodeDef: o.Expression, nodeDef: o.Expression,
nodeFlags: NodeFlags, updateDirectives?: UpdateExpression[], updateRenderer?: UpdateExpression[] nodeFlags: NodeFlags, updateDirectives?: UpdateExpression[], updateRenderer?: UpdateExpression[]
})[] = []; })[] = [];
@ -116,14 +116,15 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
private children: ViewBuilder[] = []; private children: ViewBuilder[] = [];
constructor( constructor(
private parent: ViewBuilder, private component: CompileDirectiveMetadata, private parent: ViewBuilder|null, private component: CompileDirectiveMetadata,
private embeddedViewIndex: number, private usedPipes: CompilePipeSummary[], private embeddedViewIndex: number, private usedPipes: CompilePipeSummary[],
private staticQueryIds: Map<TemplateAst, StaticAndDynamicQueryIds>, private staticQueryIds: Map<TemplateAst, StaticAndDynamicQueryIds>,
private viewBuilderFactory: ViewBuilderFactory) { private viewBuilderFactory: ViewBuilderFactory) {
// TODO(tbosch): The old view compiler used to use an `any` type // TODO(tbosch): The old view compiler used to use an `any` type
// for the context in any embedded view. We keep this behaivor for now // for the context in any embedded view. We keep this behaivor for now
// to be able to introduce the new view compiler without too many errors. // to be able to introduce the new view compiler without too many errors.
this.compType = this.embeddedViewIndex > 0 ? o.DYNAMIC_TYPE : o.importType(this.component.type); this.compType =
this.embeddedViewIndex > 0 ? o.DYNAMIC_TYPE : o.importType(this.component.type) !;
} }
get viewName(): string { get viewName(): string {
@ -188,7 +189,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
viewFlags |= ViewFlags.OnPush; viewFlags |= ViewFlags.OnPush;
} }
const viewFactory = new o.DeclareFunctionStmt( const viewFactory = new o.DeclareFunctionStmt(
this.viewName, [new o.FnParam(LOG_VAR.name)], this.viewName, [new o.FnParam(LOG_VAR.name !)],
[new o.ReturnStatement(o.importExpr(createIdentifier(Identifiers.viewDef)).callFn([ [new o.ReturnStatement(o.importExpr(createIdentifier(Identifiers.viewDef)).callFn([
o.literal(viewFlags), o.literal(viewFlags),
o.literalArr(nodeDefExprs), o.literalArr(nodeDefExprs),
@ -205,13 +206,13 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
let updateFn: o.Expression; let updateFn: o.Expression;
if (updateStmts.length > 0) { if (updateStmts.length > 0) {
const preStmts: o.Statement[] = []; const preStmts: o.Statement[] = [];
if (!this.component.isHost && o.findReadVarNames(updateStmts).has(COMP_VAR.name)) { if (!this.component.isHost && o.findReadVarNames(updateStmts).has(COMP_VAR.name !)) {
preStmts.push(COMP_VAR.set(VIEW_VAR.prop('component')).toDeclStmt(this.compType)); preStmts.push(COMP_VAR.set(VIEW_VAR.prop('component')).toDeclStmt(this.compType));
} }
updateFn = o.fn( updateFn = o.fn(
[ [
new o.FnParam(CHECK_VAR.name, o.INFERRED_TYPE), new o.FnParam(CHECK_VAR.name !, o.INFERRED_TYPE),
new o.FnParam(VIEW_VAR.name, o.INFERRED_TYPE) new o.FnParam(VIEW_VAR.name !, o.INFERRED_TYPE)
], ],
[...preStmts, ...updateStmts], o.INFERRED_TYPE); [...preStmts, ...updateStmts], o.INFERRED_TYPE);
} else { } else {
@ -245,7 +246,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
visitBoundText(ast: BoundTextAst, context: any): any { visitBoundText(ast: BoundTextAst, context: any): any {
const nodeIndex = this.nodes.length; const nodeIndex = this.nodes.length;
// reserve the space in the nodeDefs array // reserve the space in the nodeDefs array
this.nodes.push(null); this.nodes.push(null !);
const astWithSource = <ASTWithSource>ast.value; const astWithSource = <ASTWithSource>ast.value;
const inter = <Interpolation>astWithSource.ast; const inter = <Interpolation>astWithSource.ast;
@ -268,7 +269,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
visitEmbeddedTemplate(ast: EmbeddedTemplateAst, context: any): any { visitEmbeddedTemplate(ast: EmbeddedTemplateAst, context: any): any {
const nodeIndex = this.nodes.length; const nodeIndex = this.nodes.length;
// reserve the space in the nodeDefs array // reserve the space in the nodeDefs array
this.nodes.push(null); this.nodes.push(null !);
const {flags, queryMatchesExpr, hostEvents} = this._visitElementOrTemplate(nodeIndex, ast); const {flags, queryMatchesExpr, hostEvents} = this._visitElementOrTemplate(nodeIndex, ast);
@ -299,9 +300,9 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
visitElement(ast: ElementAst, context: any): any { visitElement(ast: ElementAst, context: any): any {
const nodeIndex = this.nodes.length; const nodeIndex = this.nodes.length;
// reserve the space in the nodeDefs array so we can add children // reserve the space in the nodeDefs array so we can add children
this.nodes.push(null); this.nodes.push(null !);
let elName = ast.name; let elName: string|null = ast.name;
if (ast.name === NG_CONTAINER_TAG) { if (ast.name === NG_CONTAINER_TAG) {
// Using a null element name creates an anchor. // Using a null element name creates an anchor.
elName = null; elName = null;
@ -314,13 +315,13 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
let updateRendererExpressions: UpdateExpression[] = []; let updateRendererExpressions: UpdateExpression[] = [];
let outputDefs: o.Expression[] = []; let outputDefs: o.Expression[] = [];
if (elName) { if (elName) {
const hostBindings = ast.inputs const hostBindings: any[] = ast.inputs
.map((inputAst) => ({ .map((inputAst) => ({
context: COMP_VAR as o.Expression, context: COMP_VAR as o.Expression,
inputAst, inputAst,
dirAst: null, dirAst: null as any,
})) }))
.concat(dirHostBindings); .concat(dirHostBindings);
if (hostBindings.length) { if (hostBindings.length) {
updateRendererExpressions = updateRendererExpressions =
hostBindings.map((hostBinding, bindingIndex) => this._preprocessUpdateExpression({ hostBindings.map((hostBinding, bindingIndex) => this._preprocessUpdateExpression({
@ -386,7 +387,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
queryMatches: QueryMatch[] queryMatches: QueryMatch[]
}): { }): {
flags: NodeFlags, flags: NodeFlags,
usedEvents: [string, string][], usedEvents: [string | null, string][],
queryMatchesExpr: o.Expression, queryMatchesExpr: o.Expression,
hostBindings: hostBindings:
{context: o.Expression, inputAst: BoundElementPropertyAst, dirAst: DirectiveAst}[], {context: o.Expression, inputAst: BoundElementPropertyAst, dirAst: DirectiveAst}[],
@ -396,7 +397,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
if (ast.hasViewContainer) { if (ast.hasViewContainer) {
flags |= NodeFlags.EmbeddedViews; flags |= NodeFlags.EmbeddedViews;
} }
const usedEvents = new Map<string, [string, string]>(); const usedEvents = new Map<string, [string | null, string]>();
ast.outputs.forEach((event) => { ast.outputs.forEach((event) => {
const {name, target} = elementEventNameAndTarget(event, null); const {name, target} = elementEventNameAndTarget(event, null);
usedEvents.set(elementEventFullName(target, name), [target, name]); usedEvents.set(elementEventFullName(target, name), [target, name]);
@ -416,8 +417,8 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
} }
ast.providers.forEach((providerAst, providerIndex) => { ast.providers.forEach((providerAst, providerIndex) => {
let dirAst: DirectiveAst; let dirAst: DirectiveAst = undefined !;
let dirIndex: number; let dirIndex: number = undefined !;
ast.directives.forEach((localDirAst, i) => { ast.directives.forEach((localDirAst, i) => {
if (localDirAst.directive.type.reference === tokenReference(providerAst.token)) { if (localDirAst.directive.type.reference === tokenReference(providerAst.token)) {
dirAst = localDirAst; dirAst = localDirAst;
@ -427,7 +428,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
if (dirAst) { if (dirAst) {
const {hostBindings: dirHostBindings, hostEvents: dirHostEvents} = this._visitDirective( const {hostBindings: dirHostBindings, hostEvents: dirHostEvents} = this._visitDirective(
providerAst, dirAst, dirIndex, nodeIndex, ast.references, ast.queryMatches, usedEvents, providerAst, dirAst, dirIndex, nodeIndex, ast.references, ast.queryMatches, usedEvents,
this.staticQueryIds.get(<any>ast)); this.staticQueryIds.get(<any>ast) !);
hostBindings.push(...dirHostBindings); hostBindings.push(...dirHostBindings);
hostEvents.push(...dirHostEvents); hostEvents.push(...dirHostEvents);
} else { } else {
@ -437,7 +438,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
let queryMatchExprs: o.Expression[] = []; let queryMatchExprs: o.Expression[] = [];
ast.queryMatches.forEach((match) => { ast.queryMatches.forEach((match) => {
let valueType: QueryValueType; let valueType: QueryValueType = undefined !;
if (tokenReference(match.value) === resolveIdentifier(Identifiers.ElementRef)) { if (tokenReference(match.value) === resolveIdentifier(Identifiers.ElementRef)) {
valueType = QueryValueType.ElementRef; valueType = QueryValueType.ElementRef;
} else if (tokenReference(match.value) === resolveIdentifier(Identifiers.ViewContainerRef)) { } else if (tokenReference(match.value) === resolveIdentifier(Identifiers.ViewContainerRef)) {
@ -450,7 +451,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
} }
}); });
ast.references.forEach((ref) => { ast.references.forEach((ref) => {
let valueType: QueryValueType; let valueType: QueryValueType = undefined !;
if (!ref.value) { if (!ref.value) {
valueType = QueryValueType.RenderElement; valueType = QueryValueType.RenderElement;
} else if (tokenReference(ref.value) === resolveIdentifier(Identifiers.TemplateRef)) { } else if (tokenReference(ref.value) === resolveIdentifier(Identifiers.TemplateRef)) {
@ -462,7 +463,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
} }
}); });
ast.outputs.forEach((outputAst) => { ast.outputs.forEach((outputAst) => {
hostEvents.push({context: COMP_VAR, eventAst: outputAst, dirAst: null}); hostEvents.push({context: COMP_VAR, eventAst: outputAst, dirAst: null !});
}); });
return { return {
@ -470,7 +471,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
usedEvents: Array.from(usedEvents.values()), usedEvents: Array.from(usedEvents.values()),
queryMatchesExpr: queryMatchExprs.length ? o.literalArr(queryMatchExprs) : o.NULL_EXPR, queryMatchesExpr: queryMatchExprs.length ? o.literalArr(queryMatchExprs) : o.NULL_EXPR,
hostBindings, hostBindings,
hostEvents hostEvents: hostEvents
}; };
} }
@ -484,7 +485,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
} { } {
const nodeIndex = this.nodes.length; const nodeIndex = this.nodes.length;
// reserve the space in the nodeDefs array so we can add children // reserve the space in the nodeDefs array so we can add children
this.nodes.push(null); this.nodes.push(null !);
dirAst.directive.queries.forEach((query, queryIndex) => { dirAst.directive.queries.forEach((query, queryIndex) => {
const queryId = dirAst.contentQueryStartId + queryIndex; const queryId = dirAst.contentQueryStartId + queryIndex;
@ -588,7 +589,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
private _visitProvider(providerAst: ProviderAst, queryMatches: QueryMatch[]): void { private _visitProvider(providerAst: ProviderAst, queryMatches: QueryMatch[]): void {
const nodeIndex = this.nodes.length; const nodeIndex = this.nodes.length;
// reserve the space in the nodeDefs array so we can add children // reserve the space in the nodeDefs array so we can add children
this.nodes.push(null); this.nodes.push(null !);
const {flags, queryMatchExprs, providerExpr, depsExpr} = const {flags, queryMatchExprs, providerExpr, depsExpr} =
this._visitProviderOrDirective(providerAst, queryMatches); this._visitProviderOrDirective(providerAst, queryMatches);
@ -639,12 +640,12 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
return {flags: flags | providerType, queryMatchExprs, providerExpr, depsExpr}; return {flags: flags | providerType, queryMatchExprs, providerExpr, depsExpr};
} }
getLocal(name: string): o.Expression { getLocal(name: string): o.Expression|null {
if (name == EventHandlerVars.event.name) { if (name == EventHandlerVars.event.name) {
return EventHandlerVars.event; return EventHandlerVars.event;
} }
let currViewExpr: o.Expression = VIEW_VAR; let currViewExpr: o.Expression = VIEW_VAR;
for (let currBuilder: ViewBuilder = this; currBuilder; currBuilder = currBuilder.parent, for (let currBuilder: ViewBuilder|null = this; currBuilder; currBuilder = currBuilder.parent,
currViewExpr = currViewExpr.prop('parent').cast(o.DYNAMIC_TYPE)) { currViewExpr = currViewExpr.prop('parent').cast(o.DYNAMIC_TYPE)) {
// check references // check references
const refNodeIndex = currBuilder.refNodeIndices[name]; const refNodeIndex = currBuilder.refNodeIndices[name];
@ -701,7 +702,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
} }
createPipeConverter(expression: UpdateExpression, name: string, argCount: number): createPipeConverter(expression: UpdateExpression, name: string, argCount: number):
BuiltinConverter { BuiltinConverter {
const pipe = this.usedPipes.find((pipeSummary) => pipeSummary.name === name); const pipe = this.usedPipes.find((pipeSummary) => pipeSummary.name === name) !;
if (pipe.pure) { if (pipe.pure) {
const nodeIndex = this.nodes.length; const nodeIndex = this.nodes.length;
// function purePipeDef(argCount: number): NodeDef; // function purePipeDef(argCount: number): NodeDef;
@ -740,7 +741,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
} }
} }
private _createPipe(sourceSpan: ParseSourceSpan, pipe: CompilePipeSummary): number { private _createPipe(sourceSpan: ParseSourceSpan|null, pipe: CompilePipeSummary): number {
const nodeIndex = this.nodes.length; const nodeIndex = this.nodes.length;
let flags = NodeFlags.None; let flags = NodeFlags.None;
pipe.type.lifecycleHooks.forEach((lifecycleHook) => { pipe.type.lifecycleHooks.forEach((lifecycleHook) => {
@ -816,7 +817,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
return {updateRendererStmts, updateDirectivesStmts, nodeDefExprs}; return {updateRendererStmts, updateDirectivesStmts, nodeDefExprs};
function createUpdateStatements( function createUpdateStatements(
nodeIndex: number, sourceSpan: ParseSourceSpan, expressions: UpdateExpression[], nodeIndex: number, sourceSpan: ParseSourceSpan | null, expressions: UpdateExpression[],
allowEmptyExprs: boolean): o.Statement[] { allowEmptyExprs: boolean): o.Statement[] {
const updateStmts: o.Statement[] = []; const updateStmts: o.Statement[] = [];
const exprs = expressions.map(({sourceSpan, context, value}) => { const exprs = expressions.map(({sourceSpan, context, value}) => {
@ -824,8 +825,8 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
const nameResolver = context === COMP_VAR ? self : null; const nameResolver = context === COMP_VAR ? self : null;
const {stmts, currValExpr} = const {stmts, currValExpr} =
convertPropertyBinding(nameResolver, context, value, bindingId); convertPropertyBinding(nameResolver, context, value, bindingId);
updateStmts.push( updateStmts.push(...stmts.map(
...stmts.map(stmt => o.applySourceSpanToStatementIfNeeded(stmt, sourceSpan))); (stmt: o.Statement) => o.applySourceSpanToStatementIfNeeded(stmt, sourceSpan)));
return o.applySourceSpanToExpressionIfNeeded(currValExpr, sourceSpan); return o.applySourceSpanToExpressionIfNeeded(currValExpr, sourceSpan);
}); });
if (expressions.length || allowEmptyExprs) { if (expressions.length || allowEmptyExprs) {
@ -860,14 +861,14 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
if (handleEventStmts.length > 0) { if (handleEventStmts.length > 0) {
const preStmts: o.Statement[] = const preStmts: o.Statement[] =
[ALLOW_DEFAULT_VAR.set(o.literal(true)).toDeclStmt(o.BOOL_TYPE)]; [ALLOW_DEFAULT_VAR.set(o.literal(true)).toDeclStmt(o.BOOL_TYPE)];
if (!this.component.isHost && o.findReadVarNames(handleEventStmts).has(COMP_VAR.name)) { if (!this.component.isHost && o.findReadVarNames(handleEventStmts).has(COMP_VAR.name !)) {
preStmts.push(COMP_VAR.set(VIEW_VAR.prop('component')).toDeclStmt(this.compType)); preStmts.push(COMP_VAR.set(VIEW_VAR.prop('component')).toDeclStmt(this.compType));
} }
handleEventFn = o.fn( handleEventFn = o.fn(
[ [
new o.FnParam(VIEW_VAR.name, o.INFERRED_TYPE), new o.FnParam(VIEW_VAR.name !, o.INFERRED_TYPE),
new o.FnParam(EVENT_NAME_VAR.name, o.INFERRED_TYPE), new o.FnParam(EVENT_NAME_VAR.name !, o.INFERRED_TYPE),
new o.FnParam(EventHandlerVars.event.name, o.INFERRED_TYPE) new o.FnParam(EventHandlerVars.event.name !, o.INFERRED_TYPE)
], ],
[...preStmts, ...handleEventStmts, new o.ReturnStatement(ALLOW_DEFAULT_VAR)], [...preStmts, ...handleEventStmts, new o.ReturnStatement(ALLOW_DEFAULT_VAR)],
o.INFERRED_TYPE); o.INFERRED_TYPE);
@ -933,9 +934,9 @@ function singleProviderDef(providerType: ProviderAstType, providerMeta: CompileP
let flags: NodeFlags; let flags: NodeFlags;
let deps: CompileDiDependencyMetadata[]; let deps: CompileDiDependencyMetadata[];
if (providerType === ProviderAstType.Directive || providerType === ProviderAstType.Component) { if (providerType === ProviderAstType.Directive || providerType === ProviderAstType.Component) {
providerExpr = o.importExpr(providerMeta.useClass); providerExpr = o.importExpr(providerMeta.useClass !);
flags = NodeFlags.TypeDirective; flags = NodeFlags.TypeDirective;
deps = providerMeta.deps || providerMeta.useClass.diDeps; deps = providerMeta.deps || providerMeta.useClass !.diDeps;
} else { } else {
if (providerMeta.useClass) { if (providerMeta.useClass) {
providerExpr = o.importExpr(providerMeta.useClass); providerExpr = o.importExpr(providerMeta.useClass);
@ -966,7 +967,7 @@ function tokenExpr(tokenMeta: CompileTokenMetadata): o.Expression {
function depDef(dep: CompileDiDependencyMetadata): o.Expression { function depDef(dep: CompileDiDependencyMetadata): o.Expression {
// Note: the following fields have already been normalized out by provider_analyzer: // Note: the following fields have already been normalized out by provider_analyzer:
// - isAttribute, isSelf, isHost // - isAttribute, isSelf, isHost
const expr = dep.isValue ? convertValueToOutputAst(dep.value) : tokenExpr(dep.token); const expr = dep.isValue ? convertValueToOutputAst(dep.value) : tokenExpr(dep.token !);
let flags = DepFlags.None; let flags = DepFlags.None;
if (dep.isSkipSelf) { if (dep.isSkipSelf) {
flags |= DepFlags.SkipSelf; flags |= DepFlags.SkipSelf;
@ -1110,11 +1111,11 @@ function findStaticQueryIds(
nodes.forEach((node) => { nodes.forEach((node) => {
const staticQueryIds = new Set<number>(); const staticQueryIds = new Set<number>();
const dynamicQueryIds = new Set<number>(); const dynamicQueryIds = new Set<number>();
let queryMatches: QueryMatch[]; let queryMatches: QueryMatch[] = undefined !;
if (node instanceof ElementAst) { if (node instanceof ElementAst) {
findStaticQueryIds(node.children, result); findStaticQueryIds(node.children, result);
node.children.forEach((child) => { node.children.forEach((child) => {
const childData = result.get(child); const childData = result.get(child) !;
childData.staticQueryIds.forEach(queryId => staticQueryIds.add(queryId)); childData.staticQueryIds.forEach(queryId => staticQueryIds.add(queryId));
childData.dynamicQueryIds.forEach(queryId => dynamicQueryIds.add(queryId)); childData.dynamicQueryIds.forEach(queryId => dynamicQueryIds.add(queryId));
}); });
@ -1122,7 +1123,7 @@ function findStaticQueryIds(
} else if (node instanceof EmbeddedTemplateAst) { } else if (node instanceof EmbeddedTemplateAst) {
findStaticQueryIds(node.children, result); findStaticQueryIds(node.children, result);
node.children.forEach((child) => { node.children.forEach((child) => {
const childData = result.get(child); const childData = result.get(child) !;
childData.staticQueryIds.forEach(queryId => dynamicQueryIds.add(queryId)); childData.staticQueryIds.forEach(queryId => dynamicQueryIds.add(queryId));
childData.dynamicQueryIds.forEach(queryId => dynamicQueryIds.add(queryId)); childData.dynamicQueryIds.forEach(queryId => dynamicQueryIds.add(queryId));
}); });
@ -1149,7 +1150,7 @@ function staticViewQueryIds(nodeStaticQueryIds: Map<TemplateAst, StaticAndDynami
return {staticQueryIds, dynamicQueryIds}; return {staticQueryIds, dynamicQueryIds};
} }
function createComponentFactoryResolver(directives: DirectiveAst[]): ProviderAst { function createComponentFactoryResolver(directives: DirectiveAst[]): ProviderAst|null {
const componentDirMeta = directives.find(dirAst => dirAst.directive.isComponent); const componentDirMeta = directives.find(dirAst => dirAst.directive.isComponent);
if (componentDirMeta && componentDirMeta.directive.entryComponents.length) { if (componentDirMeta && componentDirMeta.directive.entryComponents.length) {
const entryComponentFactories = componentDirMeta.directive.entryComponents.map( const entryComponentFactories = componentDirMeta.directive.entryComponents.map(
@ -1174,7 +1175,7 @@ function createComponentFactoryResolver(directives: DirectiveAst[]): ProviderAst
} }
function elementEventNameAndTarget( function elementEventNameAndTarget(
eventAst: BoundEventAst, dirAst: DirectiveAst): {name: string, target: string} { eventAst: BoundEventAst, dirAst: DirectiveAst | null): {name: string, target: string | null} {
if (eventAst.isAnimation) { if (eventAst.isAnimation) {
return { return {
name: `@${eventAst.name}.${eventAst.phase}`, name: `@${eventAst.name}.${eventAst.phase}`,

View File

@ -110,7 +110,8 @@ describe('compiler (unbundled Angular)', () => {
}); });
} }
function findLineAndColumn(file: string, token: string): {line: number, column: number} { function findLineAndColumn(
file: string, token: string): {line: number | null, column: number | null} {
const index = file.indexOf(token); const index = file.indexOf(token);
if (index === -1) { if (index === -1) {
return {line: null, column: null}; return {line: null, column: null};
@ -178,7 +179,7 @@ describe('compiler (unbundled Angular)', () => {
appDir['app.component.ts'] = createComponentSource(templateDecorator(template)); appDir['app.component.ts'] = createComponentSource(templateDecorator(template));
compileApp().then((genFile) => { compileApp().then((genFile) => {
const sourceMap = extractSourceMap(genFile.source); const sourceMap = extractSourceMap(genFile.source) !;
expect(sourceMap.file).toEqual(genFile.genFileUrl); expect(sourceMap.file).toEqual(genFile.genFileUrl);
// the generated file contains code that is not mapped to // the generated file contains code that is not mapped to
@ -199,7 +200,7 @@ describe('compiler (unbundled Angular)', () => {
appDir['app.component.ts'] = createComponentSource(templateDecorator(template)); appDir['app.component.ts'] = createComponentSource(templateDecorator(template));
compileApp().then((genFile) => { compileApp().then((genFile) => {
const sourceMap = extractSourceMap(genFile.source); const sourceMap = extractSourceMap(genFile.source) !;
expect(originalPositionFor(sourceMap, findLineAndColumn(genFile.source, `'span'`))) expect(originalPositionFor(sourceMap, findLineAndColumn(genFile.source, `'span'`)))
.toEqual({line: 2, column: 3, source: ngUrl}); .toEqual({line: 2, column: 3, source: ngUrl});
}); });
@ -211,7 +212,7 @@ describe('compiler (unbundled Angular)', () => {
appDir['app.component.ts'] = createComponentSource(templateDecorator(template)); appDir['app.component.ts'] = createComponentSource(templateDecorator(template));
compileApp().then((genFile) => { compileApp().then((genFile) => {
const sourceMap = extractSourceMap(genFile.source); const sourceMap = extractSourceMap(genFile.source) !;
expect( expect(
originalPositionFor(sourceMap, findLineAndColumn(genFile.source, `someMethod()`))) originalPositionFor(sourceMap, findLineAndColumn(genFile.source, `someMethod()`)))
.toEqual({line: 2, column: 9, source: ngUrl}); .toEqual({line: 2, column: 9, source: ngUrl});
@ -224,7 +225,7 @@ describe('compiler (unbundled Angular)', () => {
appDir['app.component.ts'] = createComponentSource(templateDecorator(template)); appDir['app.component.ts'] = createComponentSource(templateDecorator(template));
compileApp().then((genFile) => { compileApp().then((genFile) => {
const sourceMap = extractSourceMap(genFile.source); const sourceMap = extractSourceMap(genFile.source) !;
expect( expect(
originalPositionFor(sourceMap, findLineAndColumn(genFile.source, `someMethod()`))) originalPositionFor(sourceMap, findLineAndColumn(genFile.source, `someMethod()`)))
.toEqual({line: 2, column: 9, source: ngUrl}); .toEqual({line: 2, column: 9, source: ngUrl});
@ -235,7 +236,7 @@ describe('compiler (unbundled Angular)', () => {
appDir['app.component.ts'] = createComponentSource(templateDecorator('Hello World!')); appDir['app.component.ts'] = createComponentSource(templateDecorator('Hello World!'));
compileApp().then((genFile) => { compileApp().then((genFile) => {
const sourceMap = extractSourceMap(genFile.source); const sourceMap = extractSourceMap(genFile.source) !;
expect(originalPositionFor(sourceMap, {line: 1, column: 0})) expect(originalPositionFor(sourceMap, {line: 1, column: 0}))
.toEqual({line: 1, column: 0, source: ngComponentPath}); .toEqual({line: 1, column: 0, source: ngComponentPath});
}); });
@ -328,7 +329,7 @@ describe('compiler (unbundled Angular)', () => {
compile(host, aotHost, expectNoDiagnostics).then((generatedFiles) => { compile(host, aotHost, expectNoDiagnostics).then((generatedFiles) => {
const genFile = generatedFiles.find(genFile => genFile.srcFileUrl === '/app/app.ts'); const genFile = generatedFiles.find(genFile => genFile.srcFileUrl === '/app/app.ts');
const createComponentFactoryCall = const createComponentFactoryCall =
/ɵccf\([^)]*\)/m.exec(genFile.source)[0].replace(/\s*/g, ''); /ɵccf\([^)]*\)/m.exec(genFile.source) ![0].replace(/\s*/g, '');
// selector // selector
expect(createComponentFactoryCall).toContain('my-comp'); expect(createComponentFactoryCall).toContain('my-comp');
// inputs // inputs

View File

@ -360,7 +360,7 @@ describe('StaticReflector', () => {
it('should record data about the error in the exception', () => { it('should record data about the error in the exception', () => {
let threw = false; let threw = false;
try { try {
const metadata = host.getMetadataFor('/tmp/src/invalid-metadata.ts'); const metadata = host.getMetadataFor('/tmp/src/invalid-metadata.ts') !;
expect(metadata).toBeDefined(); expect(metadata).toBeDefined();
const moduleMetadata: any = metadata[0]['metadata']; const moduleMetadata: any = metadata[0]['metadata'];
expect(moduleMetadata).toBeDefined(); expect(moduleMetadata).toBeDefined();

View File

@ -382,7 +382,7 @@ export class MockSummaryResolver implements SummaryResolver<StaticSymbol> {
} }
getImportAs(symbol: StaticSymbol): StaticSymbol { getImportAs(symbol: StaticSymbol): StaticSymbol {
const entry = this.importAs.find(entry => entry.symbol === symbol); const entry = this.importAs.find(entry => entry.symbol === symbol);
return entry ? entry.importAs : undefined; return entry ? entry.importAs : undefined !;
} }
isLibraryFile(filePath: string): boolean { return filePath.endsWith('.d.ts'); } isLibraryFile(filePath: string): boolean { return filePath.endsWith('.d.ts'); }
@ -429,7 +429,7 @@ export class MockStaticSymbolResolverHost implements StaticSymbolResolverHost {
} }
if (modulePath.indexOf('.') === 0) { if (modulePath.indexOf('.') === 0) {
const baseName = pathTo(containingFile, modulePath); const baseName = pathTo(containingFile !, modulePath);
const tsName = baseName + '.ts'; const tsName = baseName + '.ts';
if (this._getMetadataFor(tsName)) { if (this._getMetadataFor(tsName)) {
return tsName; return tsName;

View File

@ -95,7 +95,7 @@ export function main() {
members: {aMethod: {__symbolic: 'function'}}, members: {aMethod: {__symbolic: 'function'}},
statics: {aStatic: true} statics: {aStatic: true}
}); });
expect(summaries[1].type.type.reference) expect(summaries[1].type !.type.reference)
.toBe(symbolCache.get('/tmp/some_service.d.ts', 'SomeService')); .toBe(symbolCache.get('/tmp/some_service.d.ts', 'SomeService'));
}); });
@ -203,7 +203,7 @@ export function main() {
expect(summaries[2].metadata).toEqual('b'); expect(summaries[2].metadata).toEqual('b');
// SomService is a transitive dep, but should have been serialized as well. // SomService is a transitive dep, but should have been serialized as well.
expect(summaries[3].symbol).toBe(symbolCache.get('/tmp/external_svc.d.ts', 'SomeService')); expect(summaries[3].symbol).toBe(symbolCache.get('/tmp/external_svc.d.ts', 'SomeService'));
expect(summaries[3].type.type.reference) expect(summaries[3].type !.type.reference)
.toBe(symbolCache.get('/tmp/external_svc.d.ts', 'SomeService')); .toBe(symbolCache.get('/tmp/external_svc.d.ts', 'SomeService'));
}); });

View File

@ -18,7 +18,7 @@ export type MockDirectory = {
[name: string]: MockData | undefined; [name: string]: MockData | undefined;
}; };
export function isDirectory(data: MockData): data is MockDirectory { export function isDirectory(data: MockData | undefined): data is MockDirectory {
return typeof data !== 'string'; return typeof data !== 'string';
} }
@ -146,6 +146,7 @@ export class EmittingCompilerHost implements ts.CompilerHost {
if (content) { if (content) {
return ts.createSourceFile(fileName, content, languageVersion, /* setParentNodes */ true); return ts.createSourceFile(fileName, content, languageVersion, /* setParentNodes */ true);
} }
throw new Error(`File not found '${fileName}'.`);
} }
getDefaultLibFileName(options: ts.CompilerOptions): string { return 'lib.d.ts'; } getDefaultLibFileName(options: ts.CompilerOptions): string { return 'lib.d.ts'; }
@ -235,7 +236,7 @@ export class MockCompilerHost implements ts.CompilerHost {
let result = open(fileName, this.data) != null; let result = open(fileName, this.data) != null;
if (!result && fileName.startsWith(MOCK_NODEMODULES_PREFIX)) { if (!result && fileName.startsWith(MOCK_NODEMODULES_PREFIX)) {
const libraryPath = fileName.substr(MOCK_NODEMODULES_PREFIX.length - 1); const libraryPath = fileName.substr(MOCK_NODEMODULES_PREFIX.length - 1);
for (const library of this.libraries) { for (const library of this.libraries !) {
if (library.has(libraryPath)) { if (library.has(libraryPath)) {
return true; return true;
} }
@ -252,7 +253,7 @@ export class MockCompilerHost implements ts.CompilerHost {
} }
} }
readFile(fileName: string): string { return this.getFileContent(fileName); } readFile(fileName: string): string { return this.getFileContent(fileName) !; }
trace(s: string): void { this.traces.push(s); } trace(s: string): void { this.traces.push(s); }
@ -265,10 +266,8 @@ export class MockCompilerHost implements ts.CompilerHost {
if (isDirectory(data)) { if (isDirectory(data)) {
return Object.keys(data).filter(k => isDirectory(data[k])); return Object.keys(data).filter(k => isDirectory(data[k]));
} }
return [];
} else {
return undefined;
} }
return [];
} }
// ts.CompilerHost // ts.CompilerHost
@ -283,7 +282,7 @@ export class MockCompilerHost implements ts.CompilerHost {
this.sourceFiles.set(fileName, result); this.sourceFiles.set(fileName, result);
} }
} }
return result; return result !;
} }
getDefaultLibFileName(options: ts.CompilerOptions): string { return 'lib.d.ts'; } getDefaultLibFileName(options: ts.CompilerOptions): string { return 'lib.d.ts'; }
@ -318,7 +317,7 @@ export class MockCompilerHost implements ts.CompilerHost {
const result = open(fileName, this.data); const result = open(fileName, this.data);
if (!result && fileName.startsWith(MOCK_NODEMODULES_PREFIX)) { if (!result && fileName.startsWith(MOCK_NODEMODULES_PREFIX)) {
const libraryPath = fileName.substr(MOCK_NODEMODULES_PREFIX.length - 1); const libraryPath = fileName.substr(MOCK_NODEMODULES_PREFIX.length - 1);
for (const library of this.libraries) { for (const library of this.libraries !) {
if (library.has(libraryPath)) return library.get(libraryPath); if (library.has(libraryPath)) return library.get(libraryPath);
} }
} }
@ -367,9 +366,9 @@ export class MockAotCompilerHost implements AotCompilerHost {
tsFilesOnly() { this.dtsAreSource = false; } tsFilesOnly() { this.dtsAreSource = false; }
// StaticSymbolResolverHost // StaticSymbolResolverHost
getMetadataFor(modulePath: string): {[key: string]: any}[] { getMetadataFor(modulePath: string): {[key: string]: any}[]|null {
if (!this.tsHost.fileExists(modulePath)) { if (!this.tsHost.fileExists(modulePath)) {
return undefined; return null;
} }
if (DTS.test(modulePath)) { if (DTS.test(modulePath)) {
if (this.metadataVisible) { if (this.metadataVisible) {
@ -384,6 +383,7 @@ export class MockAotCompilerHost implements AotCompilerHost {
const metadata = this.metadataCollector.getMetadata(sf); const metadata = this.metadataCollector.getMetadata(sf);
return metadata ? [metadata] : []; return metadata ? [metadata] : [];
} }
return null;
} }
moduleNameToFileName(moduleName: string, containingFile: string): string|null { moduleNameToFileName(moduleName: string, containingFile: string): string|null {
@ -439,11 +439,11 @@ export class MockMetadataBundlerHost implements MetadataBundlerHost {
} }
} }
function find(fileName: string, data: MockData): MockData|undefined { function find(fileName: string, data: MockData | undefined): MockData|undefined {
if (!data) return undefined; if (!data) return undefined;
let names = fileName.split('/'); let names = fileName.split('/');
if (names.length && !names[0].length) names.shift(); if (names.length && !names[0].length) names.shift();
let current = data; let current: MockData|undefined = data;
for (let name of names) { for (let name of names) {
if (typeof current === 'string') if (typeof current === 'string')
return undefined; return undefined;
@ -454,7 +454,7 @@ function find(fileName: string, data: MockData): MockData|undefined {
return current; return current;
} }
function open(fileName: string, data: MockData): string|undefined { function open(fileName: string, data: MockData | undefined): string|undefined {
let result = find(fileName, data); let result = find(fileName, data);
if (typeof result === 'string') { if (typeof result === 'string') {
return result; return result;
@ -462,7 +462,7 @@ function open(fileName: string, data: MockData): string|undefined {
return undefined; return undefined;
} }
function directoryExists(dirname: string, data: MockData): boolean { function directoryExists(dirname: string, data: MockData | undefined): boolean {
let result = find(dirname, data); let result = find(dirname, data);
return result && typeof result !== 'string'; return !!result && typeof result !== 'string';
} }

View File

@ -274,7 +274,7 @@ export function main() {
it('should throw an error if a selector is being parsed while in the wrong mode', () => { it('should throw an error if a selector is being parsed while in the wrong mode', () => {
const cssCode = '.class > tag'; const cssCode = '.class > tag';
let capturedMessage: string; let capturedMessage: string = undefined !;
try { try {
tokenize(cssCode, false, CssLexerMode.STYLE_BLOCK); tokenize(cssCode, false, CssLexerMode.STYLE_BLOCK);
} catch (e) { } catch (e) {
@ -282,7 +282,7 @@ export function main() {
} }
expect(capturedMessage).toMatch(/Unexpected character \[\>\] at column 0:7 in expression/g); expect(capturedMessage).toMatch(/Unexpected character \[\>\] at column 0:7 in expression/g);
capturedMessage = null; capturedMessage = null !;
try { try {
tokenize(cssCode, false, CssLexerMode.SELECTOR); tokenize(cssCode, false, CssLexerMode.SELECTOR);

View File

@ -111,26 +111,26 @@ export function main() {
expect(ast.rules.length).toEqual(1); expect(ast.rules.length).toEqual(1);
const rule = <CssKeyframeRuleAst>ast.rules[0]; const rule = <CssKeyframeRuleAst>ast.rules[0];
expect(rule.name.strValue).toEqual('rotateMe'); expect(rule.name !.strValue).toEqual('rotateMe');
const block = <CssBlockAst>rule.block; const block = <CssBlockAst>rule.block;
const fromRule = <CssKeyframeDefinitionAst>block.entries[0]; const fromRule = <CssKeyframeDefinitionAst>block.entries[0];
expect(fromRule.name.strValue).toEqual('from'); expect(fromRule.name !.strValue).toEqual('from');
const fromStyle = <CssDefinitionAst>(<CssBlockAst>fromRule.block).entries[0]; const fromStyle = <CssDefinitionAst>(<CssBlockAst>fromRule.block).entries[0];
expect(fromStyle.property.strValue).toEqual('transform'); expect(fromStyle.property.strValue).toEqual('transform');
assertTokens(fromStyle.value.tokens, ['rotate', '(', '-360', 'deg', ')']); assertTokens(fromStyle.value.tokens, ['rotate', '(', '-360', 'deg', ')']);
const midRule = <CssKeyframeDefinitionAst>block.entries[1]; const midRule = <CssKeyframeDefinitionAst>block.entries[1];
expect(midRule.name.strValue).toEqual('50%'); expect(midRule.name !.strValue).toEqual('50%');
const midStyle = <CssDefinitionAst>(<CssBlockAst>midRule.block).entries[0]; const midStyle = <CssDefinitionAst>(<CssBlockAst>midRule.block).entries[0];
expect(midStyle.property.strValue).toEqual('transform'); expect(midStyle.property.strValue).toEqual('transform');
assertTokens(midStyle.value.tokens, ['rotate', '(', '0', 'deg', ')']); assertTokens(midStyle.value.tokens, ['rotate', '(', '0', 'deg', ')']);
const toRule = <CssKeyframeDefinitionAst>block.entries[2]; const toRule = <CssKeyframeDefinitionAst>block.entries[2];
expect(toRule.name.strValue).toEqual('to'); expect(toRule.name !.strValue).toEqual('to');
const toStyle = <CssDefinitionAst>(<CssBlockAst>toRule.block).entries[0]; const toStyle = <CssDefinitionAst>(<CssBlockAst>toRule.block).entries[0];
expect(toStyle.property.strValue).toEqual('transform'); expect(toStyle.property.strValue).toEqual('transform');
assertTokens(toStyle.value.tokens, ['rotate', '(', '360', 'deg', ')']); assertTokens(toStyle.value.tokens, ['rotate', '(', '360', 'deg', ')']);
@ -695,7 +695,7 @@ export function main() {
const ast = output.ast; const ast = output.ast;
assertMatchesOffsetAndChar(ast.location.start, 0, '#'); assertMatchesOffsetAndChar(ast.location.start, 0, '#');
assertMatchesOffsetAndChar(ast.location.end, 22, undefined); assertMatchesOffsetAndChar(ast.location.end, 22, undefined !);
}); });
}); });

View File

@ -257,7 +257,7 @@ export function main() {
expect(captures.length).toEqual(1); expect(captures.length).toEqual(1);
const keyframe1 = <CssKeyframeRuleAst>_getCaptureAst(captures, 0); const keyframe1 = <CssKeyframeRuleAst>_getCaptureAst(captures, 0);
expect(keyframe1.name.strValue).toEqual('rotate'); expect(keyframe1.name !.strValue).toEqual('rotate');
expect(keyframe1.block.entries.length).toEqual(2); expect(keyframe1.block.entries.length).toEqual(2);
}); });

View File

@ -5,6 +5,7 @@
* Use of this source code is governed by an MIT-style license that can be * Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {CompileAnimationEntryMetadata} from '@angular/compiler';
import {CompileDirectiveMetadata, CompileStylesheetMetadata, CompileTemplateMetadata, CompileTypeMetadata} from '@angular/compiler/src/compile_metadata'; import {CompileDirectiveMetadata, CompileStylesheetMetadata, CompileTemplateMetadata, CompileTypeMetadata} from '@angular/compiler/src/compile_metadata';
import {CompilerConfig} from '@angular/compiler/src/config'; import {CompilerConfig} from '@angular/compiler/src/config';
import {DirectiveNormalizer} from '@angular/compiler/src/directive_normalizer'; import {DirectiveNormalizer} from '@angular/compiler/src/directive_normalizer';
@ -15,11 +16,137 @@ import {ViewEncapsulation} from '@angular/core/src/metadata/view';
import {TestBed} from '@angular/core/testing'; import {TestBed} from '@angular/core/testing';
import {AsyncTestCompleter, beforeEach, describe, expect, inject, it} from '@angular/core/testing/src/testing_internal'; import {AsyncTestCompleter, beforeEach, describe, expect, inject, it} from '@angular/core/testing/src/testing_internal';
import {SyncAsyncResult, noUndefined} from '../src/util';
import {SpyResourceLoader} from './spies'; import {SpyResourceLoader} from './spies';
const SOME_MODULE_URL = 'package:some/module/a.js'; const SOME_MODULE_URL = 'package:some/module/a.js';
const SOME_HTTP_MODULE_URL = 'http://some/module/a.js'; const SOME_HTTP_MODULE_URL = 'http://some/module/a.js';
function normalizeTemplate(normalizer: DirectiveNormalizer, o: {
ngModuleType?: any; componentType?: any; moduleUrl?: string; template?: string | null;
templateUrl?: string | null;
styles?: string[];
styleUrls?: string[];
interpolation?: [string, string] | null;
encapsulation?: ViewEncapsulation | null;
animations?: CompileAnimationEntryMetadata[];
}) {
return normalizer.normalizeTemplate({
ngModuleType: noUndefined(o.ngModuleType),
componentType: noUndefined(o.componentType),
moduleUrl: noUndefined(o.moduleUrl),
template: noUndefined(o.template),
templateUrl: noUndefined(o.templateUrl),
styles: noUndefined(o.styles),
styleUrls: noUndefined(o.styleUrls),
interpolation: noUndefined(o.interpolation),
encapsulation: noUndefined(o.encapsulation),
animations: noUndefined(o.animations)
});
}
function normalizeTemplateAsync(normalizer: DirectiveNormalizer, o: {
ngModuleType?: any; componentType?: any; moduleUrl?: string; template?: string | null;
templateUrl?: string | null;
styles?: string[];
styleUrls?: string[];
interpolation?: [string, string] | null;
encapsulation?: ViewEncapsulation | null;
animations?: CompileAnimationEntryMetadata[];
}) {
return normalizer.normalizeTemplateAsync({
ngModuleType: noUndefined(o.ngModuleType),
componentType: noUndefined(o.componentType),
moduleUrl: noUndefined(o.moduleUrl),
template: noUndefined(o.template),
templateUrl: noUndefined(o.templateUrl),
styles: noUndefined(o.styles),
styleUrls: noUndefined(o.styleUrls),
interpolation: noUndefined(o.interpolation),
encapsulation: noUndefined(o.encapsulation),
animations: noUndefined(o.animations)
});
}
function normalizeTemplateSync(normalizer: DirectiveNormalizer, o: {
ngModuleType?: any; componentType?: any; moduleUrl?: string; template?: string | null;
templateUrl?: string | null;
styles?: string[];
styleUrls?: string[];
interpolation?: [string, string] | null;
encapsulation?: ViewEncapsulation | null;
animations?: CompileAnimationEntryMetadata[];
}): CompileTemplateMetadata {
return normalizer.normalizeTemplateSync({
ngModuleType: noUndefined(o.ngModuleType),
componentType: noUndefined(o.componentType),
moduleUrl: noUndefined(o.moduleUrl),
template: noUndefined(o.template),
templateUrl: noUndefined(o.templateUrl),
styles: noUndefined(o.styles),
styleUrls: noUndefined(o.styleUrls),
interpolation: noUndefined(o.interpolation),
encapsulation: noUndefined(o.encapsulation),
animations: noUndefined(o.animations)
});
}
function compileTemplateMetadata({encapsulation, template, templateUrl, styles, styleUrls,
externalStylesheets, animations, ngContentSelectors,
interpolation, isInline}: {
encapsulation?: ViewEncapsulation | null,
template?: string | null,
templateUrl?: string | null,
styles?: string[],
styleUrls?: string[],
externalStylesheets?: CompileStylesheetMetadata[],
ngContentSelectors?: string[],
animations?: any[],
interpolation?: [string, string] | null,
isInline?: boolean
}): CompileTemplateMetadata {
return new CompileTemplateMetadata({
encapsulation: encapsulation || null,
template: template || null,
templateUrl: templateUrl || null,
styles: styles || [],
styleUrls: styleUrls || [],
externalStylesheets: externalStylesheets || [],
ngContentSelectors: ngContentSelectors || [],
animations: animations || [],
interpolation: interpolation || null,
isInline: !!isInline,
});
}
function normalizeLoadedTemplate(
normalizer: DirectiveNormalizer, o: {
ngModuleType?: any; componentType?: any; moduleUrl?: string; template?: string | null;
templateUrl?: string | null;
styles?: string[];
styleUrls?: string[];
interpolation?: [string, string] | null;
encapsulation?: ViewEncapsulation | null;
animations?: CompileAnimationEntryMetadata[];
},
template: string, templateAbsUrl: string) {
return normalizer.normalizeLoadedTemplate(
{
ngModuleType: o.ngModuleType || null,
componentType: o.componentType || null,
moduleUrl: o.moduleUrl || '',
template: o.template || null,
templateUrl: o.templateUrl || null,
styles: o.styles || [],
styleUrls: o.styleUrls || [],
interpolation: o.interpolation || null,
encapsulation: o.encapsulation || null,
animations: o.animations || null,
},
template, templateAbsUrl);
}
export function main() { export function main() {
describe('DirectiveNormalizer', () => { describe('DirectiveNormalizer', () => {
beforeEach(() => { TestBed.configureCompiler({providers: TEST_COMPILER_PROVIDERS}); }); beforeEach(() => { TestBed.configureCompiler({providers: TEST_COMPILER_PROVIDERS}); });
@ -27,46 +154,50 @@ export function main() {
describe('normalizeDirective', () => { describe('normalizeDirective', () => {
it('should throw if no template was specified', it('should throw if no template was specified',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
expect(() => normalizer.normalizeTemplate({ expect(() => normalizeTemplate(normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
})).toThrowError('No template specified for component SomeComp'); }))
.toThrowError('No template specified for component SomeComp');
})); }));
it('should throw if template is not a string', it('should throw if template is not a string',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
expect(() => normalizer.normalizeTemplate({ expect(() => normalizeTemplate(normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
template: <any>{} template: <any>{}
})).toThrowError('The template specified for component SomeComp is not a string'); }))
.toThrowError('The template specified for component SomeComp is not a string');
})); }));
it('should throw if templateUrl is not a string', it('should throw if templateUrl is not a string',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
expect(() => normalizer.normalizeTemplate({ expect(() => normalizeTemplate(normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
templateUrl: <any>{} templateUrl: <any>{}
})).toThrowError('The templateUrl specified for component SomeComp is not a string'); }))
.toThrowError('The templateUrl specified for component SomeComp is not a string');
})); }));
it('should throw if both template and templateUrl are defined', it('should throw if both template and templateUrl are defined',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
expect(() => normalizer.normalizeTemplate({ expect(() => normalizeTemplate(normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
template: '', template: '',
templateUrl: '', templateUrl: '',
})).toThrowError(`'SomeComp' component cannot define both template and templateUrl`); }))
.toThrowError(`'SomeComp' component cannot define both template and templateUrl`);
})); }));
}); });
describe('normalizeTemplateSync', () => { describe('normalizeTemplateSync', () => {
it('should store the template', it('should store the template',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
const template = normalizer.normalizeTemplateSync({ const template = normalizeTemplateSync(normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
@ -83,7 +214,7 @@ export function main() {
it('should resolve styles on the annotation against the moduleUrl', it('should resolve styles on the annotation against the moduleUrl',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
const template = normalizer.normalizeTemplateSync({ const template = normalizeTemplateSync(normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
@ -98,7 +229,7 @@ export function main() {
it('should resolve styles in the template against the moduleUrl', it('should resolve styles in the template against the moduleUrl',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
const template = normalizer.normalizeTemplateSync({ const template = normalizeTemplateSync(normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
@ -113,7 +244,7 @@ export function main() {
it('should use ViewEncapsulation.Emulated by default', it('should use ViewEncapsulation.Emulated by default',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
const template = normalizer.normalizeTemplateSync({ const template = normalizeTemplateSync(normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
@ -131,13 +262,13 @@ export function main() {
[CompilerConfig, DirectiveNormalizer], [CompilerConfig, DirectiveNormalizer],
(config: CompilerConfig, normalizer: DirectiveNormalizer) => { (config: CompilerConfig, normalizer: DirectiveNormalizer) => {
config.defaultEncapsulation = ViewEncapsulation.None; config.defaultEncapsulation = ViewEncapsulation.None;
const template = normalizer.normalizeTemplateSync({ const template = normalizeTemplateSync(normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
encapsulation: null, encapsulation: undefined,
template: '', template: '',
templateUrl: null, templateUrl: undefined,
styles: [], styles: [],
styleUrls: ['test.css'] styleUrls: ['test.css']
}); });
@ -153,23 +284,21 @@ export function main() {
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer, (async: AsyncTestCompleter, normalizer: DirectiveNormalizer,
resourceLoader: MockResourceLoader) => { resourceLoader: MockResourceLoader) => {
resourceLoader.expect('package:some/module/sometplurl.html', 'a'); resourceLoader.expect('package:some/module/sometplurl.html', 'a');
normalizer normalizeTemplateAsync(normalizer, {
.normalizeTemplateAsync({ ngModuleType: null,
ngModuleType: null, componentType: SomeComp,
componentType: SomeComp, moduleUrl: SOME_MODULE_URL,
moduleUrl: SOME_MODULE_URL, encapsulation: null,
encapsulation: null, template: null,
template: null, templateUrl: 'sometplurl.html',
templateUrl: 'sometplurl.html', styles: [],
styles: [], styleUrls: ['test.css']
styleUrls: ['test.css'] }).then((template: CompileTemplateMetadata) => {
}) expect(template.template).toEqual('a');
.then((template: CompileTemplateMetadata) => { expect(template.templateUrl).toEqual('package:some/module/sometplurl.html');
expect(template.template).toEqual('a'); expect(template.isInline).toBe(false);
expect(template.templateUrl).toEqual('package:some/module/sometplurl.html'); async.done();
expect(template.isInline).toBe(false); });
async.done();
});
resourceLoader.flush(); resourceLoader.flush();
})); }));
@ -179,21 +308,19 @@ export function main() {
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer, (async: AsyncTestCompleter, normalizer: DirectiveNormalizer,
resourceLoader: MockResourceLoader) => { resourceLoader: MockResourceLoader) => {
resourceLoader.expect('package:some/module/tpl/sometplurl.html', ''); resourceLoader.expect('package:some/module/tpl/sometplurl.html', '');
normalizer normalizeTemplateAsync(normalizer, {
.normalizeTemplateAsync({ ngModuleType: null,
ngModuleType: null, componentType: SomeComp,
componentType: SomeComp, moduleUrl: SOME_MODULE_URL,
moduleUrl: SOME_MODULE_URL, encapsulation: null,
encapsulation: null, template: null,
template: null, templateUrl: 'tpl/sometplurl.html',
templateUrl: 'tpl/sometplurl.html', styles: [],
styles: [], styleUrls: ['test.css']
styleUrls: ['test.css'] }).then((template: CompileTemplateMetadata) => {
}) expect(template.styleUrls).toEqual(['package:some/module/test.css']);
.then((template: CompileTemplateMetadata) => { async.done();
expect(template.styleUrls).toEqual(['package:some/module/test.css']); });
async.done();
});
resourceLoader.flush(); resourceLoader.flush();
})); }));
@ -204,21 +331,19 @@ export function main() {
resourceLoader: MockResourceLoader) => { resourceLoader: MockResourceLoader) => {
resourceLoader.expect( resourceLoader.expect(
'package:some/module/tpl/sometplurl.html', '<style>@import test.css</style>'); 'package:some/module/tpl/sometplurl.html', '<style>@import test.css</style>');
normalizer normalizeTemplateAsync(normalizer, {
.normalizeTemplateAsync({ ngModuleType: null,
ngModuleType: null, componentType: SomeComp,
componentType: SomeComp, moduleUrl: SOME_MODULE_URL,
moduleUrl: SOME_MODULE_URL, encapsulation: null,
encapsulation: null, template: null,
template: null, templateUrl: 'tpl/sometplurl.html',
templateUrl: 'tpl/sometplurl.html', styles: [],
styles: [], styleUrls: []
styleUrls: [] }).then((template: CompileTemplateMetadata) => {
}) expect(template.styleUrls).toEqual(['package:some/module/tpl/test.css']);
.then((template: CompileTemplateMetadata) => { async.done();
expect(template.styleUrls).toEqual(['package:some/module/tpl/test.css']); });
async.done();
});
resourceLoader.flush(); resourceLoader.flush();
})); }));
@ -238,7 +363,7 @@ export function main() {
resourceLoader: SpyResourceLoader) => { resourceLoader: SpyResourceLoader) => {
programResourceLoaderSpy(resourceLoader, {'package:some/module/test.css': 'a'}); programResourceLoaderSpy(resourceLoader, {'package:some/module/test.css': 'a'});
normalizer normalizer
.normalizeExternalStylesheets(new CompileTemplateMetadata({ .normalizeExternalStylesheets(compileTemplateMetadata({
template: '', template: '',
templateUrl: '', templateUrl: '',
styleUrls: ['package:some/module/test.css'] styleUrls: ['package:some/module/test.css']
@ -264,7 +389,7 @@ export function main() {
'package:some/module/test2.css': 'b' 'package:some/module/test2.css': 'b'
}); });
normalizer normalizer
.normalizeExternalStylesheets(new CompileTemplateMetadata({ .normalizeExternalStylesheets(compileTemplateMetadata({
template: '', template: '',
templateUrl: '', templateUrl: '',
styleUrls: ['package:some/module/test.css'] styleUrls: ['package:some/module/test.css']
@ -301,8 +426,8 @@ export function main() {
}; };
Promise Promise
.all([ .all([
normalizer.normalizeTemplateAsync(prenormMeta), normalizeTemplateAsync(normalizer, prenormMeta),
normalizer.normalizeTemplateAsync(prenormMeta) normalizeTemplateAsync(normalizer, prenormMeta)
]) ])
.then((templates: CompileTemplateMetadata[]) => { .then((templates: CompileTemplateMetadata[]) => {
expect(templates[0].template).toEqual('a'); expect(templates[0].template).toEqual('a');
@ -319,8 +444,8 @@ export function main() {
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
const viewEncapsulation = ViewEncapsulation.Native; const viewEncapsulation = ViewEncapsulation.Native;
const template = normalizer.normalizeLoadedTemplate( const template = normalizeLoadedTemplate(
{ normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
@ -334,8 +459,8 @@ export function main() {
it('should keep the template as html', it('should keep the template as html',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
const template = normalizer.normalizeLoadedTemplate( const template = normalizeLoadedTemplate(
{ normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
@ -349,8 +474,8 @@ export function main() {
it('should collect ngContent', it('should collect ngContent',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
const template = normalizer.normalizeLoadedTemplate( const template = normalizeLoadedTemplate(
{ normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
@ -364,8 +489,8 @@ export function main() {
it('should normalize ngContent wildcard selector', it('should normalize ngContent wildcard selector',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
const template = normalizer.normalizeLoadedTemplate( const template = normalizeLoadedTemplate(
{ normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
@ -380,8 +505,8 @@ export function main() {
it('should collect top level styles in the template', it('should collect top level styles in the template',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
const template = normalizer.normalizeLoadedTemplate( const template = normalizeLoadedTemplate(
{ normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
@ -395,8 +520,8 @@ export function main() {
it('should collect styles inside in elements', it('should collect styles inside in elements',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
const template = normalizer.normalizeLoadedTemplate( const template = normalizeLoadedTemplate(
{ normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
@ -410,8 +535,8 @@ export function main() {
it('should collect styleUrls in the template', it('should collect styleUrls in the template',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
const template = normalizer.normalizeLoadedTemplate( const template = normalizeLoadedTemplate(
{ normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
@ -425,8 +550,8 @@ export function main() {
it('should collect styleUrls in elements', it('should collect styleUrls in elements',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
const template = normalizer.normalizeLoadedTemplate( const template = normalizeLoadedTemplate(
{ normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
@ -440,8 +565,8 @@ export function main() {
it('should ignore link elements with non stylesheet rel attribute', it('should ignore link elements with non stylesheet rel attribute',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
const template = normalizer.normalizeLoadedTemplate( const template = normalizeLoadedTemplate(
{ normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
@ -455,8 +580,8 @@ export function main() {
it('should ignore link elements with absolute urls but non package: scheme', it('should ignore link elements with absolute urls but non package: scheme',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
const template = normalizer.normalizeLoadedTemplate( const template = normalizeLoadedTemplate(
{ normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
@ -470,8 +595,8 @@ export function main() {
it('should extract @import style urls into styleAbsUrl', it('should extract @import style urls into styleAbsUrl',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
const template = normalizer.normalizeLoadedTemplate( const template = normalizeLoadedTemplate(
{ normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
@ -486,8 +611,8 @@ export function main() {
it('should not resolve relative urls in inline styles', it('should not resolve relative urls in inline styles',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
const template = normalizer.normalizeLoadedTemplate( const template = normalizeLoadedTemplate(
{ normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
@ -501,8 +626,8 @@ export function main() {
it('should resolve relative style urls in styleUrls', it('should resolve relative style urls in styleUrls',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
const template = normalizer.normalizeLoadedTemplate( const template = normalizeLoadedTemplate(
{ normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
@ -517,8 +642,8 @@ export function main() {
it('should resolve relative style urls in styleUrls with http directive url', it('should resolve relative style urls in styleUrls with http directive url',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
const template = normalizer.normalizeLoadedTemplate( const template = normalizeLoadedTemplate(
{ normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_HTTP_MODULE_URL, moduleUrl: SOME_HTTP_MODULE_URL,
@ -533,8 +658,8 @@ export function main() {
it('should normalize ViewEncapsulation.Emulated to ViewEncapsulation.None if there are no styles nor stylesheets', it('should normalize ViewEncapsulation.Emulated to ViewEncapsulation.None if there are no styles nor stylesheets',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
const template = normalizer.normalizeLoadedTemplate( const template = normalizeLoadedTemplate(
{ normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
@ -548,8 +673,8 @@ export function main() {
it('should ignore ng-content in elements with ngNonBindable', it('should ignore ng-content in elements with ngNonBindable',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
const template = normalizer.normalizeLoadedTemplate( const template = normalizeLoadedTemplate(
{ normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,
@ -564,8 +689,8 @@ export function main() {
it('should still collect <style> in elements with ngNonBindable', it('should still collect <style> in elements with ngNonBindable',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
const template = normalizer.normalizeLoadedTemplate( const template = normalizeLoadedTemplate(
{ normalizer, {
ngModuleType: null, ngModuleType: null,
componentType: SomeComp, componentType: SomeComp,
moduleUrl: SOME_MODULE_URL, moduleUrl: SOME_MODULE_URL,

View File

@ -28,18 +28,18 @@ export function main() {
function parseTemplateBindingsResult( function parseTemplateBindingsResult(
text: string, location: any = null, prefix?: string): TemplateBindingParseResult { text: string, location: any = null, prefix?: string): TemplateBindingParseResult {
return createParser().parseTemplateBindings(prefix, text, location); return createParser().parseTemplateBindings(prefix || null, text, location);
} }
function parseTemplateBindings( function parseTemplateBindings(
text: string, location: any = null, prefix?: string): TemplateBinding[] { text: string, location: any = null, prefix?: string): TemplateBinding[] {
return parseTemplateBindingsResult(text, location, prefix).templateBindings; return parseTemplateBindingsResult(text, location, prefix).templateBindings;
} }
function parseInterpolation(text: string, location: any = null): ASTWithSource { function parseInterpolation(text: string, location: any = null): ASTWithSource|null {
return createParser().parseInterpolation(text, location); return createParser().parseInterpolation(text, location);
} }
function splitInterpolation(text: string, location: any = null): SplitInterpolation { function splitInterpolation(text: string, location: any = null): SplitInterpolation|null {
return createParser().splitInterpolation(text, location); return createParser().splitInterpolation(text, location);
} }
@ -48,7 +48,7 @@ export function main() {
} }
function checkInterpolation(exp: string, expected?: string) { function checkInterpolation(exp: string, expected?: string) {
const ast = parseInterpolation(exp); const ast = parseInterpolation(exp) !;
if (expected == null) expected = exp; if (expected == null) expected = exp;
expect(unparse(ast)).toEqual(expected); expect(unparse(ast)).toEqual(expected);
validate(ast); validate(ast);
@ -475,7 +475,7 @@ export function main() {
() => { expect(parseInterpolation('nothing')).toBe(null); }); () => { expect(parseInterpolation('nothing')).toBe(null); });
it('should parse no prefix/suffix interpolation', () => { it('should parse no prefix/suffix interpolation', () => {
const ast = parseInterpolation('{{a}}').ast as Interpolation; const ast = parseInterpolation('{{a}}') !.ast as Interpolation;
expect(ast.strings).toEqual(['', '']); expect(ast.strings).toEqual(['', '']);
expect(ast.expressions.length).toEqual(1); expect(ast.expressions.length).toEqual(1);
expect(ast.expressions[0].name).toEqual('a'); expect(ast.expressions[0].name).toEqual('a');
@ -483,18 +483,18 @@ export function main() {
it('should parse prefix/suffix with multiple interpolation', () => { it('should parse prefix/suffix with multiple interpolation', () => {
const originalExp = 'before {{ a }} middle {{ b }} after'; const originalExp = 'before {{ a }} middle {{ b }} after';
const ast = parseInterpolation(originalExp).ast; const ast = parseInterpolation(originalExp) !.ast;
expect(unparse(ast)).toEqual(originalExp); expect(unparse(ast)).toEqual(originalExp);
validate(ast); validate(ast);
}); });
it('should report empty interpolation expressions', () => { it('should report empty interpolation expressions', () => {
expectError( expectError(
parseInterpolation('{{}}'), parseInterpolation('{{}}') !,
'Blank expressions are not allowed in interpolated strings'); 'Blank expressions are not allowed in interpolated strings');
expectError( expectError(
parseInterpolation('foo {{ }}'), parseInterpolation('foo {{ }}') !,
'Parser Error: Blank expressions are not allowed in interpolated strings'); 'Parser Error: Blank expressions are not allowed in interpolated strings');
}); });
@ -507,7 +507,8 @@ export function main() {
it('should support custom interpolation', () => { it('should support custom interpolation', () => {
const parser = new Parser(new Lexer()); const parser = new Parser(new Lexer());
const ast = parser.parseInterpolation('{% a %}', null, {start: '{%', end: '%}'}).ast as any; const ast =
parser.parseInterpolation('{% a %}', null, {start: '{%', end: '%}'}) !.ast as any;
expect(ast.strings).toEqual(['', '']); expect(ast.strings).toEqual(['', '']);
expect(ast.expressions.length).toEqual(1); expect(ast.expressions.length).toEqual(1);
expect(ast.expressions[0].name).toEqual('a'); expect(ast.expressions[0].name).toEqual('a');
@ -586,12 +587,12 @@ export function main() {
describe('offsets', () => { describe('offsets', () => {
it('should retain the offsets of an interpolation', () => { it('should retain the offsets of an interpolation', () => {
const interpolations = splitInterpolation('{{a}} {{b}} {{c}}'); const interpolations = splitInterpolation('{{a}} {{b}} {{c}}') !;
expect(interpolations.offsets).toEqual([2, 9, 16]); expect(interpolations.offsets).toEqual([2, 9, 16]);
}); });
it('should retain the offsets into the expression AST of interpolations', () => { it('should retain the offsets into the expression AST of interpolations', () => {
const source = parseInterpolation('{{a}} {{b}} {{c}}'); const source = parseInterpolation('{{a}} {{b}} {{c}}') !;
const interpolation = source.ast as Interpolation; const interpolation = source.ast as Interpolation;
expect(interpolation.expressions.map(e => e.span.start)).toEqual([2, 9, 16]); expect(interpolation.expressions.map(e => e.span.start)).toEqual([2, 9, 16]);
}); });

View File

@ -67,7 +67,7 @@ class Unparser implements AstVisitor {
} }
visitFunctionCall(ast: FunctionCall, context: any) { visitFunctionCall(ast: FunctionCall, context: any) {
this._visit(ast.target); this._visit(ast.target !);
this._expression += '('; this._expression += '(';
let isFirst = true; let isFirst = true;
ast.args.forEach(arg => { ast.args.forEach(arg => {

View File

@ -285,7 +285,7 @@ export function main() {
}); });
it('should allow nested implicit elements', () => { it('should allow nested implicit elements', () => {
let result: any[]; let result: any[] = undefined !;
expect(() => { expect(() => {
result = extract('<div>outer<div>inner</div></div>', ['div']); result = extract('<div>outer<div>inner</div></div>', ['div']);
@ -490,7 +490,7 @@ function fakeTranslate(
messages.forEach(message => { messages.forEach(message => {
const id = digest(message); const id = digest(message);
const text = serializeI18nNodes(message.nodes).join('').replace(/</g, '['); const text = serializeI18nNodes(message.nodes).join('').replace(/</g, '[');
i18nMsgMap[id] = [new i18n.Text(`**${text}**`, null)]; i18nMsgMap[id] = [new i18n.Text(`**${text}**`, null !)];
}); });
const translations = new TranslationBundle(i18nMsgMap, null, digest); const translations = new TranslationBundle(i18nMsgMap, null, digest);

View File

@ -36,13 +36,13 @@ export function main(): void {
const visitor = new RecurseVisitor(); const visitor = new RecurseVisitor();
const container = new i18n.Container( const container = new i18n.Container(
[ [
new i18n.Text('', null), new i18n.Text('', null !),
new i18n.Placeholder('', '', null), new i18n.Placeholder('', '', null !),
new i18n.IcuPlaceholder(null, '', null), new i18n.IcuPlaceholder(null !, '', null !),
], ],
null); null !);
const tag = new i18n.TagPlaceholder('', {}, '', '', [container], false, null); const tag = new i18n.TagPlaceholder('', {}, '', '', [container], false, null !);
const icu = new i18n.Icu('', '', {tag}, null); const icu = new i18n.Icu('', '', {tag}, null !);
icu.visit(visitor); icu.visit(visitor);
expect(visitor.textCount).toEqual(1); expect(visitor.textCount).toEqual(1);

View File

@ -117,7 +117,7 @@ export function main(): void {
</translationbundle>`; </translationbundle>`;
// Invalid messages should not cause the parser to throw // Invalid messages should not cause the parser to throw
let i18nNodesByMsgId: {[id: string]: i18n.Node[]}; let i18nNodesByMsgId: {[id: string]: i18n.Node[]} = undefined !;
expect(() => { expect(() => {
i18nNodesByMsgId = serializer.load(XTB, 'url').i18nNodesByMsgId; i18nNodesByMsgId = serializer.load(XTB, 'url').i18nNodesByMsgId;
}).not.toThrow(); }).not.toThrow();

View File

@ -18,11 +18,11 @@ export function main(): void {
describe('TranslationBundle', () => { describe('TranslationBundle', () => {
const file = new ParseSourceFile('content', 'url'); const file = new ParseSourceFile('content', 'url');
const location = new ParseLocation(file, 0, 0, 0); const location = new ParseLocation(file, 0, 0, 0);
const span = new ParseSourceSpan(location, null); const span = new ParseSourceSpan(location, null !);
const srcNode = new i18n.Text('src', span); const srcNode = new i18n.Text('src', span);
it('should translate a plain message', () => { it('should translate a plain message', () => {
const msgMap = {foo: [new i18n.Text('bar', null)]}; const msgMap = {foo: [new i18n.Text('bar', null !)]};
const tb = new TranslationBundle(msgMap, null, (_) => 'foo'); const tb = new TranslationBundle(msgMap, null, (_) => 'foo');
const msg = new i18n.Message([srcNode], {}, {}, 'm', 'd', 'i'); const msg = new i18n.Message([srcNode], {}, {}, 'm', 'd', 'i');
expect(serializeNodes(tb.get(msg))).toEqual(['bar']); expect(serializeNodes(tb.get(msg))).toEqual(['bar']);
@ -31,8 +31,8 @@ export function main(): void {
it('should translate a message with placeholder', () => { it('should translate a message with placeholder', () => {
const msgMap = { const msgMap = {
foo: [ foo: [
new i18n.Text('bar', null), new i18n.Text('bar', null !),
new i18n.Placeholder('', 'ph1', null), new i18n.Placeholder('', 'ph1', null !),
] ]
}; };
const phMap = { const phMap = {
@ -46,12 +46,12 @@ export function main(): void {
it('should translate a message with placeholder referencing messages', () => { it('should translate a message with placeholder referencing messages', () => {
const msgMap = { const msgMap = {
foo: [ foo: [
new i18n.Text('--', null), new i18n.Text('--', null !),
new i18n.Placeholder('', 'ph1', null), new i18n.Placeholder('', 'ph1', null !),
new i18n.Text('++', null), new i18n.Text('++', null !),
], ],
ref: [ ref: [
new i18n.Text('*refMsg*', null), new i18n.Text('*refMsg*', null !),
], ],
}; };
const refMsg = new i18n.Message([srcNode], {}, {}, 'm', 'd', 'i'); const refMsg = new i18n.Message([srcNode], {}, {}, 'm', 'd', 'i');
@ -70,13 +70,13 @@ export function main(): void {
const digest = (_: any) => `no matching id`; const digest = (_: any) => `no matching id`;
// Empty message map -> use source messages in Ignore mode // Empty message map -> use source messages in Ignore mode
let tb = new TranslationBundle({}, null, digest, null, MissingTranslationStrategy.Ignore); let tb = new TranslationBundle({}, null, digest, null !, MissingTranslationStrategy.Ignore);
expect(serializeNodes(tb.get(messages[0])).join('')).toEqual(src); expect(serializeNodes(tb.get(messages[0])).join('')).toEqual(src);
// Empty message map -> use source messages in Warning mode // Empty message map -> use source messages in Warning mode
tb = new TranslationBundle({}, null, digest, null, MissingTranslationStrategy.Warning); tb = new TranslationBundle({}, null, digest, null !, MissingTranslationStrategy.Warning);
expect(serializeNodes(tb.get(messages[0])).join('')).toEqual(src); expect(serializeNodes(tb.get(messages[0])).join('')).toEqual(src);
// Empty message map -> throw in Error mode // Empty message map -> throw in Error mode
tb = new TranslationBundle({}, null, digest, null, MissingTranslationStrategy.Error); tb = new TranslationBundle({}, null, digest, null !, MissingTranslationStrategy.Error);
expect(() => serializeNodes(tb.get(messages[0])).join('')).toThrow(); expect(() => serializeNodes(tb.get(messages[0])).join('')).toThrow();
}); });
@ -84,7 +84,7 @@ export function main(): void {
it('should report unknown placeholders', () => { it('should report unknown placeholders', () => {
const msgMap = { const msgMap = {
foo: [ foo: [
new i18n.Text('bar', null), new i18n.Text('bar', null !),
new i18n.Placeholder('', 'ph1', span), new i18n.Placeholder('', 'ph1', span),
] ]
}; };
@ -95,7 +95,7 @@ export function main(): void {
it('should report missing translation', () => { it('should report missing translation', () => {
const tb = const tb =
new TranslationBundle({}, null, (_) => 'foo', null, MissingTranslationStrategy.Error); new TranslationBundle({}, null, (_) => 'foo', null !, MissingTranslationStrategy.Error);
const msg = new i18n.Message([srcNode], {}, {}, 'm', 'd', 'i'); const msg = new i18n.Message([srcNode], {}, {}, 'm', 'd', 'i');
expect(() => tb.get(msg)).toThrowError(/Missing translation for message "foo"/); expect(() => tb.get(msg)).toThrowError(/Missing translation for message "foo"/);
}); });
@ -108,7 +108,7 @@ export function main(): void {
}; };
const tb = new TranslationBundle( const tb = new TranslationBundle(
{}, 'en', (_) => 'foo', null, MissingTranslationStrategy.Warning, console); {}, 'en', (_) => 'foo', null !, MissingTranslationStrategy.Warning, console);
const msg = new i18n.Message([srcNode], {}, {}, 'm', 'd', 'i'); const msg = new i18n.Message([srcNode], {}, {}, 'm', 'd', 'i');
expect(() => tb.get(msg)).not.toThrowError(); expect(() => tb.get(msg)).not.toThrowError();
@ -117,8 +117,8 @@ export function main(): void {
}); });
it('should not report missing translation with MissingTranslationStrategy.Ignore', () => { it('should not report missing translation with MissingTranslationStrategy.Ignore', () => {
const tb = const tb = new TranslationBundle(
new TranslationBundle({}, null, (_) => 'foo', null, MissingTranslationStrategy.Ignore); {}, null, (_) => 'foo', null !, MissingTranslationStrategy.Ignore);
const msg = new i18n.Message([srcNode], {}, {}, 'm', 'd', 'i'); const msg = new i18n.Message([srcNode], {}, {}, 'm', 'd', 'i');
expect(() => tb.get(msg)).not.toThrowError(); expect(() => tb.get(msg)).not.toThrowError();
}); });
@ -132,15 +132,15 @@ export function main(): void {
let count = 0; let count = 0;
const digest = (_: any) => count++ ? 'ref' : 'foo'; const digest = (_: any) => count++ ? 'ref' : 'foo';
const tb = const tb =
new TranslationBundle(msgMap, null, digest, null, MissingTranslationStrategy.Error); new TranslationBundle(msgMap, null, digest, null !, MissingTranslationStrategy.Error);
expect(() => tb.get(msg)).toThrowError(/Missing translation for message "ref"/); expect(() => tb.get(msg)).toThrowError(/Missing translation for message "ref"/);
}); });
it('should report invalid translated html', () => { it('should report invalid translated html', () => {
const msgMap = { const msgMap = {
foo: [ foo: [
new i18n.Text('text', null), new i18n.Text('text', null !),
new i18n.Placeholder('', 'ph1', null), new i18n.Placeholder('', 'ph1', null !),
] ]
}; };
const phMap = { const phMap = {

View File

@ -16,7 +16,7 @@ export function main() {
let fixture: ComponentFixture<TestComponent>; let fixture: ComponentFixture<TestComponent>;
describe('directives', () => { describe('directiv es', () => {
it('should support dotted selectors', async(() => { it('should support dotted selectors', async(() => {
@Directive({selector: '[dot.name]'}) @Directive({selector: '[dot.name]'})
class MyDir { class MyDir {

View File

@ -26,9 +26,9 @@ class SomeMetadata implements SomeMetadataType {
arrayProp: any[]; arrayProp: any[];
constructor(options: SomeMetadataType) { constructor(options: SomeMetadataType) {
this.plainProp = options.plainProp; this.plainProp = options.plainProp !;
this._getterProp = options.getterProp; this._getterProp = options.getterProp !;
this.arrayProp = options.arrayProp; this.arrayProp = options.arrayProp !;
} }
} }
@ -42,7 +42,7 @@ class OtherMetadata extends SomeMetadata implements OtherMetadataType {
arrayProp: options.arrayProp arrayProp: options.arrayProp
}); });
this.otherPlainProp = options.otherPlainProp; this.otherPlainProp = options.otherPlainProp !;
} }
} }

View File

@ -215,7 +215,7 @@ export function main() {
it('should throw with descriptive error message when null is passed to declarations', it('should throw with descriptive error message when null is passed to declarations',
inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => { inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
@NgModule({declarations: [null]}) @NgModule({declarations: [null !]})
class ModuleWithNullDeclared { class ModuleWithNullDeclared {
} }
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(ModuleWithNullDeclared, true)) expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(ModuleWithNullDeclared, true))
@ -225,7 +225,7 @@ export function main() {
it('should throw with descriptive error message when null is passed to imports', it('should throw with descriptive error message when null is passed to imports',
inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => { inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
@NgModule({imports: [null]}) @NgModule({imports: [null !]})
class ModuleWithNullImported { class ModuleWithNullImported {
} }
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(ModuleWithNullImported, true)) expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(ModuleWithNullImported, true))
@ -246,7 +246,7 @@ export function main() {
it('should throw with descriptive error message when encounter invalid provider', it('should throw with descriptive error message when encounter invalid provider',
inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => { inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
@NgModule({providers: [{provide: SimpleService, useClass: undefined}]}) @NgModule({providers: [{provide: SimpleService, useClass: undefined !}]})
class SomeModule { class SomeModule {
} }
@ -256,7 +256,7 @@ export function main() {
it('should throw with descriptive error message when provider is undefined', it('should throw with descriptive error message when provider is undefined',
inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => { inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
@NgModule({providers: [undefined]}) @NgModule({providers: [undefined !]})
class SomeModule { class SomeModule {
} }
@ -288,10 +288,10 @@ export function main() {
it('should throw with descriptive error message when null or undefined is passed to module bootstrap', it('should throw with descriptive error message when null or undefined is passed to module bootstrap',
inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => { inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
@NgModule({bootstrap: [null]}) @NgModule({bootstrap: [null !]})
class ModuleWithNullBootstrap { class ModuleWithNullBootstrap {
} }
@NgModule({bootstrap: [undefined]}) @NgModule({bootstrap: [undefined !]})
class ModuleWithUndefinedBootstrap { class ModuleWithUndefinedBootstrap {
} }
@ -410,7 +410,7 @@ export function main() {
class MyModule { class MyModule {
} }
const modMeta = resolver.getNgModuleMetadata(MyModule); const modMeta = resolver.getNgModuleMetadata(MyModule) !;
expect(modMeta.declaredDirectives.length).toBe(1); expect(modMeta.declaredDirectives.length).toBe(1);
expect(modMeta.declaredDirectives[0].reference).toBe(MyComp); expect(modMeta.declaredDirectives[0].reference).toBe(MyComp);
})); }));
@ -480,11 +480,12 @@ class MyBrokenComp2 {
class SimpleService { class SimpleService {
} }
@Component({selector: 'my-broken-comp', template: '', providers: [SimpleService, null, [null]]}) @Component({selector: 'my-broken-comp', template: '', providers: [SimpleService, null !, [null]]})
class MyBrokenComp3 { class MyBrokenComp3 {
} }
@Component({selector: 'my-broken-comp', template: '', viewProviders: [null, SimpleService, [null]]}) @Component(
{selector: 'my-broken-comp', template: '', viewProviders: [null !, SimpleService, [null]]})
class MyBrokenComp4 { class MyBrokenComp4 {
} }

View File

@ -78,7 +78,7 @@ class _Humanizer implements html.Visitor {
private _appendContext(ast: html.Node, input: any[]): any[] { private _appendContext(ast: html.Node, input: any[]): any[] {
if (!this.includeSourceSpan) return input; if (!this.includeSourceSpan) return input;
input.push(ast.sourceSpan.toString()); input.push(ast.sourceSpan !.toString());
return input; return input;
} }
} }

View File

@ -395,11 +395,11 @@ export function main() {
it('should set the start and end source spans', () => { it('should set the start and end source spans', () => {
const node = <html.Element>parser.parse('<div>a</div>', 'TestComp').rootNodes[0]; const node = <html.Element>parser.parse('<div>a</div>', 'TestComp').rootNodes[0];
expect(node.startSourceSpan.start.offset).toEqual(0); expect(node.startSourceSpan !.start.offset).toEqual(0);
expect(node.startSourceSpan.end.offset).toEqual(5); expect(node.startSourceSpan !.end.offset).toEqual(5);
expect(node.endSourceSpan.start.offset).toEqual(6); expect(node.endSourceSpan !.start.offset).toEqual(6);
expect(node.endSourceSpan.end.offset).toEqual(12); expect(node.endSourceSpan !.end.offset).toEqual(12);
}); });
it('should support expansion form', () => { it('should support expansion form', () => {
@ -420,8 +420,8 @@ export function main() {
it('should report a value span for an attibute with a value', () => { it('should report a value span for an attibute with a value', () => {
const ast = parser.parse('<div bar="12"></div>', 'TestComp'); const ast = parser.parse('<div bar="12"></div>', 'TestComp');
const attr = (ast.rootNodes[0] as html.Element).attrs[0]; const attr = (ast.rootNodes[0] as html.Element).attrs[0];
expect(attr.valueSpan.start.offset).toEqual(9); expect(attr.valueSpan !.start.offset).toEqual(9);
expect(attr.valueSpan.end.offset).toEqual(13); expect(attr.valueSpan !.end.offset).toEqual(13);
}); });
}); });

View File

@ -56,28 +56,28 @@ export function main() {
const nodes = expand(`{messages.length, plural,=0 {<b>bold</b>}}`).nodes; const nodes = expand(`{messages.length, plural,=0 {<b>bold</b>}}`).nodes;
const container: html.Element = <html.Element>nodes[0]; const container: html.Element = <html.Element>nodes[0];
expect(container.sourceSpan.start.col).toEqual(0); expect(container.sourceSpan !.start.col).toEqual(0);
expect(container.sourceSpan.end.col).toEqual(42); expect(container.sourceSpan !.end.col).toEqual(42);
expect(container.startSourceSpan.start.col).toEqual(0); expect(container.startSourceSpan !.start.col).toEqual(0);
expect(container.startSourceSpan.end.col).toEqual(42); expect(container.startSourceSpan !.end.col).toEqual(42);
expect(container.endSourceSpan.start.col).toEqual(0); expect(container.endSourceSpan !.start.col).toEqual(0);
expect(container.endSourceSpan.end.col).toEqual(42); expect(container.endSourceSpan !.end.col).toEqual(42);
const switchExp = container.attrs[0]; const switchExp = container.attrs[0];
expect(switchExp.sourceSpan.start.col).toEqual(1); expect(switchExp.sourceSpan.start.col).toEqual(1);
expect(switchExp.sourceSpan.end.col).toEqual(16); expect(switchExp.sourceSpan.end.col).toEqual(16);
const template: html.Element = <html.Element>container.children[0]; const template: html.Element = <html.Element>container.children[0];
expect(template.sourceSpan.start.col).toEqual(25); expect(template.sourceSpan !.start.col).toEqual(25);
expect(template.sourceSpan.end.col).toEqual(41); expect(template.sourceSpan !.end.col).toEqual(41);
const switchCheck = template.attrs[0]; const switchCheck = template.attrs[0];
expect(switchCheck.sourceSpan.start.col).toEqual(25); expect(switchCheck.sourceSpan.start.col).toEqual(25);
expect(switchCheck.sourceSpan.end.col).toEqual(28); expect(switchCheck.sourceSpan.end.col).toEqual(28);
const b: html.Element = <html.Element>template.children[0]; const b: html.Element = <html.Element>template.children[0];
expect(b.sourceSpan.start.col).toEqual(29); expect(b.sourceSpan !.start.col).toEqual(29);
expect(b.endSourceSpan.end.col).toEqual(40); expect(b.endSourceSpan !.end.col).toEqual(40);
}); });
it('should handle other special forms', () => { it('should handle other special forms', () => {

View File

@ -443,7 +443,7 @@ export function main() {
}); });
it('should parse interpolation with custom markers', () => { it('should parse interpolation with custom markers', () => {
expect(tokenizeAndHumanizeParts('{% a %}', null, {start: '{%', end: '%}'})).toEqual([ expect(tokenizeAndHumanizeParts('{% a %}', null !, {start: '{%', end: '%}'})).toEqual([
[lex.TokenType.TEXT, '{% a %}'], [lex.TokenType.TEXT, '{% a %}'],
[lex.TokenType.EOF], [lex.TokenType.EOF],
]); ]);
@ -769,7 +769,7 @@ export function main() {
const file = new ParseSourceFile(src, 'file://'); const file = new ParseSourceFile(src, 'file://');
const location = new ParseLocation(file, 12, 123, 456); const location = new ParseLocation(file, 12, 123, 456);
const span = new ParseSourceSpan(location, location); const span = new ParseSourceSpan(location, location);
const error = new lex.TokenError('**ERROR**', null, span); const error = new lex.TokenError('**ERROR**', null !, span);
expect(error.toString()) expect(error.toString())
.toEqual(`**ERROR** ("\n222\n333\n[ERROR ->]E\n444\n555\n"): file://@123:456`); .toEqual(`**ERROR** ("\n222\n333\n[ERROR ->]E\n444\n555\n"): file://@123:456`);
}); });

View File

@ -25,7 +25,7 @@ export function main() {
ctx.print(createSourceSpan(fileA, 1), 'o1'); ctx.print(createSourceSpan(fileA, 1), 'o1');
ctx.print(createSourceSpan(fileB, 0), 'o2'); ctx.print(createSourceSpan(fileB, 0), 'o2');
ctx.print(createSourceSpan(fileB, 1), 'o3'); ctx.print(createSourceSpan(fileB, 1), 'o3');
const sm = ctx.toSourceMapGenerator('o.ts', 'o.js').toJSON(); const sm = ctx.toSourceMapGenerator('o.ts', 'o.js').toJSON() !;
expect(sm.sources).toEqual([fileA.url, fileB.url]); expect(sm.sources).toEqual([fileA.url, fileB.url]);
expect(sm.sourcesContent).toEqual([fileA.content, fileB.content]); expect(sm.sourcesContent).toEqual([fileA.content, fileB.content]);
}); });
@ -43,7 +43,7 @@ export function main() {
it('should be able to shift the content', () => { it('should be able to shift the content', () => {
ctx.print(createSourceSpan(fileA, 0), 'fileA-0'); ctx.print(createSourceSpan(fileA, 0), 'fileA-0');
const sm = ctx.toSourceMapGenerator('o.ts', 'o.js', 10).toJSON(); const sm = ctx.toSourceMapGenerator('o.ts', 'o.js', 10).toJSON() !;
expect(originalPositionFor(sm, {line: 11, column: 0})).toEqual({ expect(originalPositionFor(sm, {line: 11, column: 0})).toEqual({
line: 1, line: 1,
column: 0, column: 0,
@ -111,9 +111,9 @@ export function main() {
// All lines / columns indexes are 0-based // All lines / columns indexes are 0-based
// Note: source-map line indexes are 1-based, column 0-based // Note: source-map line indexes are 1-based, column 0-based
function expectMap( function expectMap(
ctx: EmitterVisitorContext, genLine: number, genCol: number, source: string = null, ctx: EmitterVisitorContext, genLine: number, genCol: number, source: string | null = null,
srcLine: number = null, srcCol: number = null) { srcLine: number | null = null, srcCol: number | null = null) {
const sm = ctx.toSourceMapGenerator('o.ts', 'o.js').toJSON(); const sm = ctx.toSourceMapGenerator('o.ts', 'o.js').toJSON() !;
const genPosition = {line: genLine + 1, column: genCol}; const genPosition = {line: genLine + 1, column: genCol};
const origPosition = originalPositionFor(sm, genPosition); const origPosition = originalPositionFor(sm, genPosition);
expect(origPosition.source).toEqual(source); expect(origPosition.source).toEqual(source);
@ -123,7 +123,7 @@ function expectMap(
// returns the number of segments per line // returns the number of segments per line
function nbSegmentsPerLine(ctx: EmitterVisitorContext) { function nbSegmentsPerLine(ctx: EmitterVisitorContext) {
const sm = ctx.toSourceMapGenerator('o.ts', 'o.js').toJSON(); const sm = ctx.toSourceMapGenerator('o.ts', 'o.js').toJSON() !;
const lines = sm.mappings.split(';'); const lines = sm.mappings.split(';');
return lines.map(l => { return lines.map(l => {
const m = l.match(/,/g); const m = l.match(/,/g);

View File

@ -23,8 +23,8 @@ class SimpleJsImportGenerator implements ImportResolver {
fileNameToModuleName(importedUrlStr: string, moduleUrlStr: string): string { fileNameToModuleName(importedUrlStr: string, moduleUrlStr: string): string {
return importedUrlStr; return importedUrlStr;
} }
getImportAs(symbol: StaticSymbol): StaticSymbol { return null; } getImportAs(symbol: StaticSymbol): StaticSymbol|null { return null; }
getTypeArity(symbol: StaticSymbol): number /*|null*/ { return null; } getTypeArity(symbol: StaticSymbol): number|null { return null; }
} }
export function main() { export function main() {
@ -39,12 +39,12 @@ export function main() {
}); });
function emitSourceMap( function emitSourceMap(
stmt: o.Statement | o.Statement[], exportedVars: string[] = null, stmt: o.Statement | o.Statement[], exportedVars: string[] | null = null,
preamble?: string): SourceMap { preamble?: string): SourceMap {
const stmts = Array.isArray(stmt) ? stmt : [stmt]; const stmts = Array.isArray(stmt) ? stmt : [stmt];
const source = emitter.emitStatements( const source = emitter.emitStatements(
someSourceFilePath, someGenFilePath, stmts, exportedVars || [], preamble); someSourceFilePath, someGenFilePath, stmts, exportedVars || [], preamble);
return extractSourceMap(source); return extractSourceMap(source) !;
} }
describe('source maps', () => { describe('source maps', () => {

View File

@ -29,8 +29,8 @@ class SimpleJsImportGenerator implements ImportResolver {
fileNameToModuleName(importedUrlStr: string, moduleUrlStr: string): string { fileNameToModuleName(importedUrlStr: string, moduleUrlStr: string): string {
return importedUrlStr; return importedUrlStr;
} }
getImportAs(symbol: StaticSymbol): StaticSymbol { return null; } getImportAs(symbol: StaticSymbol): StaticSymbol|null { return null; }
getTypeArity(symbol: StaticSymbol): number /*|null*/ { return null; } getTypeArity(symbol: StaticSymbol): number|null { return null; }
} }
export function main() { export function main() {
@ -49,7 +49,8 @@ export function main() {
someVar = o.variable('someVar'); someVar = o.variable('someVar');
}); });
function emitStmt(stmt: o.Statement, exportedVars: string[] = null, preamble?: string): string { function emitStmt(
stmt: o.Statement, exportedVars: string[] | null = null, preamble?: string): string {
const source = emitter.emitStatements( const source = emitter.emitStatements(
someSourceFilePath, someGenFilePath, [stmt], exportedVars || [], preamble); someSourceFilePath, someGenFilePath, [stmt], exportedVars || [], preamble);
return stripSourceMapAndNewLine(source); return stripSourceMapAndNewLine(source);
@ -224,15 +225,15 @@ export function main() {
beforeEach(() => { callSomeMethod = o.THIS_EXPR.callMethod('someMethod', []).toStmt(); }); beforeEach(() => { callSomeMethod = o.THIS_EXPR.callMethod('someMethod', []).toStmt(); });
it('should support declaring classes', () => { it('should support declaring classes', () => {
expect(emitStmt(new o.ClassStmt('SomeClass', null, [], [], null, [ expect(emitStmt(new o.ClassStmt('SomeClass', null !, [], [], null !, [
]))).toEqual(['function SomeClass() {', '}'].join('\n')); ]))).toEqual(['function SomeClass() {', '}'].join('\n'));
expect(emitStmt(new o.ClassStmt('SomeClass', null, [], [], null, []), ['SomeClass'])) expect(emitStmt(new o.ClassStmt('SomeClass', null !, [], [], null !, []), ['SomeClass']))
.toEqual([ .toEqual([
'function SomeClass() {', '}', 'function SomeClass() {', '}',
`Object.defineProperty(exports, 'SomeClass', { get: function() { return SomeClass; }});` `Object.defineProperty(exports, 'SomeClass', { get: function() { return SomeClass; }});`
].join('\n')); ].join('\n'));
expect( expect(emitStmt(
emitStmt(new o.ClassStmt('SomeClass', o.variable('SomeSuperClass'), [], [], null, []))) new o.ClassStmt('SomeClass', o.variable('SomeSuperClass'), [], [], null !, [])))
.toEqual([ .toEqual([
'function SomeClass() {', '}', 'function SomeClass() {', '}',
'SomeClass.prototype = Object.create(SomeSuperClass.prototype);' 'SomeClass.prototype = Object.create(SomeSuperClass.prototype);'
@ -241,23 +242,24 @@ export function main() {
it('should support declaring constructors', () => { it('should support declaring constructors', () => {
const superCall = o.SUPER_EXPR.callFn([o.variable('someParam')]).toStmt(); const superCall = o.SUPER_EXPR.callFn([o.variable('someParam')]).toStmt();
expect(emitStmt( expect(emitStmt(new o.ClassStmt(
new o.ClassStmt('SomeClass', null, [], [], new o.ClassMethod(null, [], []), []))) 'SomeClass', null !, [], [], new o.ClassMethod(null !, [], []), [])))
.toEqual(['function SomeClass() {', '}'].join('\n')); .toEqual(['function SomeClass() {', '}'].join('\n'));
expect(emitStmt(new o.ClassStmt( expect(emitStmt(new o.ClassStmt(
'SomeClass', null, [], [], 'SomeClass', null !, [], [],
new o.ClassMethod(null, [new o.FnParam('someParam')], []), []))) new o.ClassMethod(null !, [new o.FnParam('someParam')], []), [])))
.toEqual(['function SomeClass(someParam) {', '}'].join('\n')); .toEqual(['function SomeClass(someParam) {', '}'].join('\n'));
expect(emitStmt(new o.ClassStmt( expect(emitStmt(new o.ClassStmt(
'SomeClass', o.variable('SomeSuperClass'), [], [], 'SomeClass', o.variable('SomeSuperClass'), [], [],
new o.ClassMethod(null, [], [superCall]), []))) new o.ClassMethod(null !, [], [superCall]), [])))
.toEqual([ .toEqual([
'function SomeClass() {', ' var self = this;', 'function SomeClass() {', ' var self = this;',
' SomeSuperClass.call(this, someParam);', '}', ' SomeSuperClass.call(this, someParam);', '}',
'SomeClass.prototype = Object.create(SomeSuperClass.prototype);' 'SomeClass.prototype = Object.create(SomeSuperClass.prototype);'
].join('\n')); ].join('\n'));
expect(emitStmt(new o.ClassStmt( expect(
'SomeClass', null, [], [], new o.ClassMethod(null, [], [callSomeMethod]), []))) emitStmt(new o.ClassStmt(
'SomeClass', null !, [], [], new o.ClassMethod(null !, [], [callSomeMethod]), [])))
.toEqual([ .toEqual([
'function SomeClass() {', ' var self = this;', ' self.someMethod();', '}' 'function SomeClass() {', ' var self = this;', ' self.someMethod();', '}'
].join('\n')); ].join('\n'));
@ -265,14 +267,14 @@ export function main() {
it('should support declaring getters', () => { it('should support declaring getters', () => {
expect(emitStmt(new o.ClassStmt( expect(emitStmt(new o.ClassStmt(
'SomeClass', null, [], [new o.ClassGetter('someGetter', [])], null, []))) 'SomeClass', null !, [], [new o.ClassGetter('someGetter', [])], null !, [])))
.toEqual([ .toEqual([
'function SomeClass() {', '}', 'function SomeClass() {', '}',
`Object.defineProperty(SomeClass.prototype, 'someGetter', { get: function() {`, `}});` `Object.defineProperty(SomeClass.prototype, 'someGetter', { get: function() {`, `}});`
].join('\n')); ].join('\n'));
expect(emitStmt(new o.ClassStmt( expect(emitStmt(new o.ClassStmt(
'SomeClass', null, [], [new o.ClassGetter('someGetter', [callSomeMethod])], null, 'SomeClass', null !, [], [new o.ClassGetter('someGetter', [callSomeMethod])],
[]))) null !, [])))
.toEqual([ .toEqual([
'function SomeClass() {', '}', 'function SomeClass() {', '}',
`Object.defineProperty(SomeClass.prototype, 'someGetter', { get: function() {`, `Object.defineProperty(SomeClass.prototype, 'someGetter', { get: function() {`,
@ -282,19 +284,19 @@ export function main() {
it('should support methods', () => { it('should support methods', () => {
expect(emitStmt(new o.ClassStmt( expect(emitStmt(new o.ClassStmt(
'SomeClass', null, [], [], null, [new o.ClassMethod('someMethod', [], [])]))) 'SomeClass', null !, [], [], null !, [new o.ClassMethod('someMethod', [], [])])))
.toEqual([ .toEqual([
'function SomeClass() {', '}', 'SomeClass.prototype.someMethod = function() {', '};' 'function SomeClass() {', '}', 'SomeClass.prototype.someMethod = function() {', '};'
].join('\n')); ].join('\n'));
expect(emitStmt(new o.ClassStmt( expect(emitStmt(new o.ClassStmt(
'SomeClass', null, [], [], null, 'SomeClass', null !, [], [], null !,
[new o.ClassMethod('someMethod', [new o.FnParam('someParam')], [])]))) [new o.ClassMethod('someMethod', [new o.FnParam('someParam')], [])])))
.toEqual([ .toEqual([
'function SomeClass() {', '}', 'function SomeClass() {', '}',
'SomeClass.prototype.someMethod = function(someParam) {', '};' 'SomeClass.prototype.someMethod = function(someParam) {', '};'
].join('\n')); ].join('\n'));
expect(emitStmt(new o.ClassStmt( expect(emitStmt(new o.ClassStmt(
'SomeClass', null, [], [], null, 'SomeClass', null !, [], [], null !,
[new o.ClassMethod('someMethod', [], [callSomeMethod])]))) [new o.ClassMethod('someMethod', [], [callSomeMethod])])))
.toEqual([ .toEqual([
'function SomeClass() {', '}', 'SomeClass.prototype.someMethod = function() {', 'function SomeClass() {', '}', 'SomeClass.prototype.someMethod = function() {',

View File

@ -52,7 +52,7 @@ export function main() {
.addMapping(3, 'a.js', 5, 2); .addMapping(3, 'a.js', 5, 2);
// Generated with https://sokra.github.io/source-map-visualization using a TS source map // Generated with https://sokra.github.io/source-map-visualization using a TS source map
expect(map.toJSON().mappings) expect(map.toJSON() !.mappings)
.toEqual( .toEqual(
'AAAA,IAAM,CAAC,GAAe,CAAC,CAAC;AACxB,IAAM,CAAC,GAAG,CAAC,CAAC;AAEZ,EAAE,CAAC,OAAO,CAAC,UAAA,CAAC;IACR,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC,CAAC,CAAA'); 'AAAA,IAAM,CAAC,GAAe,CAAC,CAAC;AACxB,IAAM,CAAC,GAAG,CAAC,CAAC;AAEZ,EAAE,CAAC,OAAO,CAAC,UAAA,CAAC;IACR,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC,CAAC,CAAA');
}); });
@ -64,7 +64,7 @@ export function main() {
.addSource('url.ts', null) .addSource('url.ts', null)
.addLine() .addLine()
.addMapping(0, 'inline.ts', 0, 0) .addMapping(0, 'inline.ts', 0, 0)
.toJSON(); .toJSON() !;
expect(map.file).toEqual('out.js'); expect(map.file).toEqual('out.js');
expect(map.sources).toEqual(['inline.ts', 'url.ts']); expect(map.sources).toEqual(['inline.ts', 'url.ts']);
@ -113,7 +113,7 @@ export function main() {
it('should throw when adding segments without column', () => { it('should throw when adding segments without column', () => {
expect(() => { expect(() => {
new SourceMapGenerator('out.js').addSource('in.js').addLine().addMapping(null); new SourceMapGenerator('out.js').addSource('in.js').addLine().addMapping(null !);
}).toThrowError('The column in the generated code must be provided'); }).toThrowError('The column in the generated code must be provided');
}); });

View File

@ -17,7 +17,8 @@ export interface SourceLocation {
} }
export function originalPositionFor( export function originalPositionFor(
sourceMap: SourceMap, genPosition: {line: number, column: number}): SourceLocation { sourceMap: SourceMap,
genPosition: {line: number | null, column: number | null}): SourceLocation {
const smc = new SourceMapConsumer(sourceMap); const smc = new SourceMapConsumer(sourceMap);
// Note: We don't return the original object as it also contains a `name` property // Note: We don't return the original object as it also contains a `name` property
// which is always null and we don't want to include that in our assertions... // which is always null and we don't want to include that in our assertions...
@ -25,7 +26,7 @@ export function originalPositionFor(
return {line, column, source}; return {line, column, source};
} }
export function extractSourceMap(source: string): SourceMap { export function extractSourceMap(source: string): SourceMap|null {
let idx = source.lastIndexOf('\n//#'); let idx = source.lastIndexOf('\n//#');
if (idx == -1) return null; if (idx == -1) return null;
const smComment = source.slice(idx).trim(); const smComment = source.slice(idx).trim();

View File

@ -23,8 +23,8 @@ class SimpleJsImportGenerator implements ImportResolver {
fileNameToModuleName(importedUrlStr: string, moduleUrlStr: string): string { fileNameToModuleName(importedUrlStr: string, moduleUrlStr: string): string {
return importedUrlStr; return importedUrlStr;
} }
getImportAs(symbol: StaticSymbol): StaticSymbol { return null; } getImportAs(symbol: StaticSymbol): StaticSymbol|null { return null; }
getTypeArity(symbol: StaticSymbol): number /*|null*/ { return null; } getTypeArity(symbol: StaticSymbol): number|null { return null; }
} }
export function main() { export function main() {
@ -44,12 +44,12 @@ export function main() {
}); });
function emitSourceMap( function emitSourceMap(
stmt: o.Statement | o.Statement[], exportedVars: string[] = null, stmt: o.Statement | o.Statement[], exportedVars: string[] | null = null,
preamble?: string): SourceMap { preamble?: string): SourceMap {
const stmts = Array.isArray(stmt) ? stmt : [stmt]; const stmts = Array.isArray(stmt) ? stmt : [stmt];
const source = emitter.emitStatements( const source = emitter.emitStatements(
someSourceFilePath, someGenFilePath, stmts, exportedVars || [], preamble); someSourceFilePath, someGenFilePath, stmts, exportedVars || [], preamble);
return extractSourceMap(source); return extractSourceMap(source) !;
} }
describe('source maps', () => { describe('source maps', () => {

View File

@ -30,8 +30,8 @@ class SimpleJsImportGenerator implements ImportResolver {
fileNameToModuleName(importedUrlStr: string, moduleUrlStr: string): string { fileNameToModuleName(importedUrlStr: string, moduleUrlStr: string): string {
return importedUrlStr; return importedUrlStr;
} }
getImportAs(symbol: StaticSymbol): StaticSymbol { return null; } getImportAs(symbol: StaticSymbol): StaticSymbol|null { return null; }
getTypeArity(symbol: StaticSymbol): number /*|null*/ { return null; } getTypeArity(symbol: StaticSymbol): number|null { return null; }
} }
export function main() { export function main() {
@ -47,11 +47,11 @@ export function main() {
beforeEach(() => { beforeEach(() => {
importResolver = new SimpleJsImportGenerator(); importResolver = new SimpleJsImportGenerator();
emitter = new TypeScriptEmitter(importResolver); emitter = new TypeScriptEmitter(importResolver);
someVar = o.variable('someVar'); someVar = o.variable('someVar', null, null);
}); });
function emitStmt( function emitStmt(
stmt: o.Statement | o.Statement[], exportedVars: string[] = null, stmt: o.Statement | o.Statement[], exportedVars: string[] | null = null,
preamble?: string): string { preamble?: string): string {
const stmts = Array.isArray(stmt) ? stmt : [stmt]; const stmts = Array.isArray(stmt) ? stmt : [stmt];
const source = emitter.emitStatements( const source = emitter.emitStatements(
@ -310,31 +310,32 @@ export function main() {
it('should support declaring classes', () => { it('should support declaring classes', () => {
expect(emitStmt(new o.ClassStmt('SomeClass', null, [], [], null, [ expect(emitStmt(new o.ClassStmt('SomeClass', null !, [], [], null !, [
]))).toEqual(['class SomeClass {', '}'].join('\n')); ]))).toEqual(['class SomeClass {', '}'].join('\n'));
expect(emitStmt(new o.ClassStmt('SomeClass', null, [], [], null, []), ['SomeClass'])) expect(emitStmt(new o.ClassStmt('SomeClass', null !, [], [], null !, []), ['SomeClass']))
.toEqual(['export class SomeClass {', '}'].join('\n')); .toEqual(['export class SomeClass {', '}'].join('\n'));
expect(emitStmt(new o.ClassStmt('SomeClass', o.variable('SomeSuperClass'), [], [], null, [ expect(emitStmt(new o.ClassStmt('SomeClass', o.variable('SomeSuperClass'), [], [], null !, [
]))).toEqual(['class SomeClass extends SomeSuperClass {', '}'].join('\n')); ]))).toEqual(['class SomeClass extends SomeSuperClass {', '}'].join('\n'));
}); });
it('should support declaring constructors', () => { it('should support declaring constructors', () => {
const superCall = o.SUPER_EXPR.callFn([o.variable('someParam')]).toStmt(); const superCall = o.SUPER_EXPR.callFn([o.variable('someParam')]).toStmt();
expect(emitStmt( expect(emitStmt(new o.ClassStmt(
new o.ClassStmt('SomeClass', null, [], [], new o.ClassMethod(null, [], []), []))) 'SomeClass', null !, [], [], new o.ClassMethod(null !, [], []), [])))
.toEqual(['class SomeClass {', ' constructor() {', ' }', '}'].join('\n')); .toEqual(['class SomeClass {', ' constructor() {', ' }', '}'].join('\n'));
expect(emitStmt(new o.ClassStmt( expect(emitStmt(new o.ClassStmt(
'SomeClass', null, [], [], 'SomeClass', null !, [], [],
new o.ClassMethod(null, [new o.FnParam('someParam', o.INT_TYPE)], []), []))) new o.ClassMethod(null !, [new o.FnParam('someParam', o.INT_TYPE)], []), [])))
.toEqual( .toEqual(
['class SomeClass {', ' constructor(someParam:number) {', ' }', '}'].join('\n')); ['class SomeClass {', ' constructor(someParam:number) {', ' }', '}'].join('\n'));
expect(emitStmt(new o.ClassStmt( expect(emitStmt(new o.ClassStmt(
'SomeClass', null, [], [], new o.ClassMethod(null, [], [superCall]), []))) 'SomeClass', null !, [], [], new o.ClassMethod(null !, [], [superCall]), [])))
.toEqual([ .toEqual([
'class SomeClass {', ' constructor() {', ' super(someParam);', ' }', '}' 'class SomeClass {', ' constructor() {', ' super(someParam);', ' }', '}'
].join('\n')); ].join('\n'));
expect(emitStmt(new o.ClassStmt( expect(
'SomeClass', null, [], [], new o.ClassMethod(null, [], [callSomeMethod]), []))) emitStmt(new o.ClassStmt(
'SomeClass', null !, [], [], new o.ClassMethod(null !, [], [callSomeMethod]), [])))
.toEqual([ .toEqual([
'class SomeClass {', ' constructor() {', ' this.someMethod();', ' }', '}' 'class SomeClass {', ' constructor() {', ' this.someMethod();', ' }', '}'
].join('\n')); ].join('\n'));
@ -342,56 +343,57 @@ export function main() {
it('should support declaring fields', () => { it('should support declaring fields', () => {
expect(emitStmt(new o.ClassStmt( expect(emitStmt(new o.ClassStmt(
'SomeClass', null, [new o.ClassField('someField')], [], null, []))) 'SomeClass', null !, [new o.ClassField('someField')], [], null !, [])))
.toEqual(['class SomeClass {', ' someField:any;', '}'].join('\n')); .toEqual(['class SomeClass {', ' someField:any;', '}'].join('\n'));
expect(emitStmt(new o.ClassStmt( expect(
'SomeClass', null, [new o.ClassField('someField', o.INT_TYPE)], [], null, []))) emitStmt(new o.ClassStmt(
'SomeClass', null !, [new o.ClassField('someField', o.INT_TYPE)], [], null !, [])))
.toEqual(['class SomeClass {', ' someField:number;', '}'].join('\n')); .toEqual(['class SomeClass {', ' someField:number;', '}'].join('\n'));
expect(emitStmt(new o.ClassStmt( expect(emitStmt(new o.ClassStmt(
'SomeClass', null, 'SomeClass', null !,
[new o.ClassField('someField', o.INT_TYPE, [o.StmtModifier.Private])], [], null, [new o.ClassField('someField', o.INT_TYPE, [o.StmtModifier.Private])], [],
[]))) null !, [])))
.toEqual(['class SomeClass {', ' /*private*/ someField:number;', '}'].join('\n')); .toEqual(['class SomeClass {', ' /*private*/ someField:number;', '}'].join('\n'));
}); });
it('should support declaring getters', () => { it('should support declaring getters', () => {
expect(emitStmt(new o.ClassStmt( expect(emitStmt(new o.ClassStmt(
'SomeClass', null, [], [new o.ClassGetter('someGetter', [])], null, []))) 'SomeClass', null !, [], [new o.ClassGetter('someGetter', [])], null !, [])))
.toEqual(['class SomeClass {', ' get someGetter():any {', ' }', '}'].join('\n')); .toEqual(['class SomeClass {', ' get someGetter():any {', ' }', '}'].join('\n'));
expect(emitStmt(new o.ClassStmt( expect(emitStmt(new o.ClassStmt(
'SomeClass', null, [], [new o.ClassGetter('someGetter', [], o.INT_TYPE)], null, 'SomeClass', null !, [], [new o.ClassGetter('someGetter', [], o.INT_TYPE)],
[]))) null !, [])))
.toEqual(['class SomeClass {', ' get someGetter():number {', ' }', '}'].join('\n')); .toEqual(['class SomeClass {', ' get someGetter():number {', ' }', '}'].join('\n'));
expect(emitStmt(new o.ClassStmt( expect(emitStmt(new o.ClassStmt(
'SomeClass', null, [], [new o.ClassGetter('someGetter', [callSomeMethod])], null, 'SomeClass', null !, [], [new o.ClassGetter('someGetter', [callSomeMethod])],
[]))) null !, [])))
.toEqual([ .toEqual([
'class SomeClass {', ' get someGetter():any {', ' this.someMethod();', ' }', '}' 'class SomeClass {', ' get someGetter():any {', ' this.someMethod();', ' }', '}'
].join('\n')); ].join('\n'));
expect( expect(emitStmt(new o.ClassStmt(
emitStmt(new o.ClassStmt( 'SomeClass', null !, [],
'SomeClass', null, [], [new o.ClassGetter('someGetter', [], null !, [o.StmtModifier.Private])], null !,
[new o.ClassGetter('someGetter', [], null, [o.StmtModifier.Private])], null, []))) [])))
.toEqual( .toEqual(
['class SomeClass {', ' private get someGetter():any {', ' }', '}'].join('\n')); ['class SomeClass {', ' private get someGetter():any {', ' }', '}'].join('\n'));
}); });
it('should support methods', () => { it('should support methods', () => {
expect(emitStmt(new o.ClassStmt('SomeClass', null, [], [], null, [ expect(emitStmt(new o.ClassStmt('SomeClass', null !, [], [], null !, [
new o.ClassMethod('someMethod', [], []) new o.ClassMethod('someMethod', [], [])
]))).toEqual(['class SomeClass {', ' someMethod():void {', ' }', '}'].join('\n')); ]))).toEqual(['class SomeClass {', ' someMethod():void {', ' }', '}'].join('\n'));
expect(emitStmt(new o.ClassStmt('SomeClass', null, [], [], null, [ expect(emitStmt(new o.ClassStmt('SomeClass', null !, [], [], null !, [
new o.ClassMethod('someMethod', [], [], o.INT_TYPE) new o.ClassMethod('someMethod', [], [], o.INT_TYPE)
]))).toEqual(['class SomeClass {', ' someMethod():number {', ' }', '}'].join('\n')); ]))).toEqual(['class SomeClass {', ' someMethod():number {', ' }', '}'].join('\n'));
expect( expect(
emitStmt(new o.ClassStmt( emitStmt(new o.ClassStmt(
'SomeClass', null, [], [], null, 'SomeClass', null !, [], [], null !,
[new o.ClassMethod('someMethod', [new o.FnParam('someParam', o.INT_TYPE)], [])]))) [new o.ClassMethod('someMethod', [new o.FnParam('someParam', o.INT_TYPE)], [])])))
.toEqual([ .toEqual([
'class SomeClass {', ' someMethod(someParam:number):void {', ' }', '}' 'class SomeClass {', ' someMethod(someParam:number):void {', ' }', '}'
].join('\n')); ].join('\n'));
expect(emitStmt(new o.ClassStmt( expect(emitStmt(new o.ClassStmt(
'SomeClass', null, [], [], null, 'SomeClass', null !, [], [], null !,
[new o.ClassMethod('someMethod', [], [callSomeMethod])]))) [new o.ClassMethod('someMethod', [], [callSomeMethod])])))
.toEqual([ .toEqual([
'class SomeClass {', ' someMethod():void {', ' this.someMethod();', ' }', '}' 'class SomeClass {', ' someMethod():void {', ' this.someMethod();', ' }', '}'
@ -453,7 +455,7 @@ export function main() {
it('should support combined types', () => { it('should support combined types', () => {
const writeVarExpr = o.variable('a').set(o.NULL_EXPR); const writeVarExpr = o.variable('a').set(o.NULL_EXPR);
expect(emitStmt(writeVarExpr.toDeclStmt(new o.ArrayType(null)))) expect(emitStmt(writeVarExpr.toDeclStmt(new o.ArrayType(null !))))
.toEqual('var a:any[] = (null as any);'); .toEqual('var a:any[] = (null as any);');
expect(emitStmt(writeVarExpr.toDeclStmt(new o.ArrayType(o.INT_TYPE)))) expect(emitStmt(writeVarExpr.toDeclStmt(new o.ArrayType(o.INT_TYPE))))
.toEqual('var a:number[] = (null as any);'); .toEqual('var a:number[] = (null as any);');

Some files were not shown because too many files have changed in this diff Show More