| 
									
										
										
										
											2016-05-24 10:53:48 -07:00
										 |  |  | import {writeFileSync} from 'fs'; | 
					
						
							| 
									
										
										
										
											2016-04-28 21:57:16 -07:00
										 |  |  | import {convertDecorators} from 'tsickle'; | 
					
						
							| 
									
										
										
										
											2016-05-26 10:45:37 -07:00
										 |  |  | import * as ts from 'typescript'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-24 10:53:48 -07:00
										 |  |  | import {MetadataCollector} from './collector'; | 
					
						
							| 
									
										
										
										
											2016-04-28 21:57:16 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-26 10:45:37 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-28 21:57:16 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Implementation of CompilerHost that forwards all methods to another instance. | 
					
						
							|  |  |  |  * Useful for partial implementations to override only methods they care about. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | export abstract class DelegatingHost implements ts.CompilerHost { | 
					
						
							|  |  |  |   constructor(protected delegate: ts.CompilerHost) {} | 
					
						
							|  |  |  |   getSourceFile = | 
					
						
							|  |  |  |       (fileName: string, languageVersion: ts.ScriptTarget, onError?: (message: string) => void) => | 
					
						
							|  |  |  |           this.delegate.getSourceFile(fileName, languageVersion, onError); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   getCancellationToken = () => this.delegate.getCancellationToken(); | 
					
						
							|  |  |  |   getDefaultLibFileName = (options: ts.CompilerOptions) => | 
					
						
							|  |  |  |       this.delegate.getDefaultLibFileName(options); | 
					
						
							|  |  |  |   getDefaultLibLocation = () => this.delegate.getDefaultLibLocation(); | 
					
						
							|  |  |  |   writeFile: ts.WriteFileCallback = this.delegate.writeFile; | 
					
						
							|  |  |  |   getCurrentDirectory = () => this.delegate.getCurrentDirectory(); | 
					
						
							|  |  |  |   getCanonicalFileName = (fileName: string) => this.delegate.getCanonicalFileName(fileName); | 
					
						
							|  |  |  |   useCaseSensitiveFileNames = () => this.delegate.useCaseSensitiveFileNames(); | 
					
						
							|  |  |  |   getNewLine = () => this.delegate.getNewLine(); | 
					
						
							|  |  |  |   fileExists = (fileName: string) => this.delegate.fileExists(fileName); | 
					
						
							|  |  |  |   readFile = (fileName: string) => this.delegate.readFile(fileName); | 
					
						
							|  |  |  |   trace = (s: string) => this.delegate.trace(s); | 
					
						
							|  |  |  |   directoryExists = (directoryName: string) => this.delegate.directoryExists(directoryName); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-05-01 11:22:39 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | export class TsickleHost extends DelegatingHost { | 
					
						
							| 
									
										
										
										
											2016-04-28 21:57:16 -07:00
										 |  |  |   // Additional diagnostics gathered by pre- and post-emit transformations.
 | 
					
						
							|  |  |  |   public diagnostics: ts.Diagnostic[] = []; | 
					
						
							| 
									
										
										
										
											2016-05-03 16:08:35 -06:00
										 |  |  |   private TSICKLE_SUPPORT = `
 | 
					
						
							|  |  |  | interface DecoratorInvocation { | 
					
						
							|  |  |  |   type: Function; | 
					
						
							|  |  |  |   args?: any[]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | `;
 | 
					
						
							| 
									
										
										
										
											2016-06-07 15:42:27 -07:00
										 |  |  |   constructor(delegate: ts.CompilerHost, private program: ts.Program) { super(delegate); } | 
					
						
							| 
									
										
										
										
											2016-04-28 21:57:16 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   getSourceFile = | 
					
						
							|  |  |  |       (fileName: string, languageVersion: ts.ScriptTarget, onError?: (message: string) => void) => { | 
					
						
							|  |  |  |         const originalContent = this.delegate.readFile(fileName); | 
					
						
							|  |  |  |         let newContent = originalContent; | 
					
						
							|  |  |  |         if (!/\.d\.ts$/.test(fileName)) { | 
					
						
							| 
									
										
										
										
											2016-06-07 15:42:27 -07:00
										 |  |  |           try { | 
					
						
							|  |  |  |             const converted = convertDecorators( | 
					
						
							|  |  |  |                 this.program.getTypeChecker(), this.program.getSourceFile(fileName)); | 
					
						
							|  |  |  |             if (converted.diagnostics) { | 
					
						
							|  |  |  |               this.diagnostics.push(...converted.diagnostics); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             newContent = converted.output + this.TSICKLE_SUPPORT; | 
					
						
							|  |  |  |           } catch (e) { | 
					
						
							|  |  |  |             console.error('Cannot convertDecorators on file', fileName); | 
					
						
							|  |  |  |             throw e; | 
					
						
							| 
									
										
										
										
											2016-04-28 21:57:16 -07:00
										 |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return ts.createSourceFile(fileName, newContent, languageVersion, true); | 
					
						
							| 
									
										
										
										
											2016-05-24 10:53:48 -07:00
										 |  |  |       }; | 
					
						
							| 
									
										
										
										
											2016-04-28 21:57:16 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-02 17:50:09 -07:00
										 |  |  | const IGNORED_FILES = /\.ngfactory\.js$|\.css\.js$|\.css\.shim\.js$/; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-01 11:22:39 -07:00
										 |  |  | export class MetadataWriterHost extends DelegatingHost { | 
					
						
							| 
									
										
										
										
											2016-05-24 10:53:48 -07:00
										 |  |  |   private metadataCollector = new MetadataCollector(); | 
					
						
							| 
									
										
										
										
											2016-05-26 10:45:37 -07:00
										 |  |  |   constructor(delegate: ts.CompilerHost, private program: ts.Program) { super(delegate); } | 
					
						
							| 
									
										
										
										
											2016-05-24 10:53:48 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   private writeMetadata(emitFilePath: string, sourceFile: ts.SourceFile) { | 
					
						
							|  |  |  |     // TODO: replace with DTS filePath when https://github.com/Microsoft/TypeScript/pull/8412 is
 | 
					
						
							|  |  |  |     // released
 | 
					
						
							|  |  |  |     if (/*DTS*/ /\.js$/.test(emitFilePath)) { | 
					
						
							|  |  |  |       const path = emitFilePath.replace(/*DTS*/ /\.js$/, '.metadata.json'); | 
					
						
							| 
									
										
										
										
											2016-05-31 11:00:39 -07:00
										 |  |  |       const metadata = this.metadataCollector.getMetadata(sourceFile); | 
					
						
							| 
									
										
										
										
											2016-05-24 10:53:48 -07:00
										 |  |  |       if (metadata && metadata.metadata) { | 
					
						
							|  |  |  |         const metadataText = JSON.stringify(metadata); | 
					
						
							|  |  |  |         writeFileSync(path, metadataText, {encoding: 'utf-8'}); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-05-01 11:22:39 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-26 10:45:37 -07:00
										 |  |  |   writeFile: ts.WriteFileCallback = | 
					
						
							|  |  |  |       (fileName: string, data: string, writeByteOrderMark: boolean, | 
					
						
							|  |  |  |        onError?: (message: string) => void, sourceFiles?: ts.SourceFile[]) => { | 
					
						
							|  |  |  |         if (/\.d\.ts$/.test(fileName)) { | 
					
						
							|  |  |  |           // Let the original file be written first; this takes care of creating parent directories
 | 
					
						
							|  |  |  |           this.delegate.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles); | 
					
						
							| 
									
										
										
										
											2016-05-01 11:22:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-26 10:45:37 -07:00
										 |  |  |           // TODO: remove this early return after https://github.com/Microsoft/TypeScript/pull/8412
 | 
					
						
							|  |  |  |           // is
 | 
					
						
							|  |  |  |           // released
 | 
					
						
							|  |  |  |           return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-05-01 11:22:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-26 10:45:37 -07:00
										 |  |  |         if (IGNORED_FILES.test(fileName)) { | 
					
						
							|  |  |  |           return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-05-02 17:50:09 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-26 10:45:37 -07:00
										 |  |  |         if (!sourceFiles) { | 
					
						
							|  |  |  |           throw new Error( | 
					
						
							|  |  |  |               'Metadata emit requires the sourceFiles are passed to WriteFileCallback. ' + | 
					
						
							|  |  |  |               'Update to TypeScript ^1.9.0-dev'); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (sourceFiles.length > 1) { | 
					
						
							|  |  |  |           throw new Error('Bundled emit with --out is not supported'); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         this.writeMetadata(fileName, sourceFiles[0]); | 
					
						
							|  |  |  |       }; | 
					
						
							| 
									
										
										
										
											2016-05-01 11:22:39 -07:00
										 |  |  | } |