From 89c8b568a6e858a4a18c244fb2b86861d000ea2a Mon Sep 17 00:00:00 2001 From: ukrukarg Date: Mon, 25 Mar 2019 11:59:24 -0700 Subject: [PATCH] refactor(schematics): merge ast-utils and route-utils into ast-utils (#1648) --- modules/effects/schematics-core/index.ts | 2 +- .../schematics-core/utility/ast-utils.ts | 103 +++++++++++++++- .../schematics-core/utility/ngrx-utils.ts | 3 +- .../schematics-core/utility/route-utils.ts | 110 ------------------ modules/entity/schematics-core/index.ts | 2 +- .../schematics-core/utility/ast-utils.ts | 103 +++++++++++++++- .../schematics-core/utility/ngrx-utils.ts | 3 +- .../schematics-core/utility/route-utils.ts | 110 ------------------ modules/router-store/schematics-core/index.ts | 2 +- .../schematics-core/utility/ast-utils.ts | 103 +++++++++++++++- .../schematics-core/utility/ngrx-utils.ts | 3 +- .../schematics-core/utility/route-utils.ts | 110 ------------------ modules/schematics-core/index.ts | 2 +- modules/schematics-core/utility/ast-utils.ts | 103 +++++++++++++++- modules/schematics-core/utility/ngrx-utils.ts | 3 +- .../schematics-core/utility/route-utils.ts | 110 ------------------ modules/schematics/schematics-core/index.ts | 2 +- .../schematics-core/utility/ast-utils.ts | 103 +++++++++++++++- .../schematics-core/utility/ngrx-utils.ts | 3 +- .../schematics-core/utility/route-utils.ts | 110 ------------------ .../store-devtools/schematics-core/index.ts | 2 +- .../schematics-core/utility/ast-utils.ts | 103 +++++++++++++++- .../schematics-core/utility/ngrx-utils.ts | 3 +- .../schematics-core/utility/route-utils.ts | 110 ------------------ modules/store/schematics-core/index.ts | 2 +- .../schematics-core/utility/ast-utils.ts | 103 +++++++++++++++- .../schematics-core/utility/ngrx-utils.ts | 3 +- .../schematics-core/utility/route-utils.ts | 110 ------------------ 28 files changed, 721 insertions(+), 805 deletions(-) delete mode 100644 modules/effects/schematics-core/utility/route-utils.ts delete mode 100644 modules/entity/schematics-core/utility/route-utils.ts delete mode 100644 modules/router-store/schematics-core/utility/route-utils.ts delete mode 100644 modules/schematics-core/utility/route-utils.ts delete mode 100644 modules/schematics/schematics-core/utility/route-utils.ts delete mode 100644 modules/store-devtools/schematics-core/utility/route-utils.ts delete mode 100644 modules/store/schematics-core/utility/route-utils.ts diff --git a/modules/effects/schematics-core/index.ts b/modules/effects/schematics-core/index.ts index 36cc0abbcf..9608baec44 100644 --- a/modules/effects/schematics-core/index.ts +++ b/modules/effects/schematics-core/index.ts @@ -15,6 +15,7 @@ export { getDecoratorMetadata, getContentOfKeyLiteral, insertAfterLastOccurrence, + insertImport, addBootstrapToModule, addDeclarationToModule, addExportToModule, @@ -49,7 +50,6 @@ export { } from './utility/ngrx-utils'; export { getProjectPath, getProject, isLib } from './utility/project'; -export { insertImport } from './utility/route-utils'; export const stringUtils = { dasherize, diff --git a/modules/effects/schematics-core/utility/ast-utils.ts b/modules/effects/schematics-core/utility/ast-utils.ts index b1f263974e..f6174fc4b1 100644 --- a/modules/effects/schematics-core/utility/ast-utils.ts +++ b/modules/effects/schematics-core/utility/ast-utils.ts @@ -7,8 +7,7 @@ * found in the LICENSE file at https://angular.io/license */ import * as ts from 'typescript'; -import { Change, InsertChange } from './change'; -import { insertImport } from './route-utils'; +import { Change, InsertChange, NoopChange } from './change'; /** * Find all nodes from the AST in the subtree of node of SyntaxKind kind. @@ -537,3 +536,103 @@ export function addBootstrapToModule( importPath ); } + +/** + * Add Import `import { symbolName } from fileName` if the import doesn't exit + * already. Assumes fileToEdit can be resolved and accessed. + * @param fileToEdit (file we want to add import to) + * @param symbolName (item to import) + * @param fileName (path to the file) + * @param isDefault (if true, import follows style for importing default exports) + * @return Change + */ + +export function insertImport( + source: ts.SourceFile, + fileToEdit: string, + symbolName: string, + fileName: string, + isDefault = false +): Change { + const rootNode = source; + const allImports = findNodes(rootNode, ts.SyntaxKind.ImportDeclaration); + + // get nodes that map to import statements from the file fileName + const relevantImports = allImports.filter(node => { + // StringLiteral of the ImportDeclaration is the import file (fileName in this case). + const importFiles = node + .getChildren() + .filter(child => child.kind === ts.SyntaxKind.StringLiteral) + .map(n => (n as ts.StringLiteral).text); + + return importFiles.filter(file => file === fileName).length === 1; + }); + + if (relevantImports.length > 0) { + let importsAsterisk = false; + // imports from import file + const imports: ts.Node[] = []; + relevantImports.forEach(n => { + Array.prototype.push.apply( + imports, + findNodes(n, ts.SyntaxKind.Identifier) + ); + if (findNodes(n, ts.SyntaxKind.AsteriskToken).length > 0) { + importsAsterisk = true; + } + }); + + // if imports * from fileName, don't add symbolName + if (importsAsterisk) { + return new NoopChange(); + } + + const importTextNodes = imports.filter( + n => (n as ts.Identifier).text === symbolName + ); + + // insert import if it's not there + if (importTextNodes.length === 0) { + const fallbackPos = + findNodes( + relevantImports[0], + ts.SyntaxKind.CloseBraceToken + )[0].getStart() || + findNodes(relevantImports[0], ts.SyntaxKind.FromKeyword)[0].getStart(); + + return insertAfterLastOccurrence( + imports, + `, ${symbolName}`, + fileToEdit, + fallbackPos + ); + } + + return new NoopChange(); + } + + // no such import declaration exists + const useStrict = findNodes(rootNode, ts.SyntaxKind.StringLiteral).filter( + n => n.getText() === 'use strict' + ); + let fallbackPos = 0; + if (useStrict.length > 0) { + fallbackPos = useStrict[0].end; + } + const open = isDefault ? '' : '{ '; + const close = isDefault ? '' : ' }'; + // if there are no imports or 'use strict' statement, insert import at beginning of file + const insertAtBeginning = allImports.length === 0 && useStrict.length === 0; + const separator = insertAtBeginning ? '' : ';\n'; + const toInsert = + `${separator}import ${open}${symbolName}${close}` + + ` from '${fileName}'${insertAtBeginning ? ';\n' : ''}`; + + return insertAfterLastOccurrence( + allImports, + toInsert, + fileToEdit, + fallbackPos, + ts.SyntaxKind.StringLiteral + ); +} diff --git a/modules/effects/schematics-core/utility/ngrx-utils.ts b/modules/effects/schematics-core/utility/ngrx-utils.ts index 0dd26b3398..d856f79346 100644 --- a/modules/effects/schematics-core/utility/ngrx-utils.ts +++ b/modules/effects/schematics-core/utility/ngrx-utils.ts @@ -4,8 +4,7 @@ import { InsertChange, Change, NoopChange } from './change'; import { Tree, SchematicsException, Rule } from '@angular-devkit/schematics'; import { normalize } from '@angular-devkit/core'; import { buildRelativePath } from './find-module'; -import { insertImport } from './route-utils'; -import { addImportToModule } from './ast-utils'; +import { addImportToModule, insertImport } from './ast-utils'; export function addReducerToState(options: any): Rule { return (host: Tree) => { diff --git a/modules/effects/schematics-core/utility/route-utils.ts b/modules/effects/schematics-core/utility/route-utils.ts deleted file mode 100644 index d25cc059a8..0000000000 --- a/modules/effects/schematics-core/utility/route-utils.ts +++ /dev/null @@ -1,110 +0,0 @@ -/** - * @license - * Copyright Google Inc. All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ -import * as ts from 'typescript'; -import { findNodes, insertAfterLastOccurrence } from './ast-utils'; -import { Change, NoopChange } from './change'; - -/** - * Add Import `import { symbolName } from fileName` if the import doesn't exit - * already. Assumes fileToEdit can be resolved and accessed. - * @param fileToEdit (file we want to add import to) - * @param symbolName (item to import) - * @param fileName (path to the file) - * @param isDefault (if true, import follows style for importing default exports) - * @return Change - */ - -export function insertImport( - source: ts.SourceFile, - fileToEdit: string, - symbolName: string, - fileName: string, - isDefault = false -): Change { - const rootNode = source; - const allImports = findNodes(rootNode, ts.SyntaxKind.ImportDeclaration); - - // get nodes that map to import statements from the file fileName - const relevantImports = allImports.filter(node => { - // StringLiteral of the ImportDeclaration is the import file (fileName in this case). - const importFiles = node - .getChildren() - .filter(child => child.kind === ts.SyntaxKind.StringLiteral) - .map(n => (n as ts.StringLiteral).text); - - return importFiles.filter(file => file === fileName).length === 1; - }); - - if (relevantImports.length > 0) { - let importsAsterisk = false; - // imports from import file - const imports: ts.Node[] = []; - relevantImports.forEach(n => { - Array.prototype.push.apply( - imports, - findNodes(n, ts.SyntaxKind.Identifier) - ); - if (findNodes(n, ts.SyntaxKind.AsteriskToken).length > 0) { - importsAsterisk = true; - } - }); - - // if imports * from fileName, don't add symbolName - if (importsAsterisk) { - return new NoopChange(); - } - - const importTextNodes = imports.filter( - n => (n as ts.Identifier).text === symbolName - ); - - // insert import if it's not there - if (importTextNodes.length === 0) { - const fallbackPos = - findNodes( - relevantImports[0], - ts.SyntaxKind.CloseBraceToken - )[0].getStart() || - findNodes(relevantImports[0], ts.SyntaxKind.FromKeyword)[0].getStart(); - - return insertAfterLastOccurrence( - imports, - `, ${symbolName}`, - fileToEdit, - fallbackPos - ); - } - - return new NoopChange(); - } - - // no such import declaration exists - const useStrict = findNodes(rootNode, ts.SyntaxKind.StringLiteral).filter( - n => n.getText() === 'use strict' - ); - let fallbackPos = 0; - if (useStrict.length > 0) { - fallbackPos = useStrict[0].end; - } - const open = isDefault ? '' : '{ '; - const close = isDefault ? '' : ' }'; - // if there are no imports or 'use strict' statement, insert import at beginning of file - const insertAtBeginning = allImports.length === 0 && useStrict.length === 0; - const separator = insertAtBeginning ? '' : ';\n'; - const toInsert = - `${separator}import ${open}${symbolName}${close}` + - ` from '${fileName}'${insertAtBeginning ? ';\n' : ''}`; - - return insertAfterLastOccurrence( - allImports, - toInsert, - fileToEdit, - fallbackPos, - ts.SyntaxKind.StringLiteral - ); -} diff --git a/modules/entity/schematics-core/index.ts b/modules/entity/schematics-core/index.ts index 36cc0abbcf..9608baec44 100644 --- a/modules/entity/schematics-core/index.ts +++ b/modules/entity/schematics-core/index.ts @@ -15,6 +15,7 @@ export { getDecoratorMetadata, getContentOfKeyLiteral, insertAfterLastOccurrence, + insertImport, addBootstrapToModule, addDeclarationToModule, addExportToModule, @@ -49,7 +50,6 @@ export { } from './utility/ngrx-utils'; export { getProjectPath, getProject, isLib } from './utility/project'; -export { insertImport } from './utility/route-utils'; export const stringUtils = { dasherize, diff --git a/modules/entity/schematics-core/utility/ast-utils.ts b/modules/entity/schematics-core/utility/ast-utils.ts index b1f263974e..f6174fc4b1 100644 --- a/modules/entity/schematics-core/utility/ast-utils.ts +++ b/modules/entity/schematics-core/utility/ast-utils.ts @@ -7,8 +7,7 @@ * found in the LICENSE file at https://angular.io/license */ import * as ts from 'typescript'; -import { Change, InsertChange } from './change'; -import { insertImport } from './route-utils'; +import { Change, InsertChange, NoopChange } from './change'; /** * Find all nodes from the AST in the subtree of node of SyntaxKind kind. @@ -537,3 +536,103 @@ export function addBootstrapToModule( importPath ); } + +/** + * Add Import `import { symbolName } from fileName` if the import doesn't exit + * already. Assumes fileToEdit can be resolved and accessed. + * @param fileToEdit (file we want to add import to) + * @param symbolName (item to import) + * @param fileName (path to the file) + * @param isDefault (if true, import follows style for importing default exports) + * @return Change + */ + +export function insertImport( + source: ts.SourceFile, + fileToEdit: string, + symbolName: string, + fileName: string, + isDefault = false +): Change { + const rootNode = source; + const allImports = findNodes(rootNode, ts.SyntaxKind.ImportDeclaration); + + // get nodes that map to import statements from the file fileName + const relevantImports = allImports.filter(node => { + // StringLiteral of the ImportDeclaration is the import file (fileName in this case). + const importFiles = node + .getChildren() + .filter(child => child.kind === ts.SyntaxKind.StringLiteral) + .map(n => (n as ts.StringLiteral).text); + + return importFiles.filter(file => file === fileName).length === 1; + }); + + if (relevantImports.length > 0) { + let importsAsterisk = false; + // imports from import file + const imports: ts.Node[] = []; + relevantImports.forEach(n => { + Array.prototype.push.apply( + imports, + findNodes(n, ts.SyntaxKind.Identifier) + ); + if (findNodes(n, ts.SyntaxKind.AsteriskToken).length > 0) { + importsAsterisk = true; + } + }); + + // if imports * from fileName, don't add symbolName + if (importsAsterisk) { + return new NoopChange(); + } + + const importTextNodes = imports.filter( + n => (n as ts.Identifier).text === symbolName + ); + + // insert import if it's not there + if (importTextNodes.length === 0) { + const fallbackPos = + findNodes( + relevantImports[0], + ts.SyntaxKind.CloseBraceToken + )[0].getStart() || + findNodes(relevantImports[0], ts.SyntaxKind.FromKeyword)[0].getStart(); + + return insertAfterLastOccurrence( + imports, + `, ${symbolName}`, + fileToEdit, + fallbackPos + ); + } + + return new NoopChange(); + } + + // no such import declaration exists + const useStrict = findNodes(rootNode, ts.SyntaxKind.StringLiteral).filter( + n => n.getText() === 'use strict' + ); + let fallbackPos = 0; + if (useStrict.length > 0) { + fallbackPos = useStrict[0].end; + } + const open = isDefault ? '' : '{ '; + const close = isDefault ? '' : ' }'; + // if there are no imports or 'use strict' statement, insert import at beginning of file + const insertAtBeginning = allImports.length === 0 && useStrict.length === 0; + const separator = insertAtBeginning ? '' : ';\n'; + const toInsert = + `${separator}import ${open}${symbolName}${close}` + + ` from '${fileName}'${insertAtBeginning ? ';\n' : ''}`; + + return insertAfterLastOccurrence( + allImports, + toInsert, + fileToEdit, + fallbackPos, + ts.SyntaxKind.StringLiteral + ); +} diff --git a/modules/entity/schematics-core/utility/ngrx-utils.ts b/modules/entity/schematics-core/utility/ngrx-utils.ts index 0dd26b3398..d856f79346 100644 --- a/modules/entity/schematics-core/utility/ngrx-utils.ts +++ b/modules/entity/schematics-core/utility/ngrx-utils.ts @@ -4,8 +4,7 @@ import { InsertChange, Change, NoopChange } from './change'; import { Tree, SchematicsException, Rule } from '@angular-devkit/schematics'; import { normalize } from '@angular-devkit/core'; import { buildRelativePath } from './find-module'; -import { insertImport } from './route-utils'; -import { addImportToModule } from './ast-utils'; +import { addImportToModule, insertImport } from './ast-utils'; export function addReducerToState(options: any): Rule { return (host: Tree) => { diff --git a/modules/entity/schematics-core/utility/route-utils.ts b/modules/entity/schematics-core/utility/route-utils.ts deleted file mode 100644 index d25cc059a8..0000000000 --- a/modules/entity/schematics-core/utility/route-utils.ts +++ /dev/null @@ -1,110 +0,0 @@ -/** - * @license - * Copyright Google Inc. All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ -import * as ts from 'typescript'; -import { findNodes, insertAfterLastOccurrence } from './ast-utils'; -import { Change, NoopChange } from './change'; - -/** - * Add Import `import { symbolName } from fileName` if the import doesn't exit - * already. Assumes fileToEdit can be resolved and accessed. - * @param fileToEdit (file we want to add import to) - * @param symbolName (item to import) - * @param fileName (path to the file) - * @param isDefault (if true, import follows style for importing default exports) - * @return Change - */ - -export function insertImport( - source: ts.SourceFile, - fileToEdit: string, - symbolName: string, - fileName: string, - isDefault = false -): Change { - const rootNode = source; - const allImports = findNodes(rootNode, ts.SyntaxKind.ImportDeclaration); - - // get nodes that map to import statements from the file fileName - const relevantImports = allImports.filter(node => { - // StringLiteral of the ImportDeclaration is the import file (fileName in this case). - const importFiles = node - .getChildren() - .filter(child => child.kind === ts.SyntaxKind.StringLiteral) - .map(n => (n as ts.StringLiteral).text); - - return importFiles.filter(file => file === fileName).length === 1; - }); - - if (relevantImports.length > 0) { - let importsAsterisk = false; - // imports from import file - const imports: ts.Node[] = []; - relevantImports.forEach(n => { - Array.prototype.push.apply( - imports, - findNodes(n, ts.SyntaxKind.Identifier) - ); - if (findNodes(n, ts.SyntaxKind.AsteriskToken).length > 0) { - importsAsterisk = true; - } - }); - - // if imports * from fileName, don't add symbolName - if (importsAsterisk) { - return new NoopChange(); - } - - const importTextNodes = imports.filter( - n => (n as ts.Identifier).text === symbolName - ); - - // insert import if it's not there - if (importTextNodes.length === 0) { - const fallbackPos = - findNodes( - relevantImports[0], - ts.SyntaxKind.CloseBraceToken - )[0].getStart() || - findNodes(relevantImports[0], ts.SyntaxKind.FromKeyword)[0].getStart(); - - return insertAfterLastOccurrence( - imports, - `, ${symbolName}`, - fileToEdit, - fallbackPos - ); - } - - return new NoopChange(); - } - - // no such import declaration exists - const useStrict = findNodes(rootNode, ts.SyntaxKind.StringLiteral).filter( - n => n.getText() === 'use strict' - ); - let fallbackPos = 0; - if (useStrict.length > 0) { - fallbackPos = useStrict[0].end; - } - const open = isDefault ? '' : '{ '; - const close = isDefault ? '' : ' }'; - // if there are no imports or 'use strict' statement, insert import at beginning of file - const insertAtBeginning = allImports.length === 0 && useStrict.length === 0; - const separator = insertAtBeginning ? '' : ';\n'; - const toInsert = - `${separator}import ${open}${symbolName}${close}` + - ` from '${fileName}'${insertAtBeginning ? ';\n' : ''}`; - - return insertAfterLastOccurrence( - allImports, - toInsert, - fileToEdit, - fallbackPos, - ts.SyntaxKind.StringLiteral - ); -} diff --git a/modules/router-store/schematics-core/index.ts b/modules/router-store/schematics-core/index.ts index 36cc0abbcf..9608baec44 100644 --- a/modules/router-store/schematics-core/index.ts +++ b/modules/router-store/schematics-core/index.ts @@ -15,6 +15,7 @@ export { getDecoratorMetadata, getContentOfKeyLiteral, insertAfterLastOccurrence, + insertImport, addBootstrapToModule, addDeclarationToModule, addExportToModule, @@ -49,7 +50,6 @@ export { } from './utility/ngrx-utils'; export { getProjectPath, getProject, isLib } from './utility/project'; -export { insertImport } from './utility/route-utils'; export const stringUtils = { dasherize, diff --git a/modules/router-store/schematics-core/utility/ast-utils.ts b/modules/router-store/schematics-core/utility/ast-utils.ts index b1f263974e..f6174fc4b1 100644 --- a/modules/router-store/schematics-core/utility/ast-utils.ts +++ b/modules/router-store/schematics-core/utility/ast-utils.ts @@ -7,8 +7,7 @@ * found in the LICENSE file at https://angular.io/license */ import * as ts from 'typescript'; -import { Change, InsertChange } from './change'; -import { insertImport } from './route-utils'; +import { Change, InsertChange, NoopChange } from './change'; /** * Find all nodes from the AST in the subtree of node of SyntaxKind kind. @@ -537,3 +536,103 @@ export function addBootstrapToModule( importPath ); } + +/** + * Add Import `import { symbolName } from fileName` if the import doesn't exit + * already. Assumes fileToEdit can be resolved and accessed. + * @param fileToEdit (file we want to add import to) + * @param symbolName (item to import) + * @param fileName (path to the file) + * @param isDefault (if true, import follows style for importing default exports) + * @return Change + */ + +export function insertImport( + source: ts.SourceFile, + fileToEdit: string, + symbolName: string, + fileName: string, + isDefault = false +): Change { + const rootNode = source; + const allImports = findNodes(rootNode, ts.SyntaxKind.ImportDeclaration); + + // get nodes that map to import statements from the file fileName + const relevantImports = allImports.filter(node => { + // StringLiteral of the ImportDeclaration is the import file (fileName in this case). + const importFiles = node + .getChildren() + .filter(child => child.kind === ts.SyntaxKind.StringLiteral) + .map(n => (n as ts.StringLiteral).text); + + return importFiles.filter(file => file === fileName).length === 1; + }); + + if (relevantImports.length > 0) { + let importsAsterisk = false; + // imports from import file + const imports: ts.Node[] = []; + relevantImports.forEach(n => { + Array.prototype.push.apply( + imports, + findNodes(n, ts.SyntaxKind.Identifier) + ); + if (findNodes(n, ts.SyntaxKind.AsteriskToken).length > 0) { + importsAsterisk = true; + } + }); + + // if imports * from fileName, don't add symbolName + if (importsAsterisk) { + return new NoopChange(); + } + + const importTextNodes = imports.filter( + n => (n as ts.Identifier).text === symbolName + ); + + // insert import if it's not there + if (importTextNodes.length === 0) { + const fallbackPos = + findNodes( + relevantImports[0], + ts.SyntaxKind.CloseBraceToken + )[0].getStart() || + findNodes(relevantImports[0], ts.SyntaxKind.FromKeyword)[0].getStart(); + + return insertAfterLastOccurrence( + imports, + `, ${symbolName}`, + fileToEdit, + fallbackPos + ); + } + + return new NoopChange(); + } + + // no such import declaration exists + const useStrict = findNodes(rootNode, ts.SyntaxKind.StringLiteral).filter( + n => n.getText() === 'use strict' + ); + let fallbackPos = 0; + if (useStrict.length > 0) { + fallbackPos = useStrict[0].end; + } + const open = isDefault ? '' : '{ '; + const close = isDefault ? '' : ' }'; + // if there are no imports or 'use strict' statement, insert import at beginning of file + const insertAtBeginning = allImports.length === 0 && useStrict.length === 0; + const separator = insertAtBeginning ? '' : ';\n'; + const toInsert = + `${separator}import ${open}${symbolName}${close}` + + ` from '${fileName}'${insertAtBeginning ? ';\n' : ''}`; + + return insertAfterLastOccurrence( + allImports, + toInsert, + fileToEdit, + fallbackPos, + ts.SyntaxKind.StringLiteral + ); +} diff --git a/modules/router-store/schematics-core/utility/ngrx-utils.ts b/modules/router-store/schematics-core/utility/ngrx-utils.ts index 0dd26b3398..d856f79346 100644 --- a/modules/router-store/schematics-core/utility/ngrx-utils.ts +++ b/modules/router-store/schematics-core/utility/ngrx-utils.ts @@ -4,8 +4,7 @@ import { InsertChange, Change, NoopChange } from './change'; import { Tree, SchematicsException, Rule } from '@angular-devkit/schematics'; import { normalize } from '@angular-devkit/core'; import { buildRelativePath } from './find-module'; -import { insertImport } from './route-utils'; -import { addImportToModule } from './ast-utils'; +import { addImportToModule, insertImport } from './ast-utils'; export function addReducerToState(options: any): Rule { return (host: Tree) => { diff --git a/modules/router-store/schematics-core/utility/route-utils.ts b/modules/router-store/schematics-core/utility/route-utils.ts deleted file mode 100644 index d25cc059a8..0000000000 --- a/modules/router-store/schematics-core/utility/route-utils.ts +++ /dev/null @@ -1,110 +0,0 @@ -/** - * @license - * Copyright Google Inc. All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ -import * as ts from 'typescript'; -import { findNodes, insertAfterLastOccurrence } from './ast-utils'; -import { Change, NoopChange } from './change'; - -/** - * Add Import `import { symbolName } from fileName` if the import doesn't exit - * already. Assumes fileToEdit can be resolved and accessed. - * @param fileToEdit (file we want to add import to) - * @param symbolName (item to import) - * @param fileName (path to the file) - * @param isDefault (if true, import follows style for importing default exports) - * @return Change - */ - -export function insertImport( - source: ts.SourceFile, - fileToEdit: string, - symbolName: string, - fileName: string, - isDefault = false -): Change { - const rootNode = source; - const allImports = findNodes(rootNode, ts.SyntaxKind.ImportDeclaration); - - // get nodes that map to import statements from the file fileName - const relevantImports = allImports.filter(node => { - // StringLiteral of the ImportDeclaration is the import file (fileName in this case). - const importFiles = node - .getChildren() - .filter(child => child.kind === ts.SyntaxKind.StringLiteral) - .map(n => (n as ts.StringLiteral).text); - - return importFiles.filter(file => file === fileName).length === 1; - }); - - if (relevantImports.length > 0) { - let importsAsterisk = false; - // imports from import file - const imports: ts.Node[] = []; - relevantImports.forEach(n => { - Array.prototype.push.apply( - imports, - findNodes(n, ts.SyntaxKind.Identifier) - ); - if (findNodes(n, ts.SyntaxKind.AsteriskToken).length > 0) { - importsAsterisk = true; - } - }); - - // if imports * from fileName, don't add symbolName - if (importsAsterisk) { - return new NoopChange(); - } - - const importTextNodes = imports.filter( - n => (n as ts.Identifier).text === symbolName - ); - - // insert import if it's not there - if (importTextNodes.length === 0) { - const fallbackPos = - findNodes( - relevantImports[0], - ts.SyntaxKind.CloseBraceToken - )[0].getStart() || - findNodes(relevantImports[0], ts.SyntaxKind.FromKeyword)[0].getStart(); - - return insertAfterLastOccurrence( - imports, - `, ${symbolName}`, - fileToEdit, - fallbackPos - ); - } - - return new NoopChange(); - } - - // no such import declaration exists - const useStrict = findNodes(rootNode, ts.SyntaxKind.StringLiteral).filter( - n => n.getText() === 'use strict' - ); - let fallbackPos = 0; - if (useStrict.length > 0) { - fallbackPos = useStrict[0].end; - } - const open = isDefault ? '' : '{ '; - const close = isDefault ? '' : ' }'; - // if there are no imports or 'use strict' statement, insert import at beginning of file - const insertAtBeginning = allImports.length === 0 && useStrict.length === 0; - const separator = insertAtBeginning ? '' : ';\n'; - const toInsert = - `${separator}import ${open}${symbolName}${close}` + - ` from '${fileName}'${insertAtBeginning ? ';\n' : ''}`; - - return insertAfterLastOccurrence( - allImports, - toInsert, - fileToEdit, - fallbackPos, - ts.SyntaxKind.StringLiteral - ); -} diff --git a/modules/schematics-core/index.ts b/modules/schematics-core/index.ts index 36cc0abbcf..9608baec44 100644 --- a/modules/schematics-core/index.ts +++ b/modules/schematics-core/index.ts @@ -15,6 +15,7 @@ export { getDecoratorMetadata, getContentOfKeyLiteral, insertAfterLastOccurrence, + insertImport, addBootstrapToModule, addDeclarationToModule, addExportToModule, @@ -49,7 +50,6 @@ export { } from './utility/ngrx-utils'; export { getProjectPath, getProject, isLib } from './utility/project'; -export { insertImport } from './utility/route-utils'; export const stringUtils = { dasherize, diff --git a/modules/schematics-core/utility/ast-utils.ts b/modules/schematics-core/utility/ast-utils.ts index b1f263974e..f6174fc4b1 100644 --- a/modules/schematics-core/utility/ast-utils.ts +++ b/modules/schematics-core/utility/ast-utils.ts @@ -7,8 +7,7 @@ * found in the LICENSE file at https://angular.io/license */ import * as ts from 'typescript'; -import { Change, InsertChange } from './change'; -import { insertImport } from './route-utils'; +import { Change, InsertChange, NoopChange } from './change'; /** * Find all nodes from the AST in the subtree of node of SyntaxKind kind. @@ -537,3 +536,103 @@ export function addBootstrapToModule( importPath ); } + +/** + * Add Import `import { symbolName } from fileName` if the import doesn't exit + * already. Assumes fileToEdit can be resolved and accessed. + * @param fileToEdit (file we want to add import to) + * @param symbolName (item to import) + * @param fileName (path to the file) + * @param isDefault (if true, import follows style for importing default exports) + * @return Change + */ + +export function insertImport( + source: ts.SourceFile, + fileToEdit: string, + symbolName: string, + fileName: string, + isDefault = false +): Change { + const rootNode = source; + const allImports = findNodes(rootNode, ts.SyntaxKind.ImportDeclaration); + + // get nodes that map to import statements from the file fileName + const relevantImports = allImports.filter(node => { + // StringLiteral of the ImportDeclaration is the import file (fileName in this case). + const importFiles = node + .getChildren() + .filter(child => child.kind === ts.SyntaxKind.StringLiteral) + .map(n => (n as ts.StringLiteral).text); + + return importFiles.filter(file => file === fileName).length === 1; + }); + + if (relevantImports.length > 0) { + let importsAsterisk = false; + // imports from import file + const imports: ts.Node[] = []; + relevantImports.forEach(n => { + Array.prototype.push.apply( + imports, + findNodes(n, ts.SyntaxKind.Identifier) + ); + if (findNodes(n, ts.SyntaxKind.AsteriskToken).length > 0) { + importsAsterisk = true; + } + }); + + // if imports * from fileName, don't add symbolName + if (importsAsterisk) { + return new NoopChange(); + } + + const importTextNodes = imports.filter( + n => (n as ts.Identifier).text === symbolName + ); + + // insert import if it's not there + if (importTextNodes.length === 0) { + const fallbackPos = + findNodes( + relevantImports[0], + ts.SyntaxKind.CloseBraceToken + )[0].getStart() || + findNodes(relevantImports[0], ts.SyntaxKind.FromKeyword)[0].getStart(); + + return insertAfterLastOccurrence( + imports, + `, ${symbolName}`, + fileToEdit, + fallbackPos + ); + } + + return new NoopChange(); + } + + // no such import declaration exists + const useStrict = findNodes(rootNode, ts.SyntaxKind.StringLiteral).filter( + n => n.getText() === 'use strict' + ); + let fallbackPos = 0; + if (useStrict.length > 0) { + fallbackPos = useStrict[0].end; + } + const open = isDefault ? '' : '{ '; + const close = isDefault ? '' : ' }'; + // if there are no imports or 'use strict' statement, insert import at beginning of file + const insertAtBeginning = allImports.length === 0 && useStrict.length === 0; + const separator = insertAtBeginning ? '' : ';\n'; + const toInsert = + `${separator}import ${open}${symbolName}${close}` + + ` from '${fileName}'${insertAtBeginning ? ';\n' : ''}`; + + return insertAfterLastOccurrence( + allImports, + toInsert, + fileToEdit, + fallbackPos, + ts.SyntaxKind.StringLiteral + ); +} diff --git a/modules/schematics-core/utility/ngrx-utils.ts b/modules/schematics-core/utility/ngrx-utils.ts index 0dd26b3398..d856f79346 100644 --- a/modules/schematics-core/utility/ngrx-utils.ts +++ b/modules/schematics-core/utility/ngrx-utils.ts @@ -4,8 +4,7 @@ import { InsertChange, Change, NoopChange } from './change'; import { Tree, SchematicsException, Rule } from '@angular-devkit/schematics'; import { normalize } from '@angular-devkit/core'; import { buildRelativePath } from './find-module'; -import { insertImport } from './route-utils'; -import { addImportToModule } from './ast-utils'; +import { addImportToModule, insertImport } from './ast-utils'; export function addReducerToState(options: any): Rule { return (host: Tree) => { diff --git a/modules/schematics-core/utility/route-utils.ts b/modules/schematics-core/utility/route-utils.ts deleted file mode 100644 index d25cc059a8..0000000000 --- a/modules/schematics-core/utility/route-utils.ts +++ /dev/null @@ -1,110 +0,0 @@ -/** - * @license - * Copyright Google Inc. All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ -import * as ts from 'typescript'; -import { findNodes, insertAfterLastOccurrence } from './ast-utils'; -import { Change, NoopChange } from './change'; - -/** - * Add Import `import { symbolName } from fileName` if the import doesn't exit - * already. Assumes fileToEdit can be resolved and accessed. - * @param fileToEdit (file we want to add import to) - * @param symbolName (item to import) - * @param fileName (path to the file) - * @param isDefault (if true, import follows style for importing default exports) - * @return Change - */ - -export function insertImport( - source: ts.SourceFile, - fileToEdit: string, - symbolName: string, - fileName: string, - isDefault = false -): Change { - const rootNode = source; - const allImports = findNodes(rootNode, ts.SyntaxKind.ImportDeclaration); - - // get nodes that map to import statements from the file fileName - const relevantImports = allImports.filter(node => { - // StringLiteral of the ImportDeclaration is the import file (fileName in this case). - const importFiles = node - .getChildren() - .filter(child => child.kind === ts.SyntaxKind.StringLiteral) - .map(n => (n as ts.StringLiteral).text); - - return importFiles.filter(file => file === fileName).length === 1; - }); - - if (relevantImports.length > 0) { - let importsAsterisk = false; - // imports from import file - const imports: ts.Node[] = []; - relevantImports.forEach(n => { - Array.prototype.push.apply( - imports, - findNodes(n, ts.SyntaxKind.Identifier) - ); - if (findNodes(n, ts.SyntaxKind.AsteriskToken).length > 0) { - importsAsterisk = true; - } - }); - - // if imports * from fileName, don't add symbolName - if (importsAsterisk) { - return new NoopChange(); - } - - const importTextNodes = imports.filter( - n => (n as ts.Identifier).text === symbolName - ); - - // insert import if it's not there - if (importTextNodes.length === 0) { - const fallbackPos = - findNodes( - relevantImports[0], - ts.SyntaxKind.CloseBraceToken - )[0].getStart() || - findNodes(relevantImports[0], ts.SyntaxKind.FromKeyword)[0].getStart(); - - return insertAfterLastOccurrence( - imports, - `, ${symbolName}`, - fileToEdit, - fallbackPos - ); - } - - return new NoopChange(); - } - - // no such import declaration exists - const useStrict = findNodes(rootNode, ts.SyntaxKind.StringLiteral).filter( - n => n.getText() === 'use strict' - ); - let fallbackPos = 0; - if (useStrict.length > 0) { - fallbackPos = useStrict[0].end; - } - const open = isDefault ? '' : '{ '; - const close = isDefault ? '' : ' }'; - // if there are no imports or 'use strict' statement, insert import at beginning of file - const insertAtBeginning = allImports.length === 0 && useStrict.length === 0; - const separator = insertAtBeginning ? '' : ';\n'; - const toInsert = - `${separator}import ${open}${symbolName}${close}` + - ` from '${fileName}'${insertAtBeginning ? ';\n' : ''}`; - - return insertAfterLastOccurrence( - allImports, - toInsert, - fileToEdit, - fallbackPos, - ts.SyntaxKind.StringLiteral - ); -} diff --git a/modules/schematics/schematics-core/index.ts b/modules/schematics/schematics-core/index.ts index 36cc0abbcf..9608baec44 100644 --- a/modules/schematics/schematics-core/index.ts +++ b/modules/schematics/schematics-core/index.ts @@ -15,6 +15,7 @@ export { getDecoratorMetadata, getContentOfKeyLiteral, insertAfterLastOccurrence, + insertImport, addBootstrapToModule, addDeclarationToModule, addExportToModule, @@ -49,7 +50,6 @@ export { } from './utility/ngrx-utils'; export { getProjectPath, getProject, isLib } from './utility/project'; -export { insertImport } from './utility/route-utils'; export const stringUtils = { dasherize, diff --git a/modules/schematics/schematics-core/utility/ast-utils.ts b/modules/schematics/schematics-core/utility/ast-utils.ts index b1f263974e..f6174fc4b1 100644 --- a/modules/schematics/schematics-core/utility/ast-utils.ts +++ b/modules/schematics/schematics-core/utility/ast-utils.ts @@ -7,8 +7,7 @@ * found in the LICENSE file at https://angular.io/license */ import * as ts from 'typescript'; -import { Change, InsertChange } from './change'; -import { insertImport } from './route-utils'; +import { Change, InsertChange, NoopChange } from './change'; /** * Find all nodes from the AST in the subtree of node of SyntaxKind kind. @@ -537,3 +536,103 @@ export function addBootstrapToModule( importPath ); } + +/** + * Add Import `import { symbolName } from fileName` if the import doesn't exit + * already. Assumes fileToEdit can be resolved and accessed. + * @param fileToEdit (file we want to add import to) + * @param symbolName (item to import) + * @param fileName (path to the file) + * @param isDefault (if true, import follows style for importing default exports) + * @return Change + */ + +export function insertImport( + source: ts.SourceFile, + fileToEdit: string, + symbolName: string, + fileName: string, + isDefault = false +): Change { + const rootNode = source; + const allImports = findNodes(rootNode, ts.SyntaxKind.ImportDeclaration); + + // get nodes that map to import statements from the file fileName + const relevantImports = allImports.filter(node => { + // StringLiteral of the ImportDeclaration is the import file (fileName in this case). + const importFiles = node + .getChildren() + .filter(child => child.kind === ts.SyntaxKind.StringLiteral) + .map(n => (n as ts.StringLiteral).text); + + return importFiles.filter(file => file === fileName).length === 1; + }); + + if (relevantImports.length > 0) { + let importsAsterisk = false; + // imports from import file + const imports: ts.Node[] = []; + relevantImports.forEach(n => { + Array.prototype.push.apply( + imports, + findNodes(n, ts.SyntaxKind.Identifier) + ); + if (findNodes(n, ts.SyntaxKind.AsteriskToken).length > 0) { + importsAsterisk = true; + } + }); + + // if imports * from fileName, don't add symbolName + if (importsAsterisk) { + return new NoopChange(); + } + + const importTextNodes = imports.filter( + n => (n as ts.Identifier).text === symbolName + ); + + // insert import if it's not there + if (importTextNodes.length === 0) { + const fallbackPos = + findNodes( + relevantImports[0], + ts.SyntaxKind.CloseBraceToken + )[0].getStart() || + findNodes(relevantImports[0], ts.SyntaxKind.FromKeyword)[0].getStart(); + + return insertAfterLastOccurrence( + imports, + `, ${symbolName}`, + fileToEdit, + fallbackPos + ); + } + + return new NoopChange(); + } + + // no such import declaration exists + const useStrict = findNodes(rootNode, ts.SyntaxKind.StringLiteral).filter( + n => n.getText() === 'use strict' + ); + let fallbackPos = 0; + if (useStrict.length > 0) { + fallbackPos = useStrict[0].end; + } + const open = isDefault ? '' : '{ '; + const close = isDefault ? '' : ' }'; + // if there are no imports or 'use strict' statement, insert import at beginning of file + const insertAtBeginning = allImports.length === 0 && useStrict.length === 0; + const separator = insertAtBeginning ? '' : ';\n'; + const toInsert = + `${separator}import ${open}${symbolName}${close}` + + ` from '${fileName}'${insertAtBeginning ? ';\n' : ''}`; + + return insertAfterLastOccurrence( + allImports, + toInsert, + fileToEdit, + fallbackPos, + ts.SyntaxKind.StringLiteral + ); +} diff --git a/modules/schematics/schematics-core/utility/ngrx-utils.ts b/modules/schematics/schematics-core/utility/ngrx-utils.ts index 0dd26b3398..d856f79346 100644 --- a/modules/schematics/schematics-core/utility/ngrx-utils.ts +++ b/modules/schematics/schematics-core/utility/ngrx-utils.ts @@ -4,8 +4,7 @@ import { InsertChange, Change, NoopChange } from './change'; import { Tree, SchematicsException, Rule } from '@angular-devkit/schematics'; import { normalize } from '@angular-devkit/core'; import { buildRelativePath } from './find-module'; -import { insertImport } from './route-utils'; -import { addImportToModule } from './ast-utils'; +import { addImportToModule, insertImport } from './ast-utils'; export function addReducerToState(options: any): Rule { return (host: Tree) => { diff --git a/modules/schematics/schematics-core/utility/route-utils.ts b/modules/schematics/schematics-core/utility/route-utils.ts deleted file mode 100644 index d25cc059a8..0000000000 --- a/modules/schematics/schematics-core/utility/route-utils.ts +++ /dev/null @@ -1,110 +0,0 @@ -/** - * @license - * Copyright Google Inc. All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ -import * as ts from 'typescript'; -import { findNodes, insertAfterLastOccurrence } from './ast-utils'; -import { Change, NoopChange } from './change'; - -/** - * Add Import `import { symbolName } from fileName` if the import doesn't exit - * already. Assumes fileToEdit can be resolved and accessed. - * @param fileToEdit (file we want to add import to) - * @param symbolName (item to import) - * @param fileName (path to the file) - * @param isDefault (if true, import follows style for importing default exports) - * @return Change - */ - -export function insertImport( - source: ts.SourceFile, - fileToEdit: string, - symbolName: string, - fileName: string, - isDefault = false -): Change { - const rootNode = source; - const allImports = findNodes(rootNode, ts.SyntaxKind.ImportDeclaration); - - // get nodes that map to import statements from the file fileName - const relevantImports = allImports.filter(node => { - // StringLiteral of the ImportDeclaration is the import file (fileName in this case). - const importFiles = node - .getChildren() - .filter(child => child.kind === ts.SyntaxKind.StringLiteral) - .map(n => (n as ts.StringLiteral).text); - - return importFiles.filter(file => file === fileName).length === 1; - }); - - if (relevantImports.length > 0) { - let importsAsterisk = false; - // imports from import file - const imports: ts.Node[] = []; - relevantImports.forEach(n => { - Array.prototype.push.apply( - imports, - findNodes(n, ts.SyntaxKind.Identifier) - ); - if (findNodes(n, ts.SyntaxKind.AsteriskToken).length > 0) { - importsAsterisk = true; - } - }); - - // if imports * from fileName, don't add symbolName - if (importsAsterisk) { - return new NoopChange(); - } - - const importTextNodes = imports.filter( - n => (n as ts.Identifier).text === symbolName - ); - - // insert import if it's not there - if (importTextNodes.length === 0) { - const fallbackPos = - findNodes( - relevantImports[0], - ts.SyntaxKind.CloseBraceToken - )[0].getStart() || - findNodes(relevantImports[0], ts.SyntaxKind.FromKeyword)[0].getStart(); - - return insertAfterLastOccurrence( - imports, - `, ${symbolName}`, - fileToEdit, - fallbackPos - ); - } - - return new NoopChange(); - } - - // no such import declaration exists - const useStrict = findNodes(rootNode, ts.SyntaxKind.StringLiteral).filter( - n => n.getText() === 'use strict' - ); - let fallbackPos = 0; - if (useStrict.length > 0) { - fallbackPos = useStrict[0].end; - } - const open = isDefault ? '' : '{ '; - const close = isDefault ? '' : ' }'; - // if there are no imports or 'use strict' statement, insert import at beginning of file - const insertAtBeginning = allImports.length === 0 && useStrict.length === 0; - const separator = insertAtBeginning ? '' : ';\n'; - const toInsert = - `${separator}import ${open}${symbolName}${close}` + - ` from '${fileName}'${insertAtBeginning ? ';\n' : ''}`; - - return insertAfterLastOccurrence( - allImports, - toInsert, - fileToEdit, - fallbackPos, - ts.SyntaxKind.StringLiteral - ); -} diff --git a/modules/store-devtools/schematics-core/index.ts b/modules/store-devtools/schematics-core/index.ts index 36cc0abbcf..9608baec44 100644 --- a/modules/store-devtools/schematics-core/index.ts +++ b/modules/store-devtools/schematics-core/index.ts @@ -15,6 +15,7 @@ export { getDecoratorMetadata, getContentOfKeyLiteral, insertAfterLastOccurrence, + insertImport, addBootstrapToModule, addDeclarationToModule, addExportToModule, @@ -49,7 +50,6 @@ export { } from './utility/ngrx-utils'; export { getProjectPath, getProject, isLib } from './utility/project'; -export { insertImport } from './utility/route-utils'; export const stringUtils = { dasherize, diff --git a/modules/store-devtools/schematics-core/utility/ast-utils.ts b/modules/store-devtools/schematics-core/utility/ast-utils.ts index b1f263974e..f6174fc4b1 100644 --- a/modules/store-devtools/schematics-core/utility/ast-utils.ts +++ b/modules/store-devtools/schematics-core/utility/ast-utils.ts @@ -7,8 +7,7 @@ * found in the LICENSE file at https://angular.io/license */ import * as ts from 'typescript'; -import { Change, InsertChange } from './change'; -import { insertImport } from './route-utils'; +import { Change, InsertChange, NoopChange } from './change'; /** * Find all nodes from the AST in the subtree of node of SyntaxKind kind. @@ -537,3 +536,103 @@ export function addBootstrapToModule( importPath ); } + +/** + * Add Import `import { symbolName } from fileName` if the import doesn't exit + * already. Assumes fileToEdit can be resolved and accessed. + * @param fileToEdit (file we want to add import to) + * @param symbolName (item to import) + * @param fileName (path to the file) + * @param isDefault (if true, import follows style for importing default exports) + * @return Change + */ + +export function insertImport( + source: ts.SourceFile, + fileToEdit: string, + symbolName: string, + fileName: string, + isDefault = false +): Change { + const rootNode = source; + const allImports = findNodes(rootNode, ts.SyntaxKind.ImportDeclaration); + + // get nodes that map to import statements from the file fileName + const relevantImports = allImports.filter(node => { + // StringLiteral of the ImportDeclaration is the import file (fileName in this case). + const importFiles = node + .getChildren() + .filter(child => child.kind === ts.SyntaxKind.StringLiteral) + .map(n => (n as ts.StringLiteral).text); + + return importFiles.filter(file => file === fileName).length === 1; + }); + + if (relevantImports.length > 0) { + let importsAsterisk = false; + // imports from import file + const imports: ts.Node[] = []; + relevantImports.forEach(n => { + Array.prototype.push.apply( + imports, + findNodes(n, ts.SyntaxKind.Identifier) + ); + if (findNodes(n, ts.SyntaxKind.AsteriskToken).length > 0) { + importsAsterisk = true; + } + }); + + // if imports * from fileName, don't add symbolName + if (importsAsterisk) { + return new NoopChange(); + } + + const importTextNodes = imports.filter( + n => (n as ts.Identifier).text === symbolName + ); + + // insert import if it's not there + if (importTextNodes.length === 0) { + const fallbackPos = + findNodes( + relevantImports[0], + ts.SyntaxKind.CloseBraceToken + )[0].getStart() || + findNodes(relevantImports[0], ts.SyntaxKind.FromKeyword)[0].getStart(); + + return insertAfterLastOccurrence( + imports, + `, ${symbolName}`, + fileToEdit, + fallbackPos + ); + } + + return new NoopChange(); + } + + // no such import declaration exists + const useStrict = findNodes(rootNode, ts.SyntaxKind.StringLiteral).filter( + n => n.getText() === 'use strict' + ); + let fallbackPos = 0; + if (useStrict.length > 0) { + fallbackPos = useStrict[0].end; + } + const open = isDefault ? '' : '{ '; + const close = isDefault ? '' : ' }'; + // if there are no imports or 'use strict' statement, insert import at beginning of file + const insertAtBeginning = allImports.length === 0 && useStrict.length === 0; + const separator = insertAtBeginning ? '' : ';\n'; + const toInsert = + `${separator}import ${open}${symbolName}${close}` + + ` from '${fileName}'${insertAtBeginning ? ';\n' : ''}`; + + return insertAfterLastOccurrence( + allImports, + toInsert, + fileToEdit, + fallbackPos, + ts.SyntaxKind.StringLiteral + ); +} diff --git a/modules/store-devtools/schematics-core/utility/ngrx-utils.ts b/modules/store-devtools/schematics-core/utility/ngrx-utils.ts index 0dd26b3398..d856f79346 100644 --- a/modules/store-devtools/schematics-core/utility/ngrx-utils.ts +++ b/modules/store-devtools/schematics-core/utility/ngrx-utils.ts @@ -4,8 +4,7 @@ import { InsertChange, Change, NoopChange } from './change'; import { Tree, SchematicsException, Rule } from '@angular-devkit/schematics'; import { normalize } from '@angular-devkit/core'; import { buildRelativePath } from './find-module'; -import { insertImport } from './route-utils'; -import { addImportToModule } from './ast-utils'; +import { addImportToModule, insertImport } from './ast-utils'; export function addReducerToState(options: any): Rule { return (host: Tree) => { diff --git a/modules/store-devtools/schematics-core/utility/route-utils.ts b/modules/store-devtools/schematics-core/utility/route-utils.ts deleted file mode 100644 index d25cc059a8..0000000000 --- a/modules/store-devtools/schematics-core/utility/route-utils.ts +++ /dev/null @@ -1,110 +0,0 @@ -/** - * @license - * Copyright Google Inc. All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ -import * as ts from 'typescript'; -import { findNodes, insertAfterLastOccurrence } from './ast-utils'; -import { Change, NoopChange } from './change'; - -/** - * Add Import `import { symbolName } from fileName` if the import doesn't exit - * already. Assumes fileToEdit can be resolved and accessed. - * @param fileToEdit (file we want to add import to) - * @param symbolName (item to import) - * @param fileName (path to the file) - * @param isDefault (if true, import follows style for importing default exports) - * @return Change - */ - -export function insertImport( - source: ts.SourceFile, - fileToEdit: string, - symbolName: string, - fileName: string, - isDefault = false -): Change { - const rootNode = source; - const allImports = findNodes(rootNode, ts.SyntaxKind.ImportDeclaration); - - // get nodes that map to import statements from the file fileName - const relevantImports = allImports.filter(node => { - // StringLiteral of the ImportDeclaration is the import file (fileName in this case). - const importFiles = node - .getChildren() - .filter(child => child.kind === ts.SyntaxKind.StringLiteral) - .map(n => (n as ts.StringLiteral).text); - - return importFiles.filter(file => file === fileName).length === 1; - }); - - if (relevantImports.length > 0) { - let importsAsterisk = false; - // imports from import file - const imports: ts.Node[] = []; - relevantImports.forEach(n => { - Array.prototype.push.apply( - imports, - findNodes(n, ts.SyntaxKind.Identifier) - ); - if (findNodes(n, ts.SyntaxKind.AsteriskToken).length > 0) { - importsAsterisk = true; - } - }); - - // if imports * from fileName, don't add symbolName - if (importsAsterisk) { - return new NoopChange(); - } - - const importTextNodes = imports.filter( - n => (n as ts.Identifier).text === symbolName - ); - - // insert import if it's not there - if (importTextNodes.length === 0) { - const fallbackPos = - findNodes( - relevantImports[0], - ts.SyntaxKind.CloseBraceToken - )[0].getStart() || - findNodes(relevantImports[0], ts.SyntaxKind.FromKeyword)[0].getStart(); - - return insertAfterLastOccurrence( - imports, - `, ${symbolName}`, - fileToEdit, - fallbackPos - ); - } - - return new NoopChange(); - } - - // no such import declaration exists - const useStrict = findNodes(rootNode, ts.SyntaxKind.StringLiteral).filter( - n => n.getText() === 'use strict' - ); - let fallbackPos = 0; - if (useStrict.length > 0) { - fallbackPos = useStrict[0].end; - } - const open = isDefault ? '' : '{ '; - const close = isDefault ? '' : ' }'; - // if there are no imports or 'use strict' statement, insert import at beginning of file - const insertAtBeginning = allImports.length === 0 && useStrict.length === 0; - const separator = insertAtBeginning ? '' : ';\n'; - const toInsert = - `${separator}import ${open}${symbolName}${close}` + - ` from '${fileName}'${insertAtBeginning ? ';\n' : ''}`; - - return insertAfterLastOccurrence( - allImports, - toInsert, - fileToEdit, - fallbackPos, - ts.SyntaxKind.StringLiteral - ); -} diff --git a/modules/store/schematics-core/index.ts b/modules/store/schematics-core/index.ts index 36cc0abbcf..9608baec44 100644 --- a/modules/store/schematics-core/index.ts +++ b/modules/store/schematics-core/index.ts @@ -15,6 +15,7 @@ export { getDecoratorMetadata, getContentOfKeyLiteral, insertAfterLastOccurrence, + insertImport, addBootstrapToModule, addDeclarationToModule, addExportToModule, @@ -49,7 +50,6 @@ export { } from './utility/ngrx-utils'; export { getProjectPath, getProject, isLib } from './utility/project'; -export { insertImport } from './utility/route-utils'; export const stringUtils = { dasherize, diff --git a/modules/store/schematics-core/utility/ast-utils.ts b/modules/store/schematics-core/utility/ast-utils.ts index b1f263974e..f6174fc4b1 100644 --- a/modules/store/schematics-core/utility/ast-utils.ts +++ b/modules/store/schematics-core/utility/ast-utils.ts @@ -7,8 +7,7 @@ * found in the LICENSE file at https://angular.io/license */ import * as ts from 'typescript'; -import { Change, InsertChange } from './change'; -import { insertImport } from './route-utils'; +import { Change, InsertChange, NoopChange } from './change'; /** * Find all nodes from the AST in the subtree of node of SyntaxKind kind. @@ -537,3 +536,103 @@ export function addBootstrapToModule( importPath ); } + +/** + * Add Import `import { symbolName } from fileName` if the import doesn't exit + * already. Assumes fileToEdit can be resolved and accessed. + * @param fileToEdit (file we want to add import to) + * @param symbolName (item to import) + * @param fileName (path to the file) + * @param isDefault (if true, import follows style for importing default exports) + * @return Change + */ + +export function insertImport( + source: ts.SourceFile, + fileToEdit: string, + symbolName: string, + fileName: string, + isDefault = false +): Change { + const rootNode = source; + const allImports = findNodes(rootNode, ts.SyntaxKind.ImportDeclaration); + + // get nodes that map to import statements from the file fileName + const relevantImports = allImports.filter(node => { + // StringLiteral of the ImportDeclaration is the import file (fileName in this case). + const importFiles = node + .getChildren() + .filter(child => child.kind === ts.SyntaxKind.StringLiteral) + .map(n => (n as ts.StringLiteral).text); + + return importFiles.filter(file => file === fileName).length === 1; + }); + + if (relevantImports.length > 0) { + let importsAsterisk = false; + // imports from import file + const imports: ts.Node[] = []; + relevantImports.forEach(n => { + Array.prototype.push.apply( + imports, + findNodes(n, ts.SyntaxKind.Identifier) + ); + if (findNodes(n, ts.SyntaxKind.AsteriskToken).length > 0) { + importsAsterisk = true; + } + }); + + // if imports * from fileName, don't add symbolName + if (importsAsterisk) { + return new NoopChange(); + } + + const importTextNodes = imports.filter( + n => (n as ts.Identifier).text === symbolName + ); + + // insert import if it's not there + if (importTextNodes.length === 0) { + const fallbackPos = + findNodes( + relevantImports[0], + ts.SyntaxKind.CloseBraceToken + )[0].getStart() || + findNodes(relevantImports[0], ts.SyntaxKind.FromKeyword)[0].getStart(); + + return insertAfterLastOccurrence( + imports, + `, ${symbolName}`, + fileToEdit, + fallbackPos + ); + } + + return new NoopChange(); + } + + // no such import declaration exists + const useStrict = findNodes(rootNode, ts.SyntaxKind.StringLiteral).filter( + n => n.getText() === 'use strict' + ); + let fallbackPos = 0; + if (useStrict.length > 0) { + fallbackPos = useStrict[0].end; + } + const open = isDefault ? '' : '{ '; + const close = isDefault ? '' : ' }'; + // if there are no imports or 'use strict' statement, insert import at beginning of file + const insertAtBeginning = allImports.length === 0 && useStrict.length === 0; + const separator = insertAtBeginning ? '' : ';\n'; + const toInsert = + `${separator}import ${open}${symbolName}${close}` + + ` from '${fileName}'${insertAtBeginning ? ';\n' : ''}`; + + return insertAfterLastOccurrence( + allImports, + toInsert, + fileToEdit, + fallbackPos, + ts.SyntaxKind.StringLiteral + ); +} diff --git a/modules/store/schematics-core/utility/ngrx-utils.ts b/modules/store/schematics-core/utility/ngrx-utils.ts index 0dd26b3398..d856f79346 100644 --- a/modules/store/schematics-core/utility/ngrx-utils.ts +++ b/modules/store/schematics-core/utility/ngrx-utils.ts @@ -4,8 +4,7 @@ import { InsertChange, Change, NoopChange } from './change'; import { Tree, SchematicsException, Rule } from '@angular-devkit/schematics'; import { normalize } from '@angular-devkit/core'; import { buildRelativePath } from './find-module'; -import { insertImport } from './route-utils'; -import { addImportToModule } from './ast-utils'; +import { addImportToModule, insertImport } from './ast-utils'; export function addReducerToState(options: any): Rule { return (host: Tree) => { diff --git a/modules/store/schematics-core/utility/route-utils.ts b/modules/store/schematics-core/utility/route-utils.ts deleted file mode 100644 index d25cc059a8..0000000000 --- a/modules/store/schematics-core/utility/route-utils.ts +++ /dev/null @@ -1,110 +0,0 @@ -/** - * @license - * Copyright Google Inc. All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ -import * as ts from 'typescript'; -import { findNodes, insertAfterLastOccurrence } from './ast-utils'; -import { Change, NoopChange } from './change'; - -/** - * Add Import `import { symbolName } from fileName` if the import doesn't exit - * already. Assumes fileToEdit can be resolved and accessed. - * @param fileToEdit (file we want to add import to) - * @param symbolName (item to import) - * @param fileName (path to the file) - * @param isDefault (if true, import follows style for importing default exports) - * @return Change - */ - -export function insertImport( - source: ts.SourceFile, - fileToEdit: string, - symbolName: string, - fileName: string, - isDefault = false -): Change { - const rootNode = source; - const allImports = findNodes(rootNode, ts.SyntaxKind.ImportDeclaration); - - // get nodes that map to import statements from the file fileName - const relevantImports = allImports.filter(node => { - // StringLiteral of the ImportDeclaration is the import file (fileName in this case). - const importFiles = node - .getChildren() - .filter(child => child.kind === ts.SyntaxKind.StringLiteral) - .map(n => (n as ts.StringLiteral).text); - - return importFiles.filter(file => file === fileName).length === 1; - }); - - if (relevantImports.length > 0) { - let importsAsterisk = false; - // imports from import file - const imports: ts.Node[] = []; - relevantImports.forEach(n => { - Array.prototype.push.apply( - imports, - findNodes(n, ts.SyntaxKind.Identifier) - ); - if (findNodes(n, ts.SyntaxKind.AsteriskToken).length > 0) { - importsAsterisk = true; - } - }); - - // if imports * from fileName, don't add symbolName - if (importsAsterisk) { - return new NoopChange(); - } - - const importTextNodes = imports.filter( - n => (n as ts.Identifier).text === symbolName - ); - - // insert import if it's not there - if (importTextNodes.length === 0) { - const fallbackPos = - findNodes( - relevantImports[0], - ts.SyntaxKind.CloseBraceToken - )[0].getStart() || - findNodes(relevantImports[0], ts.SyntaxKind.FromKeyword)[0].getStart(); - - return insertAfterLastOccurrence( - imports, - `, ${symbolName}`, - fileToEdit, - fallbackPos - ); - } - - return new NoopChange(); - } - - // no such import declaration exists - const useStrict = findNodes(rootNode, ts.SyntaxKind.StringLiteral).filter( - n => n.getText() === 'use strict' - ); - let fallbackPos = 0; - if (useStrict.length > 0) { - fallbackPos = useStrict[0].end; - } - const open = isDefault ? '' : '{ '; - const close = isDefault ? '' : ' }'; - // if there are no imports or 'use strict' statement, insert import at beginning of file - const insertAtBeginning = allImports.length === 0 && useStrict.length === 0; - const separator = insertAtBeginning ? '' : ';\n'; - const toInsert = - `${separator}import ${open}${symbolName}${close}` + - ` from '${fileName}'${insertAtBeginning ? ';\n' : ''}`; - - return insertAfterLastOccurrence( - allImports, - toInsert, - fileToEdit, - fallbackPos, - ts.SyntaxKind.StringLiteral - ); -}