Skip to content

Commit 9e76468

Browse files
crisbetodylhunn
authored andcommitted
fix(migrations): handle nested classes in block entities migration (angular#52309)
Fixes that the block entities migration was only processing top-level classes. Nested classes could come up during unit tests. PR Close angular#52309
1 parent c5e30f1 commit 9e76468

File tree

2 files changed

+32
-7
lines changed

2 files changed

+32
-7
lines changed

packages/core/schematics/migrations/block-template-entities/util.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,7 @@ export class AnalyzedFile {
6666
* @param analyzedFiles Map in which to store the results.
6767
*/
6868
export function analyze(sourceFile: ts.SourceFile, analyzedFiles: Map<string, AnalyzedFile>) {
69-
for (const node of sourceFile.statements) {
70-
if (!ts.isClassDeclaration(node)) {
71-
continue;
72-
}
73-
69+
forEachClass(sourceFile, node => {
7470
// Note: we have a utility to resolve the Angular decorators from a class declaration already.
7571
// We don't use it here, because it requires access to the type checker which makes it more
7672
// time-consuming to run internally.
@@ -86,7 +82,7 @@ export function analyze(sourceFile: ts.SourceFile, analyzedFiles: Map<string, An
8682
null;
8783

8884
if (!metadata) {
89-
continue;
85+
return;
9086
}
9187

9288
for (const prop of metadata.properties) {
@@ -112,7 +108,7 @@ export function analyze(sourceFile: ts.SourceFile, analyzedFiles: Map<string, An
112108
break;
113109
}
114110
}
115-
}
111+
});
116112
}
117113

118114
/**
@@ -183,3 +179,13 @@ class TextRangeCollector extends RecursiveVisitor {
183179
super.visitText(text, null);
184180
}
185181
}
182+
183+
/** Executes a callback on each class declaration in a file. */
184+
function forEachClass(sourceFile: ts.SourceFile, callback: (node: ts.ClassDeclaration) => void) {
185+
sourceFile.forEachChild(function walk(node) {
186+
if (ts.isClassDeclaration(node)) {
187+
callback(node);
188+
}
189+
node.forEachChild(walk);
190+
});
191+
}

packages/core/schematics/test/block_template_entities_spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,4 +276,23 @@ describe('Block template entities migration', () => {
276276

277277
expect(content).toBe('My email is admin&#64;test.com');
278278
});
279+
280+
it('should migrate a component that is not at the top level', async () => {
281+
writeFile('/comp.ts', `
282+
import {Component} from '@angular/core';
283+
284+
function foo() {
285+
@Component({
286+
template: \`<div><span>My email is [email protected]</span></div><h1>This is a brace }</h1>\`
287+
})
288+
class Comp {}
289+
}
290+
`);
291+
292+
await runMigration();
293+
const content = tree.readContent('/comp.ts');
294+
295+
expect(content).toContain(
296+
'template: `<div><span>My email is admin&#64;test.com</span></div><h1>This is a brace &#125;</h1>`');
297+
});
279298
});

0 commit comments

Comments
 (0)