Skip to content

Commit caa3142

Browse files
authored
fix(find-lazy-modules): Allow for any valid keys/value to be used (#1987)
* 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 #1972 * cleanup
1 parent a647e51 commit caa3142

File tree

3 files changed

+80
-37
lines changed

3 files changed

+80
-37
lines changed

addon/ng2/models/find-lazy-modules.ts

+30-31
Original file line numberDiff line numberDiff line change
@@ -6,48 +6,47 @@ import * as ts from 'typescript';
66
import {getSource, findNodes, getContentOfKeyLiteral} from '../utilities/ast-utils';
77

88

9-
function flatMap<T, R>(obj: Array<T>, mapFn: (item: T) => R | R[]): Array<R> {
10-
return obj.reduce((arr: R[], current: T) => {
11-
const result = mapFn.call(null, current);
12-
return result !== undefined ? arr.concat(result) : arr;
13-
}, <R[]>[]);
14-
}
15-
16-
179
export function findLoadChildren(tsFilePath: string): string[] {
1810
const source = getSource(tsFilePath);
1911
const unique: { [path: string]: boolean } = {};
2012

21-
let nodes = flatMap(
22-
findNodes(source, ts.SyntaxKind.ObjectLiteralExpression),
23-
node => findNodes(node, ts.SyntaxKind.PropertyAssignment))
24-
.filter((node: ts.PropertyAssignment) => {
25-
const key = getContentOfKeyLiteral(source, node.name);
26-
if (!key) {
27-
// key is an expression, can't do anything.
28-
return false;
29-
}
30-
return key == 'loadChildren';
31-
})
32-
// Remove initializers that are not files.
33-
.filter((node: ts.PropertyAssignment) => {
34-
return node.initializer.kind === ts.SyntaxKind.StringLiteral;
35-
})
36-
// Get the full text of the initializer.
37-
.map((node: ts.PropertyAssignment) => {
38-
return JSON.parse(node.initializer.getText(source)); // tslint:disable-line
39-
});
40-
41-
return nodes
13+
return (
14+
// Find all object literals.
15+
findNodes(source, ts.SyntaxKind.ObjectLiteralExpression)
16+
// Get all their property assignments.
17+
.map(node => findNodes(node, ts.SyntaxKind.PropertyAssignment))
18+
// Flatten into a single array (from an array of array<property assignments>).
19+
.reduce((prev, curr) => curr ? prev.concat(curr) : prev, [])
20+
// Remove every property assignment that aren't 'loadChildren'.
21+
.filter((node: ts.PropertyAssignment) => {
22+
const key = getContentOfKeyLiteral(source, node.name);
23+
if (!key) {
24+
// key is an expression, can't do anything.
25+
return false;
26+
}
27+
return key == 'loadChildren';
28+
})
29+
// Remove initializers that are not files.
30+
.filter((node: ts.PropertyAssignment) => {
31+
return node.initializer.kind === ts.SyntaxKind.StringLiteral;
32+
})
33+
// Get the full text of the initializer.
34+
.map((node: ts.PropertyAssignment) => {
35+
const literal = node.initializer as ts.StringLiteral;
36+
return literal.text;
37+
})
38+
// Map to the module name itself.
39+
.map((moduleName: string) => moduleName.split('#')[0])
40+
// Only get unique values (there might be multiple modules from a single URL, or a module used
41+
// multiple times).
4242
.filter((value: string) => {
4343
if (unique[value]) {
4444
return false;
4545
} else {
4646
unique[value] = true;
4747
return true;
4848
}
49-
})
50-
.map((moduleName: string) => moduleName.split('#')[0]);
49+
}));
5150
}
5251

5352

packages/ast-tools/src/ast-utils.ts

+2-6
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,9 @@ export function insertAfterLastOccurrence(nodes: ts.Node[], toInsert: string,
9696

9797
export function getContentOfKeyLiteral(source: ts.SourceFile, node: ts.Node): string {
9898
if (node.kind == ts.SyntaxKind.Identifier) {
99-
return (<ts.Identifier>node).text;
99+
return (node as ts.Identifier).text;
100100
} else if (node.kind == ts.SyntaxKind.StringLiteral) {
101-
try {
102-
return JSON.parse(node.getFullText(source));
103-
} catch (e) {
104-
return null;
105-
}
101+
return (node as ts.StringLiteral).text;
106102
} else {
107103
return null;
108104
}
+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import * as mockFs from 'mock-fs';
2+
import {stripIndents} from 'common-tags';
3+
import {expect} from 'chai';
4+
5+
import {findLazyModules} from '../../addon/ng2/models/find-lazy-modules';
6+
7+
8+
describe('find-lazy-module', () => {
9+
beforeEach(() => {
10+
mockFs({
11+
'project-root': {
12+
'fileA.ts': stripIndents`
13+
const r1 = {
14+
"loadChildren": "moduleA"
15+
};
16+
const r2 = {
17+
loadChildren: "moduleB"
18+
};
19+
const r3 = {
20+
'loadChildren': 'moduleC'
21+
};
22+
const r4 = {
23+
"loadChildren": 'app/+workspace/+settings/settings.module#SettingsModule'
24+
};
25+
const r5 = {
26+
loadChildren: 'unexistentModule'
27+
};
28+
`,
29+
// Create those files too as they have to exist.
30+
'moduleA.ts': '',
31+
'moduleB.ts': '',
32+
'moduleC.ts': '',
33+
'moduleD.ts': '',
34+
'app': { '+workspace': { '+settings': { 'settings.module.ts': '' } } }
35+
}
36+
});
37+
});
38+
afterEach(() => mockFs.restore());
39+
40+
it('works', () => {
41+
expect(findLazyModules('project-root')).to.eql([
42+
'moduleA',
43+
'moduleB',
44+
'moduleC',
45+
'app/+workspace/+settings/settings.module'
46+
]);
47+
});
48+
});

0 commit comments

Comments
 (0)