fix(compiler): Update types for TypeScript nullability support
This commit is contained in:
@ -64,7 +64,7 @@ export class BindingParser {
|
||||
|
||||
createDirectiveHostPropertyAsts(
|
||||
dirMeta: CompileDirectiveSummary, elementSelector: string,
|
||||
sourceSpan: ParseSourceSpan): BoundElementPropertyAst[] {
|
||||
sourceSpan: ParseSourceSpan): BoundElementPropertyAst[]|null {
|
||||
if (dirMeta.hostProperties) {
|
||||
const boundProps: BoundProperty[] = [];
|
||||
Object.keys(dirMeta.hostProperties).forEach(propName => {
|
||||
@ -79,10 +79,11 @@ export class BindingParser {
|
||||
});
|
||||
return boundProps.map((prop) => this.createElementPropertyAst(elementSelector, prop));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
createDirectiveHostEventAsts(dirMeta: CompileDirectiveSummary, sourceSpan: ParseSourceSpan):
|
||||
BoundEventAst[] {
|
||||
BoundEventAst[]|null {
|
||||
if (dirMeta.hostListeners) {
|
||||
const targetEventAsts: BoundEventAst[] = [];
|
||||
Object.keys(dirMeta.hostListeners).forEach(propName => {
|
||||
@ -97,13 +98,15 @@ export class BindingParser {
|
||||
});
|
||||
return targetEventAsts;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
parseInterpolation(value: string, sourceSpan: ParseSourceSpan): ASTWithSource {
|
||||
const sourceInfo = sourceSpan.start.toString();
|
||||
|
||||
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);
|
||||
this._checkPipes(ast, sourceSpan);
|
||||
return ast;
|
||||
@ -153,8 +156,8 @@ export class BindingParser {
|
||||
}
|
||||
|
||||
parseLiteralAttr(
|
||||
name: string, value: string, sourceSpan: ParseSourceSpan, targetMatchableAttrs: string[][],
|
||||
targetProps: BoundProperty[]) {
|
||||
name: string, value: string|null, sourceSpan: ParseSourceSpan,
|
||||
targetMatchableAttrs: string[][], targetProps: BoundProperty[]) {
|
||||
if (_isAnimationLabel(name)) {
|
||||
name = name.substring(1);
|
||||
if (value) {
|
||||
@ -206,18 +209,18 @@ export class BindingParser {
|
||||
private _parsePropertyAst(
|
||||
name: string, ast: ASTWithSource, sourceSpan: ParseSourceSpan,
|
||||
targetMatchableAttrs: string[][], targetProps: BoundProperty[]) {
|
||||
targetMatchableAttrs.push([name, ast.source]);
|
||||
targetMatchableAttrs.push([name, ast.source !]);
|
||||
targetProps.push(new BoundProperty(name, ast, BoundPropertyType.DEFAULT, sourceSpan));
|
||||
}
|
||||
|
||||
private _parseAnimation(
|
||||
name: string, expression: string, sourceSpan: ParseSourceSpan,
|
||||
name: string, expression: string|null, sourceSpan: ParseSourceSpan,
|
||||
targetMatchableAttrs: string[][], targetProps: BoundProperty[]) {
|
||||
// This will occur when a @trigger is not paired with an expression.
|
||||
// For animations it is valid to not have an expression since */void
|
||||
// states will be applied by angular when the element is attached/detached
|
||||
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));
|
||||
}
|
||||
|
||||
@ -246,11 +249,11 @@ export class BindingParser {
|
||||
null, boundProp.sourceSpan);
|
||||
}
|
||||
|
||||
let unit: string = null;
|
||||
let bindingType: PropertyBindingType;
|
||||
let boundPropertyName: string = null;
|
||||
let unit: string|null = null;
|
||||
let bindingType: PropertyBindingType = undefined !;
|
||||
let boundPropertyName: string|null = null;
|
||||
const parts = boundProp.name.split(PROPERTY_PARTS_SEPARATOR);
|
||||
let securityContexts: SecurityContext[];
|
||||
let securityContexts: SecurityContext[] = undefined !;
|
||||
|
||||
// Check check for special cases (prefix style, attr, class)
|
||||
if (parts.length > 1) {
|
||||
@ -336,9 +339,9 @@ export class BindingParser {
|
||||
name: string, expression: string, sourceSpan: ParseSourceSpan,
|
||||
targetMatchableAttrs: string[][], targetEvents: BoundEventAst[]) {
|
||||
// long format: 'target: eventName'
|
||||
const [target, eventName] = splitAtColon(name, [null, name]);
|
||||
const [target, eventName] = splitAtColon(name, [null !, name]);
|
||||
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));
|
||||
// Don't detect directives for event names for now,
|
||||
// so don't add the event name to the matchableAttrs
|
||||
@ -405,7 +408,7 @@ export class BindingParser {
|
||||
const report = isAttr ? this._schemaRegistry.validateAttribute(propName) :
|
||||
this._schemaRegistry.validateProperty(propName);
|
||||
if (report.error) {
|
||||
this._reportError(report.msg, sourceSpan, ParseErrorLevel.ERROR);
|
||||
this._reportError(report.msg !, sourceSpan, ParseErrorLevel.ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ export interface TemplateAst {
|
||||
/**
|
||||
* The source span from which this node was parsed.
|
||||
*/
|
||||
sourceSpan: ParseSourceSpan;
|
||||
sourceSpan: ParseSourceSpan|null;
|
||||
|
||||
/**
|
||||
* Visit this node and possibly transform it.
|
||||
@ -62,7 +62,7 @@ export class AttrAst implements TemplateAst {
|
||||
export class BoundElementPropertyAst implements TemplateAst {
|
||||
constructor(
|
||||
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) {}
|
||||
visit(visitor: TemplateAstVisitor, context: any): any {
|
||||
return visitor.visitElementProperty(this, context);
|
||||
@ -75,7 +75,7 @@ export class BoundElementPropertyAst implements TemplateAst {
|
||||
* `(@trigger.phase)="callback($event)"`).
|
||||
*/
|
||||
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) {
|
||||
return `${target}:${name}`;
|
||||
} else if (phase) {
|
||||
@ -86,8 +86,8 @@ export class BoundEventAst implements TemplateAst {
|
||||
}
|
||||
|
||||
constructor(
|
||||
public name: string, public target: string, public phase: string, public handler: AST,
|
||||
public sourceSpan: ParseSourceSpan) {}
|
||||
public name: string, public target: string|null, public phase: string|null,
|
||||
public handler: AST, public sourceSpan: ParseSourceSpan) {}
|
||||
visit(visitor: TemplateAstVisitor, context: any): any {
|
||||
return visitor.visitEvent(this, context);
|
||||
}
|
||||
@ -126,8 +126,8 @@ export class ElementAst implements TemplateAst {
|
||||
public outputs: BoundEventAst[], public references: ReferenceAst[],
|
||||
public directives: DirectiveAst[], public providers: ProviderAst[],
|
||||
public hasViewContainer: boolean, public queryMatches: QueryMatch[],
|
||||
public children: TemplateAst[], public ngContentIndex: number,
|
||||
public sourceSpan: ParseSourceSpan, public endSourceSpan: ParseSourceSpan) {}
|
||||
public children: TemplateAst[], public ngContentIndex: number|null,
|
||||
public sourceSpan: ParseSourceSpan|null, public endSourceSpan: ParseSourceSpan|null) {}
|
||||
|
||||
visit(visitor: TemplateAstVisitor, context: any): any {
|
||||
return visitor.visitElement(this, context);
|
||||
@ -275,7 +275,7 @@ export function templateVisitAll(
|
||||
visitor: TemplateAstVisitor, asts: TemplateAst[], context: any = null): any[] {
|
||||
const result: any[] = [];
|
||||
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);
|
||||
asts.forEach(ast => {
|
||||
const astResult = visit(ast);
|
||||
|
@ -115,11 +115,11 @@ export class TemplateParser {
|
||||
templateUrl: string): {template: TemplateAst[], pipes: CompilePipeSummary[]} {
|
||||
const result = this.tryParse(component, template, directives, pipes, schemas, templateUrl);
|
||||
const warnings =
|
||||
result.errors.filter(error => error.level === ParseErrorLevel.WARNING).filter(warnOnlyOnce([
|
||||
TEMPLATE_ATTR_DEPRECATION_WARNING, TEMPLATE_ELEMENT_DEPRECATION_WARNING
|
||||
]));
|
||||
result.errors !.filter(error => error.level === ParseErrorLevel.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) {
|
||||
this._console.warn(`Template parse warnings:\n${warnings.join('\n')}`);
|
||||
@ -130,7 +130,7 @@ export class TemplateParser {
|
||||
throw syntaxError(`Template parse errors:\n${errorString}`);
|
||||
}
|
||||
|
||||
return {template: result.templateAst, pipes: result.usedPipes};
|
||||
return {template: result.templateAst !, pipes: result.usedPipes !};
|
||||
}
|
||||
|
||||
tryParse(
|
||||
@ -138,7 +138,7 @@ export class TemplateParser {
|
||||
pipes: CompilePipeSummary[], schemas: SchemaMetadata[],
|
||||
templateUrl: string): TemplateParseResult {
|
||||
return this.tryParseHtml(
|
||||
this.expandHtml(this._htmlParser.parse(
|
||||
this.expandHtml(this._htmlParser !.parse(
|
||||
template, templateUrl, true, this.getInterpolationConfig(component))),
|
||||
component, template, directives, pipes, schemas, templateUrl);
|
||||
}
|
||||
@ -154,7 +154,7 @@ export class TemplateParser {
|
||||
const uniqDirectives = removeSummaryDuplicates(directives);
|
||||
const uniqPipes = removeSummaryDuplicates(pipes);
|
||||
const providerViewContext = new ProviderViewContext(component);
|
||||
let interpolationConfig: InterpolationConfig;
|
||||
let interpolationConfig: InterpolationConfig = undefined !;
|
||||
if (component.template && component.template.interpolation) {
|
||||
interpolationConfig = {
|
||||
start: component.template.interpolation[0],
|
||||
@ -162,7 +162,7 @@ export class TemplateParser {
|
||||
};
|
||||
}
|
||||
const bindingParser = new BindingParser(
|
||||
this._exprParser, interpolationConfig, this._schemaRegistry, uniqPipes, errors);
|
||||
this._exprParser, interpolationConfig !, this._schemaRegistry, uniqPipes, errors);
|
||||
const parseVisitor = new TemplateParseVisitor(
|
||||
this._config, providerViewContext, uniqDirectives, bindingParser, this._schemaRegistry,
|
||||
schemas, errors);
|
||||
@ -198,10 +198,11 @@ export class TemplateParser {
|
||||
return htmlAstWithErrors;
|
||||
}
|
||||
|
||||
getInterpolationConfig(component: CompileDirectiveMetadata): InterpolationConfig {
|
||||
getInterpolationConfig(component: CompileDirectiveMetadata): InterpolationConfig|undefined {
|
||||
if (component.template) {
|
||||
return InterpolationConfig.fromArray(component.template.interpolation);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/** @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!
|
||||
this.contentQueryStartId = providerViewContext.component.viewQueries.length + 1;
|
||||
directives.forEach((directive, index) => {
|
||||
const selector = CssSelector.parse(directive.selector);
|
||||
const selector = CssSelector.parse(directive.selector !);
|
||||
this.selectorMatcher.addSelectables(selector, directive);
|
||||
this.directivesIndex.set(directive, index);
|
||||
});
|
||||
@ -249,10 +250,10 @@ class TemplateParseVisitor implements html.Visitor {
|
||||
visitExpansionCase(expansionCase: html.ExpansionCase, context: any): any { return null; }
|
||||
|
||||
visitText(text: html.Text, parent: ElementContext): any {
|
||||
const ngContentIndex = parent.findNgContentIndex(TEXT_CSS_SELECTOR);
|
||||
const expr = this._bindingParser.parseInterpolation(text.value, text.sourceSpan);
|
||||
return expr ? new BoundTextAst(expr, ngContentIndex, text.sourceSpan) :
|
||||
new TextAst(text.value, ngContentIndex, text.sourceSpan);
|
||||
const ngContentIndex = parent.findNgContentIndex(TEXT_CSS_SELECTOR) !;
|
||||
const expr = this._bindingParser.parseInterpolation(text.value, text.sourceSpan !);
|
||||
return expr ? new BoundTextAst(expr, ngContentIndex, text.sourceSpan !) :
|
||||
new TextAst(text.value, ngContentIndex, text.sourceSpan !);
|
||||
}
|
||||
|
||||
visitAttribute(attribute: html.Attribute, context: any): any {
|
||||
@ -322,7 +323,7 @@ class TemplateParseVisitor implements html.Visitor {
|
||||
}
|
||||
hasInlineTemplates = true;
|
||||
this._bindingParser.parseInlineTemplateBinding(
|
||||
prefixToken, templateBindingsSource, attr.sourceSpan, templateMatchableAttrs,
|
||||
prefixToken !, templateBindingsSource !, attr.sourceSpan, templateMatchableAttrs,
|
||||
templateElementOrDirectiveProps, templateElementVars);
|
||||
}
|
||||
|
||||
@ -340,48 +341,49 @@ class TemplateParseVisitor implements html.Visitor {
|
||||
const boundDirectivePropNames = new Set<string>();
|
||||
const directiveAsts = this._createDirectiveAsts(
|
||||
isTemplateElement, element.name, directiveMetas, elementOrDirectiveProps,
|
||||
elementOrDirectiveRefs, element.sourceSpan, references, boundDirectivePropNames);
|
||||
elementOrDirectiveRefs, element.sourceSpan !, references, boundDirectivePropNames);
|
||||
const elementProps: BoundElementPropertyAst[] = this._createElementPropertyAsts(
|
||||
element.name, elementOrDirectiveProps, boundDirectivePropNames);
|
||||
const isViewRoot = parent.isTemplateElement || hasInlineTemplates;
|
||||
|
||||
const providerContext = new ProviderElementContext(
|
||||
this.providerViewContext, parent.providerContext, isViewRoot, directiveAsts, attrs,
|
||||
references, isTemplateElement, queryStartIndex, element.sourceSpan);
|
||||
this.providerViewContext, parent.providerContext !, isViewRoot, directiveAsts, attrs,
|
||||
references, isTemplateElement, queryStartIndex, element.sourceSpan !);
|
||||
|
||||
const children: TemplateAst[] = html.visitAll(
|
||||
preparsedElement.nonBindable ? NON_BINDABLE_VISITOR : this, element.children,
|
||||
ElementContext.create(
|
||||
isTemplateElement, directiveAsts,
|
||||
isTemplateElement ? parent.providerContext : providerContext));
|
||||
isTemplateElement ? parent.providerContext ! : providerContext));
|
||||
providerContext.afterElement();
|
||||
// Override the actual selector when the `ngProjectAs` attribute is provided
|
||||
const projectionSelector = preparsedElement.projectAs != null ?
|
||||
CssSelector.parse(preparsedElement.projectAs)[0] :
|
||||
elementCssSelector;
|
||||
const ngContentIndex = parent.findNgContentIndex(projectionSelector);
|
||||
const ngContentIndex = parent.findNgContentIndex(projectionSelector) !;
|
||||
let parsedElement: TemplateAst;
|
||||
|
||||
if (preparsedElement.type === PreparsedElementType.NG_CONTENT) {
|
||||
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(
|
||||
this.ngContentCount++, hasInlineTemplates ? null : ngContentIndex, element.sourceSpan);
|
||||
this.ngContentCount++, hasInlineTemplates ? null ! : ngContentIndex,
|
||||
element.sourceSpan !);
|
||||
} else if (isTemplateElement) {
|
||||
this._assertAllEventsPublishedByDirectives(directiveAsts, events);
|
||||
this._assertNoComponentsNorElementBindingsOnTemplate(
|
||||
directiveAsts, elementProps, element.sourceSpan);
|
||||
directiveAsts, elementProps, element.sourceSpan !);
|
||||
|
||||
parsedElement = new EmbeddedTemplateAst(
|
||||
attrs, events, references, elementVars, providerContext.transformedDirectiveAsts,
|
||||
providerContext.transformProviders, providerContext.transformedHasViewContainer,
|
||||
providerContext.queryMatches, children, hasInlineTemplates ? null : ngContentIndex,
|
||||
element.sourceSpan);
|
||||
providerContext.queryMatches, children, hasInlineTemplates ? null ! : ngContentIndex,
|
||||
element.sourceSpan !);
|
||||
} else {
|
||||
this._assertElementExists(matchElement, element);
|
||||
this._assertOnlyOneComponent(directiveAsts, element.sourceSpan);
|
||||
this._assertOnlyOneComponent(directiveAsts, element.sourceSpan !);
|
||||
|
||||
const ngContentIndex =
|
||||
hasInlineTemplates ? null : parent.findNgContentIndex(projectionSelector);
|
||||
@ -389,7 +391,8 @@ class TemplateParseVisitor implements html.Visitor {
|
||||
nodeName, attrs, elementProps, events, references,
|
||||
providerContext.transformedDirectiveAsts, providerContext.transformProviders,
|
||||
providerContext.transformedHasViewContainer, providerContext.queryMatches, children,
|
||||
hasInlineTemplates ? null : ngContentIndex, element.sourceSpan, element.endSourceSpan);
|
||||
hasInlineTemplates ? null : ngContentIndex, element.sourceSpan || null,
|
||||
element.endSourceSpan || null);
|
||||
}
|
||||
|
||||
if (hasInlineTemplates) {
|
||||
@ -400,21 +403,21 @@ class TemplateParseVisitor implements html.Visitor {
|
||||
const templateBoundDirectivePropNames = new Set<string>();
|
||||
const templateDirectiveAsts = this._createDirectiveAsts(
|
||||
true, element.name, templateDirectiveMetas, templateElementOrDirectiveProps, [],
|
||||
element.sourceSpan, [], templateBoundDirectivePropNames);
|
||||
element.sourceSpan !, [], templateBoundDirectivePropNames);
|
||||
const templateElementProps: BoundElementPropertyAst[] = this._createElementPropertyAsts(
|
||||
element.name, templateElementOrDirectiveProps, templateBoundDirectivePropNames);
|
||||
this._assertNoComponentsNorElementBindingsOnTemplate(
|
||||
templateDirectiveAsts, templateElementProps, element.sourceSpan);
|
||||
templateDirectiveAsts, templateElementProps, element.sourceSpan !);
|
||||
const templateProviderContext = new ProviderElementContext(
|
||||
this.providerViewContext, parent.providerContext, parent.isTemplateElement,
|
||||
templateDirectiveAsts, [], [], true, templateQueryStartIndex, element.sourceSpan);
|
||||
this.providerViewContext, parent.providerContext !, parent.isTemplateElement,
|
||||
templateDirectiveAsts, [], [], true, templateQueryStartIndex, element.sourceSpan !);
|
||||
templateProviderContext.afterElement();
|
||||
|
||||
parsedElement = new EmbeddedTemplateAst(
|
||||
[], [], [], templateElementVars, templateProviderContext.transformedDirectiveAsts,
|
||||
templateProviderContext.transformProviders,
|
||||
templateProviderContext.transformedHasViewContainer, templateProviderContext.queryMatches,
|
||||
[parsedElement], ngContentIndex, element.sourceSpan);
|
||||
[parsedElement], ngContentIndex, element.sourceSpan !);
|
||||
}
|
||||
|
||||
return parsedElement;
|
||||
@ -531,7 +534,7 @@ class TemplateParseVisitor implements html.Visitor {
|
||||
let matchElement = false;
|
||||
|
||||
selectorMatcher.match(elementCssSelector, (selector, directive) => {
|
||||
directives[this.directivesIndex.get(directive)] = directive;
|
||||
directives[this.directivesIndex.get(directive) !] = directive;
|
||||
matchElement = matchElement || selector.hasElementSelector();
|
||||
});
|
||||
|
||||
@ -547,7 +550,7 @@ class TemplateParseVisitor implements html.Visitor {
|
||||
elementSourceSpan: ParseSourceSpan, targetReferences: ReferenceAst[],
|
||||
targetBoundDirectivePropNames: Set<string>): DirectiveAst[] {
|
||||
const matchedReferences = new Set<string>();
|
||||
let component: CompileDirectiveSummary = null;
|
||||
let component: CompileDirectiveSummary = null !;
|
||||
|
||||
const directiveAsts = directives.map((directive) => {
|
||||
const sourceSpan = new ParseSourceSpan(
|
||||
@ -559,11 +562,11 @@ class TemplateParseVisitor implements html.Visitor {
|
||||
}
|
||||
const directiveProperties: BoundDirectivePropertyAst[] = [];
|
||||
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,
|
||||
// as we don't know the element name in the DirectiveWrapperCompiler yet.
|
||||
hostProperties = this._checkPropertiesInSchema(elementName, hostProperties);
|
||||
const hostEvents = this._bindingParser.createDirectiveHostEventAsts(directive, sourceSpan);
|
||||
const hostEvents = this._bindingParser.createDirectiveHostEventAsts(directive, sourceSpan) !;
|
||||
this._createDirectivePropertyAsts(
|
||||
directive.inputs, props, directiveProperties, targetBoundDirectivePropNames);
|
||||
elementOrDirectiveRefs.forEach((elOrDirRef) => {
|
||||
@ -589,7 +592,7 @@ class TemplateParseVisitor implements html.Visitor {
|
||||
elOrDirRef.sourceSpan);
|
||||
}
|
||||
} else if (!component) {
|
||||
let refToken: CompileTokenMetadata = null;
|
||||
let refToken: CompileTokenMetadata = null !;
|
||||
if (isTemplateElement) {
|
||||
refToken = createIdentifierToken(Identifiers.TemplateRef);
|
||||
}
|
||||
@ -648,7 +651,7 @@ class TemplateParseVisitor implements html.Visitor {
|
||||
|
||||
private _findComponentDirectiveNames(directives: DirectiveAst[]): string[] {
|
||||
return this._findComponentDirectives(directives)
|
||||
.map(directive => identifierName(directive.directive.type));
|
||||
.map(directive => identifierName(directive.directive.type) !);
|
||||
}
|
||||
|
||||
private _assertOnlyOneComponent(directives: DirectiveAst[], sourceSpan: ParseSourceSpan) {
|
||||
@ -685,7 +688,7 @@ class TemplateParseVisitor implements html.Visitor {
|
||||
errorMsg +=
|
||||
`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 {
|
||||
visitElement(ast: html.Element, parent: ElementContext): ElementAst {
|
||||
visitElement(ast: html.Element, parent: ElementContext): ElementAst|null {
|
||||
const preparsedElement = preparseElement(ast);
|
||||
if (preparsedElement.type === PreparsedElementType.SCRIPT ||
|
||||
preparsedElement.type === PreparsedElementType.STYLE ||
|
||||
@ -783,8 +786,8 @@ class NonBindableVisitor implements html.Visitor {
|
||||
}
|
||||
|
||||
visitText(text: html.Text, parent: ElementContext): TextAst {
|
||||
const ngContentIndex = parent.findNgContentIndex(TEXT_CSS_SELECTOR);
|
||||
return new TextAst(text.value, ngContentIndex, text.sourceSpan);
|
||||
const ngContentIndex = parent.findNgContentIndex(TEXT_CSS_SELECTOR) !;
|
||||
return new TextAst(text.value, ngContentIndex, text.sourceSpan !);
|
||||
}
|
||||
|
||||
visitExpansion(expansion: html.Expansion, context: any): any { return expansion; }
|
||||
@ -805,10 +808,10 @@ class ElementContext {
|
||||
isTemplateElement: boolean, directives: DirectiveAst[],
|
||||
providerContext: ProviderElementContext): ElementContext {
|
||||
const matcher = new SelectorMatcher();
|
||||
let wildcardNgContentIndex: number = null;
|
||||
let wildcardNgContentIndex: number = null !;
|
||||
const component = directives.find(directive => directive.directive.isComponent);
|
||||
if (component) {
|
||||
const ngContentSelectors = component.directive.template.ngContentSelectors;
|
||||
const ngContentSelectors = component.directive.template !.ngContentSelectors;
|
||||
for (let i = 0; i < ngContentSelectors.length; i++) {
|
||||
const selector = ngContentSelectors[i];
|
||||
if (selector === '*') {
|
||||
@ -822,9 +825,10 @@ class ElementContext {
|
||||
}
|
||||
constructor(
|
||||
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[] = [];
|
||||
this._ngContentIndexMatcher.match(
|
||||
selector, (selector, ngContentIndex) => { ngContentIndices.push(ngContentIndex); });
|
||||
@ -893,10 +897,9 @@ function isTemplate(
|
||||
// `<template>` is HTML and case insensitive
|
||||
if (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 false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -21,11 +21,11 @@ const NG_NON_BINDABLE_ATTR = 'ngNonBindable';
|
||||
const NG_PROJECT_AS = 'ngProjectAs';
|
||||
|
||||
export function preparseElement(ast: html.Element): PreparsedElement {
|
||||
let selectAttr: string = null;
|
||||
let hrefAttr: string = null;
|
||||
let relAttr: string = null;
|
||||
let selectAttr: string = null !;
|
||||
let hrefAttr: string = null !;
|
||||
let relAttr: string = null !;
|
||||
let nonBindable = false;
|
||||
let projectAs: string = null;
|
||||
let projectAs: string = null !;
|
||||
ast.attrs.forEach(attr => {
|
||||
const lcAttrName = attr.name.toLowerCase();
|
||||
if (lcAttrName == NG_CONTENT_SELECT_ATTR) {
|
||||
|
Reference in New Issue
Block a user