From 5ff159ebdde5c0eb3f003a70449eb00f7c6d5f16 Mon Sep 17 00:00:00 2001 From: Hans Larsen Date: Mon, 5 Sep 2016 12:34:24 -0700 Subject: [PATCH 1/2] fix(find-lazy-modules): Allow for any valid keys/value to be used and properly understand and return the modules in this case. Also refactored that function to be clearer, and added a test to cover. I made sure the test was failing before this PR ;) Fixes #1891, #1960. cc @filipesilva @ericjim @chalin - See similar https://github.com/angular/angular-cli/pull/1972 --- addon/ng2/models/find-lazy-modules.ts | 62 +++++++++++------------ lib/bootstrap-local.js | 2 +- packages/ast-tools/src/ast-utils.ts | 10 ++-- tests/acceptance/find-lazy-module.spec.ts | 49 ++++++++++++++++++ tsconfig.json | 2 +- 5 files changed, 86 insertions(+), 39 deletions(-) create mode 100644 tests/acceptance/find-lazy-module.spec.ts diff --git a/addon/ng2/models/find-lazy-modules.ts b/addon/ng2/models/find-lazy-modules.ts index 9b98a9079ec2..4d9a1c4e7768 100644 --- a/addon/ng2/models/find-lazy-modules.ts +++ b/addon/ng2/models/find-lazy-modules.ts @@ -6,39 +6,39 @@ import * as ts from 'typescript'; import {getSource, findNodes, getContentOfKeyLiteral} from '../utilities/ast-utils'; -function flatMap(obj: Array, mapFn: (item: T) => R | R[]): Array { - return obj.reduce((arr: R[], current: T) => { - const result = mapFn.call(null, current); - return result !== undefined ? arr.concat(result) : arr; - }, []); -} - - export function findLoadChildren(tsFilePath: string): string[] { const source = getSource(tsFilePath); const unique: { [path: string]: boolean } = {}; - let nodes = flatMap( - findNodes(source, ts.SyntaxKind.ObjectLiteralExpression), - node => findNodes(node, ts.SyntaxKind.PropertyAssignment)) - .filter((node: ts.PropertyAssignment) => { - const key = getContentOfKeyLiteral(source, node.name); - if (!key) { - // key is an expression, can't do anything. - return false; - } - return key == 'loadChildren'; - }) - // Remove initializers that are not files. - .filter((node: ts.PropertyAssignment) => { - return node.initializer.kind === ts.SyntaxKind.StringLiteral; - }) - // Get the full text of the initializer. - .map((node: ts.PropertyAssignment) => { - return JSON.parse(node.initializer.getText(source)); // tslint:disable-line - }); - - return nodes + return ( + // Find all object literals. + findNodes(source, ts.SyntaxKind.ObjectLiteralExpression) + // Get all their property assignments. + .map(node => findNodes(node, ts.SyntaxKind.PropertyAssignment)) + // Flatten into a single array (from an array of array). + .reduce((prev, curr) => curr ? prev.concat(curr) : prev, []) + // Remove every property assignment that aren't 'loadChildren'. + .filter((node: ts.PropertyAssignment) => { + const key = getContentOfKeyLiteral(source, node.name); + if (!key) { + // key is an expression, can't do anything. + return false; + } + return key == 'loadChildren'; + }) + // Remove initializers that are not files. + .filter((node: ts.PropertyAssignment) => { + return node.initializer.kind === ts.SyntaxKind.StringLiteral; + }) + // Get the full text of the initializer. + .map((node: ts.PropertyAssignment) => { + const literal = node.initializer as ts.StringLiteral; + return literal.text; + }) + // Map to the module name itself. + .map((moduleName: string) => moduleName.split('#')[0]) + // Only get unique values (there might be multiple modules from a single URL, or a module used + // multiple times). .filter((value: string) => { if (unique[value]) { return false; @@ -46,8 +46,7 @@ export function findLoadChildren(tsFilePath: string): string[] { unique[value] = true; return true; } - }) - .map((moduleName: string) => moduleName.split('#')[0]); + })); } @@ -57,6 +56,7 @@ export function findLazyModules(projectRoot: any): string[] { .forEach(tsPath => { findLoadChildren(tsPath).forEach(moduleName => { const fileName = path.resolve(path.dirname(tsPath), moduleName) + '.ts'; + console.log(1, fileName); if (fs.existsSync(fileName)) { result[moduleName] = true; } diff --git a/lib/bootstrap-local.js b/lib/bootstrap-local.js index 80e219cbce88..b2291b4087aa 100644 --- a/lib/bootstrap-local.js +++ b/lib/bootstrap-local.js @@ -24,7 +24,7 @@ require.extensions['.ts'] = function(m, filename) { const source = fs.readFileSync(filename).toString(); try { - const result = ts.transpile(source, compilerOptions); + const result = ts.transpile(source, compilerOptions, filename); // Send it to node to execute. return m._compile(result, filename); diff --git a/packages/ast-tools/src/ast-utils.ts b/packages/ast-tools/src/ast-utils.ts index 0ffe4c6d8580..ea1703892e28 100644 --- a/packages/ast-tools/src/ast-utils.ts +++ b/packages/ast-tools/src/ast-utils.ts @@ -95,14 +95,12 @@ export function insertAfterLastOccurrence(nodes: ts.Node[], toInsert: string, export function getContentOfKeyLiteral(source: ts.SourceFile, node: ts.Node): string { + console.log(10, node.kind, (node as any).text); if (node.kind == ts.SyntaxKind.Identifier) { - return (node).text; + return (node as ts.Identifier).text; } else if (node.kind == ts.SyntaxKind.StringLiteral) { - try { - return JSON.parse(node.getFullText(source)); - } catch (e) { - return null; - } + const literal = node as ts.StringLiteral; + return literal.text; } else { return null; } diff --git a/tests/acceptance/find-lazy-module.spec.ts b/tests/acceptance/find-lazy-module.spec.ts new file mode 100644 index 000000000000..3940e780521f --- /dev/null +++ b/tests/acceptance/find-lazy-module.spec.ts @@ -0,0 +1,49 @@ +import * as mockFs from 'mock-fs'; +import {stripIndents} from 'common-tags'; +import {expect} from 'chai'; + +import {findLazyModules} from '../../addon/ng2/models/find-lazy-modules'; + + +describe('find-lazy-module', () => { + beforeEach(() => { + mockFs({ + 'project-root': { + 'fileA.ts': stripIndents` + const r1 = { + "loadChildren": "moduleA" + }; + const r2 = { + loadChildren: "moduleB" + }; + const r3 = { + 'loadChildren': 'moduleC' + }; + const r4 = { + "loadChildren": 'app/+workspace/+settings/settings.module#SettingsModule' + }; + const r5 = { + loadChildren: 'unexistentModule' + }; + `, + // Create those files too as they have to exist. + 'moduleA.ts': '', + 'moduleB.ts': '', + 'moduleC.ts': '', + 'moduleD.ts': '', + 'app': { '+workspace': { '+settings': { 'settings.module.ts': '' } } } + } + }) + }); + afterEach(() => mockFs.restore()); + + it('works', () => { + debugger; + expect(findLazyModules('project-root')).to.eql([ + 'moduleA', + 'moduleB', + 'moduleC', + 'app/+workspace/+settings/settings.module' + ]); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index 6b1b9c40b8dd..c04634f881e7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,7 +9,7 @@ "outDir": "./dist/", "rootDir": ".", "sourceMap": true, - "sourceRoot": "", + "inlineSourceMap": true, "target": "es5", "lib": ["es6"], "baseUrl": "", From 49e32bc92215f1850f5142e80632e35039cf484d Mon Sep 17 00:00:00 2001 From: Hans Larsen Date: Mon, 5 Sep 2016 12:38:50 -0700 Subject: [PATCH 2/2] cleanup --- addon/ng2/models/find-lazy-modules.ts | 1 - lib/bootstrap-local.js | 2 +- packages/ast-tools/src/ast-utils.ts | 4 +--- tests/acceptance/find-lazy-module.spec.ts | 3 +-- tsconfig.json | 2 +- 5 files changed, 4 insertions(+), 8 deletions(-) diff --git a/addon/ng2/models/find-lazy-modules.ts b/addon/ng2/models/find-lazy-modules.ts index 4d9a1c4e7768..8874c8802ebe 100644 --- a/addon/ng2/models/find-lazy-modules.ts +++ b/addon/ng2/models/find-lazy-modules.ts @@ -56,7 +56,6 @@ export function findLazyModules(projectRoot: any): string[] { .forEach(tsPath => { findLoadChildren(tsPath).forEach(moduleName => { const fileName = path.resolve(path.dirname(tsPath), moduleName) + '.ts'; - console.log(1, fileName); if (fs.existsSync(fileName)) { result[moduleName] = true; } diff --git a/lib/bootstrap-local.js b/lib/bootstrap-local.js index b2291b4087aa..80e219cbce88 100644 --- a/lib/bootstrap-local.js +++ b/lib/bootstrap-local.js @@ -24,7 +24,7 @@ require.extensions['.ts'] = function(m, filename) { const source = fs.readFileSync(filename).toString(); try { - const result = ts.transpile(source, compilerOptions, filename); + const result = ts.transpile(source, compilerOptions); // Send it to node to execute. return m._compile(result, filename); diff --git a/packages/ast-tools/src/ast-utils.ts b/packages/ast-tools/src/ast-utils.ts index ea1703892e28..40ebfb5aa5e2 100644 --- a/packages/ast-tools/src/ast-utils.ts +++ b/packages/ast-tools/src/ast-utils.ts @@ -95,12 +95,10 @@ export function insertAfterLastOccurrence(nodes: ts.Node[], toInsert: string, export function getContentOfKeyLiteral(source: ts.SourceFile, node: ts.Node): string { - console.log(10, node.kind, (node as any).text); if (node.kind == ts.SyntaxKind.Identifier) { return (node as ts.Identifier).text; } else if (node.kind == ts.SyntaxKind.StringLiteral) { - const literal = node as ts.StringLiteral; - return literal.text; + return (node as ts.StringLiteral).text; } else { return null; } diff --git a/tests/acceptance/find-lazy-module.spec.ts b/tests/acceptance/find-lazy-module.spec.ts index 3940e780521f..4d44804dd549 100644 --- a/tests/acceptance/find-lazy-module.spec.ts +++ b/tests/acceptance/find-lazy-module.spec.ts @@ -33,12 +33,11 @@ describe('find-lazy-module', () => { 'moduleD.ts': '', 'app': { '+workspace': { '+settings': { 'settings.module.ts': '' } } } } - }) + }); }); afterEach(() => mockFs.restore()); it('works', () => { - debugger; expect(findLazyModules('project-root')).to.eql([ 'moduleA', 'moduleB', diff --git a/tsconfig.json b/tsconfig.json index c04634f881e7..6b1b9c40b8dd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,7 +9,7 @@ "outDir": "./dist/", "rootDir": ".", "sourceMap": true, - "inlineSourceMap": true, + "sourceRoot": "", "target": "es5", "lib": ["es6"], "baseUrl": "",