| 
									
										
										
										
											2019-04-16 23:06:06 -05:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							| 
									
										
										
										
											2020-05-19 12:08:49 -07:00
										 |  |  |  * Copyright Google LLC All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2019-04-16 23:06:06 -05: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 {Rule, SchematicsException, Tree} from '@angular-devkit/schematics'; | 
					
						
							| 
									
										
										
										
											2020-04-02 11:01:43 +02:00
										 |  |  | import {relative} from 'path'; | 
					
						
							| 
									
										
										
										
											2019-04-16 23:06:06 -05:00
										 |  |  | import * as ts from 'typescript'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths'; | 
					
						
							| 
									
										
										
										
											2020-04-02 11:01:43 +02:00
										 |  |  | import {createMigrationProgram} from '../../utils/typescript/compiler_host'; | 
					
						
							| 
									
										
										
										
											2019-09-24 12:19:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-16 23:06:06 -05:00
										 |  |  | import {COMMON_IMPORT, DOCUMENT_TOKEN_NAME, DocumentImportVisitor, ResolvedDocumentImport} from './document_import_visitor'; | 
					
						
							|  |  |  | import {addToImport, createImport, removeFromImport} from './move-import'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** Entry point for the V8 move-document migration. */ | 
					
						
							|  |  |  | export default function(): Rule { | 
					
						
							|  |  |  |   return (tree: Tree) => { | 
					
						
							| 
									
										
										
										
											2019-04-22 21:11:29 +02:00
										 |  |  |     const {buildPaths, testPaths} = getProjectTsConfigPaths(tree); | 
					
						
							| 
									
										
										
										
											2019-04-16 23:06:06 -05:00
										 |  |  |     const basePath = process.cwd(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 21:11:29 +02:00
										 |  |  |     if (!buildPaths.length && !testPaths.length) { | 
					
						
							| 
									
										
										
										
											2020-05-19 12:08:49 -07:00
										 |  |  |       throw new SchematicsException(`Could not find any tsconfig file. Cannot migrate DOCUMENT
 | 
					
						
							| 
									
										
										
										
											2019-04-16 23:06:06 -05:00
										 |  |  |           to new import source.`);
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 21:11:29 +02:00
										 |  |  |     for (const tsconfigPath of [...buildPaths, ...testPaths]) { | 
					
						
							| 
									
										
										
										
											2019-04-16 23:06:06 -05:00
										 |  |  |       runMoveDocumentMigration(tree, tsconfigPath, basePath); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Runs the DOCUMENT InjectionToken import migration for the given TypeScript project. The | 
					
						
							|  |  |  |  * schematic analyzes the imports within the project and moves the deprecated symbol to the | 
					
						
							|  |  |  |  * new import source. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function runMoveDocumentMigration(tree: Tree, tsconfigPath: string, basePath: string) { | 
					
						
							| 
									
										
										
										
											2020-04-02 11:01:43 +02:00
										 |  |  |   const {program} = createMigrationProgram(tree, tsconfigPath, basePath); | 
					
						
							| 
									
										
										
										
											2019-04-16 23:06:06 -05:00
										 |  |  |   const typeChecker = program.getTypeChecker(); | 
					
						
							|  |  |  |   const visitor = new DocumentImportVisitor(typeChecker); | 
					
						
							| 
									
										
										
										
											2019-05-05 12:02:35 +02:00
										 |  |  |   const sourceFiles = program.getSourceFiles().filter( | 
					
						
							|  |  |  |       f => !f.isDeclarationFile && !program.isSourceFileFromExternalLibrary(f)); | 
					
						
							| 
									
										
										
										
											2019-04-16 23:06:06 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Analyze source files by finding imports.
 | 
					
						
							| 
									
										
										
										
											2019-05-05 12:02:35 +02:00
										 |  |  |   sourceFiles.forEach(sourceFile => visitor.visitNode(sourceFile)); | 
					
						
							| 
									
										
										
										
											2019-04-16 23:06:06 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const {importsMap} = visitor; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Walk through all source files that contain resolved queries and update
 | 
					
						
							|  |  |  |   // the source files if needed. Note that we need to update multiple queries
 | 
					
						
							|  |  |  |   // within a source file within the same recorder in order to not throw off
 | 
					
						
							|  |  |  |   // the TypeScript node offsets.
 | 
					
						
							|  |  |  |   importsMap.forEach((resolvedImport: ResolvedDocumentImport, sourceFile: ts.SourceFile) => { | 
					
						
							|  |  |  |     const {platformBrowserImport, commonImport, documentElement} = resolvedImport; | 
					
						
							|  |  |  |     if (!documentElement || !platformBrowserImport) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     const update = tree.beginUpdate(relative(basePath, sourceFile.fileName)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const platformBrowserDeclaration = platformBrowserImport.parent.parent; | 
					
						
							|  |  |  |     const newPlatformBrowserText = | 
					
						
							|  |  |  |         removeFromImport(platformBrowserImport, sourceFile, DOCUMENT_TOKEN_NAME); | 
					
						
							|  |  |  |     const newCommonText = commonImport ? | 
					
						
							|  |  |  |         addToImport(commonImport, sourceFile, documentElement.name, documentElement.propertyName) : | 
					
						
							|  |  |  |         createImport(COMMON_IMPORT, sourceFile, documentElement.name, documentElement.propertyName); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Replace the existing query decorator call expression with the updated
 | 
					
						
							|  |  |  |     // call expression node.
 | 
					
						
							|  |  |  |     update.remove(platformBrowserDeclaration.getStart(), platformBrowserDeclaration.getWidth()); | 
					
						
							|  |  |  |     update.insertRight(platformBrowserDeclaration.getStart(), newPlatformBrowserText); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (commonImport) { | 
					
						
							|  |  |  |       const commonDeclaration = commonImport.parent.parent; | 
					
						
							|  |  |  |       update.remove(commonDeclaration.getStart(), commonDeclaration.getWidth()); | 
					
						
							|  |  |  |       update.insertRight(commonDeclaration.getStart(), newCommonText); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       update.insertRight(platformBrowserDeclaration.getStart(), newCommonText); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     tree.commitUpdate(update); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } |