| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							| 
									
										
										
										
											2020-05-19 12:08:49 -07:00
										 |  |  |  * Copyright Google LLC All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * 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
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import * as ts from 'typescript'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import {MetadataCollector} from '../../src/metadata/collector'; | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  | import {ClassMetadata, ConstructorMetadata, isClassMetadata, isMetadataGlobalReferenceExpression, METADATA_VERSION, MetadataEntry, MetadataMap, MetadataSymbolicExpression, ModuleMetadata} from '../../src/metadata/schema'; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  | import {Directory, expectValidSources, Host} from './typescript.mocks'; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | describe('Collector', () => { | 
					
						
							|  |  |  |   const documentRegistry = ts.createDocumentRegistry(); | 
					
						
							|  |  |  |   let host: Host; | 
					
						
							|  |  |  |   let service: ts.LanguageService; | 
					
						
							|  |  |  |   let program: ts.Program; | 
					
						
							|  |  |  |   let collector: MetadataCollector; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   beforeEach(() => { | 
					
						
							|  |  |  |     host = new Host(FILES, [ | 
					
						
							| 
									
										
										
										
											2017-12-22 09:36:47 -08:00
										 |  |  |       '/app/app.component.ts',    '/app/cases-data.ts', | 
					
						
							|  |  |  |       '/app/error-cases.ts',      '/promise.ts', | 
					
						
							|  |  |  |       '/unsupported-1.ts',        '/unsupported-2.ts', | 
					
						
							|  |  |  |       '/unsupported-3.ts',        'class-arity.ts', | 
					
						
							|  |  |  |       'declarations.d.ts',        'import-star.ts', | 
					
						
							|  |  |  |       'exported-classes.ts',      'exported-functions.ts', | 
					
						
							|  |  |  |       'exported-enum.ts',         'exported-type.ts', | 
					
						
							|  |  |  |       'exported-consts.ts',       'local-symbol-ref.ts', | 
					
						
							|  |  |  |       'local-function-ref.ts',    'local-symbol-ref-func.ts', | 
					
						
							|  |  |  |       'private-enum.ts',          're-exports.ts', | 
					
						
							|  |  |  |       're-exports-2.ts',          'export-as.d.ts', | 
					
						
							|  |  |  |       'named-module.d.ts',        'static-field-reference.ts', | 
					
						
							|  |  |  |       'static-method.ts',         'static-method-call.ts', | 
					
						
							|  |  |  |       'static-method-with-if.ts', 'static-method-with-default.ts', | 
					
						
							|  |  |  |       'class-inheritance.ts',     'class-inheritance-parent.ts', | 
					
						
							| 
									
										
										
										
											2019-12-07 17:26:25 +01:00
										 |  |  |       'interface-reference.ts',   'static-type-check-members.ts', | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     ]); | 
					
						
							|  |  |  |     service = ts.createLanguageService(host, documentRegistry); | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     program = service.getProgram()!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     collector = new MetadataCollector({quotedNames: true}); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |   it('should not have errors in test data', () => { | 
					
						
							|  |  |  |     expectValidSources(service, program); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   it('should return undefined for modules that have no metadata', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const sourceFile = program.getSourceFile('app/empty.ts')!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     const metadata = collector.getMetadata(sourceFile); | 
					
						
							|  |  |  |     expect(metadata).toBeUndefined(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-20 16:25:08 -07:00
										 |  |  |   it('should treat all symbols of .d.ts files as exported', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const sourceFile = program.getSourceFile('declarations.d.ts')!; | 
					
						
							| 
									
										
										
										
											2017-09-20 16:25:08 -07:00
										 |  |  |     const metadata = collector.getMetadata(sourceFile); | 
					
						
							|  |  |  |     expect(metadata).toEqual({ | 
					
						
							|  |  |  |       __symbolic: 'module', | 
					
						
							| 
									
										
										
										
											2017-09-26 13:31:59 -07:00
										 |  |  |       version: METADATA_VERSION, | 
					
						
							| 
									
										
										
										
											2017-09-20 16:25:08 -07:00
										 |  |  |       metadata: { | 
					
						
							|  |  |  |         DeclaredClass: {__symbolic: 'class'}, | 
					
						
							| 
									
										
										
										
											2019-07-17 17:49:16 -07:00
										 |  |  |         declaredFn: {__symbolic: 'function'} as any, | 
					
						
							| 
									
										
										
										
											2017-09-20 16:25:08 -07:00
										 |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |   it('should return an interface reference for types', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const sourceFile = program.getSourceFile('/exported-type.ts')!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     const metadata = collector.getMetadata(sourceFile); | 
					
						
							| 
									
										
										
										
											2017-09-26 13:31:59 -07:00
										 |  |  |     expect(metadata).toEqual({ | 
					
						
							|  |  |  |       __symbolic: 'module', | 
					
						
							|  |  |  |       version: METADATA_VERSION, | 
					
						
							|  |  |  |       metadata: {SomeType: {__symbolic: 'interface'}} | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should return an interface reference for interfaces', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const sourceFile = program.getSourceFile('app/hero.ts')!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     const metadata = collector.getMetadata(sourceFile); | 
					
						
							| 
									
										
										
										
											2017-09-26 13:31:59 -07:00
										 |  |  |     expect(metadata).toEqual({ | 
					
						
							|  |  |  |       __symbolic: 'module', | 
					
						
							|  |  |  |       version: METADATA_VERSION, | 
					
						
							|  |  |  |       metadata: {Hero: {__symbolic: 'interface'}} | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-30 14:34:01 -08:00
										 |  |  |   it('should preserve module names from TypeScript sources', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const sourceFile = program.getSourceFile('named-module.d.ts')!; | 
					
						
							| 
									
										
										
										
											2017-11-30 14:34:01 -08:00
										 |  |  |     const metadata = collector.getMetadata(sourceFile); | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     expect(metadata!['importAs']).toEqual('some-named-module'); | 
					
						
							| 
									
										
										
										
											2017-11-30 14:34:01 -08:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |   it('should be able to collect a simple component\'s metadata', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const sourceFile = program.getSourceFile('app/hero-detail.component.ts')!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     const metadata = collector.getMetadata(sourceFile); | 
					
						
							|  |  |  |     expect(metadata).toEqual({ | 
					
						
							|  |  |  |       __symbolic: 'module', | 
					
						
							| 
									
										
										
										
											2017-09-26 13:31:59 -07:00
										 |  |  |       version: METADATA_VERSION, | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |       metadata: { | 
					
						
							|  |  |  |         HeroDetailComponent: { | 
					
						
							|  |  |  |           __symbolic: 'class', | 
					
						
							|  |  |  |           decorators: [{ | 
					
						
							|  |  |  |             __symbolic: 'call', | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |             expression: { | 
					
						
							|  |  |  |               __symbolic: 'reference', | 
					
						
							|  |  |  |               module: 'angular2/core', | 
					
						
							|  |  |  |               name: 'Component', | 
					
						
							|  |  |  |               line: 4, | 
					
						
							|  |  |  |               character: 7 | 
					
						
							|  |  |  |             }, | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |             arguments: [{ | 
					
						
							|  |  |  |               selector: 'my-hero-detail', | 
					
						
							|  |  |  |               template: `
 | 
					
						
							|  |  |  |         <div *ngIf="hero"> | 
					
						
							|  |  |  |           <h2>{{hero.name}} details!</h2> | 
					
						
							|  |  |  |           <div><label>id: </label>{{hero.id}}</div> | 
					
						
							|  |  |  |           <div> | 
					
						
							|  |  |  |             <label>name: </label> | 
					
						
							|  |  |  |             <input [(ngModel)]="hero.name" placeholder="name"/> | 
					
						
							|  |  |  |           </div> | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |       `
 | 
					
						
							|  |  |  |             }] | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           members: { | 
					
						
							|  |  |  |             hero: [{ | 
					
						
							|  |  |  |               __symbolic: 'property', | 
					
						
							|  |  |  |               decorators: [{ | 
					
						
							|  |  |  |                 __symbolic: 'call', | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |                 expression: { | 
					
						
							|  |  |  |                   __symbolic: 'reference', | 
					
						
							|  |  |  |                   module: 'angular2/core', | 
					
						
							|  |  |  |                   name: 'Input', | 
					
						
							|  |  |  |                   line: 18, | 
					
						
							|  |  |  |                   character: 9 | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |               }] | 
					
						
							|  |  |  |             }] | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should be able to get a more complicated component\'s metadata', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const sourceFile = program.getSourceFile('/app/app.component.ts')!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     const metadata = collector.getMetadata(sourceFile); | 
					
						
							|  |  |  |     expect(metadata).toEqual({ | 
					
						
							|  |  |  |       __symbolic: 'module', | 
					
						
							| 
									
										
										
										
											2017-09-26 13:31:59 -07:00
										 |  |  |       version: METADATA_VERSION, | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |       metadata: { | 
					
						
							|  |  |  |         AppComponent: { | 
					
						
							|  |  |  |           __symbolic: 'class', | 
					
						
							|  |  |  |           decorators: [{ | 
					
						
							|  |  |  |             __symbolic: 'call', | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |             expression: { | 
					
						
							|  |  |  |               __symbolic: 'reference', | 
					
						
							|  |  |  |               module: 'angular2/core', | 
					
						
							|  |  |  |               name: 'Component', | 
					
						
							|  |  |  |               line: 9, | 
					
						
							|  |  |  |               character: 7 | 
					
						
							|  |  |  |             }, | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |             arguments: [{ | 
					
						
							|  |  |  |               selector: 'my-app', | 
					
						
							|  |  |  |               template: `
 | 
					
						
							|  |  |  |         <h2>My Heroes</h2> | 
					
						
							|  |  |  |         <ul class="heroes"> | 
					
						
							|  |  |  |           <li *ngFor="#hero of heroes" | 
					
						
							|  |  |  |             (click)="onSelect(hero)" | 
					
						
							|  |  |  |             [class.selected]="hero === selectedHero"> | 
					
						
							|  |  |  |             <span class="badge">{{hero.id | lowercase}}</span> {{hero.name | uppercase}} | 
					
						
							|  |  |  |           </li> | 
					
						
							|  |  |  |         </ul> | 
					
						
							|  |  |  |         <my-hero-detail [hero]="selectedHero"></my-hero-detail> | 
					
						
							|  |  |  |         `,
 | 
					
						
							|  |  |  |               directives: [ | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                   __symbolic: 'reference', | 
					
						
							|  |  |  |                   module: './hero-detail.component', | 
					
						
							|  |  |  |                   name: 'HeroDetailComponent', | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |                   line: 22, | 
					
						
							|  |  |  |                   character: 21 | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |                 }, | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |                 { | 
					
						
							|  |  |  |                   __symbolic: 'reference', | 
					
						
							|  |  |  |                   module: 'angular2/common', | 
					
						
							|  |  |  |                   name: 'NgFor', | 
					
						
							|  |  |  |                   line: 22, | 
					
						
							|  |  |  |                   character: 42 | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |               ], | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |               providers: [{ | 
					
						
							|  |  |  |                 __symbolic: 'reference', | 
					
						
							|  |  |  |                 module: './hero.service', | 
					
						
							|  |  |  |                 default: true, | 
					
						
							|  |  |  |                 line: 23, | 
					
						
							|  |  |  |                 character: 20 | 
					
						
							|  |  |  |               }], | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |               pipes: [ | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |                 { | 
					
						
							|  |  |  |                   __symbolic: 'reference', | 
					
						
							|  |  |  |                   module: 'angular2/common', | 
					
						
							|  |  |  |                   name: 'LowerCasePipe', | 
					
						
							|  |  |  |                   line: 24, | 
					
						
							|  |  |  |                   character: 16 | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                   __symbolic: 'reference', | 
					
						
							|  |  |  |                   module: 'angular2/common', | 
					
						
							|  |  |  |                   name: 'UpperCasePipe', | 
					
						
							|  |  |  |                   line: 24, | 
					
						
							|  |  |  |                   character: 38 | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |               ] | 
					
						
							|  |  |  |             }] | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           members: { | 
					
						
							|  |  |  |             __ctor__: [{ | 
					
						
							|  |  |  |               __symbolic: 'constructor', | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |               parameters: [{ | 
					
						
							|  |  |  |                 __symbolic: 'reference', | 
					
						
							|  |  |  |                 module: './hero.service', | 
					
						
							|  |  |  |                 default: true, | 
					
						
							|  |  |  |                 line: 31, | 
					
						
							|  |  |  |                 character: 42 | 
					
						
							|  |  |  |               }] | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |             }], | 
					
						
							|  |  |  |             onSelect: [{__symbolic: 'method'}], | 
					
						
							|  |  |  |             ngOnInit: [{__symbolic: 'method'}], | 
					
						
							|  |  |  |             getHeroes: [{__symbolic: 'method'}] | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should return the values of exported variables', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const sourceFile = program.getSourceFile('/app/mock-heroes.ts')!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     const metadata = collector.getMetadata(sourceFile); | 
					
						
							|  |  |  |     expect(metadata).toEqual({ | 
					
						
							|  |  |  |       __symbolic: 'module', | 
					
						
							| 
									
										
										
										
											2017-09-26 13:31:59 -07:00
										 |  |  |       version: METADATA_VERSION, | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |       metadata: { | 
					
						
							|  |  |  |         HEROES: [ | 
					
						
							| 
									
										
										
										
											2019-04-18 13:09:56 +05:30
										 |  |  |           {'id': 11, 'name': 'Dr Nice', '$quoted$': ['id', 'name']}, | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |           {'id': 12, 'name': 'Narco', '$quoted$': ['id', 'name']}, | 
					
						
							|  |  |  |           {'id': 13, 'name': 'Bombasto', '$quoted$': ['id', 'name']}, | 
					
						
							|  |  |  |           {'id': 14, 'name': 'Celeritas', '$quoted$': ['id', 'name']}, | 
					
						
							|  |  |  |           {'id': 15, 'name': 'Magneta', '$quoted$': ['id', 'name']}, | 
					
						
							|  |  |  |           {'id': 16, 'name': 'RubberMan', '$quoted$': ['id', 'name']}, | 
					
						
							|  |  |  |           {'id': 17, 'name': 'Dynama', '$quoted$': ['id', 'name']}, | 
					
						
							|  |  |  |           {'id': 18, 'name': 'Dr IQ', '$quoted$': ['id', 'name']}, | 
					
						
							|  |  |  |           {'id': 19, 'name': 'Magma', '$quoted$': ['id', 'name']}, | 
					
						
							|  |  |  |           {'id': 20, 'name': 'Tornado', '$quoted$': ['id', 'name']} | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   let casesFile: ts.SourceFile; | 
					
						
							|  |  |  |   let casesMetadata: ModuleMetadata; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   beforeEach(() => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     casesFile = program.getSourceFile('/app/cases-data.ts')!; | 
					
						
							|  |  |  |     casesMetadata = collector.getMetadata(casesFile)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should provide any reference for an any ctor parameter type', () => { | 
					
						
							|  |  |  |     const casesAny = <ClassMetadata>casesMetadata.metadata['CaseAny']; | 
					
						
							|  |  |  |     expect(casesAny).toBeTruthy(); | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const ctorData = casesAny.members!['__ctor__'] as ConstructorMetadata[]; | 
					
						
							| 
									
										
										
										
											2017-10-24 14:54:08 +03:00
										 |  |  |     expect(ctorData).toEqual([{ | 
					
						
							|  |  |  |       __symbolic: 'constructor', | 
					
						
							|  |  |  |       parameters: [{__symbolic: 'reference', name: 'any'} as MetadataSymbolicExpression] | 
					
						
							|  |  |  |     }]); | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should record annotations on set and get declarations', () => { | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |     const propertyData = (line: number) => ({ | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |       name: [{ | 
					
						
							|  |  |  |         __symbolic: 'property', | 
					
						
							|  |  |  |         decorators: [{ | 
					
						
							|  |  |  |           __symbolic: 'call', | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |           expression: | 
					
						
							|  |  |  |               {__symbolic: 'reference', module: 'angular2/core', name: 'Input', line, character: 9}, | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |           arguments: ['firstName'] | 
					
						
							|  |  |  |         }] | 
					
						
							|  |  |  |       }] | 
					
						
							| 
									
										
										
										
											2017-10-24 14:54:08 +03:00
										 |  |  |     } as any as MetadataMap);  // TODO: Review use of `any` here (#19904)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     const caseGetProp = <ClassMetadata>casesMetadata.metadata['GetProp']; | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |     expect(caseGetProp.members).toEqual(propertyData(11)); | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     const caseSetProp = <ClassMetadata>casesMetadata.metadata['SetProp']; | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |     expect(caseSetProp.members).toEqual(propertyData(19)); | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     const caseFullProp = <ClassMetadata>casesMetadata.metadata['FullProp']; | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |     expect(caseFullProp.members).toEqual(propertyData(27)); | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should record references to parameterized types', () => { | 
					
						
							|  |  |  |     const casesForIn = <ClassMetadata>casesMetadata.metadata['NgFor']; | 
					
						
							|  |  |  |     expect(casesForIn).toEqual({ | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |       __symbolic: 'class', | 
					
						
							|  |  |  |       decorators: [{ | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |         __symbolic: 'call', | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |         expression: { | 
					
						
							|  |  |  |           __symbolic: 'reference', | 
					
						
							|  |  |  |           module: 'angular2/core', | 
					
						
							|  |  |  |           name: 'Injectable', | 
					
						
							|  |  |  |           line: 40, | 
					
						
							|  |  |  |           character: 7 | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |       }], | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |       members: { | 
					
						
							|  |  |  |         __ctor__: [{ | 
					
						
							|  |  |  |           __symbolic: 'constructor', | 
					
						
							|  |  |  |           parameters: [{ | 
					
						
							|  |  |  |             __symbolic: 'reference', | 
					
						
							|  |  |  |             name: 'ClassReference', | 
					
						
							|  |  |  |             arguments: [{__symbolic: 'reference', name: 'NgForRow'}] | 
					
						
							|  |  |  |           }] | 
					
						
							|  |  |  |         }] | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2017-10-24 14:54:08 +03:00
										 |  |  |     } as any as ClassMetadata);  // TODO: Review use of `any` here (#19904)
 | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should report errors for destructured imports', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const unsupported1 = program.getSourceFile('/unsupported-1.ts')!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     const metadata = collector.getMetadata(unsupported1); | 
					
						
							|  |  |  |     expect(metadata).toEqual({ | 
					
						
							|  |  |  |       __symbolic: 'module', | 
					
						
							| 
									
										
										
										
											2017-09-26 13:31:59 -07:00
										 |  |  |       version: METADATA_VERSION, | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |       metadata: { | 
					
						
							|  |  |  |         a: {__symbolic: 'error', message: 'Destructuring not supported', line: 1, character: 16}, | 
					
						
							|  |  |  |         b: {__symbolic: 'error', message: 'Destructuring not supported', line: 1, character: 19}, | 
					
						
							|  |  |  |         c: {__symbolic: 'error', message: 'Destructuring not supported', line: 2, character: 16}, | 
					
						
							|  |  |  |         d: {__symbolic: 'error', message: 'Destructuring not supported', line: 2, character: 19}, | 
					
						
							|  |  |  |         e: {__symbolic: 'error', message: 'Variable not initialized', line: 3, character: 15} | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should report an error for references to unexpected types', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const unsupported1 = program.getSourceFile('/unsupported-2.ts')!; | 
					
						
							|  |  |  |     const metadata = collector.getMetadata(unsupported1)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     const barClass = <ClassMetadata>metadata.metadata['Bar']; | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const ctor = <ConstructorMetadata>barClass.members!['__ctor__'][0]; | 
					
						
							|  |  |  |     const parameter = ctor.parameters![0]; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     expect(parameter).toEqual({ | 
					
						
							|  |  |  |       __symbolic: 'error', | 
					
						
							|  |  |  |       message: 'Reference to non-exported class', | 
					
						
							|  |  |  |       line: 3, | 
					
						
							|  |  |  |       character: 4, | 
					
						
							|  |  |  |       context: {className: 'Foo'} | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should be able to handle import star type references', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const importStar = program.getSourceFile('/import-star.ts')!; | 
					
						
							|  |  |  |     const metadata = collector.getMetadata(importStar)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     const someClass = <ClassMetadata>metadata.metadata['SomeClass']; | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const ctor = <ConstructorMetadata>someClass.members!['__ctor__'][0]; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     const parameters = ctor.parameters; | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     expect(parameters).toEqual([ | 
					
						
							|  |  |  |       {__symbolic: 'reference', module: 'angular2/common', name: 'NgFor', line: 6, character: 29} as | 
					
						
							|  |  |  |       MetadataSymbolicExpression | 
					
						
							|  |  |  |     ]); | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should record all exported classes', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const sourceFile = program.getSourceFile('/exported-classes.ts')!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     const metadata = collector.getMetadata(sourceFile); | 
					
						
							|  |  |  |     expect(metadata).toEqual({ | 
					
						
							|  |  |  |       __symbolic: 'module', | 
					
						
							| 
									
										
										
										
											2017-09-26 13:31:59 -07:00
										 |  |  |       version: METADATA_VERSION, | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |       metadata: { | 
					
						
							|  |  |  |         SimpleClass: {__symbolic: 'class'}, | 
					
						
							|  |  |  |         AbstractClass: {__symbolic: 'class'}, | 
					
						
							|  |  |  |         DeclaredClass: {__symbolic: 'class'} | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should be able to record functions', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const exportedFunctions = program.getSourceFile('/exported-functions.ts')!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     const metadata = collector.getMetadata(exportedFunctions); | 
					
						
							|  |  |  |     expect(metadata).toEqual({ | 
					
						
							|  |  |  |       __symbolic: 'module', | 
					
						
							| 
									
										
										
										
											2017-09-26 13:31:59 -07:00
										 |  |  |       version: METADATA_VERSION, | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |       metadata: { | 
					
						
							|  |  |  |         one: { | 
					
						
							|  |  |  |           __symbolic: 'function', | 
					
						
							|  |  |  |           parameters: ['a', 'b', 'c'], | 
					
						
							|  |  |  |           value: { | 
					
						
							|  |  |  |             a: {__symbolic: 'reference', name: 'a'}, | 
					
						
							|  |  |  |             b: {__symbolic: 'reference', name: 'b'}, | 
					
						
							|  |  |  |             c: {__symbolic: 'reference', name: 'c'} | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         two: { | 
					
						
							|  |  |  |           __symbolic: 'function', | 
					
						
							|  |  |  |           parameters: ['a', 'b', 'c'], | 
					
						
							|  |  |  |           value: { | 
					
						
							|  |  |  |             a: {__symbolic: 'reference', name: 'a'}, | 
					
						
							|  |  |  |             b: {__symbolic: 'reference', name: 'b'}, | 
					
						
							|  |  |  |             c: {__symbolic: 'reference', name: 'c'} | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         three: { | 
					
						
							|  |  |  |           __symbolic: 'function', | 
					
						
							|  |  |  |           parameters: ['a', 'b', 'c'], | 
					
						
							|  |  |  |           value: [ | 
					
						
							|  |  |  |             {__symbolic: 'reference', name: 'a'}, {__symbolic: 'reference', name: 'b'}, | 
					
						
							|  |  |  |             {__symbolic: 'reference', name: 'c'} | 
					
						
							|  |  |  |           ] | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         supportsState: { | 
					
						
							|  |  |  |           __symbolic: 'function', | 
					
						
							|  |  |  |           parameters: [], | 
					
						
							|  |  |  |           value: { | 
					
						
							|  |  |  |             __symbolic: 'pre', | 
					
						
							|  |  |  |             operator: '!', | 
					
						
							|  |  |  |             operand: { | 
					
						
							|  |  |  |               __symbolic: 'pre', | 
					
						
							|  |  |  |               operator: '!', | 
					
						
							|  |  |  |               operand: { | 
					
						
							|  |  |  |                 __symbolic: 'select', | 
					
						
							|  |  |  |                 expression: { | 
					
						
							|  |  |  |                   __symbolic: 'select', | 
					
						
							|  |  |  |                   expression: {__symbolic: 'reference', name: 'window'}, | 
					
						
							|  |  |  |                   member: 'history' | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |                 member: 'pushState' | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2019-07-17 17:49:16 -07:00
										 |  |  |         complexFn: {__symbolic: 'function'} as any, | 
					
						
							|  |  |  |         declaredFn: {__symbolic: 'function'} as any, | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should be able to handle import star type references', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const importStar = program.getSourceFile('/import-star.ts')!; | 
					
						
							|  |  |  |     const metadata = collector.getMetadata(importStar)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     const someClass = <ClassMetadata>metadata.metadata['SomeClass']; | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const ctor = <ConstructorMetadata>someClass.members!['__ctor__'][0]; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     const parameters = ctor.parameters; | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     expect(parameters).toEqual([ | 
					
						
							|  |  |  |       {__symbolic: 'reference', module: 'angular2/common', name: 'NgFor', line: 6, character: 29} as | 
					
						
							|  |  |  |       MetadataSymbolicExpression | 
					
						
							|  |  |  |     ]); | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should be able to collect the value of an enum', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const enumSource = program.getSourceFile('/exported-enum.ts')!; | 
					
						
							|  |  |  |     const metadata = collector.getMetadata(enumSource)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     const someEnum: any = metadata.metadata['SomeEnum']; | 
					
						
							|  |  |  |     expect(someEnum).toEqual({A: 0, B: 1, C: 100, D: 101}); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should ignore a non-export enum', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const enumSource = program.getSourceFile('/private-enum.ts')!; | 
					
						
							|  |  |  |     const metadata = collector.getMetadata(enumSource)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     const publicEnum: any = metadata.metadata['PublicEnum']; | 
					
						
							|  |  |  |     const privateEnum: any = metadata.metadata['PrivateEnum']; | 
					
						
							|  |  |  |     expect(publicEnum).toEqual({a: 0, b: 1, c: 2}); | 
					
						
							|  |  |  |     expect(privateEnum).toBeUndefined(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should be able to collect enums initialized from consts', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const enumSource = program.getSourceFile('/exported-enum.ts')!; | 
					
						
							|  |  |  |     const metadata = collector.getMetadata(enumSource)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     const complexEnum: any = metadata.metadata['ComplexEnum']; | 
					
						
							|  |  |  |     expect(complexEnum).toEqual({ | 
					
						
							|  |  |  |       A: 0, | 
					
						
							|  |  |  |       B: 1, | 
					
						
							|  |  |  |       C: 30, | 
					
						
							|  |  |  |       D: 40, | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |       E: { | 
					
						
							|  |  |  |         __symbolic: 'reference', | 
					
						
							|  |  |  |         module: './exported-consts', | 
					
						
							|  |  |  |         name: 'constValue', | 
					
						
							|  |  |  |         line: 5, | 
					
						
							|  |  |  |         character: 75 | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should be able to collect a simple static method', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const staticSource = program.getSourceFile('/static-method.ts')!; | 
					
						
							|  |  |  |     const metadata = collector.getMetadata(staticSource)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     expect(metadata).toBeDefined(); | 
					
						
							|  |  |  |     const classData = <ClassMetadata>metadata.metadata['MyModule']; | 
					
						
							|  |  |  |     expect(classData).toBeDefined(); | 
					
						
							|  |  |  |     expect(classData.statics).toEqual({ | 
					
						
							|  |  |  |       with: { | 
					
						
							|  |  |  |         __symbolic: 'function', | 
					
						
							|  |  |  |         parameters: ['comp'], | 
					
						
							|  |  |  |         value: [ | 
					
						
							|  |  |  |           {__symbolic: 'reference', name: 'MyModule'}, | 
					
						
							|  |  |  |           {provider: 'a', useValue: {__symbolic: 'reference', name: 'comp'}} | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should be able to collect a call to a static method', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const staticSource = program.getSourceFile('/static-method-call.ts')!; | 
					
						
							|  |  |  |     const metadata = collector.getMetadata(staticSource)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     expect(metadata).toBeDefined(); | 
					
						
							|  |  |  |     const classData = <ClassMetadata>metadata.metadata['Foo']; | 
					
						
							|  |  |  |     expect(classData).toBeDefined(); | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     expect(classData.decorators).toEqual([ | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         __symbolic: 'call', | 
					
						
							|  |  |  |         expression: { | 
					
						
							|  |  |  |           __symbolic: 'reference', | 
					
						
							|  |  |  |           module: 'angular2/core', | 
					
						
							|  |  |  |           name: 'Component', | 
					
						
							|  |  |  |           line: 4, | 
					
						
							|  |  |  |           character: 5 | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         arguments: [{ | 
					
						
							|  |  |  |           providers: { | 
					
						
							|  |  |  |             __symbolic: 'call', | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |             expression: { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |               __symbolic: 'select', | 
					
						
							|  |  |  |               expression: { | 
					
						
							|  |  |  |                 __symbolic: 'reference', | 
					
						
							|  |  |  |                 module: './static-method', | 
					
						
							|  |  |  |                 name: 'MyModule', | 
					
						
							|  |  |  |                 line: 5, | 
					
						
							|  |  |  |                 character: 17 | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |               member: 'with' | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |             }, | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |             arguments: ['a'] | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }] | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     ] as any as MetadataSymbolicExpression[]);  // TODO: Review use of `any` here (#19904)
 | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should be able to collect a static field', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const staticSource = program.getSourceFile('/static-field.ts')!; | 
					
						
							|  |  |  |     const metadata = collector.getMetadata(staticSource)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     expect(metadata).toBeDefined(); | 
					
						
							|  |  |  |     const classData = <ClassMetadata>metadata.metadata['MyModule']; | 
					
						
							|  |  |  |     expect(classData).toBeDefined(); | 
					
						
							|  |  |  |     expect(classData.statics).toEqual({VALUE: 'Some string'}); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-07 17:26:25 +01:00
										 |  |  |   it('should ignore static type check members without a value', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const typeCheckMembers = program.getSourceFile('/static-type-check-members.ts')!; | 
					
						
							|  |  |  |     const metadata = collector.getMetadata(typeCheckMembers)!; | 
					
						
							| 
									
										
										
										
											2019-12-07 17:26:25 +01:00
										 |  |  |     const classData = <ClassMetadata>metadata.metadata['MyDirective']; | 
					
						
							|  |  |  |     expect(classData.statics).toEqual({ | 
					
						
							|  |  |  |       foo: 'bar', | 
					
						
							|  |  |  |       declared: {__symbolic: 'error', message: 'Variable not initialized', line: 3, character: 13}, | 
					
						
							|  |  |  |       ngTemplateContextGuard: {__symbolic: 'function', parameters: ['dir', 'ctx'], value: true}, | 
					
						
							|  |  |  |       ngTemplateGuard_value: {__symbolic: 'function', parameters: ['dir', 'expr'], value: true}, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |   it('should be able to collect a reference to a static field', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const staticSource = program.getSourceFile('/static-field-reference.ts')!; | 
					
						
							|  |  |  |     const metadata = collector.getMetadata(staticSource)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     expect(metadata).toBeDefined(); | 
					
						
							|  |  |  |     const classData = <ClassMetadata>metadata.metadata['Foo']; | 
					
						
							|  |  |  |     expect(classData).toBeDefined(); | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     expect(classData.decorators).toEqual([ | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         __symbolic: 'call', | 
					
						
							|  |  |  |         expression: { | 
					
						
							|  |  |  |           __symbolic: 'reference', | 
					
						
							|  |  |  |           module: 'angular2/core', | 
					
						
							|  |  |  |           name: 'Component', | 
					
						
							|  |  |  |           line: 4, | 
					
						
							|  |  |  |           character: 5 | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         arguments: [{ | 
					
						
							|  |  |  |           providers: [{ | 
					
						
							|  |  |  |             provide: 'a', | 
					
						
							|  |  |  |             useValue: { | 
					
						
							|  |  |  |               __symbolic: 'select', | 
					
						
							|  |  |  |               expression: { | 
					
						
							|  |  |  |                 __symbolic: 'reference', | 
					
						
							|  |  |  |                 module: './static-field', | 
					
						
							|  |  |  |                 name: 'MyModule', | 
					
						
							|  |  |  |                 line: 5, | 
					
						
							|  |  |  |                 character: 45 | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |               member: 'VALUE' | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }] | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |         }] | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |       } | 
					
						
							|  |  |  |     ] as any as MetadataSymbolicExpression[]);  // TODO: Review use of `any` here (#19904)
 | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should be able to collect a method with a conditional expression', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const source = program.getSourceFile('/static-method-with-if.ts')!; | 
					
						
							|  |  |  |     const metadata = collector.getMetadata(source)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     expect(metadata).toBeDefined(); | 
					
						
							|  |  |  |     const classData = <ClassMetadata>metadata.metadata['MyModule']; | 
					
						
							|  |  |  |     expect(classData).toBeDefined(); | 
					
						
							|  |  |  |     expect(classData.statics).toEqual({ | 
					
						
							|  |  |  |       with: { | 
					
						
							|  |  |  |         __symbolic: 'function', | 
					
						
							|  |  |  |         parameters: ['cond'], | 
					
						
							|  |  |  |         value: [ | 
					
						
							|  |  |  |           {__symbolic: 'reference', name: 'MyModule'}, { | 
					
						
							|  |  |  |             provider: 'a', | 
					
						
							|  |  |  |             useValue: { | 
					
						
							|  |  |  |               __symbolic: 'if', | 
					
						
							|  |  |  |               condition: {__symbolic: 'reference', name: 'cond'}, | 
					
						
							|  |  |  |               thenExpression: '1', | 
					
						
							|  |  |  |               elseExpression: '2' | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should be able to collect a method with a default parameter', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const source = program.getSourceFile('/static-method-with-default.ts')!; | 
					
						
							|  |  |  |     const metadata = collector.getMetadata(source)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     expect(metadata).toBeDefined(); | 
					
						
							|  |  |  |     const classData = <ClassMetadata>metadata.metadata['MyModule']; | 
					
						
							|  |  |  |     expect(classData).toBeDefined(); | 
					
						
							|  |  |  |     expect(classData.statics).toEqual({ | 
					
						
							|  |  |  |       with: { | 
					
						
							|  |  |  |         __symbolic: 'function', | 
					
						
							|  |  |  |         parameters: ['comp', 'foo', 'bar'], | 
					
						
							|  |  |  |         defaults: [undefined, true, false], | 
					
						
							|  |  |  |         value: [ | 
					
						
							|  |  |  |           {__symbolic: 'reference', name: 'MyModule'}, { | 
					
						
							|  |  |  |             __symbolic: 'if', | 
					
						
							|  |  |  |             condition: {__symbolic: 'reference', name: 'foo'}, | 
					
						
							|  |  |  |             thenExpression: {provider: 'a', useValue: {__symbolic: 'reference', name: 'comp'}}, | 
					
						
							|  |  |  |             elseExpression: {provider: 'b', useValue: {__symbolic: 'reference', name: 'comp'}} | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             __symbolic: 'if', | 
					
						
							|  |  |  |             condition: {__symbolic: 'reference', name: 'bar'}, | 
					
						
							|  |  |  |             thenExpression: {provider: 'c', useValue: {__symbolic: 'reference', name: 'comp'}}, | 
					
						
							|  |  |  |             elseExpression: {provider: 'd', useValue: {__symbolic: 'reference', name: 'comp'}} | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should be able to collect re-exported symbols', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const source = program.getSourceFile('/re-exports.ts')!; | 
					
						
							|  |  |  |     const metadata = collector.getMetadata(source)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     expect(metadata.exports).toEqual([ | 
					
						
							|  |  |  |       {from: './static-field', export: ['MyModule']}, | 
					
						
							|  |  |  |       {from: './static-field-reference', export: [{name: 'Foo', as: 'OtherModule'}]}, | 
					
						
							|  |  |  |       {from: 'angular2/core'} | 
					
						
							|  |  |  |     ]); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should be able to collect a export as symbol', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const source = program.getSourceFile('export-as.d.ts')!; | 
					
						
							|  |  |  |     const metadata = collector.getMetadata(source)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     expect(metadata.metadata).toEqual({SomeFunction: {__symbolic: 'function'}}); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should be able to collect exports with no module specifier', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const source = program.getSourceFile('/re-exports-2.ts')!; | 
					
						
							|  |  |  |     const metadata = collector.getMetadata(source)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     expect(metadata.metadata).toEqual({ | 
					
						
							|  |  |  |       MyClass: Object({__symbolic: 'class'}), | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |       OtherModule: { | 
					
						
							|  |  |  |         __symbolic: 'reference', | 
					
						
							|  |  |  |         module: './static-field-reference', | 
					
						
							|  |  |  |         name: 'Foo', | 
					
						
							|  |  |  |         line: 4, | 
					
						
							|  |  |  |         character: 12 | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       MyOtherModule: { | 
					
						
							|  |  |  |         __symbolic: 'reference', | 
					
						
							|  |  |  |         module: './static-field', | 
					
						
							|  |  |  |         name: 'MyModule', | 
					
						
							|  |  |  |         line: 4, | 
					
						
							|  |  |  |         character: 25 | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should collect an error symbol if collecting a reference to a non-exported symbol', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const source = program.getSourceFile('/local-symbol-ref.ts')!; | 
					
						
							|  |  |  |     const metadata = collector.getMetadata(source)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     expect(metadata.metadata).toEqual({ | 
					
						
							|  |  |  |       REQUIRED_VALIDATOR: { | 
					
						
							|  |  |  |         __symbolic: 'error', | 
					
						
							|  |  |  |         message: 'Reference to a local symbol', | 
					
						
							|  |  |  |         line: 3, | 
					
						
							|  |  |  |         character: 8, | 
					
						
							|  |  |  |         context: {name: 'REQUIRED'} | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       SomeComponent: { | 
					
						
							|  |  |  |         __symbolic: 'class', | 
					
						
							|  |  |  |         decorators: [{ | 
					
						
							|  |  |  |           __symbolic: 'call', | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |           expression: { | 
					
						
							|  |  |  |             __symbolic: 'reference', | 
					
						
							|  |  |  |             module: 'angular2/core', | 
					
						
							|  |  |  |             name: 'Component', | 
					
						
							|  |  |  |             line: 11, | 
					
						
							|  |  |  |             character: 5 | 
					
						
							|  |  |  |           }, | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |           arguments: [{providers: [{__symbolic: 'reference', name: 'REQUIRED_VALIDATOR'}]}] | 
					
						
							|  |  |  |         }] | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should collect an error symbol if collecting a reference to a non-exported function', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const source = program.getSourceFile('/local-function-ref.ts')!; | 
					
						
							|  |  |  |     const metadata = collector.getMetadata(source)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     expect(metadata.metadata).toEqual({ | 
					
						
							|  |  |  |       REQUIRED_VALIDATOR: { | 
					
						
							|  |  |  |         __symbolic: 'error', | 
					
						
							|  |  |  |         message: 'Reference to a non-exported function', | 
					
						
							|  |  |  |         line: 3, | 
					
						
							|  |  |  |         character: 13, | 
					
						
							|  |  |  |         context: {name: 'required'} | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       SomeComponent: { | 
					
						
							|  |  |  |         __symbolic: 'class', | 
					
						
							|  |  |  |         decorators: [{ | 
					
						
							|  |  |  |           __symbolic: 'call', | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |           expression: { | 
					
						
							|  |  |  |             __symbolic: 'reference', | 
					
						
							|  |  |  |             module: 'angular2/core', | 
					
						
							|  |  |  |             name: 'Component', | 
					
						
							|  |  |  |             line: 11, | 
					
						
							|  |  |  |             character: 5 | 
					
						
							|  |  |  |           }, | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |           arguments: [{providers: [{__symbolic: 'reference', name: 'REQUIRED_VALIDATOR'}]}] | 
					
						
							|  |  |  |         }] | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should collect an error for a simple function that references a local variable', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const source = program.getSourceFile('/local-symbol-ref-func.ts')!; | 
					
						
							|  |  |  |     const metadata = collector.getMetadata(source)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     expect(metadata.metadata).toEqual({ | 
					
						
							|  |  |  |       foo: { | 
					
						
							|  |  |  |         __symbolic: 'function', | 
					
						
							|  |  |  |         parameters: ['index'], | 
					
						
							|  |  |  |         value: { | 
					
						
							|  |  |  |           __symbolic: 'error', | 
					
						
							|  |  |  |           message: 'Reference to a local symbol', | 
					
						
							|  |  |  |           line: 1, | 
					
						
							|  |  |  |           character: 8, | 
					
						
							|  |  |  |           context: {name: 'localSymbol'} | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should collect any for interface parameter reference', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const source = program.getSourceFile('/interface-reference.ts')!; | 
					
						
							|  |  |  |     const metadata = collector.getMetadata(source)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     expect((metadata.metadata['SomeClass'] as ClassMetadata).members).toEqual({ | 
					
						
							|  |  |  |       __ctor__: [{ | 
					
						
							|  |  |  |         __symbolic: 'constructor', | 
					
						
							|  |  |  |         parameterDecorators: [[{ | 
					
						
							|  |  |  |           __symbolic: 'call', | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |           expression: { | 
					
						
							|  |  |  |             __symbolic: 'reference', | 
					
						
							|  |  |  |             module: 'angular2/core', | 
					
						
							|  |  |  |             name: 'Inject', | 
					
						
							|  |  |  |             line: 6, | 
					
						
							|  |  |  |             character: 19 | 
					
						
							|  |  |  |           }, | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |           arguments: ['a'] | 
					
						
							|  |  |  |         }]], | 
					
						
							|  |  |  |         parameters: [{__symbolic: 'reference', name: 'any'}] | 
					
						
							|  |  |  |       }] | 
					
						
							| 
									
										
										
										
											2017-10-24 14:54:08 +03:00
										 |  |  |     } as any as MetadataMap);  // TODO: Review use of `any` here (#19904)
 | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('with interpolations', () => { | 
					
						
							|  |  |  |     function e(expr: string, prefix?: string) { | 
					
						
							|  |  |  |       const metadata = collectSource(`${prefix || ''} export let value = ${expr};`); | 
					
						
							|  |  |  |       return expect(metadata.metadata['value']); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     it('should be able to collect a raw interpolated string', () => { | 
					
						
							|  |  |  |       e('`simple value`').toBe('simple value'); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     it('should be able to interpolate a single value', () => { | 
					
						
							|  |  |  |       e('`${foo}`', 'const foo = "foo value"').toBe('foo value'); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it('should be able to interpolate multiple values', () => { | 
					
						
							|  |  |  |       e('`foo:${foo}, bar:${bar}, end`', 'const foo = "foo"; const bar = "bar";') | 
					
						
							|  |  |  |           .toBe('foo:foo, bar:bar, end'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should be able to interpolate with an imported reference', () => { | 
					
						
							|  |  |  |       e('`external:${external}`', 'import {external} from "./external";').toEqual({ | 
					
						
							|  |  |  |         __symbolic: 'binop', | 
					
						
							|  |  |  |         operator: '+', | 
					
						
							|  |  |  |         left: 'external:', | 
					
						
							|  |  |  |         right: { | 
					
						
							|  |  |  |           __symbolic: 'reference', | 
					
						
							|  |  |  |           module: './external', | 
					
						
							|  |  |  |           name: 'external', | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |           line: 0, | 
					
						
							|  |  |  |           character: 68, | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |         } | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should simplify a redundant template', () => { | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |       e('`${external}`', 'import {external} from "./external";').toEqual({ | 
					
						
							|  |  |  |         __symbolic: 'reference', | 
					
						
							|  |  |  |         module: './external', | 
					
						
							|  |  |  |         name: 'external', | 
					
						
							|  |  |  |         line: 0, | 
					
						
							|  |  |  |         character: 59 | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should be able to collect complex template with imported references', () => { | 
					
						
							|  |  |  |       e('`foo:${foo}, bar:${bar}, end`', 'import {foo, bar} from "./external";').toEqual({ | 
					
						
							|  |  |  |         __symbolic: 'binop', | 
					
						
							|  |  |  |         operator: '+', | 
					
						
							|  |  |  |         left: { | 
					
						
							|  |  |  |           __symbolic: 'binop', | 
					
						
							|  |  |  |           operator: '+', | 
					
						
							|  |  |  |           left: { | 
					
						
							|  |  |  |             __symbolic: 'binop', | 
					
						
							|  |  |  |             operator: '+', | 
					
						
							|  |  |  |             left: { | 
					
						
							|  |  |  |               __symbolic: 'binop', | 
					
						
							|  |  |  |               operator: '+', | 
					
						
							|  |  |  |               left: 'foo:', | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |               right: { | 
					
						
							|  |  |  |                 __symbolic: 'reference', | 
					
						
							|  |  |  |                 module: './external', | 
					
						
							|  |  |  |                 name: 'foo', | 
					
						
							|  |  |  |                 line: 0, | 
					
						
							|  |  |  |                 character: 63 | 
					
						
							|  |  |  |               } | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |             }, | 
					
						
							|  |  |  |             right: ', bar:' | 
					
						
							|  |  |  |           }, | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |           right: | 
					
						
							|  |  |  |               {__symbolic: 'reference', module: './external', name: 'bar', line: 0, character: 75} | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |         }, | 
					
						
							|  |  |  |         right: ', end' | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should reject a tagged literal', () => { | 
					
						
							|  |  |  |       e('tag`some value`').toEqual({ | 
					
						
							|  |  |  |         __symbolic: 'error', | 
					
						
							|  |  |  |         message: 'Tagged template expressions are not supported in metadata', | 
					
						
							|  |  |  |         line: 0, | 
					
						
							|  |  |  |         character: 20 | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should ignore |null or |undefined in type expressions', () => { | 
					
						
							|  |  |  |     const metadata = collectSource(`
 | 
					
						
							|  |  |  |       import {Foo} from './foo'; | 
					
						
							|  |  |  |       export class SomeClass { | 
					
						
							|  |  |  |         constructor (a: Foo, b: Foo | null, c: Foo | undefined, d: Foo | undefined | null, e: Foo | undefined | null | Foo) {} | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     `);
 | 
					
						
							|  |  |  |     expect((metadata.metadata['SomeClass'] as ClassMetadata).members).toEqual({ | 
					
						
							|  |  |  |       __ctor__: [{ | 
					
						
							|  |  |  |         __symbolic: 'constructor', | 
					
						
							|  |  |  |         parameters: [ | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |           {__symbolic: 'reference', module: './foo', name: 'Foo', line: 3, character: 24}, | 
					
						
							|  |  |  |           {__symbolic: 'reference', module: './foo', name: 'Foo', line: 3, character: 24}, | 
					
						
							|  |  |  |           {__symbolic: 'reference', module: './foo', name: 'Foo', line: 3, character: 24}, | 
					
						
							|  |  |  |           {__symbolic: 'reference', module: './foo', name: 'Foo', line: 3, character: 24}, | 
					
						
							|  |  |  |           {__symbolic: 'reference', module: './foo', name: 'Foo', line: 3, character: 24} | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |         ] | 
					
						
							|  |  |  |       }] | 
					
						
							| 
									
										
										
										
											2017-10-24 14:54:08 +03:00
										 |  |  |     } as any as MetadataMap);  // TODO: Review use of `any` here (#19904)
 | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should treat exported class expressions as a class', () => { | 
					
						
							|  |  |  |     const source = ts.createSourceFile( | 
					
						
							|  |  |  |         '', `
 | 
					
						
							|  |  |  |     export const InjectionToken: {new<T>(desc: string): InjectionToken<T>;} = class { | 
					
						
							|  |  |  |       constructor(protected _desc: string) {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-21 14:22:06 -07:00
										 |  |  |       toString(): string { return \`InjectionToken \${this._desc}\`; }
 | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     } as any;`,
 | 
					
						
							|  |  |  |         ts.ScriptTarget.Latest, true); | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     const metadata = collector.getMetadata(source)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     expect(metadata.metadata).toEqual({InjectionToken: {__symbolic: 'class'}}); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('in strict mode', () => { | 
					
						
							|  |  |  |     it('should throw if an error symbol is collecting a reference to a non-exported symbol', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |       const source = program.getSourceFile('/local-symbol-ref.ts')!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |       expect(() => collector.getMetadata(source, true)).toThrowError(/Reference to a local symbol/); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw if an error if collecting a reference to a non-exported function', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |       const source = program.getSourceFile('/local-function-ref.ts')!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |       expect(() => collector.getMetadata(source, true)) | 
					
						
							|  |  |  |           .toThrowError(/Reference to a non-exported function/); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw for references to unexpected types', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |       const unsupported2 = program.getSourceFile('/unsupported-2.ts')!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |       expect(() => collector.getMetadata(unsupported2, true)) | 
					
						
							|  |  |  |           .toThrowError(/Reference to non-exported class/); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw for errors in a static method', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |       const unsupported3 = program.getSourceFile('/unsupported-3.ts')!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |       expect(() => collector.getMetadata(unsupported3, true)) | 
					
						
							|  |  |  |           .toThrowError(/Reference to a non-exported class/); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('with invalid input', () => { | 
					
						
							|  |  |  |     it('should not throw with a class with no name', () => { | 
					
						
							|  |  |  |       const fileName = '/invalid-class.ts'; | 
					
						
							|  |  |  |       override(fileName, 'export class'); | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |       const invalidClass = program.getSourceFile(fileName)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |       expect(() => collector.getMetadata(invalidClass)).not.toThrow(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should not throw with a function with no name', () => { | 
					
						
							|  |  |  |       const fileName = '/invalid-function.ts'; | 
					
						
							|  |  |  |       override(fileName, 'export function'); | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |       const invalidFunction = program.getSourceFile(fileName)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |       expect(() => collector.getMetadata(invalidFunction)).not.toThrow(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |   describe( | 
					
						
							|  |  |  |       'inheritance', () => { | 
					
						
							|  |  |  |         it('should record `extends` clauses for declared classes', | 
					
						
							|  |  |  |            () => { | 
					
						
							|  |  |  |              const metadata = | 
					
						
							|  |  |  |                  collector.getMetadata(program.getSourceFile('/class-inheritance.ts')!)!; | 
					
						
							|  |  |  |              expect(metadata.metadata['DeclaredChildClass']) | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |           .toEqual({__symbolic: 'class', extends: {__symbolic: 'reference', name: 'ParentClass'}}); | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |            }); | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |         it('should record `extends` clauses for classes in the same file', | 
					
						
							|  |  |  |            () => { | 
					
						
							|  |  |  |              const metadata = | 
					
						
							|  |  |  |                  collector.getMetadata(program.getSourceFile('/class-inheritance.ts')!)!; | 
					
						
							|  |  |  |              expect(metadata.metadata['ChildClassSameFile']) | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |           .toEqual({__symbolic: 'class', extends: {__symbolic: 'reference', name: 'ParentClass'}}); | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |            }); | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |         it('should record `extends` clauses for classes in a different file', () => { | 
					
						
							|  |  |  |           const metadata = collector.getMetadata(program.getSourceFile('/class-inheritance.ts')!)!; | 
					
						
							|  |  |  |           expect(metadata.metadata['ChildClassOtherFile']).toEqual({ | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |         __symbolic: 'class', | 
					
						
							|  |  |  |         extends: { | 
					
						
							|  |  |  |           __symbolic: 'reference', | 
					
						
							|  |  |  |           module: './class-inheritance-parent', | 
					
						
							| 
									
										
										
										
											2017-11-14 17:49:47 -08:00
										 |  |  |           name: 'ParentClassFromOtherFile', | 
					
						
							|  |  |  |           line: 9, | 
					
						
							|  |  |  |           character: 45, | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |         } | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |         function expectClass(entry: MetadataEntry): entry is ClassMetadata { | 
					
						
							|  |  |  |           const result = isClassMetadata(entry); | 
					
						
							|  |  |  |           expect(result).toBeTruthy(); | 
					
						
							|  |  |  |           return result; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |         it('should collect the correct arity for a class', () => { | 
					
						
							|  |  |  |           const metadata = collector.getMetadata(program.getSourceFile('/class-arity.ts')!)!; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const zero = metadata.metadata['Zero']; | 
					
						
							|  |  |  |           if (expectClass(zero)) expect(zero.arity).toBeUndefined(); | 
					
						
							|  |  |  |           const one = metadata.metadata['One']; | 
					
						
							|  |  |  |           if (expectClass(one)) expect(one.arity).toBe(1); | 
					
						
							|  |  |  |           const two = metadata.metadata['Two']; | 
					
						
							|  |  |  |           if (expectClass(two)) expect(two.arity).toBe(2); | 
					
						
							|  |  |  |           const three = metadata.metadata['Three']; | 
					
						
							|  |  |  |           if (expectClass(three)) expect(three.arity).toBe(3); | 
					
						
							|  |  |  |           const nine = metadata.metadata['Nine']; | 
					
						
							|  |  |  |           if (expectClass(nine)) expect(nine.arity).toBe(9); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-25 11:11:22 +02:00
										 |  |  |   describe('regression', () => { | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     it('should be able to collect a short-hand property value', () => { | 
					
						
							|  |  |  |       const metadata = collectSource(`
 | 
					
						
							|  |  |  |         const children = { f1: 1 }; | 
					
						
							|  |  |  |         export const r = [ | 
					
						
							|  |  |  |           {path: ':locale', children} | 
					
						
							|  |  |  |         ]; | 
					
						
							|  |  |  |       `);
 | 
					
						
							|  |  |  |       expect(metadata.metadata).toEqual({r: [{path: ':locale', children: {f1: 1}}]}); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // #17518
 | 
					
						
							|  |  |  |     it('should skip a default function', () => { | 
					
						
							|  |  |  |       const metadata = collectSource(`
 | 
					
						
							|  |  |  |         export default function () { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const mainRoutes = [ | 
					
						
							|  |  |  |             {name: 'a', abstract: true, component: 'main'}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             {name: 'a.welcome', url: '/welcome', component: 'welcome'} | 
					
						
							|  |  |  |           ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           return mainRoutes; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         }`);
 | 
					
						
							|  |  |  |       expect(metadata).toBeUndefined(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should skip a named default export', () => { | 
					
						
							|  |  |  |       const metadata = collectSource(`
 | 
					
						
							|  |  |  |         function mainRoutes() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const mainRoutes = [ | 
					
						
							|  |  |  |             {name: 'a', abstract: true, component: 'main'}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             {name: 'a.welcome', url: '/welcome', component: 'welcome'} | 
					
						
							|  |  |  |           ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           return mainRoutes; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         exports = foo; | 
					
						
							|  |  |  |         `);
 | 
					
						
							|  |  |  |       expect(metadata).toBeUndefined(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-29 16:29:05 -08:00
										 |  |  |     it('should collect type guards', () => { | 
					
						
							|  |  |  |       const metadata = collectSource(`
 | 
					
						
							|  |  |  |         import {Directive, Input, TemplateRef} from '@angular/core'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         @Directive({selector: '[myIf]'}) | 
					
						
							|  |  |  |         export class MyIf { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           constructor(private templateRef: TemplateRef) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           @Input() myIf: any; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           static typeGuard: <T>(v: T | null | undefined): v is T; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       `);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect((metadata.metadata.MyIf as any).statics.typeGuard) | 
					
						
							|  |  |  |           .not.toBeUndefined('typeGuard was not collected'); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('references', () => { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     beforeEach(() => { | 
					
						
							|  |  |  |       collector = new MetadataCollector({quotedNames: true}); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it('should record a reference to an exported field of a useValue', () => { | 
					
						
							|  |  |  |       const metadata = collectSource(`
 | 
					
						
							|  |  |  |         export var someValue = 1; | 
					
						
							|  |  |  |         export const v = { | 
					
						
							|  |  |  |           useValue: someValue | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |       `);
 | 
					
						
							|  |  |  |       expect(metadata.metadata['someValue']).toEqual(1); | 
					
						
							|  |  |  |       expect(metadata.metadata['v']).toEqual({ | 
					
						
							|  |  |  |         useValue: {__symbolic: 'reference', name: 'someValue'} | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should leave external references in place in an object literal', () => { | 
					
						
							|  |  |  |       const metadata = collectSource(`
 | 
					
						
							|  |  |  |         export const myLambda = () => [1, 2, 3]; | 
					
						
							|  |  |  |         const indirect = [{a: 1, b: 3: c: myLambda}]; | 
					
						
							|  |  |  |         export const v = { | 
					
						
							|  |  |  |           v: {i: indirect} | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       `);
 | 
					
						
							|  |  |  |       expect(metadata.metadata['v']).toEqual({ | 
					
						
							|  |  |  |         v: {i: [{a: 1, b: 3, c: {__symbolic: 'reference', name: 'myLambda'}}]} | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should leave an external reference in place in an array literal', () => { | 
					
						
							|  |  |  |       const metadata = collectSource(`
 | 
					
						
							|  |  |  |         export const myLambda = () => [1, 2, 3]; | 
					
						
							|  |  |  |         const indirect = [1, 3, myLambda}]; | 
					
						
							|  |  |  |         export const v = { | 
					
						
							|  |  |  |           v: {i: indirect} | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       `);
 | 
					
						
							|  |  |  |       expect(metadata.metadata['v']).toEqual({ | 
					
						
							|  |  |  |         v: {i: [1, 3, {__symbolic: 'reference', name: 'myLambda'}]} | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('substitutions', () => { | 
					
						
							|  |  |  |     const lambdaTemp = 'lambdaTemp'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should be able to substitute a lambda', () => { | 
					
						
							|  |  |  |       const source = createSource(`
 | 
					
						
							|  |  |  |         const b = 1; | 
					
						
							|  |  |  |         export const a = () => b; | 
					
						
							|  |  |  |       `);
 | 
					
						
							|  |  |  |       const metadata = collector.getMetadata(source, /* strict */ false, (value, node) => { | 
					
						
							|  |  |  |         if (node.kind === ts.SyntaxKind.ArrowFunction) { | 
					
						
							|  |  |  |           return {__symbolic: 'reference', name: lambdaTemp}; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return value; | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |       expect(metadata!.metadata['a']).toEqual({__symbolic: 'reference', name: lambdaTemp}); | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should compose substitution functions', () => { | 
					
						
							|  |  |  |       const collector = new MetadataCollector({ | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |         substituteExpression: (value, node) => | 
					
						
							|  |  |  |             isMetadataGlobalReferenceExpression(value) && value.name == lambdaTemp ? | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |             {__symbolic: 'reference', name: value.name + '2'} : | 
					
						
							|  |  |  |             value | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       const source = createSource(`
 | 
					
						
							|  |  |  |         const b = 1; | 
					
						
							|  |  |  |         export const a = () => b; | 
					
						
							|  |  |  |       `);
 | 
					
						
							|  |  |  |       const metadata = collector.getMetadata(source, /* strict */ false, (value, node) => { | 
					
						
							|  |  |  |         if (node.kind === ts.SyntaxKind.ArrowFunction) { | 
					
						
							|  |  |  |           return {__symbolic: 'reference', name: lambdaTemp}; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return value; | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |       expect(metadata!.metadata['a']).toEqual({__symbolic: 'reference', name: lambdaTemp + '2'}); | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function override(fileName: string, content: string) { | 
					
						
							|  |  |  |     host.overrideFile(fileName, content); | 
					
						
							|  |  |  |     host.addFile(fileName); | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     program = service.getProgram()!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function collectSource(content: string): ModuleMetadata { | 
					
						
							|  |  |  |     const sourceFile = createSource(content); | 
					
						
							| 
									
										
										
										
											2020-04-07 12:43:43 -07:00
										 |  |  |     return collector.getMetadata(sourceFile)!; | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TODO: Do not use \` in a template literal as it confuses clang-format
 | 
					
						
							|  |  |  | const FILES: Directory = { | 
					
						
							|  |  |  |   'app': { | 
					
						
							|  |  |  |     'app.component.ts': `
 | 
					
						
							|  |  |  |       import {Component as MyComponent, OnInit} from 'angular2/core'; | 
					
						
							|  |  |  |       import * as common from 'angular2/common'; | 
					
						
							|  |  |  |       import {Hero} from './hero'; | 
					
						
							|  |  |  |       import {HeroDetailComponent} from './hero-detail.component'; | 
					
						
							|  |  |  |       import HeroService from './hero.service'; | 
					
						
							|  |  |  |       // thrown away
 | 
					
						
							|  |  |  |       import 'angular2/core'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       @MyComponent({ | 
					
						
							|  |  |  |         selector: 'my-app', | 
					
						
							|  |  |  |         template:` +
 | 
					
						
							|  |  |  |         '`' + | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |         <h2>My Heroes</h2> | 
					
						
							|  |  |  |         <ul class="heroes"> | 
					
						
							|  |  |  |           <li *ngFor="#hero of heroes" | 
					
						
							|  |  |  |             (click)="onSelect(hero)" | 
					
						
							|  |  |  |             [class.selected]="hero === selectedHero"> | 
					
						
							|  |  |  |             <span class="badge">{{hero.id | lowercase}}</span> {{hero.name | uppercase}} | 
					
						
							|  |  |  |           </li> | 
					
						
							|  |  |  |         </ul> | 
					
						
							|  |  |  |         <my-hero-detail [hero]="selectedHero"></my-hero-detail> | 
					
						
							|  |  |  |         ` +
 | 
					
						
							|  |  |  |         '`' + | 
					
						
							|  |  |  |         `,
 | 
					
						
							|  |  |  |         directives: [HeroDetailComponent, common.NgFor], | 
					
						
							|  |  |  |         providers: [HeroService], | 
					
						
							|  |  |  |         pipes: [common.LowerCasePipe, common.UpperCasePipe] | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |       export class AppComponent implements OnInit { | 
					
						
							|  |  |  |         public title = 'Tour of Heroes'; | 
					
						
							|  |  |  |         public heroes: Hero[]; | 
					
						
							|  |  |  |         public selectedHero: Hero; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         constructor(private _heroService: HeroService) { } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         onSelect(hero: Hero) { this.selectedHero = hero; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ngOnInit() { | 
					
						
							|  |  |  |             this.getHeroes() | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         getHeroes() { | 
					
						
							|  |  |  |           this._heroService.getHeroesSlowly().then(heroes => this.heroes = heroes); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }`,
 | 
					
						
							|  |  |  |     'hero.ts': `
 | 
					
						
							|  |  |  |       export interface Hero { | 
					
						
							|  |  |  |         id: number; | 
					
						
							|  |  |  |         name: string; | 
					
						
							|  |  |  |       }`,
 | 
					
						
							|  |  |  |     'empty.ts': ``, | 
					
						
							|  |  |  |     'hero-detail.component.ts': `
 | 
					
						
							|  |  |  |       import {Component, Input} from 'angular2/core'; | 
					
						
							|  |  |  |       import {Hero} from './hero'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       @Component({ | 
					
						
							|  |  |  |         selector: 'my-hero-detail', | 
					
						
							|  |  |  |         template: ` +
 | 
					
						
							|  |  |  |         '`' + | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |         <div *ngIf="hero"> | 
					
						
							|  |  |  |           <h2>{{hero.name}} details!</h2> | 
					
						
							|  |  |  |           <div><label>id: </label>{{hero.id}}</div> | 
					
						
							|  |  |  |           <div> | 
					
						
							|  |  |  |             <label>name: </label> | 
					
						
							|  |  |  |             <input [(ngModel)]="hero.name" placeholder="name"/> | 
					
						
							|  |  |  |           </div> | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |       ` +
 | 
					
						
							|  |  |  |         '`' + | 
					
						
							|  |  |  |         `,
 | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |       export class HeroDetailComponent { | 
					
						
							|  |  |  |         @Input() public hero: Hero; | 
					
						
							|  |  |  |       }`,
 | 
					
						
							|  |  |  |     'mock-heroes.ts': `
 | 
					
						
							|  |  |  |       import {Hero as Hero} from './hero'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       export const HEROES: Hero[] = [ | 
					
						
							| 
									
										
										
										
											2019-04-18 13:09:56 +05:30
										 |  |  |           {"id": 11, "name": "Dr Nice"}, | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |           {"id": 12, "name": "Narco"}, | 
					
						
							|  |  |  |           {"id": 13, "name": "Bombasto"}, | 
					
						
							|  |  |  |           {"id": 14, "name": "Celeritas"}, | 
					
						
							|  |  |  |           {"id": 15, "name": "Magneta"}, | 
					
						
							|  |  |  |           {"id": 16, "name": "RubberMan"}, | 
					
						
							|  |  |  |           {"id": 17, "name": "Dynama"}, | 
					
						
							|  |  |  |           {"id": 18, "name": "Dr IQ"}, | 
					
						
							|  |  |  |           {"id": 19, "name": "Magma"}, | 
					
						
							|  |  |  |           {"id": 20, "name": "Tornado"} | 
					
						
							|  |  |  |       ];`,
 | 
					
						
							|  |  |  |     'default-exporter.ts': `
 | 
					
						
							|  |  |  |       let a: string; | 
					
						
							|  |  |  |       export default a; | 
					
						
							|  |  |  |     `,
 | 
					
						
							|  |  |  |     'hero.service.ts': `
 | 
					
						
							|  |  |  |       import {Injectable} from 'angular2/core'; | 
					
						
							|  |  |  |       import {HEROES} from './mock-heroes'; | 
					
						
							|  |  |  |       import {Hero} from './hero'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       @Injectable() | 
					
						
							|  |  |  |       class HeroService { | 
					
						
							|  |  |  |           getHeros() { | 
					
						
							|  |  |  |               return Promise.resolve(HEROES); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           getHeroesSlowly() { | 
					
						
							|  |  |  |               return new Promise<Hero[]>(resolve => | 
					
						
							|  |  |  |                 setTimeout(()=>resolve(HEROES), 2000)); // 2 seconds
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       export default HeroService;`,
 | 
					
						
							|  |  |  |     'cases-data.ts': `
 | 
					
						
							|  |  |  |       import {Injectable, Input} from 'angular2/core'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       @Injectable() | 
					
						
							|  |  |  |       export class CaseAny { | 
					
						
							|  |  |  |         constructor(param: any) {} | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       @Injectable() | 
					
						
							|  |  |  |       export class GetProp { | 
					
						
							|  |  |  |         private _name: string; | 
					
						
							|  |  |  |         @Input('firstName') get name(): string { | 
					
						
							|  |  |  |           return this._name; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       @Injectable() | 
					
						
							|  |  |  |       export class SetProp { | 
					
						
							|  |  |  |         private _name: string; | 
					
						
							|  |  |  |         @Input('firstName') set name(value: string) { | 
					
						
							|  |  |  |           this._name = value; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       @Injectable() | 
					
						
							|  |  |  |       export class FullProp { | 
					
						
							|  |  |  |         private _name: string; | 
					
						
							|  |  |  |         @Input('firstName') get name(): string { | 
					
						
							|  |  |  |           return this._name; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         set name(value: string) { | 
					
						
							|  |  |  |           this._name = value; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       export class ClassReference<T> { } | 
					
						
							|  |  |  |       export class NgForRow { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       @Injectable() | 
					
						
							|  |  |  |       export class NgFor { | 
					
						
							|  |  |  |         constructor (public ref: ClassReference<NgForRow>) {} | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |      `,
 | 
					
						
							|  |  |  |     'error-cases.ts': `
 | 
					
						
							|  |  |  |       import HeroService from './hero.service'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       export class CaseCtor { | 
					
						
							|  |  |  |         constructor(private _heroService: HeroService) { } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     `
 | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   'promise.ts': `
 | 
					
						
							|  |  |  |     interface PromiseLike<T> { | 
					
						
							|  |  |  |         then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<TResult>; | 
					
						
							|  |  |  |         then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): PromiseLike<TResult>; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     interface Promise<T> { | 
					
						
							|  |  |  |         then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): Promise<TResult>; | 
					
						
							|  |  |  |         then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): Promise<TResult>; | 
					
						
							|  |  |  |         catch(onrejected?: (reason: any) => T | PromiseLike<T>): Promise<T>; | 
					
						
							|  |  |  |         catch(onrejected?: (reason: any) => void): Promise<T>; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     interface PromiseConstructor { | 
					
						
							|  |  |  |         prototype: Promise<any>; | 
					
						
							|  |  |  |         new <T>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void): Promise<T>; | 
					
						
							|  |  |  |         reject(reason: any): Promise<void>; | 
					
						
							|  |  |  |         reject<T>(reason: any): Promise<T>; | 
					
						
							|  |  |  |         resolve<T>(value: T | PromiseLike<T>): Promise<T>; | 
					
						
							|  |  |  |         resolve(): Promise<void>; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     declare var Promise: PromiseConstructor; | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'class-arity.ts': `
 | 
					
						
							|  |  |  |     export class Zero {} | 
					
						
							|  |  |  |     export class One<T> {} | 
					
						
							|  |  |  |     export class Two<T, V> {} | 
					
						
							|  |  |  |     export class Three<T1, T2, T3> {} | 
					
						
							|  |  |  |     export class Nine<T1, T2, T3, T4, T5, T6, T7, T8, T9> {} | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'unsupported-1.ts': `
 | 
					
						
							|  |  |  |     export let {a, b} = {a: 1, b: 2}; | 
					
						
							|  |  |  |     export let [c, d] = [1, 2]; | 
					
						
							|  |  |  |     export let e; | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'unsupported-2.ts': `
 | 
					
						
							|  |  |  |     import {Injectable} from 'angular2/core'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class Foo {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @Injectable() | 
					
						
							|  |  |  |     export class Bar { | 
					
						
							|  |  |  |       constructor(private f: Foo) {} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'unsupported-3.ts': `
 | 
					
						
							|  |  |  |     class Foo {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     export class SomeClass { | 
					
						
							|  |  |  |       static someStatic() { | 
					
						
							|  |  |  |         return Foo; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'interface-reference.ts': `
 | 
					
						
							|  |  |  |     import {Injectable, Inject} from 'angular2/core'; | 
					
						
							|  |  |  |     export interface Test {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @Injectable() | 
					
						
							|  |  |  |     export class SomeClass { | 
					
						
							|  |  |  |       constructor(@Inject("a") test: Test) {} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'import-star.ts': `
 | 
					
						
							|  |  |  |     import {Injectable} from 'angular2/core'; | 
					
						
							|  |  |  |     import * as common from 'angular2/common'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @Injectable() | 
					
						
							|  |  |  |     export class SomeClass { | 
					
						
							|  |  |  |       constructor(private f: common.NgFor) {} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   `,
 | 
					
						
							| 
									
										
										
										
											2017-09-20 16:25:08 -07:00
										 |  |  |   'declarations.d.ts': `
 | 
					
						
							|  |  |  |     declare class DeclaredClass {} | 
					
						
							|  |  |  |     declare function declaredFn(); | 
					
						
							|  |  |  |   `,
 | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |   'exported-classes.ts': `
 | 
					
						
							|  |  |  |     export class SimpleClass {} | 
					
						
							|  |  |  |     export abstract class AbstractClass {} | 
					
						
							|  |  |  |     export declare class DeclaredClass {} | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'class-inheritance-parent.ts': `
 | 
					
						
							|  |  |  |     export class ParentClassFromOtherFile {} | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'class-inheritance.ts': `
 | 
					
						
							|  |  |  |     import {ParentClassFromOtherFile} from './class-inheritance-parent'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     export class ParentClass {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     export declare class DeclaredChildClass extends ParentClass {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     export class ChildClassSameFile extends ParentClass {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     export class ChildClassOtherFile extends ParentClassFromOtherFile {} | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'exported-functions.ts': `
 | 
					
						
							|  |  |  |     export function one(a: string, b: string, c: string) { | 
					
						
							|  |  |  |       return {a: a, b: b, c: c}; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     export function two(a: string, b: string, c: string) { | 
					
						
							|  |  |  |       return {a, b, c}; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     export function three({a, b, c}: {a: string, b: string, c: string}) { | 
					
						
							|  |  |  |       return [a, b, c]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     export function supportsState(): boolean { | 
					
						
							|  |  |  |      return !!window.history.pushState; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     export function complexFn(x: any): boolean { | 
					
						
							|  |  |  |       if (x) { | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     export declare function declaredFn(); | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'exported-type.ts': `
 | 
					
						
							|  |  |  |     export type SomeType = 'a' | 'b'; | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'exported-enum.ts': `
 | 
					
						
							|  |  |  |     import {constValue} from './exported-consts'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     export const someValue = 30; | 
					
						
							|  |  |  |     export enum SomeEnum { A, B, C = 100, D }; | 
					
						
							|  |  |  |     export enum ComplexEnum { A, B, C = someValue, D = someValue + 10, E = constValue }; | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'exported-consts.ts': `
 | 
					
						
							|  |  |  |     export const constValue = 100; | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'static-method.ts': `
 | 
					
						
							|  |  |  |     export class MyModule { | 
					
						
							|  |  |  |       static with(comp: any): any[] { | 
					
						
							|  |  |  |         return [ | 
					
						
							|  |  |  |           MyModule, | 
					
						
							|  |  |  |           { provider: 'a', useValue: comp } | 
					
						
							|  |  |  |         ]; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'static-method-with-default.ts': `
 | 
					
						
							|  |  |  |     export class MyModule { | 
					
						
							|  |  |  |       static with(comp: any, foo: boolean = true, bar: boolean = false): any[] { | 
					
						
							|  |  |  |         return [ | 
					
						
							|  |  |  |           MyModule, | 
					
						
							|  |  |  |           foo ? { provider: 'a', useValue: comp } : {provider: 'b', useValue: comp}, | 
					
						
							|  |  |  |           bar ? { provider: 'c', useValue: comp } : {provider: 'd', useValue: comp} | 
					
						
							|  |  |  |         ]; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'static-method-call.ts': `
 | 
					
						
							|  |  |  |     import {Component} from 'angular2/core'; | 
					
						
							|  |  |  |     import {MyModule} from './static-method'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @Component({ | 
					
						
							|  |  |  |       providers: MyModule.with('a') | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     export class Foo { } | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'static-field.ts': `
 | 
					
						
							|  |  |  |     export class MyModule { | 
					
						
							|  |  |  |       static VALUE = 'Some string'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   `,
 | 
					
						
							| 
									
										
										
										
											2019-12-07 17:26:25 +01:00
										 |  |  |   'static-type-check-members.ts': `
 | 
					
						
							|  |  |  |     export class MyDirective<T> { | 
					
						
							|  |  |  |       static foo = 'bar'; | 
					
						
							|  |  |  |       static declared: string; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       static ngAcceptInputType_disabled: boolean|string; | 
					
						
							|  |  |  |       static ngTemplateContextGuard(dir: any, ctx: any): any { return true; }; | 
					
						
							|  |  |  |       static ngTemplateGuard_declared: 'binding'; | 
					
						
							|  |  |  |       static ngTemplateGuard_value(dir: any, expr: any): any { return true; }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   `,
 | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |   'static-field-reference.ts': `
 | 
					
						
							|  |  |  |     import {Component} from 'angular2/core'; | 
					
						
							|  |  |  |     import {MyModule} from './static-field'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @Component({ | 
					
						
							|  |  |  |       providers: [ { provide: 'a', useValue: MyModule.VALUE } ] | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     export class Foo { } | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'static-method-with-if.ts': `
 | 
					
						
							|  |  |  |     export class MyModule { | 
					
						
							|  |  |  |       static with(cond: boolean): any[] { | 
					
						
							|  |  |  |         return [ | 
					
						
							|  |  |  |           MyModule, | 
					
						
							|  |  |  |           { provider: 'a', useValue: cond ? '1' : '2' } | 
					
						
							|  |  |  |         ]; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   're-exports.ts': `
 | 
					
						
							|  |  |  |     export {MyModule} from './static-field'; | 
					
						
							|  |  |  |     export {Foo as OtherModule} from './static-field-reference'; | 
					
						
							|  |  |  |     export * from 'angular2/core'; | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   're-exports-2.ts': `
 | 
					
						
							|  |  |  |     import {MyModule} from './static-field'; | 
					
						
							|  |  |  |     import {Foo as OtherModule} from './static-field-reference'; | 
					
						
							|  |  |  |     class MyClass {} | 
					
						
							|  |  |  |     export {OtherModule, MyModule as MyOtherModule, MyClass}; | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'export-as.d.ts': `
 | 
					
						
							|  |  |  |      declare function someFunction(): void; | 
					
						
							|  |  |  |      export { someFunction as SomeFunction }; | 
					
						
							|  |  |  |  `,
 | 
					
						
							| 
									
										
										
										
											2017-11-30 14:34:01 -08:00
										 |  |  |   'named-module.d.ts': `
 | 
					
						
							|  |  |  |     /// <amd-module name="some-named-module" />
 | 
					
						
							|  |  |  |     export type SomeType = 'a'; | 
					
						
							|  |  |  |   `,
 | 
					
						
							| 
									
										
										
										
											2017-09-13 16:55:42 -07:00
										 |  |  |   'local-symbol-ref.ts': `
 | 
					
						
							|  |  |  |     import {Component, Validators} from 'angular2/core'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     var REQUIRED; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     export const REQUIRED_VALIDATOR: any = { | 
					
						
							|  |  |  |       provide: 'SomeToken', | 
					
						
							|  |  |  |       useValue: REQUIRED, | 
					
						
							|  |  |  |       multi: true | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @Component({ | 
					
						
							|  |  |  |       providers: [REQUIRED_VALIDATOR] | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     export class SomeComponent {} | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'private-enum.ts': `
 | 
					
						
							|  |  |  |     export enum PublicEnum { a, b, c } | 
					
						
							|  |  |  |     enum PrivateEnum { e, f, g } | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'local-function-ref.ts': `
 | 
					
						
							|  |  |  |     import {Component, Validators} from 'angular2/core'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function required() {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     export const REQUIRED_VALIDATOR: any = { | 
					
						
							|  |  |  |       provide: 'SomeToken', | 
					
						
							|  |  |  |       useValue: required, | 
					
						
							|  |  |  |       multi: true | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @Component({ | 
					
						
							|  |  |  |       providers: [REQUIRED_VALIDATOR] | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     export class SomeComponent {} | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'local-symbol-ref-func.ts': `
 | 
					
						
							|  |  |  |     var localSymbol: any[]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     export function foo(index: number): string { | 
					
						
							|  |  |  |       return localSymbol[index]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   'node_modules': { | 
					
						
							|  |  |  |     'angular2': { | 
					
						
							|  |  |  |       'core.d.ts': `
 | 
					
						
							|  |  |  |           export interface Type extends Function { } | 
					
						
							|  |  |  |           export interface TypeDecorator { | 
					
						
							|  |  |  |               <T extends Type>(type: T): T; | 
					
						
							|  |  |  |               (target: Object, propertyKey?: string | symbol, parameterIndex?: number): void; | 
					
						
							|  |  |  |               annotations: any[]; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           export interface ComponentDecorator extends TypeDecorator { } | 
					
						
							|  |  |  |           export interface ComponentFactory { | 
					
						
							|  |  |  |               (obj: { | 
					
						
							|  |  |  |                   selector?: string; | 
					
						
							|  |  |  |                   inputs?: string[]; | 
					
						
							|  |  |  |                   outputs?: string[]; | 
					
						
							|  |  |  |                   properties?: string[]; | 
					
						
							|  |  |  |                   events?: string[]; | 
					
						
							|  |  |  |                   host?: { | 
					
						
							|  |  |  |                       [key: string]: string; | 
					
						
							|  |  |  |                   }; | 
					
						
							|  |  |  |                   bindings?: any[]; | 
					
						
							|  |  |  |                   providers?: any[]; | 
					
						
							|  |  |  |                   exportAs?: string; | 
					
						
							|  |  |  |                   moduleId?: string; | 
					
						
							|  |  |  |                   queries?: { | 
					
						
							|  |  |  |                       [key: string]: any; | 
					
						
							|  |  |  |                   }; | 
					
						
							|  |  |  |                   viewBindings?: any[]; | 
					
						
							|  |  |  |                   viewProviders?: any[]; | 
					
						
							|  |  |  |                   templateUrl?: string; | 
					
						
							|  |  |  |                   template?: string; | 
					
						
							|  |  |  |                   styleUrls?: string[]; | 
					
						
							|  |  |  |                   styles?: string[]; | 
					
						
							|  |  |  |                   directives?: Array<Type | any[]>; | 
					
						
							|  |  |  |                   pipes?: Array<Type | any[]>; | 
					
						
							|  |  |  |               }): ComponentDecorator; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           export declare var Component: ComponentFactory; | 
					
						
							|  |  |  |           export interface InputFactory { | 
					
						
							|  |  |  |               (bindingPropertyName?: string): any; | 
					
						
							|  |  |  |               new (bindingPropertyName?: string): any; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           export declare var Input: InputFactory; | 
					
						
							|  |  |  |           export interface InjectableFactory { | 
					
						
							|  |  |  |               (): any; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           export declare var Injectable: InjectableFactory; | 
					
						
							|  |  |  |           export interface InjectFactory { | 
					
						
							|  |  |  |             (binding?: any): any; | 
					
						
							|  |  |  |             new (binding?: any): any; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           export declare var Inject: InjectFactory; | 
					
						
							|  |  |  |           export interface OnInit { | 
					
						
							|  |  |  |               ngOnInit(): any; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           export class Validators { | 
					
						
							|  |  |  |             static required(): void; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |       `,
 | 
					
						
							|  |  |  |       'common.d.ts': `
 | 
					
						
							|  |  |  |         export declare class NgFor { | 
					
						
							|  |  |  |             ngForOf: any; | 
					
						
							|  |  |  |             ngForTemplate: any; | 
					
						
							|  |  |  |             ngDoCheck(): void; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         export declare class LowerCasePipe  { | 
					
						
							|  |  |  |           transform(value: string, args?: any[]): string; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         export declare class UpperCasePipe { | 
					
						
							|  |  |  |             transform(value: string, args?: any[]): string; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       `
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function createSource(text: string): ts.SourceFile { | 
					
						
							|  |  |  |   return ts.createSourceFile('', text, ts.ScriptTarget.Latest, true); | 
					
						
							|  |  |  | } |