Skip to content

Commit d0528da

Browse files
AlitzelMendezAlitzel Mendeztimotheeguerin
authored
Fix circular-ref when navigating paging properties (#7480)
issue: #7436 still validating if this will solve the issue --------- Co-authored-by: Alitzel Mendez <[email protected]> Co-authored-by: Timothee Guerin <[email protected]>
1 parent e11162d commit d0528da

File tree

3 files changed

+28
-5
lines changed

3 files changed

+28
-5
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
changeKind: fix
3+
packages:
4+
- "@typespec/compiler"
5+
---
6+
7+
Fix infinite recursion when navigating paging properties by detecting and handling circular model references.

packages/compiler/src/lib/paging.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -298,21 +298,24 @@ function navigateProperties(
298298
type: Type,
299299
callback: (prop: ModelProperty, path: ModelProperty[]) => void,
300300
path: ModelProperty[] = [],
301+
visited: Set<Type> = new Set(),
301302
): void {
303+
if (visited.has(type)) return;
304+
visited.add(type);
302305
switch (type.kind) {
303306
case "Model":
304307
for (const prop of type.properties.values()) {
305308
callback(prop, [...path, prop]);
306-
navigateProperties(prop.type, callback, [...path, prop]);
309+
navigateProperties(prop.type, callback, [...path, prop], visited);
307310
}
308311
break;
309312
case "Union":
310313
for (const member of type.variants.values()) {
311-
navigateProperties(member, callback, path);
314+
navigateProperties(member, callback, path, visited);
312315
}
313316
break;
314317
case "UnionVariant":
315-
navigateProperties(type.type, callback, path);
318+
navigateProperties(type.type, callback, path, visited);
316319
break;
317320
}
318321
}

packages/compiler/test/decorators/paging.test.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { beforeEach, describe, expect, it } from "vitest";
22
import { ignoreDiagnostics, ModelProperty, Operation } from "../../src/index.js";
33
import { getPagingOperation, PagingOperation } from "../../src/lib/paging.js";
4-
import { expectDiagnostics } from "../../src/testing/expect.js";
4+
import { expectDiagnosticEmpty, expectDiagnostics } from "../../src/testing/expect.js";
55
import { createTestRunner } from "../../src/testing/test-host.js";
66
import { BasicTestRunner } from "../../src/testing/types.js";
77

@@ -39,7 +39,20 @@ it("emit error if missing pageItems property", async () => {
3939
});
4040
});
4141

42-
describe("emit conflict diagnostic if multiple properties are annotated with teh same property marker", () => {
42+
it("@list decorator handle recursive models without infinite loop", async () => {
43+
const diagnostics = await runner.diagnose(`
44+
model MyPage {
45+
selfRef?: MyPage;
46+
@pageItems items: string[];
47+
@nextLink next: string;
48+
}
49+
50+
@list op foo(): MyPage;
51+
`);
52+
expectDiagnosticEmpty(diagnostics);
53+
});
54+
55+
describe("emit conflict diagnostic if multiple properties are annotated with the same property marker", () => {
4356
it.each([
4457
["offset", "int32"],
4558
["pageSize", "int32"],

0 commit comments

Comments
 (0)