| 
									
										
										
										
											2016-06-23 09:47:54 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							|  |  |  |  * Copyright Google Inc. All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Use of this source code is governed by an MIT-style license that can be | 
					
						
							|  |  |  |  * found in the LICENSE file at https://angular.io/license
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-27 17:12:25 -07:00
										 |  |  | import {AST, AstVisitor, Binary, BindingPipe, Chain, Conditional, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralPrimitive, MethodCall, PrefixNot, PropertyRead, PropertyWrite, Quote, SafeMethodCall, SafePropertyRead} from '../../src/expression_parser/ast'; | 
					
						
							| 
									
										
										
										
											2016-08-01 12:19:09 -07:00
										 |  |  | import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../../src/ml_parser/interpolation_config'; | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-06 14:06:47 -07:00
										 |  |  | class Unparser implements AstVisitor { | 
					
						
							| 
									
										
										
										
											2015-06-23 12:46:38 +02:00
										 |  |  |   private static _quoteRegExp = /"/g; | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |   private _expression: string; | 
					
						
							| 
									
										
										
										
											2016-06-20 09:52:41 -07:00
										 |  |  |   private _interpolationConfig: InterpolationConfig; | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-06 14:06:47 -07:00
										 |  |  |   unparse(ast: AST, interpolationConfig: InterpolationConfig) { | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     this._expression = ''; | 
					
						
							| 
									
										
										
										
											2016-06-20 09:52:41 -07:00
										 |  |  |     this._interpolationConfig = interpolationConfig; | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     this._visit(ast); | 
					
						
							|  |  |  |     return this._expression; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   visitPropertyRead(ast: PropertyRead, context: any) { | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     this._visit(ast.receiver); | 
					
						
							|  |  |  |     this._expression += ast.receiver instanceof ImplicitReceiver ? `${ast.name}` : `.${ast.name}`; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   visitPropertyWrite(ast: PropertyWrite, context: any) { | 
					
						
							| 
									
										
										
										
											2015-08-12 16:26:21 -07:00
										 |  |  |     this._visit(ast.receiver); | 
					
						
							|  |  |  |     this._expression += | 
					
						
							|  |  |  |         ast.receiver instanceof ImplicitReceiver ? `${ast.name} = ` : `.${ast.name} = `; | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     this._visit(ast.value); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   visitBinary(ast: Binary, context: any) { | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     this._visit(ast.left); | 
					
						
							|  |  |  |     this._expression += ` ${ast.operation} `; | 
					
						
							|  |  |  |     this._visit(ast.right); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   visitChain(ast: Chain, context: any) { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |     const len = ast.expressions.length; | 
					
						
							| 
									
										
										
										
											2015-06-10 11:11:01 +02:00
										 |  |  |     for (let i = 0; i < len; i++) { | 
					
						
							|  |  |  |       this._visit(ast.expressions[i]); | 
					
						
							|  |  |  |       this._expression += i == len - 1 ? ';' : '; '; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   visitConditional(ast: Conditional, context: any) { | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     this._visit(ast.condition); | 
					
						
							|  |  |  |     this._expression += ' ? '; | 
					
						
							|  |  |  |     this._visit(ast.trueExp); | 
					
						
							|  |  |  |     this._expression += ' : '; | 
					
						
							|  |  |  |     this._visit(ast.falseExp); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   visitPipe(ast: BindingPipe, context: any) { | 
					
						
							| 
									
										
										
										
											2015-06-04 19:06:09 +02:00
										 |  |  |     this._expression += '('; | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     this._visit(ast.exp); | 
					
						
							|  |  |  |     this._expression += ` | ${ast.name}`; | 
					
						
							|  |  |  |     ast.args.forEach(arg => { | 
					
						
							|  |  |  |       this._expression += ':'; | 
					
						
							|  |  |  |       this._visit(arg); | 
					
						
							| 
									
										
										
										
											2015-06-04 19:06:09 +02:00
										 |  |  |     }); | 
					
						
							|  |  |  |     this._expression += ')'; | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   visitFunctionCall(ast: FunctionCall, context: any) { | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     this._visit(ast.target); | 
					
						
							|  |  |  |     this._expression += '('; | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |     let isFirst = true; | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     ast.args.forEach(arg => { | 
					
						
							|  |  |  |       if (!isFirst) this._expression += ', '; | 
					
						
							|  |  |  |       isFirst = false; | 
					
						
							|  |  |  |       this._visit(arg); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     this._expression += ')'; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   visitImplicitReceiver(ast: ImplicitReceiver, context: any) {} | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   visitInterpolation(ast: Interpolation, context: any) { | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     for (let i = 0; i < ast.strings.length; i++) { | 
					
						
							|  |  |  |       this._expression += ast.strings[i]; | 
					
						
							|  |  |  |       if (i < ast.expressions.length) { | 
					
						
							| 
									
										
										
										
											2016-06-20 09:52:41 -07:00
										 |  |  |         this._expression += `${this._interpolationConfig.start} `; | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |         this._visit(ast.expressions[i]); | 
					
						
							| 
									
										
										
										
											2016-06-20 09:52:41 -07:00
										 |  |  |         this._expression += ` ${this._interpolationConfig.end}`; | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   visitKeyedRead(ast: KeyedRead, context: any) { | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     this._visit(ast.obj); | 
					
						
							|  |  |  |     this._expression += '['; | 
					
						
							|  |  |  |     this._visit(ast.key); | 
					
						
							|  |  |  |     this._expression += ']'; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   visitKeyedWrite(ast: KeyedWrite, context: any) { | 
					
						
							| 
									
										
										
										
											2015-08-12 16:26:21 -07:00
										 |  |  |     this._visit(ast.obj); | 
					
						
							|  |  |  |     this._expression += '['; | 
					
						
							|  |  |  |     this._visit(ast.key); | 
					
						
							|  |  |  |     this._expression += '] = '; | 
					
						
							|  |  |  |     this._visit(ast.value); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   visitLiteralArray(ast: LiteralArray, context: any) { | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     this._expression += '['; | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |     let isFirst = true; | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     ast.expressions.forEach(expression => { | 
					
						
							|  |  |  |       if (!isFirst) this._expression += ', '; | 
					
						
							|  |  |  |       isFirst = false; | 
					
						
							|  |  |  |       this._visit(expression); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     this._expression += ']'; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   visitLiteralMap(ast: LiteralMap, context: any) { | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     this._expression += '{'; | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |     let isFirst = true; | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     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 += '}'; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   visitLiteralPrimitive(ast: LiteralPrimitive, context: any) { | 
					
						
							| 
									
										
										
										
											2016-10-19 13:42:39 -07:00
										 |  |  |     if (typeof ast.value === 'string') { | 
					
						
							| 
									
										
										
										
											2016-10-06 15:10:27 -07:00
										 |  |  |       this._expression += `"${ast.value.replace( Unparser._quoteRegExp,  '\"')}"`; | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     } else { | 
					
						
							|  |  |  |       this._expression += `${ast.value}`; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   visitMethodCall(ast: MethodCall, context: any) { | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     this._visit(ast.receiver); | 
					
						
							| 
									
										
										
										
											2015-07-10 11:29:41 +02:00
										 |  |  |     this._expression += ast.receiver instanceof ImplicitReceiver ? `${ast.name}(` : `.${ast.name}(`; | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |     let isFirst = true; | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     ast.args.forEach(arg => { | 
					
						
							|  |  |  |       if (!isFirst) this._expression += ', '; | 
					
						
							|  |  |  |       isFirst = false; | 
					
						
							|  |  |  |       this._visit(arg); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     this._expression += ')'; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   visitPrefixNot(ast: PrefixNot, context: any) { | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     this._expression += '!'; | 
					
						
							|  |  |  |     this._visit(ast.expression); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   visitSafePropertyRead(ast: SafePropertyRead, context: any) { | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     this._visit(ast.receiver); | 
					
						
							|  |  |  |     this._expression += `?.${ast.name}`; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   visitSafeMethodCall(ast: SafeMethodCall, context: any) { | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     this._visit(ast.receiver); | 
					
						
							|  |  |  |     this._expression += `?.${ast.name}(`; | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |     let isFirst = true; | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |     ast.args.forEach(arg => { | 
					
						
							|  |  |  |       if (!isFirst) this._expression += ', '; | 
					
						
							|  |  |  |       isFirst = false; | 
					
						
							|  |  |  |       this._visit(arg); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     this._expression += ')'; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   visitQuote(ast: Quote, context: any) { | 
					
						
							|  |  |  |     this._expression += `${ast.prefix}:${ast.uninterpretedExpression}`; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-11-23 17:58:12 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-06 11:15:14 +02:00
										 |  |  |   private _visit(ast: AST) { ast.visit(this); } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-07-06 14:06:47 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | const sharedUnparser = new Unparser(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export function unparse( | 
					
						
							|  |  |  |     ast: AST, interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG): string { | 
					
						
							|  |  |  |   return sharedUnparser.unparse(ast, interpolationConfig); | 
					
						
							|  |  |  | } |