| 
									
										
										
										
											2016-10-23 22:37:15 +02: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-03-10 13:39:19 -08:00
										 |  |  | import * as fs from 'fs'; | 
					
						
							| 
									
										
										
										
											2016-05-26 10:45:37 -07:00
										 |  |  | import * as ts from 'typescript'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-22 17:11:42 -07:00
										 |  |  | import {Evaluator} from '../src/evaluator'; | 
					
						
							|  |  |  | import {Symbols} from '../src/symbols'; | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-26 10:45:37 -07:00
										 |  |  | import {Directory, Host, expectNoDiagnostics, findVar} from './typescript.mocks'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  | describe('Evaluator', () => { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |   const documentRegistry = ts.createDocumentRegistry(); | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  |   let host: ts.LanguageServiceHost; | 
					
						
							|  |  |  |   let service: ts.LanguageService; | 
					
						
							|  |  |  |   let program: ts.Program; | 
					
						
							|  |  |  |   let typeChecker: ts.TypeChecker; | 
					
						
							|  |  |  |   let symbols: Symbols; | 
					
						
							|  |  |  |   let evaluator: Evaluator; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   beforeEach(() => { | 
					
						
							| 
									
										
										
										
											2016-05-31 11:00:39 -07:00
										 |  |  |     host = new Host(FILES, [ | 
					
						
							|  |  |  |       'expressions.ts', 'consts.ts', 'const_expr.ts', 'forwardRef.ts', 'classes.ts', | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |       'newExpression.ts', 'errors.ts', 'declared.ts' | 
					
						
							| 
									
										
										
										
											2016-05-31 11:00:39 -07:00
										 |  |  |     ]); | 
					
						
							| 
									
										
										
										
											2016-06-03 15:43:09 -07:00
										 |  |  |     service = ts.createLanguageService(host, documentRegistry); | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  |     program = service.getProgram(); | 
					
						
							|  |  |  |     typeChecker = program.getTypeChecker(); | 
					
						
							| 
									
										
										
										
											2016-05-31 11:00:39 -07:00
										 |  |  |     symbols = new Symbols(null); | 
					
						
							| 
									
										
										
										
											2016-08-22 17:37:48 -07:00
										 |  |  |     evaluator = new Evaluator(symbols, new Map()); | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should not have typescript errors in test data', () => { | 
					
						
							|  |  |  |     expectNoDiagnostics(service.getCompilerOptionsDiagnostics()); | 
					
						
							|  |  |  |     for (const sourceFile of program.getSourceFiles()) { | 
					
						
							|  |  |  |       expectNoDiagnostics(service.getSyntacticDiagnostics(sourceFile.fileName)); | 
					
						
							| 
									
										
										
										
											2016-06-03 15:43:09 -07:00
										 |  |  |       if (sourceFile.fileName != 'errors.ts') { | 
					
						
							|  |  |  |         // Skip errors.ts because we it has intentional semantic errors that we are testing for.
 | 
					
						
							|  |  |  |         expectNoDiagnostics(service.getSemanticDiagnostics(sourceFile.fileName)); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  |     } | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should be able to fold literal expressions', () => { | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |     const consts = program.getSourceFile('consts.ts'); | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  |     expect(evaluator.isFoldable(findVar(consts, 'someName').initializer)).toBeTruthy(); | 
					
						
							|  |  |  |     expect(evaluator.isFoldable(findVar(consts, 'someBool').initializer)).toBeTruthy(); | 
					
						
							|  |  |  |     expect(evaluator.isFoldable(findVar(consts, 'one').initializer)).toBeTruthy(); | 
					
						
							|  |  |  |     expect(evaluator.isFoldable(findVar(consts, 'two').initializer)).toBeTruthy(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should be able to fold expressions with foldable references', () => { | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |     const expressions = program.getSourceFile('expressions.ts'); | 
					
						
							| 
									
										
										
										
											2016-06-13 15:56:51 -07:00
										 |  |  |     symbols.define('someName', 'some-name'); | 
					
						
							|  |  |  |     symbols.define('someBool', true); | 
					
						
							|  |  |  |     symbols.define('one', 1); | 
					
						
							|  |  |  |     symbols.define('two', 2); | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  |     expect(evaluator.isFoldable(findVar(expressions, 'three').initializer)).toBeTruthy(); | 
					
						
							|  |  |  |     expect(evaluator.isFoldable(findVar(expressions, 'four').initializer)).toBeTruthy(); | 
					
						
							| 
									
										
										
										
											2016-06-13 15:56:51 -07:00
										 |  |  |     symbols.define('three', 3); | 
					
						
							|  |  |  |     symbols.define('four', 4); | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  |     expect(evaluator.isFoldable(findVar(expressions, 'obj').initializer)).toBeTruthy(); | 
					
						
							|  |  |  |     expect(evaluator.isFoldable(findVar(expressions, 'arr').initializer)).toBeTruthy(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should be able to evaluate literal expressions', () => { | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |     const consts = program.getSourceFile('consts.ts'); | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  |     expect(evaluator.evaluateNode(findVar(consts, 'someName').initializer)).toBe('some-name'); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(consts, 'someBool').initializer)).toBe(true); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(consts, 'one').initializer)).toBe(1); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(consts, 'two').initializer)).toBe(2); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should be able to evaluate expressions', () => { | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |     const expressions = program.getSourceFile('expressions.ts'); | 
					
						
							| 
									
										
										
										
											2016-05-31 11:00:39 -07:00
										 |  |  |     symbols.define('someName', 'some-name'); | 
					
						
							|  |  |  |     symbols.define('someBool', true); | 
					
						
							|  |  |  |     symbols.define('one', 1); | 
					
						
							|  |  |  |     symbols.define('two', 2); | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'three').initializer)).toBe(3); | 
					
						
							| 
									
										
										
										
											2016-05-31 11:00:39 -07:00
										 |  |  |     symbols.define('three', 3); | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'four').initializer)).toBe(4); | 
					
						
							| 
									
										
										
										
											2016-05-31 11:00:39 -07:00
										 |  |  |     symbols.define('four', 4); | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'obj').initializer)) | 
					
						
							|  |  |  |         .toEqual({one: 1, two: 2, three: 3, four: 4}); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'arr').initializer)).toEqual([1, 2, 3, 4]); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'bTrue').initializer)).toEqual(true); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'bFalse').initializer)).toEqual(false); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'bAnd').initializer)).toEqual(true); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'bOr').initializer)).toEqual(true); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'nDiv').initializer)).toEqual(2); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'nMod').initializer)).toEqual(1); | 
					
						
							| 
									
										
										
										
											2016-03-22 17:11:42 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'bLOr').initializer)).toEqual(false || true); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'bLAnd').initializer)).toEqual(true && true); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'bBOr').initializer)).toEqual(0x11 | 0x22); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'bBAnd').initializer)).toEqual(0x11 & 0x03); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'bXor').initializer)).toEqual(0x11 ^ 0x21); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'bEqual').initializer)) | 
					
						
							| 
									
										
										
										
											2016-05-26 10:45:37 -07:00
										 |  |  |         .toEqual(1 == <any>'1'); | 
					
						
							| 
									
										
										
										
											2016-03-22 17:11:42 -07:00
										 |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'bNotEqual').initializer)) | 
					
						
							| 
									
										
										
										
											2016-05-26 10:45:37 -07:00
										 |  |  |         .toEqual(1 != <any>'1'); | 
					
						
							| 
									
										
										
										
											2016-03-22 17:11:42 -07:00
										 |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'bIdentical').initializer)) | 
					
						
							| 
									
										
										
										
											2016-05-26 10:45:37 -07:00
										 |  |  |         .toEqual(1 === <any>'1'); | 
					
						
							| 
									
										
										
										
											2016-03-22 17:11:42 -07:00
										 |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'bNotIdentical').initializer)) | 
					
						
							| 
									
										
										
										
											2016-05-26 10:45:37 -07:00
										 |  |  |         .toEqual(1 !== <any>'1'); | 
					
						
							| 
									
										
										
										
											2016-03-22 17:11:42 -07:00
										 |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'bLessThan').initializer)).toEqual(1 < 2); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'bGreaterThan').initializer)).toEqual(1 > 2); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'bLessThanEqual').initializer)) | 
					
						
							|  |  |  |         .toEqual(1 <= 2); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'bGreaterThanEqual').initializer)) | 
					
						
							|  |  |  |         .toEqual(1 >= 2); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'bShiftLeft').initializer)).toEqual(1 << 2); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'bShiftRight').initializer)) | 
					
						
							|  |  |  |         .toEqual(-1 >> 2); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'bShiftRightU').initializer)) | 
					
						
							|  |  |  |         .toEqual(-1 >>> 2); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should report recursive references as symbolic', () => { | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |     const expressions = program.getSourceFile('expressions.ts'); | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'recursiveA').initializer)) | 
					
						
							| 
									
										
										
										
											2016-05-31 11:00:39 -07:00
										 |  |  |         .toEqual({__symbolic: 'reference', name: 'recursiveB'}); | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  |     expect(evaluator.evaluateNode(findVar(expressions, 'recursiveB').initializer)) | 
					
						
							| 
									
										
										
										
											2016-05-31 11:00:39 -07:00
										 |  |  |         .toEqual({__symbolic: 'reference', name: 'recursiveA'}); | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2016-04-26 16:00:48 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   it('should correctly handle special cases for CONST_EXPR', () => { | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |     const const_expr = program.getSourceFile('const_expr.ts'); | 
					
						
							| 
									
										
										
										
											2016-04-26 16:00:48 -07:00
										 |  |  |     expect(evaluator.evaluateNode(findVar(const_expr, 'bTrue').initializer)).toEqual(true); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(const_expr, 'bFalse').initializer)).toEqual(false); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should resolve a forwardRef', () => { | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |     const forwardRef = program.getSourceFile('forwardRef.ts'); | 
					
						
							| 
									
										
										
										
											2016-04-26 16:00:48 -07:00
										 |  |  |     expect(evaluator.evaluateNode(findVar(forwardRef, 'bTrue').initializer)).toEqual(true); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(forwardRef, 'bFalse').initializer)).toEqual(false); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-01 11:38:42 -07:00
										 |  |  |   it('should return new expressions', () => { | 
					
						
							| 
									
										
										
										
											2016-05-31 11:00:39 -07:00
										 |  |  |     symbols.define('Value', {__symbolic: 'reference', module: './classes', name: 'Value'}); | 
					
						
							| 
									
										
										
										
											2016-08-22 17:37:48 -07:00
										 |  |  |     evaluator = new Evaluator(symbols, new Map()); | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |     const newExpression = program.getSourceFile('newExpression.ts'); | 
					
						
							| 
									
										
										
										
											2016-05-26 10:45:37 -07:00
										 |  |  |     expect(evaluator.evaluateNode(findVar(newExpression, 'someValue').initializer)).toEqual({ | 
					
						
							|  |  |  |       __symbolic: 'new', | 
					
						
							|  |  |  |       expression: {__symbolic: 'reference', name: 'Value', module: './classes'}, | 
					
						
							|  |  |  |       arguments: ['name', 12] | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(findVar(newExpression, 'complex').initializer)).toEqual({ | 
					
						
							|  |  |  |       __symbolic: 'new', | 
					
						
							|  |  |  |       expression: {__symbolic: 'reference', name: 'Value', module: './classes'}, | 
					
						
							|  |  |  |       arguments: ['name', 12] | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-04-26 16:00:48 -07:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2016-06-03 15:43:09 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |   it('should support referene to a declared module type', () => { | 
					
						
							|  |  |  |     const declared = program.getSourceFile('declared.ts'); | 
					
						
							|  |  |  |     const aDecl = findVar(declared, 'a'); | 
					
						
							| 
									
										
										
										
											2016-06-03 15:43:09 -07:00
										 |  |  |     expect(evaluator.evaluateNode(aDecl.type)).toEqual({ | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |       __symbolic: 'select', | 
					
						
							|  |  |  |       expression: {__symbolic: 'reference', name: 'Foo'}, | 
					
						
							|  |  |  |       member: 'A' | 
					
						
							| 
									
										
										
										
											2016-06-03 15:43:09 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should return errors for unsupported expressions', () => { | 
					
						
							|  |  |  |     const errors = program.getSourceFile('errors.ts'); | 
					
						
							|  |  |  |     const fDecl = findVar(errors, 'f'); | 
					
						
							| 
									
										
										
										
											2016-06-09 13:23:29 -07:00
										 |  |  |     expect(evaluator.evaluateNode(fDecl.initializer)) | 
					
						
							|  |  |  |         .toEqual( | 
					
						
							| 
									
										
										
										
											2016-08-22 17:37:48 -07:00
										 |  |  |             {__symbolic: 'error', message: 'Function call not supported', line: 1, character: 12}); | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |     const eDecl = findVar(errors, 'e'); | 
					
						
							| 
									
										
										
										
											2016-06-03 15:43:09 -07:00
										 |  |  |     expect(evaluator.evaluateNode(eDecl.type)).toEqual({ | 
					
						
							|  |  |  |       __symbolic: 'error', | 
					
						
							| 
									
										
										
										
											2016-06-09 13:23:29 -07:00
										 |  |  |       message: 'Could not resolve type', | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |       line: 2, | 
					
						
							| 
									
										
										
										
											2016-08-22 17:37:48 -07:00
										 |  |  |       character: 11, | 
					
						
							| 
									
										
										
										
											2016-06-09 13:23:29 -07:00
										 |  |  |       context: {typeName: 'NotFound'} | 
					
						
							| 
									
										
										
										
											2016-06-03 15:43:09 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |     const sDecl = findVar(errors, 's'); | 
					
						
							| 
									
										
										
										
											2016-06-03 15:43:09 -07:00
										 |  |  |     expect(evaluator.evaluateNode(sDecl.initializer)).toEqual({ | 
					
						
							|  |  |  |       __symbolic: 'error', | 
					
						
							| 
									
										
										
										
											2016-06-09 13:23:29 -07:00
										 |  |  |       message: 'Name expected', | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |       line: 3, | 
					
						
							| 
									
										
										
										
											2016-08-22 17:37:48 -07:00
										 |  |  |       character: 14, | 
					
						
							| 
									
										
										
										
											2016-06-09 13:23:29 -07:00
										 |  |  |       context: {received: '1'} | 
					
						
							| 
									
										
										
										
											2016-06-03 15:43:09 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |     const tDecl = findVar(errors, 't'); | 
					
						
							| 
									
										
										
										
											2016-06-03 15:43:09 -07:00
										 |  |  |     expect(evaluator.evaluateNode(tDecl.initializer)).toEqual({ | 
					
						
							|  |  |  |       __symbolic: 'error', | 
					
						
							| 
									
										
										
										
											2016-06-09 13:23:29 -07:00
										 |  |  |       message: 'Expression form not supported', | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |       line: 4, | 
					
						
							| 
									
										
										
										
											2016-08-22 17:37:48 -07:00
										 |  |  |       character: 12 | 
					
						
							| 
									
										
										
										
											2016-06-03 15:43:09 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2016-06-13 15:56:51 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   it('should be able to fold an array spread', () => { | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |     const expressions = program.getSourceFile('expressions.ts'); | 
					
						
							| 
									
										
										
										
											2016-06-13 15:56:51 -07:00
										 |  |  |     symbols.define('arr', [1, 2, 3, 4]); | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |     const arrSpread = findVar(expressions, 'arrSpread'); | 
					
						
							| 
									
										
										
										
											2016-06-13 15:56:51 -07:00
										 |  |  |     expect(evaluator.evaluateNode(arrSpread.initializer)).toEqual([0, 1, 2, 3, 4, 5]); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should be able to produce a spread expression', () => { | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |     const expressions = program.getSourceFile('expressions.ts'); | 
					
						
							|  |  |  |     const arrSpreadRef = findVar(expressions, 'arrSpreadRef'); | 
					
						
							| 
									
										
										
										
											2016-06-13 15:56:51 -07:00
										 |  |  |     expect(evaluator.evaluateNode(arrSpreadRef.initializer)).toEqual([ | 
					
						
							|  |  |  |       0, {__symbolic: 'spread', expression: {__symbolic: 'reference', name: 'arrImport'}}, 5 | 
					
						
							|  |  |  |     ]); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2017-04-13 11:53:26 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   it('should be able to handle a new expression with no arguments', () => { | 
					
						
							|  |  |  |     const source = sourceFileOf(`
 | 
					
						
							|  |  |  |       export var a = new f; | 
					
						
							|  |  |  |     `);
 | 
					
						
							|  |  |  |     const expr = findVar(source, 'a'); | 
					
						
							|  |  |  |     expect(evaluator.evaluateNode(expr.initializer)) | 
					
						
							|  |  |  |         .toEqual({__symbolic: 'new', expression: {__symbolic: 'reference', name: 'f'}}); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-13 11:53:26 -07:00
										 |  |  | function sourceFileOf(text: string): ts.SourceFile { | 
					
						
							|  |  |  |   return ts.createSourceFile('test.ts', text, ts.ScriptTarget.Latest, true); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-22 17:11:42 -07:00
										 |  |  | const FILES: Directory = { | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  |   'directives.ts': `
 | 
					
						
							|  |  |  |     export function Pipe(options: { name?: string, pure?: boolean}) { | 
					
						
							|  |  |  |       return function(fn: Function) { } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     `,
 | 
					
						
							| 
									
										
										
										
											2016-04-26 16:00:48 -07:00
										 |  |  |   'classes.ts': `
 | 
					
						
							|  |  |  |     export class Value { | 
					
						
							|  |  |  |       constructor(public name: string, public value: any) {} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   `,
 | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  |   'consts.ts': `
 | 
					
						
							|  |  |  |     export var someName = 'some-name'; | 
					
						
							|  |  |  |     export var someBool = true; | 
					
						
							|  |  |  |     export var one = 1; | 
					
						
							|  |  |  |     export var two = 2; | 
					
						
							| 
									
										
										
										
											2016-06-13 15:56:51 -07:00
										 |  |  |     export var arrImport = [1, 2, 3, 4]; | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  |   `,
 | 
					
						
							|  |  |  |   'expressions.ts': `
 | 
					
						
							| 
									
										
										
										
											2016-06-13 15:56:51 -07:00
										 |  |  |     import {arrImport} from './consts'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-31 11:00:39 -07:00
										 |  |  |     export var someName = 'some-name'; | 
					
						
							|  |  |  |     export var someBool = true; | 
					
						
							|  |  |  |     export var one = 1; | 
					
						
							|  |  |  |     export var two = 2; | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     export var three = one + two; | 
					
						
							|  |  |  |     export var four = two * two; | 
					
						
							|  |  |  |     export var obj = { one: one, two: two, three: three, four: four }; | 
					
						
							|  |  |  |     export var arr = [one, two, three, four]; | 
					
						
							|  |  |  |     export var bTrue = someBool; | 
					
						
							|  |  |  |     export var bFalse = !someBool; | 
					
						
							|  |  |  |     export var bAnd = someBool && someBool; | 
					
						
							|  |  |  |     export var bOr = someBool || someBool; | 
					
						
							|  |  |  |     export var nDiv = four / two; | 
					
						
							|  |  |  |     export var nMod = (four + one) % two; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-22 17:11:42 -07:00
										 |  |  |     export var bLOr = false || true;             // true
 | 
					
						
							|  |  |  |     export var bLAnd = true && true;             // true
 | 
					
						
							|  |  |  |     export var bBOr = 0x11 | 0x22;               // 0x33
 | 
					
						
							|  |  |  |     export var bBAnd = 0x11 & 0x03;              // 0x01
 | 
					
						
							|  |  |  |     export var bXor = 0x11 ^ 0x21;               // 0x20
 | 
					
						
							|  |  |  |     export var bEqual = 1 == <any>"1";           // true
 | 
					
						
							|  |  |  |     export var bNotEqual = 1 != <any>"1";        // false
 | 
					
						
							|  |  |  |     export var bIdentical = 1 === <any>"1";      // false
 | 
					
						
							|  |  |  |     export var bNotIdentical = 1 !== <any>"1";   // true
 | 
					
						
							|  |  |  |     export var bLessThan = 1 < 2;                // true
 | 
					
						
							|  |  |  |     export var bGreaterThan = 1 > 2;             // false
 | 
					
						
							|  |  |  |     export var bLessThanEqual = 1 <= 2;          // true
 | 
					
						
							|  |  |  |     export var bGreaterThanEqual = 1 >= 2;       // false
 | 
					
						
							|  |  |  |     export var bShiftLeft = 1 << 2;              // 0x04
 | 
					
						
							|  |  |  |     export var bShiftRight = -1 >> 2;            // -1
 | 
					
						
							|  |  |  |     export var bShiftRightU = -1 >>> 2;          // 0x3fffffff
 | 
					
						
							| 
									
										
										
										
											2016-06-03 15:43:09 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-13 15:56:51 -07:00
										 |  |  |     export var arrSpread = [0, ...arr, 5]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     export var arrSpreadRef = [0, ...arrImport, 5]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-10 13:39:19 -08:00
										 |  |  |     export var recursiveA = recursiveB; | 
					
						
							|  |  |  |     export var recursiveB = recursiveA; | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'A.ts': `
 | 
					
						
							|  |  |  |     import {Pipe} from './directives'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @Pipe({name: 'A', pure: false}) | 
					
						
							|  |  |  |     export class A {}`,
 | 
					
						
							|  |  |  |   'B.ts': `
 | 
					
						
							|  |  |  |     import {Pipe} from './directives'; | 
					
						
							|  |  |  |     import {someName, someBool} from './consts'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @Pipe({name: someName, pure: someBool}) | 
					
						
							| 
									
										
										
										
											2016-04-26 16:00:48 -07:00
										 |  |  |     export class B {}`,
 | 
					
						
							|  |  |  |   'const_expr.ts': `
 | 
					
						
							|  |  |  |     function CONST_EXPR(value: any) { return value; } | 
					
						
							|  |  |  |     export var bTrue = CONST_EXPR(true); | 
					
						
							|  |  |  |     export var bFalse = CONST_EXPR(false); | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'forwardRef.ts': `
 | 
					
						
							|  |  |  |     function forwardRef(value: any) { return value; } | 
					
						
							|  |  |  |     export var bTrue = forwardRef(() => true); | 
					
						
							|  |  |  |     export var bFalse = forwardRef(() => false); | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'newExpression.ts': `
 | 
					
						
							|  |  |  |     import {Value} from './classes'; | 
					
						
							|  |  |  |     function CONST_EXPR(value: any) { return value; } | 
					
						
							|  |  |  |     function forwardRef(value: any) { return value; } | 
					
						
							|  |  |  |     export const someValue = new Value("name", 12); | 
					
						
							|  |  |  |     export const complex = CONST_EXPR(new Value("name", forwardRef(() => 12))); | 
					
						
							| 
									
										
										
										
											2016-06-03 15:43:09 -07:00
										 |  |  |   `,
 | 
					
						
							|  |  |  |   'errors.ts': `
 | 
					
						
							|  |  |  |     let f = () => 1; | 
					
						
							|  |  |  |     let e: NotFound; | 
					
						
							|  |  |  |     let s = { 1: 1, 2: 2 }; | 
					
						
							|  |  |  |     let t = typeof 12; | 
					
						
							|  |  |  |   `,
 | 
					
						
							| 
									
										
										
										
											2016-07-11 17:26:35 -07:00
										 |  |  |   'declared.ts': `
 | 
					
						
							|  |  |  |     declare namespace Foo { | 
					
						
							|  |  |  |       type A = string; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let a: Foo.A = 'some value'; | 
					
						
							|  |  |  |   `
 | 
					
						
							| 
									
										
										
										
											2016-04-25 21:29:06 -07:00
										 |  |  | }; |