Skip to content

Commit 5564d02

Browse files
thePunderWomanAndrewKushnir
authored andcommitted
fix(migrations): Fixes control flow migration if then else case (#53006)
With if then else use cases, we now properly account for the length of the original element's contents when tracking new offsets. fixes: #52927 PR Close #53006
1 parent f84057d commit 5564d02

File tree

3 files changed

+63
-5
lines changed

3 files changed

+63
-5
lines changed

packages/core/schematics/ng-generate/control-flow-migration/ifs.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,9 @@ function buildIfThenElseBlock(
175175

176176
const updatedTmpl = tmplStart + ifThenElseBlock + tmplEnd;
177177

178-
const pre = originals.start.length - startBlock.length;
178+
// We ignore the contents of the element on if then else.
179+
// If there's anything there, we need to account for the length in the offset.
180+
const pre = originals.start.length + originals.childLength - startBlock.length;
179181
const post = originals.end.length - postBlock.length;
180182

181183
return {tmpl: updatedTmpl, offsets: {pre, post}};

packages/core/schematics/ng-generate/control-flow-migration/util.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -336,24 +336,27 @@ export function removeImports(
336336
* retrieves the original block of text in the template for length comparison during migration
337337
* processing
338338
*/
339-
export function getOriginals(
340-
etm: ElementToMigrate, tmpl: string, offset: number): {start: string, end: string} {
339+
export function getOriginals(etm: ElementToMigrate, tmpl: string, offset: number):
340+
{start: string, end: string, childLength: number} {
341341
// original opening block
342342
if (etm.el.children.length > 0) {
343+
const childStart = etm.el.children[0].sourceSpan.start.offset - offset;
344+
const childEnd = etm.el.children[etm.el.children.length - 1].sourceSpan.end.offset - offset;
343345
const start = tmpl.slice(
344346
etm.el.sourceSpan.start.offset - offset,
345347
etm.el.children[0].sourceSpan.start.offset - offset);
346348
// original closing block
347349
const end = tmpl.slice(
348350
etm.el.children[etm.el.children.length - 1].sourceSpan.end.offset - offset,
349351
etm.el.sourceSpan.end.offset - offset);
350-
return {start, end};
352+
const childLength = childEnd - childStart;
353+
return {start, end, childLength};
351354
}
352355
// self closing or no children
353356
const start =
354357
tmpl.slice(etm.el.sourceSpan.start.offset - offset, etm.el.sourceSpan.end.offset - offset);
355358
// original closing block
356-
return {start, end: ''};
359+
return {start, end: '', childLength: 0};
357360
}
358361

359362
function isI18nTemplate(etm: ElementToMigrate, i18nAttr: Attribute|undefined): boolean {

packages/core/schematics/test/control_flow_migration_spec.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,59 @@ describe('control flow migration', () => {
828828
].join('\n'));
829829
});
830830

831+
it('should migrate a complex if then else case on ng-containers', async () => {
832+
writeFile('/comp.ts', `
833+
import {Component} from '@angular/core';
834+
import {NgIf} from '@angular/common';
835+
836+
@Component({
837+
templateUrl: './comp.html'
838+
})
839+
class Comp {
840+
show = false;
841+
}
842+
`);
843+
844+
writeFile('/comp.html', [
845+
`<ng-container>`,
846+
` <ng-container`,
847+
` *ngIf="loading; then loadingTmpl; else showTmpl"`,
848+
` >`,
849+
` </ng-container>`,
850+
`<ng-template #showTmpl>`,
851+
` <ng-container`,
852+
` *ngIf="selected; else emptyTmpl"`,
853+
` >`,
854+
` <div></div>`,
855+
` </ng-container>`,
856+
`</ng-template>`,
857+
`<ng-template #emptyTmpl>`,
858+
` Empty`,
859+
`</ng-template>`,
860+
`</ng-container>`,
861+
`<ng-template #loadingTmpl>`,
862+
` <p>Loading</p>`,
863+
`</ng-template>`,
864+
].join('\n'));
865+
866+
await runMigration();
867+
const content = tree.readContent('/comp.html');
868+
869+
expect(content).toBe([
870+
`<ng-container>`,
871+
` @if (loading) {`,
872+
` <p>Loading</p>`,
873+
` } @else {`,
874+
` @if (selected) {`,
875+
` <div></div>`,
876+
` } @else {`,
877+
` Empty`,
878+
` }`,
879+
` }`,
880+
`</ng-container>`,
881+
].join('\n'));
882+
});
883+
831884
it('should migrate but not remove ng-templates when referenced elsewhere', async () => {
832885
writeFile('/comp.ts', `
833886
import {Component} from '@angular/core';

0 commit comments

Comments
 (0)