feat(parser): allows users install custom AST transformers

Closes #5382
This commit is contained in:
Yegor Jbanov
2015-11-19 10:51:16 -08:00
committed by Yegor
parent 125fa3885e
commit a43ed79ee7
4 changed files with 80 additions and 26 deletions

View File

@ -13,7 +13,8 @@ import {
assertionsEnabled,
isBlank
} from 'angular2/src/facade/lang';
import {Injectable} from 'angular2/src/core/di';
import {Injectable, Inject, Injector, OpaqueToken, Optional} from 'angular2/core';
import {CONST_EXPR} from 'angular2/src/facade/lang';
import {BaseException} from 'angular2/src/facade/exceptions';
import {Parser, AST, ASTWithSource} from 'angular2/src/core/change_detection/change_detection';
import {TemplateBinding} from 'angular2/src/core/change_detection/parser/ast';
@ -28,6 +29,8 @@ import {
BoundEventAst,
VariableAst,
TemplateAst,
TemplateAstVisitor,
templateVisitAll,
TextAst,
BoundTextAst,
EmbeddedTemplateAst,
@ -78,6 +81,8 @@ const STYLE_PREFIX = 'style';
var TEXT_CSS_SELECTOR = CssSelector.parse('*')[0];
export const TEMPLATE_TRANSFORMS = CONST_EXPR(new OpaqueToken('TemplateTransforms'));
export class TemplateParseError extends ParseError {
constructor(message: string, location: ParseLocation) { super(location, message); }
}
@ -85,7 +90,8 @@ export class TemplateParseError extends ParseError {
@Injectable()
export class TemplateParser {
constructor(private _exprParser: Parser, private _schemaRegistry: ElementSchemaRegistry,
private _htmlParser: HtmlParser) {}
private _htmlParser: HtmlParser,
@Optional() @Inject(TEMPLATE_TRANSFORMS) public transforms: TemplateAstVisitor[]) {}
parse(template: string, directives: CompileDirectiveMetadata[],
templateUrl: string): TemplateAst[] {
@ -97,6 +103,10 @@ export class TemplateParser {
var errorString = errors.join('\n');
throw new BaseException(`Template parse errors:\n${errorString}`);
}
if (isPresent(this.transforms)) {
this.transforms.forEach(
(transform: TemplateAstVisitor) => { result = templateVisitAll(transform, result); });
}
return result;
}
}

View File

@ -58,7 +58,6 @@ export class KeyedWrite extends AST {
export class BindingPipe extends AST {
constructor(public exp: AST, public name: string, public args: any[]) { super(); }
visit(visitor: AstVisitor): any { return visitor.visitPipe(this); }
}
@ -79,7 +78,7 @@ export class LiteralMap extends AST {
export class Interpolation extends AST {
constructor(public strings: any[], public expressions: any[]) { super(); }
visit(visitor: AstVisitor) { visitor.visitInterpolation(this); }
visit(visitor: AstVisitor): any { return visitor.visitInterpolation(this); }
}
export class Binary extends AST {
@ -214,68 +213,66 @@ export class RecursiveAstVisitor implements AstVisitor {
}
export class AstTransformer implements AstVisitor {
visitImplicitReceiver(ast: ImplicitReceiver): ImplicitReceiver { return ast; }
visitImplicitReceiver(ast: ImplicitReceiver): AST { return ast; }
visitInterpolation(ast: Interpolation): Interpolation {
visitInterpolation(ast: Interpolation): AST {
return new Interpolation(ast.strings, this.visitAll(ast.expressions));
}
visitLiteralPrimitive(ast: LiteralPrimitive): LiteralPrimitive {
return new LiteralPrimitive(ast.value);
}
visitLiteralPrimitive(ast: LiteralPrimitive): AST { return new LiteralPrimitive(ast.value); }
visitPropertyRead(ast: PropertyRead): PropertyRead {
visitPropertyRead(ast: PropertyRead): AST {
return new PropertyRead(ast.receiver.visit(this), ast.name, ast.getter);
}
visitPropertyWrite(ast: PropertyWrite): PropertyWrite {
visitPropertyWrite(ast: PropertyWrite): AST {
return new PropertyWrite(ast.receiver.visit(this), ast.name, ast.setter, ast.value);
}
visitSafePropertyRead(ast: SafePropertyRead): SafePropertyRead {
visitSafePropertyRead(ast: SafePropertyRead): AST {
return new SafePropertyRead(ast.receiver.visit(this), ast.name, ast.getter);
}
visitMethodCall(ast: MethodCall): MethodCall {
visitMethodCall(ast: MethodCall): AST {
return new MethodCall(ast.receiver.visit(this), ast.name, ast.fn, this.visitAll(ast.args));
}
visitSafeMethodCall(ast: SafeMethodCall): SafeMethodCall {
visitSafeMethodCall(ast: SafeMethodCall): AST {
return new SafeMethodCall(ast.receiver.visit(this), ast.name, ast.fn, this.visitAll(ast.args));
}
visitFunctionCall(ast: FunctionCall): FunctionCall {
visitFunctionCall(ast: FunctionCall): AST {
return new FunctionCall(ast.target.visit(this), this.visitAll(ast.args));
}
visitLiteralArray(ast: LiteralArray): LiteralArray {
visitLiteralArray(ast: LiteralArray): AST {
return new LiteralArray(this.visitAll(ast.expressions));
}
visitLiteralMap(ast: LiteralMap): LiteralMap {
visitLiteralMap(ast: LiteralMap): AST {
return new LiteralMap(ast.keys, this.visitAll(ast.values));
}
visitBinary(ast: Binary): Binary {
visitBinary(ast: Binary): AST {
return new Binary(ast.operation, ast.left.visit(this), ast.right.visit(this));
}
visitPrefixNot(ast: PrefixNot): PrefixNot { return new PrefixNot(ast.expression.visit(this)); }
visitPrefixNot(ast: PrefixNot): AST { return new PrefixNot(ast.expression.visit(this)); }
visitConditional(ast: Conditional): Conditional {
visitConditional(ast: Conditional): AST {
return new Conditional(ast.condition.visit(this), ast.trueExp.visit(this),
ast.falseExp.visit(this));
}
visitPipe(ast: BindingPipe): BindingPipe {
visitPipe(ast: BindingPipe): AST {
return new BindingPipe(ast.exp.visit(this), ast.name, this.visitAll(ast.args));
}
visitKeyedRead(ast: KeyedRead): KeyedRead {
visitKeyedRead(ast: KeyedRead): AST {
return new KeyedRead(ast.obj.visit(this), ast.key.visit(this));
}
visitKeyedWrite(ast: KeyedWrite): KeyedWrite {
visitKeyedWrite(ast: KeyedWrite): AST {
return new KeyedWrite(ast.obj.visit(this), ast.key.visit(this), ast.value.visit(this));
}
@ -287,5 +284,5 @@ export class AstTransformer implements AstVisitor {
return res;
}
visitChain(ast: Chain): Chain { return new Chain(this.visitAll(ast.expressions)); }
visitChain(ast: Chain): AST { return new Chain(this.visitAll(ast.expressions)); }
}