From 798947efa413e90ce704945af47bb7c752585e2b Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Wed, 5 Jul 2017 10:54:05 -0700 Subject: [PATCH] feat(compiler): adds support for quoted object keys in the parser --- .../compiler/src/compiler_util/expression_converter.ts | 2 +- packages/compiler/src/expression_parser/ast.ts | 6 +++++- packages/compiler/src/expression_parser/parser.ts | 8 ++++---- packages/compiler/test/expression_parser/parser_spec.ts | 4 ++-- packages/compiler/test/expression_parser/unparser.ts | 4 +++- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/packages/compiler/src/compiler_util/expression_converter.ts b/packages/compiler/src/compiler_util/expression_converter.ts index 61e976a573..d61cea3037 100644 --- a/packages/compiler/src/compiler_util/expression_converter.ts +++ b/packages/compiler/src/compiler_util/expression_converter.ts @@ -170,7 +170,7 @@ class _BuiltinAstConverter extends cdAst.AstTransformer { visitLiteralMap(ast: cdAst.LiteralMap, context: any): any { const args = ast.values.map(ast => ast.visit(this, context)); return new BuiltinFunctionCall( - ast.span, args, this._converterFactory.createLiteralMapConverter(ast.keys)); + ast.span, args, this._converterFactory.createLiteralMapConverter(ast.keys.map(k => k.key))); } } diff --git a/packages/compiler/src/expression_parser/ast.ts b/packages/compiler/src/expression_parser/ast.ts index 3f3417c8b5..b6b1b03f61 100644 --- a/packages/compiler/src/expression_parser/ast.ts +++ b/packages/compiler/src/expression_parser/ast.ts @@ -136,8 +136,12 @@ export class LiteralArray extends AST { } } +export type LiteralMapKey = { + key: string; quoted: boolean; +}; + export class LiteralMap extends AST { - constructor(span: ParseSpan, public keys: any[], public values: any[]) { super(span); } + constructor(span: ParseSpan, public keys: LiteralMapKey[], public values: any[]) { super(span); } visit(visitor: AstVisitor, context: any = null): any { return visitor.visitLiteralMap(this, context); } diff --git a/packages/compiler/src/expression_parser/parser.ts b/packages/compiler/src/expression_parser/parser.ts index 9503b0f64e..14dacda156 100644 --- a/packages/compiler/src/expression_parser/parser.ts +++ b/packages/compiler/src/expression_parser/parser.ts @@ -11,10 +11,9 @@ import {CompilerInjectable} from '../injectable'; import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../ml_parser/interpolation_config'; import {escapeRegExp} from '../util'; -import {AST, ASTWithSource, AstVisitor, Binary, BindingPipe, Chain, Conditional, EmptyExpr, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralPrimitive, MethodCall, NonNullAssert, ParseSpan, ParserError, PrefixNot, PropertyRead, PropertyWrite, Quote, SafeMethodCall, SafePropertyRead, TemplateBinding} from './ast'; +import {AST, ASTWithSource, AstVisitor, Binary, BindingPipe, Chain, Conditional, EmptyExpr, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralMapKey, LiteralPrimitive, MethodCall, NonNullAssert, ParseSpan, ParserError, PrefixNot, PropertyRead, PropertyWrite, Quote, SafeMethodCall, SafePropertyRead, TemplateBinding} from './ast'; import {EOF, Lexer, Token, TokenType, isIdentifier, isQuote} from './lexer'; - export class SplitInterpolation { constructor(public strings: string[], public expressions: string[], public offsets: number[]) {} } @@ -605,15 +604,16 @@ export class _ParseAST { } parseLiteralMap(): LiteralMap { - const keys: string[] = []; + const keys: LiteralMapKey[] = []; const values: AST[] = []; const start = this.inputIndex; this.expectCharacter(chars.$LBRACE); if (!this.optionalCharacter(chars.$RBRACE)) { this.rbracesExpected++; do { + const quoted = this.next.isString(); const key = this.expectIdentifierOrKeywordOrString(); - keys.push(key); + keys.push({key, quoted}); this.expectCharacter(chars.$COLON); values.push(this.parsePipe()); } while (this.optionalCharacter(chars.$COMMA)); diff --git a/packages/compiler/test/expression_parser/parser_spec.ts b/packages/compiler/test/expression_parser/parser_spec.ts index a71fdd99c2..260a516be0 100644 --- a/packages/compiler/test/expression_parser/parser_spec.ts +++ b/packages/compiler/test/expression_parser/parser_spec.ts @@ -165,7 +165,7 @@ export function main() { it('should parse map', () => { checkAction('{}'); - checkAction('{a: 1}[2]'); + checkAction('{a: 1, "b": 2}[2]'); checkAction('{}["a"]'); }); @@ -263,7 +263,7 @@ export function main() { checkBinding('a(b | c)', 'a((b | c))'); checkBinding('a.b(c.d(e) | f)', 'a.b((c.d(e) | f))'); checkBinding('[1, 2, 3] | a', '([1, 2, 3] | a)'); - checkBinding('{a: 1} | b', '({a: 1} | b)'); + checkBinding('{a: 1, "b": 2} | c', '({a: 1, "b": 2} | c)'); checkBinding('a[b] | c', '(a[b] | c)'); checkBinding('a?.b | c', '(a?.b | c)'); checkBinding('true | a', '(true | a)'); diff --git a/packages/compiler/test/expression_parser/unparser.ts b/packages/compiler/test/expression_parser/unparser.ts index 308852f732..4f9aa33e4e 100644 --- a/packages/compiler/test/expression_parser/unparser.ts +++ b/packages/compiler/test/expression_parser/unparser.ts @@ -124,7 +124,9 @@ class Unparser implements AstVisitor { for (let i = 0; i < ast.keys.length; i++) { if (!isFirst) this._expression += ', '; isFirst = false; - this._expression += `${ast.keys[i]}: `; + const key = ast.keys[i]; + this._expression += key.quoted ? JSON.stringify(key.key) : key.key; + this._expression += ': '; this._visit(ast.values[i]); }