Skip to content

Commit 0775093

Browse files
feat(component): add ngrxPush migration (#2452)
Related to #2450
1 parent 3545df2 commit 0775093

File tree

21 files changed

+1930
-232
lines changed

21 files changed

+1930
-232
lines changed

modules/data/schematics-core/index.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,12 @@ export { addPackageToPackageJson } from './utility/package';
8181

8282
export { platformVersion } from './utility/libs-version';
8383

84-
export { visitTSSourceFiles, visitNgModuleImports } from './utility/visitors';
84+
export {
85+
visitTSSourceFiles,
86+
visitNgModuleImports,
87+
visitNgModuleExports,
88+
visitComponents,
89+
visitDecorator,
90+
visitNgModules,
91+
visitTemplates,
92+
} from './utility/visitors';

modules/data/schematics-core/utility/visitors.ts

Lines changed: 185 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as ts from 'typescript';
2+
import { normalize, resolve } from '@angular-devkit/core';
23
import { Tree, DirEntry } from '@angular-devkit/schematics';
34

45
export function visitTSSourceFiles<Result = void>(
@@ -17,6 +18,190 @@ export function visitTSSourceFiles<Result = void>(
1718
return result;
1819
}
1920

21+
export function visitTemplates(
22+
tree: Tree,
23+
visitor: (
24+
template: {
25+
fileName: string;
26+
content: string;
27+
inline: boolean;
28+
start: number;
29+
},
30+
tree: Tree
31+
) => void
32+
): void {
33+
visitTSSourceFiles(tree, source => {
34+
visitComponents(source, (_, decoratorExpressionNode) => {
35+
ts.forEachChild(decoratorExpressionNode, function findTemplates(n) {
36+
if (ts.isPropertyAssignment(n) && ts.isIdentifier(n.name)) {
37+
if (
38+
n.name.text === 'template' &&
39+
ts.isStringLiteralLike(n.initializer)
40+
) {
41+
// Need to add an offset of one to the start because the template quotes are
42+
// not part of the template content.
43+
const templateStartIdx = n.initializer.getStart() + 1;
44+
visitor(
45+
{
46+
fileName: source.fileName,
47+
content: n.initializer.text,
48+
inline: true,
49+
start: templateStartIdx,
50+
},
51+
tree
52+
);
53+
return;
54+
} else if (
55+
n.name.text === 'templateUrl' &&
56+
ts.isStringLiteralLike(n.initializer)
57+
) {
58+
const parts = normalize(source.fileName)
59+
.split('/')
60+
.slice(0, -1);
61+
const templatePath = resolve(
62+
normalize(parts.join('/')),
63+
normalize(n.initializer.text)
64+
);
65+
if (!tree.exists(templatePath)) {
66+
return;
67+
}
68+
69+
const fileContent = tree.read(templatePath);
70+
if (!fileContent) {
71+
return;
72+
}
73+
74+
visitor(
75+
{
76+
fileName: templatePath,
77+
content: fileContent.toString(),
78+
inline: false,
79+
start: 0,
80+
},
81+
tree
82+
);
83+
return;
84+
}
85+
}
86+
87+
ts.forEachChild(n, findTemplates);
88+
});
89+
});
90+
});
91+
}
92+
93+
export function visitNgModuleImports(
94+
sourceFile: ts.SourceFile,
95+
callback: (
96+
importNode: ts.PropertyAssignment,
97+
elementExpressions: ts.NodeArray<ts.Expression>
98+
) => void
99+
) {
100+
visitNgModuleProperty(sourceFile, callback, 'imports');
101+
}
102+
103+
export function visitNgModuleExports(
104+
sourceFile: ts.SourceFile,
105+
callback: (
106+
exportNode: ts.PropertyAssignment,
107+
elementExpressions: ts.NodeArray<ts.Expression>
108+
) => void
109+
) {
110+
visitNgModuleProperty(sourceFile, callback, 'exports');
111+
}
112+
113+
function visitNgModuleProperty(
114+
sourceFile: ts.SourceFile,
115+
callback: (
116+
nodes: ts.PropertyAssignment,
117+
elementExpressions: ts.NodeArray<ts.Expression>
118+
) => void,
119+
property: string
120+
) {
121+
visitNgModules(sourceFile, (_, decoratorExpressionNode) => {
122+
ts.forEachChild(decoratorExpressionNode, function findTemplates(n) {
123+
if (
124+
ts.isPropertyAssignment(n) &&
125+
ts.isIdentifier(n.name) &&
126+
n.name.text === property &&
127+
ts.isArrayLiteralExpression(n.initializer)
128+
) {
129+
callback(n, n.initializer.elements);
130+
return;
131+
}
132+
133+
ts.forEachChild(n, findTemplates);
134+
});
135+
});
136+
}
137+
export function visitComponents(
138+
sourceFile: ts.SourceFile,
139+
callback: (
140+
classDeclarationNode: ts.ClassDeclaration,
141+
decoratorExpressionNode: ts.ObjectLiteralExpression
142+
) => void
143+
) {
144+
visitDecorator(sourceFile, 'Component', callback);
145+
}
146+
147+
export function visitNgModules(
148+
sourceFile: ts.SourceFile,
149+
callback: (
150+
classDeclarationNode: ts.ClassDeclaration,
151+
decoratorExpressionNode: ts.ObjectLiteralExpression
152+
) => void
153+
) {
154+
visitDecorator(sourceFile, 'NgModule', callback);
155+
}
156+
157+
export function visitDecorator(
158+
sourceFile: ts.SourceFile,
159+
decoratorName: string,
160+
callback: (
161+
classDeclarationNode: ts.ClassDeclaration,
162+
decoratorExpressionNode: ts.ObjectLiteralExpression
163+
) => void
164+
) {
165+
ts.forEachChild(sourceFile, function findClassDeclaration(node) {
166+
if (!ts.isClassDeclaration(node)) {
167+
ts.forEachChild(node, findClassDeclaration);
168+
}
169+
170+
const classDeclarationNode = node as ts.ClassDeclaration;
171+
172+
if (
173+
!classDeclarationNode.decorators ||
174+
!classDeclarationNode.decorators.length
175+
) {
176+
return;
177+
}
178+
179+
const componentDecorator = classDeclarationNode.decorators.find(d => {
180+
return (
181+
ts.isCallExpression(d.expression) &&
182+
ts.isIdentifier(d.expression.expression) &&
183+
d.expression.expression.text === decoratorName
184+
);
185+
});
186+
187+
if (!componentDecorator) {
188+
return;
189+
}
190+
191+
const { expression } = componentDecorator;
192+
if (!ts.isCallExpression(expression)) {
193+
return;
194+
}
195+
196+
const [arg] = expression.arguments;
197+
if (!ts.isObjectLiteralExpression(arg)) {
198+
return;
199+
}
200+
201+
callback(classDeclarationNode, arg);
202+
});
203+
}
204+
20205
function* visit(directory: DirEntry): IterableIterator<ts.SourceFile> {
21206
for (const path of directory.subfiles) {
22207
if (path.endsWith('.ts') && !path.endsWith('.d.ts')) {
@@ -42,31 +227,3 @@ function* visit(directory: DirEntry): IterableIterator<ts.SourceFile> {
42227
yield* visit(directory.dir(path));
43228
}
44229
}
45-
46-
export function visitNgModuleImports(
47-
sourceFile: ts.SourceFile,
48-
callback: (
49-
importNode: ts.PropertyAssignment,
50-
elementExpressions: ts.NodeArray<ts.Expression>
51-
) => void
52-
) {
53-
ts.forEachChild(sourceFile, function findDecorator(node) {
54-
if (!ts.isDecorator(node)) {
55-
ts.forEachChild(node, findDecorator);
56-
return;
57-
}
58-
59-
ts.forEachChild(node, function findImportsNode(n) {
60-
if (
61-
ts.isPropertyAssignment(n) &&
62-
ts.isArrayLiteralExpression(n.initializer) &&
63-
ts.isIdentifier(n.name) &&
64-
n.name.text === 'imports'
65-
) {
66-
callback(n, n.initializer.elements);
67-
}
68-
69-
ts.forEachChild(n, findImportsNode);
70-
});
71-
});
72-
}

modules/effects/schematics-core/index.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,12 @@ export { addPackageToPackageJson } from './utility/package';
8181

8282
export { platformVersion } from './utility/libs-version';
8383

84-
export { visitTSSourceFiles, visitNgModuleImports } from './utility/visitors';
84+
export {
85+
visitTSSourceFiles,
86+
visitNgModuleImports,
87+
visitNgModuleExports,
88+
visitComponents,
89+
visitDecorator,
90+
visitNgModules,
91+
visitTemplates,
92+
} from './utility/visitors';

0 commit comments

Comments
 (0)