refactor(compiler): introduce summaries for metadata (#12799)
This does not yet introduce loading / serialization of summaries. Part of #12787
This commit is contained in:

committed by
Victor Berchet

parent
ef881475e9
commit
fcb4e66493
@ -8,7 +8,7 @@
|
||||
|
||||
import {SecurityContext} from '@angular/core';
|
||||
|
||||
import {CompileDirectiveMetadata, CompilePipeMetadata} from '../compile_metadata';
|
||||
import {CompileDirectiveSummary, CompilePipeSummary} from '../compile_metadata';
|
||||
import {AST, ASTWithSource, BindingPipe, EmptyExpr, Interpolation, LiteralPrimitive, ParserError, RecursiveAstVisitor, TemplateBinding} from '../expression_parser/ast';
|
||||
import {Parser} from '../expression_parser/parser';
|
||||
import {isPresent} from '../facade/lang';
|
||||
@ -52,16 +52,16 @@ export class BoundProperty {
|
||||
* Parses bindings in templates and in the directive host area.
|
||||
*/
|
||||
export class BindingParser {
|
||||
pipesByName: Map<string, CompilePipeMetadata> = new Map();
|
||||
pipesByName: Map<string, CompilePipeSummary> = new Map();
|
||||
|
||||
constructor(
|
||||
private _exprParser: Parser, private _interpolationConfig: InterpolationConfig,
|
||||
private _schemaRegistry: ElementSchemaRegistry, pipes: CompilePipeMetadata[],
|
||||
private _schemaRegistry: ElementSchemaRegistry, pipes: CompilePipeSummary[],
|
||||
private _targetErrors: ParseError[]) {
|
||||
pipes.forEach(pipe => this.pipesByName.set(pipe.name, pipe));
|
||||
}
|
||||
|
||||
createDirectiveHostPropertyAsts(dirMeta: CompileDirectiveMetadata, sourceSpan: ParseSourceSpan):
|
||||
createDirectiveHostPropertyAsts(dirMeta: CompileDirectiveSummary, sourceSpan: ParseSourceSpan):
|
||||
BoundElementPropertyAst[] {
|
||||
if (dirMeta.hostProperties) {
|
||||
const boundProps: BoundProperty[] = [];
|
||||
@ -79,7 +79,7 @@ export class BindingParser {
|
||||
}
|
||||
}
|
||||
|
||||
createDirectiveHostEventAsts(dirMeta: CompileDirectiveMetadata, sourceSpan: ParseSourceSpan):
|
||||
createDirectiveHostEventAsts(dirMeta: CompileDirectiveSummary, sourceSpan: ParseSourceSpan):
|
||||
BoundEventAst[] {
|
||||
if (dirMeta.hostListeners) {
|
||||
const targetEventAsts: BoundEventAst[] = [];
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
import {SecurityContext} from '@angular/core';
|
||||
|
||||
import {CompileDirectiveMetadata, CompileProviderMetadata, CompileTokenMetadata} from '../compile_metadata';
|
||||
import {CompileDirectiveSummary, CompileProviderMetadata, CompileTokenMetadata} from '../compile_metadata';
|
||||
import {AST} from '../expression_parser/ast';
|
||||
import {ParseSourceSpan} from '../parse_util';
|
||||
import {LifecycleHooks} from '../private_import_core';
|
||||
@ -168,7 +168,7 @@ export class BoundDirectivePropertyAst implements TemplateAst {
|
||||
*/
|
||||
export class DirectiveAst implements TemplateAst {
|
||||
constructor(
|
||||
public directive: CompileDirectiveMetadata, public inputs: BoundDirectivePropertyAst[],
|
||||
public directive: CompileDirectiveSummary, public inputs: BoundDirectivePropertyAst[],
|
||||
public hostProperties: BoundElementPropertyAst[], public hostEvents: BoundEventAst[],
|
||||
public sourceSpan: ParseSourceSpan) {}
|
||||
visit(visitor: TemplateAstVisitor, context: any): any {
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
import {Inject, Injectable, OpaqueToken, Optional, SchemaMetadata, SecurityContext} from '@angular/core';
|
||||
|
||||
import {CompileDirectiveMetadata, CompilePipeMetadata, CompileTemplateMetadata, CompileTokenMetadata, removeIdentifierDuplicates} from '../compile_metadata';
|
||||
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompilePipeSummary, CompileTemplateMetadata, CompileTemplateSummary, CompileTokenMetadata, CompileTypeMetadata, removeIdentifierDuplicates} from '../compile_metadata';
|
||||
import {AST, ASTWithSource, BindingPipe, EmptyExpr, Interpolation, ParserError, RecursiveAstVisitor, TemplateBinding} from '../expression_parser/ast';
|
||||
import {Parser} from '../expression_parser/parser';
|
||||
import {isPresent} from '../facade/lang';
|
||||
@ -90,8 +90,8 @@ export class TemplateParser {
|
||||
@Optional() @Inject(TEMPLATE_TRANSFORMS) public transforms: TemplateAstVisitor[]) {}
|
||||
|
||||
parse(
|
||||
component: CompileDirectiveMetadata, template: string, directives: CompileDirectiveMetadata[],
|
||||
pipes: CompilePipeMetadata[], schemas: SchemaMetadata[], templateUrl: string): TemplateAst[] {
|
||||
component: CompileDirectiveMetadata, template: string, directives: CompileDirectiveSummary[],
|
||||
pipes: CompilePipeSummary[], schemas: SchemaMetadata[], templateUrl: string): TemplateAst[] {
|
||||
const result = this.tryParse(component, template, directives, pipes, schemas, templateUrl);
|
||||
const warnings = result.errors.filter(error => error.level === ParseErrorLevel.WARNING);
|
||||
const errors = result.errors.filter(error => error.level === ParseErrorLevel.FATAL);
|
||||
@ -109,8 +109,8 @@ export class TemplateParser {
|
||||
}
|
||||
|
||||
tryParse(
|
||||
component: CompileDirectiveMetadata, template: string, directives: CompileDirectiveMetadata[],
|
||||
pipes: CompilePipeMetadata[], schemas: SchemaMetadata[],
|
||||
component: CompileDirectiveMetadata, template: string, directives: CompileDirectiveSummary[],
|
||||
pipes: CompilePipeSummary[], schemas: SchemaMetadata[],
|
||||
templateUrl: string): TemplateParseResult {
|
||||
return this.tryParseHtml(
|
||||
this.expandHtml(this._htmlParser.parse(
|
||||
@ -120,13 +120,13 @@ export class TemplateParser {
|
||||
|
||||
tryParseHtml(
|
||||
htmlAstWithErrors: ParseTreeResult, component: CompileDirectiveMetadata, template: string,
|
||||
directives: CompileDirectiveMetadata[], pipes: CompilePipeMetadata[],
|
||||
schemas: SchemaMetadata[], templateUrl: string): TemplateParseResult {
|
||||
directives: CompileDirectiveSummary[], pipes: CompilePipeSummary[], schemas: SchemaMetadata[],
|
||||
templateUrl: string): TemplateParseResult {
|
||||
var result: TemplateAst[];
|
||||
var errors = htmlAstWithErrors.errors;
|
||||
if (htmlAstWithErrors.rootNodes.length > 0) {
|
||||
const uniqDirectives = removeIdentifierDuplicates(directives);
|
||||
const uniqPipes = removeIdentifierDuplicates(pipes);
|
||||
const uniqDirectives = removeSummaryDuplicates(directives);
|
||||
const uniqPipes = removeSummaryDuplicates(pipes);
|
||||
const providerViewContext =
|
||||
new ProviderViewContext(component, htmlAstWithErrors.rootNodes[0].sourceSpan);
|
||||
let interpolationConfig: InterpolationConfig;
|
||||
@ -200,14 +200,14 @@ export class TemplateParser {
|
||||
|
||||
class TemplateParseVisitor implements html.Visitor {
|
||||
selectorMatcher = new SelectorMatcher();
|
||||
directivesIndex = new Map<CompileDirectiveMetadata, number>();
|
||||
directivesIndex = new Map<CompileDirectiveSummary, number>();
|
||||
ngContentCount: number = 0;
|
||||
|
||||
constructor(
|
||||
public providerViewContext: ProviderViewContext, directives: CompileDirectiveMetadata[],
|
||||
public providerViewContext: ProviderViewContext, directives: CompileDirectiveSummary[],
|
||||
private _bindingParser: BindingParser, private _schemaRegistry: ElementSchemaRegistry,
|
||||
private _schemas: SchemaMetadata[], private _targetErrors: TemplateParseError[]) {
|
||||
directives.forEach((directive: CompileDirectiveMetadata, index: number) => {
|
||||
directives.forEach((directive, index) => {
|
||||
const selector = CssSelector.parse(directive.selector);
|
||||
this.selectorMatcher.addSelectables(selector, directive);
|
||||
this.directivesIndex.set(directive, index);
|
||||
@ -360,7 +360,8 @@ class TemplateParseVisitor implements html.Visitor {
|
||||
componentDirectiveAst.directive.template));
|
||||
|
||||
const componentTemplate = providerContext.viewContext.component.template;
|
||||
this._validateElementAnimationInputOutputs(elementProps, events, componentTemplate);
|
||||
this._validateElementAnimationInputOutputs(
|
||||
elementProps, events, componentTemplate.toSummary());
|
||||
}
|
||||
|
||||
if (hasInlineTemplates) {
|
||||
@ -392,9 +393,9 @@ class TemplateParseVisitor implements html.Visitor {
|
||||
|
||||
private _validateElementAnimationInputOutputs(
|
||||
inputs: BoundElementPropertyAst[], outputs: BoundEventAst[],
|
||||
template: CompileTemplateMetadata) {
|
||||
template: CompileTemplateSummary) {
|
||||
const triggerLookup = new Set<string>();
|
||||
template.animations.forEach(entry => { triggerLookup.add(entry.name); });
|
||||
template.animations.forEach(entry => { triggerLookup.add(entry); });
|
||||
|
||||
const animationInputs = inputs.filter(input => input.isAnimation);
|
||||
animationInputs.forEach(input => {
|
||||
@ -518,7 +519,7 @@ class TemplateParseVisitor implements html.Visitor {
|
||||
}
|
||||
|
||||
private _parseDirectives(selectorMatcher: SelectorMatcher, elementCssSelector: CssSelector):
|
||||
{directives: CompileDirectiveMetadata[], matchElement: boolean} {
|
||||
{directives: CompileDirectiveSummary[], matchElement: boolean} {
|
||||
// Need to sort the directives so that we get consistent results throughout,
|
||||
// as selectorMatcher uses Maps inside.
|
||||
// Also deduplicate directives as they might match more than one time!
|
||||
@ -538,12 +539,12 @@ class TemplateParseVisitor implements html.Visitor {
|
||||
}
|
||||
|
||||
private _createDirectiveAsts(
|
||||
isTemplateElement: boolean, elementName: string, directives: CompileDirectiveMetadata[],
|
||||
isTemplateElement: boolean, elementName: string, directives: CompileDirectiveSummary[],
|
||||
props: BoundProperty[], elementOrDirectiveRefs: ElementOrDirectiveRef[],
|
||||
elementSourceSpan: ParseSourceSpan, targetReferences: ReferenceAst[]): DirectiveAst[] {
|
||||
const matchedReferences = new Set<string>();
|
||||
let component: CompileDirectiveMetadata = null;
|
||||
const directiveAsts = directives.map((directive: CompileDirectiveMetadata) => {
|
||||
let component: CompileDirectiveSummary = null;
|
||||
const directiveAsts = directives.map((directive) => {
|
||||
const sourceSpan = new ParseSourceSpan(
|
||||
elementSourceSpan.start, elementSourceSpan.end, `Directive ${directive.type.name}`);
|
||||
if (directive.isComponent) {
|
||||
@ -837,3 +838,15 @@ const NON_BINDABLE_VISITOR = new NonBindableVisitor();
|
||||
function _isEmptyTextNode(node: html.Node): boolean {
|
||||
return node instanceof html.Text && node.value.trim().length == 0;
|
||||
}
|
||||
|
||||
export function removeSummaryDuplicates<T extends{type: CompileTypeMetadata}>(items: T[]): T[] {
|
||||
const map = new Map<any, T>();
|
||||
|
||||
items.forEach((item) => {
|
||||
if (!map.get(item.type.reference)) {
|
||||
map.set(item.type.reference, item);
|
||||
}
|
||||
});
|
||||
|
||||
return Array.from(map.values());
|
||||
}
|
||||
|
Reference in New Issue
Block a user