
committed by
Tobias Bosch

parent
92f1af86d8
commit
331a051e75
180
modules/angular2/test/change_detection/parser/unparser.ts
Normal file
180
modules/angular2/test/change_detection/parser/unparser.ts
Normal file
@ -0,0 +1,180 @@
|
||||
import {
|
||||
AST,
|
||||
AstVisitor,
|
||||
AccessMember,
|
||||
Assignment,
|
||||
Binary,
|
||||
Chain,
|
||||
Conditional,
|
||||
Pipe,
|
||||
FunctionCall,
|
||||
ImplicitReceiver,
|
||||
Interpolation,
|
||||
KeyedAccess,
|
||||
LiteralArray,
|
||||
LiteralMap,
|
||||
LiteralPrimitive,
|
||||
MethodCall,
|
||||
PrefixNot,
|
||||
SafeAccessMember,
|
||||
SafeMethodCall
|
||||
} from 'angular2/src/change_detection/parser/ast';
|
||||
|
||||
|
||||
import {StringWrapper, RegExpWrapper} from 'angular2/src/facade/lang';
|
||||
|
||||
var quoteRegExp = RegExpWrapper.create('"');
|
||||
|
||||
export class Unparser implements AstVisitor {
|
||||
private _expression: string;
|
||||
|
||||
unparse(ast: AST) {
|
||||
this._expression = '';
|
||||
this._visit(ast);
|
||||
return this._expression;
|
||||
}
|
||||
|
||||
visitAccessMember(ast: AccessMember) {
|
||||
this._visit(ast.receiver);
|
||||
|
||||
this._expression += ast.receiver instanceof ImplicitReceiver ? `${ast.name}` : `.${ast.name}`;
|
||||
}
|
||||
|
||||
visitAssignment(ast: Assignment) {
|
||||
this._visit(ast.target);
|
||||
this._expression += ' = ';
|
||||
this._visit(ast.value);
|
||||
}
|
||||
|
||||
visitBinary(ast: Binary) {
|
||||
this._visit(ast.left);
|
||||
this._expression += ` ${ast.operation} `;
|
||||
this._visit(ast.right);
|
||||
}
|
||||
|
||||
visitChain(ast: Chain) {
|
||||
ast.expressions.forEach(expression => {
|
||||
this._visit(expression);
|
||||
this._expression += ';'
|
||||
});
|
||||
}
|
||||
|
||||
visitConditional(ast: Conditional) {
|
||||
this._visit(ast.condition);
|
||||
this._expression += ' ? ';
|
||||
this._visit(ast.trueExp);
|
||||
this._expression += ' : ';
|
||||
this._visit(ast.falseExp);
|
||||
}
|
||||
|
||||
visitPipe(ast: Pipe) {
|
||||
this._visit(ast.exp);
|
||||
this._expression += ` | ${ast.name}`;
|
||||
ast.args.forEach(arg => {
|
||||
this._expression += ':';
|
||||
this._visit(arg);
|
||||
})
|
||||
}
|
||||
|
||||
visitFunctionCall(ast: FunctionCall) {
|
||||
this._visit(ast.target);
|
||||
this._expression += '(';
|
||||
var isFirst = true;
|
||||
ast.args.forEach(arg => {
|
||||
if (!isFirst) this._expression += ', ';
|
||||
isFirst = false;
|
||||
this._visit(arg);
|
||||
});
|
||||
this._expression += ')';
|
||||
}
|
||||
|
||||
visitImplicitReceiver(ast: ImplicitReceiver) {}
|
||||
|
||||
visitInterpolation(ast: Interpolation) {
|
||||
for (let i = 0; i < ast.strings.length; i++) {
|
||||
this._expression += ast.strings[i];
|
||||
if (i < ast.expressions.length) {
|
||||
this._expression += '{{ ';
|
||||
this._visit(ast.expressions[i]);
|
||||
this._expression += ' }}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visitKeyedAccess(ast: KeyedAccess) {
|
||||
this._visit(ast.obj);
|
||||
this._expression += '[';
|
||||
this._visit(ast.key);
|
||||
this._expression += ']';
|
||||
}
|
||||
|
||||
visitLiteralArray(ast: LiteralArray) {
|
||||
this._expression += '[';
|
||||
var isFirst = true;
|
||||
ast.expressions.forEach(expression => {
|
||||
if (!isFirst) this._expression += ', ';
|
||||
isFirst = false;
|
||||
this._visit(expression);
|
||||
});
|
||||
|
||||
this._expression += ']';
|
||||
}
|
||||
|
||||
visitLiteralMap(ast: LiteralMap) {
|
||||
this._expression += '{';
|
||||
var isFirst = true;
|
||||
for (let i = 0; i < ast.keys.length; i++) {
|
||||
if (!isFirst) this._expression += ', ';
|
||||
isFirst = false;
|
||||
this._expression += `${ast.keys[i]}: `;
|
||||
this._visit(ast.values[i]);
|
||||
}
|
||||
|
||||
this._expression += '}';
|
||||
}
|
||||
|
||||
visitLiteralPrimitive(ast: LiteralPrimitive) {
|
||||
if (StringWrapper.isString(ast.value)) {
|
||||
this._expression += `"${StringWrapper.replaceAll(ast.value, quoteRegExp, '\"')}"`;
|
||||
} else {
|
||||
this._expression += `${ast.value}`;
|
||||
}
|
||||
}
|
||||
|
||||
visitMethodCall(ast: MethodCall) {
|
||||
this._visit(ast.receiver);
|
||||
this._expression += ast.receiver instanceof ImplicitReceiver ? `${ast.name}(` :
|
||||
`.${ast.name}(`;
|
||||
var isFirst = true;
|
||||
ast.args.forEach(arg => {
|
||||
if (!isFirst) this._expression += ', ';
|
||||
isFirst = false;
|
||||
this._visit(arg);
|
||||
});
|
||||
this._expression += ')';
|
||||
}
|
||||
|
||||
visitPrefixNot(ast: PrefixNot) {
|
||||
this._expression += '!';
|
||||
this._visit(ast.expression);
|
||||
}
|
||||
|
||||
visitSafeAccessMember(ast: SafeAccessMember) {
|
||||
this._visit(ast.receiver);
|
||||
this._expression += `?.${ast.name}`;
|
||||
}
|
||||
|
||||
visitSafeMethodCall(ast: SafeMethodCall) {
|
||||
this._visit(ast.receiver);
|
||||
this._expression += `?.${ast.name}(`;
|
||||
var isFirst = true;
|
||||
ast.args.forEach(arg => {
|
||||
if (!isFirst) this._expression += ', ';
|
||||
isFirst = false;
|
||||
this._visit(arg);
|
||||
});
|
||||
this._expression += ')';
|
||||
}
|
||||
|
||||
private _visit(ast: AST) { ast.visit(this); }
|
||||
}
|
112
modules/angular2/test/change_detection/parser/unparser_spec.ts
Normal file
112
modules/angular2/test/change_detection/parser/unparser_spec.ts
Normal file
@ -0,0 +1,112 @@
|
||||
import {ddescribe, describe, it, xit, iit, expect, beforeEach} from 'angular2/test_lib';
|
||||
|
||||
import {
|
||||
AST,
|
||||
ASTWithSource,
|
||||
AccessMember,
|
||||
Assignment,
|
||||
Binary,
|
||||
Chain,
|
||||
Conditional,
|
||||
Pipe,
|
||||
ImplicitReceiver,
|
||||
Interpolation,
|
||||
KeyedAccess,
|
||||
LiteralArray,
|
||||
LiteralMap,
|
||||
LiteralPrimitive,
|
||||
MethodCall,
|
||||
PrefixNot,
|
||||
SafeAccessMember,
|
||||
SafeMethodCall
|
||||
} from 'angular2/src/change_detection/parser/ast';
|
||||
|
||||
import {Parser} from 'angular2/src/change_detection/parser/parser';
|
||||
import {Lexer} from 'angular2/src/change_detection/parser/lexer';
|
||||
import {Unparser} from './unparser';
|
||||
|
||||
import {reflector} from 'angular2/src/reflection/reflection';
|
||||
|
||||
import {isPresent, Type} from 'angular2/src/facade/lang';
|
||||
|
||||
export function main() {
|
||||
let parser: Parser = new Parser(new Lexer(), reflector);
|
||||
let unparser: Unparser = new Unparser();
|
||||
|
||||
function parseAction(text, location = null): ASTWithSource {
|
||||
return parser.parseAction(text, location);
|
||||
}
|
||||
|
||||
function parseBinding(text, location = null): ASTWithSource {
|
||||
return parser.parseBinding(text, location);
|
||||
}
|
||||
|
||||
function check(expression: string, type: Type): void {
|
||||
var ast = parseAction(expression).ast;
|
||||
if (isPresent(type)) {
|
||||
expect(ast).toBeAnInstanceOf(type);
|
||||
}
|
||||
expect(unparser.unparse(ast)).toEqual(expression);
|
||||
}
|
||||
|
||||
describe('Unparser', () => {
|
||||
it('should support AccessMember', () => {
|
||||
check('a', AccessMember);
|
||||
check('a.b', AccessMember);
|
||||
});
|
||||
|
||||
it('should support Assignment', () => { check('a = b', Assignment); });
|
||||
|
||||
it('should support Binary', () => { check('a && b', Binary); });
|
||||
|
||||
it('should support Chain', () => { check('a;b;', Chain); });
|
||||
|
||||
it('should support Conditional', () => { check('a ? b : c', Conditional); });
|
||||
|
||||
it('should support Pipe', () => {
|
||||
var originalExp = 'a | b';
|
||||
var ast = parseBinding(originalExp).ast;
|
||||
expect(ast).toBeAnInstanceOf(Pipe);
|
||||
expect(unparser.unparse(ast)).toEqual(originalExp);
|
||||
});
|
||||
|
||||
it('should support KeyedAccess', () => { check('a[b]', KeyedAccess); });
|
||||
|
||||
it('should support LiteralArray', () => { check('[a, b]', LiteralArray); });
|
||||
|
||||
it('should support LiteralMap', () => { check('{a: b, c: d}', LiteralMap); });
|
||||
|
||||
it('should support LiteralPrimitive', () => {
|
||||
check('true', LiteralPrimitive);
|
||||
check('"a"', LiteralPrimitive);
|
||||
check('1.234', LiteralPrimitive);
|
||||
});
|
||||
|
||||
it('should support MethodCall', () => {
|
||||
check('a(b, c)', MethodCall);
|
||||
check('a.b(c, d)', MethodCall);
|
||||
});
|
||||
|
||||
it('should support PrefixNot', () => { check('!a', PrefixNot); });
|
||||
|
||||
it('should support SafeAccessMember', () => { check('a?.b', SafeAccessMember); });
|
||||
|
||||
it('should support SafeMethodCall', () => { check('a?.b(c, d)', SafeMethodCall); });
|
||||
|
||||
it('should support complex expression', () => {
|
||||
var originalExp = 'a + 3 * fn([c + d | e.f], {a: 3})[g].h && i';
|
||||
var ast = parseBinding(originalExp).ast;
|
||||
expect(unparser.unparse(ast)).toEqual(originalExp);
|
||||
});
|
||||
|
||||
it('should support Interpolation', () => {
|
||||
var ast = parser.parseInterpolation('a {{ b }}', null).ast;
|
||||
expect(ast).toBeAnInstanceOf(Interpolation);
|
||||
expect(unparser.unparse(ast)).toEqual('a {{ b }}');
|
||||
|
||||
ast = parser.parseInterpolation('a {{ b }} c', null).ast;
|
||||
expect(ast).toBeAnInstanceOf(Interpolation);
|
||||
expect(unparser.unparse(ast)).toEqual('a {{ b }} c');
|
||||
});
|
||||
});
|
||||
}
|
Reference in New Issue
Block a user