From 64f2319d8c878a65d1a53f7a13961c88bd9c1e27 Mon Sep 17 00:00:00 2001 From: Jose Manuel Heredia Hidalgo Date: Mon, 27 Jan 2025 16:29:03 -0800 Subject: [PATCH 1/2] Add option to enable semantic walker to visit derived models --- packages/compiler/src/core/semantic-walker.ts | 11 ++ .../compiler/test/semantic-walker.test.ts | 104 +++++++++++++++++- 2 files changed, 114 insertions(+), 1 deletion(-) diff --git a/packages/compiler/src/core/semantic-walker.ts b/packages/compiler/src/core/semantic-walker.ts index 693313c692..7b0e9d3761 100644 --- a/packages/compiler/src/core/semantic-walker.ts +++ b/packages/compiler/src/core/semantic-walker.ts @@ -27,6 +27,10 @@ export interface NavigationOptions { * Skip non instantiated templates. */ includeTemplateDeclaration?: boolean; + /** + * Visit derived types. + */ + visitDerivedTypes?: boolean; } export interface NamespaceNavigationOptions { @@ -253,6 +257,13 @@ function navigateModelType(model: Model, context: NavigationContext) { if (model.indexer && model.indexer.value) { navigateTypeInternal(model.indexer.value, context); } + + if (context.options.visitDerivedTypes) { + for (const derived of model.derivedModels) { + navigateModelType(derived, context); + } + } + context.emit("exitModel", model); } diff --git a/packages/compiler/test/semantic-walker.test.ts b/packages/compiler/test/semantic-walker.test.ts index 8d35b1c883..ce86966de3 100644 --- a/packages/compiler/test/semantic-walker.test.ts +++ b/packages/compiler/test/semantic-walker.test.ts @@ -17,15 +17,23 @@ import { import { getProperty, navigateProgram, + navigateType, navigateTypesInNamespace, } from "../src/core/semantic-walker.js"; -import { TestHost, createTestHost } from "../src/testing/index.js"; +import { + BasicTestRunner, + TestHost, + createTestHost, + createTestRunner, +} from "../src/testing/index.js"; describe("compiler: semantic walker", () => { let host: TestHost; + let runner: BasicTestRunner; beforeEach(async () => { host = await createTestHost(); + runner = await createTestRunner(); }); function createCollector(customListener?: SemanticNodeListener) { @@ -138,6 +146,100 @@ describe("compiler: semantic walker", () => { return result; } + it("finds derived models", async () => { + const { Bird } = (await runner.compile(` + namespace Test; + + @discriminator("kind") + @test + model Bird { + kind: string; + wingspan: int32; + } + + model SeaGull extends Bird { + kind: "seagull"; + } + + model Sparrow extends Bird { + kind: "sparrow"; + } + + model Goose extends Bird { + kind: "goose"; + } + + model Eagle extends Bird { + kind: "eagle"; + friends?: Bird[]; + hate?: Record; + partner?: Bird; + } + `)) as { Bird: Model }; + + const visitedModels: Model[] = []; + navigateType( + Bird, + { + model(model) { + visitedModels.push(model); + }, + }, + { includeTemplateDeclaration: false, visitDerivedTypes: true }, + ); + + const expectedModels = ["Bird", "SeaGull", "Sparrow", "Goose", "Eagle"]; + strictEqual( + expectedModels.every((element) => visitedModels.map((m) => m.name).includes(element)), + true, + ); + }); + + it("doesn't visit derived models without the option", async () => { + const { Bird } = (await runner.compile(` + namespace Test; + + @discriminator("kind") + @test + model Bird { + kind: string; + wingspan: int32; + } + + model SeaGull extends Bird { + kind: "seagull"; + } + + model Sparrow extends Bird { + kind: "sparrow"; + } + + model Goose extends Bird { + kind: "goose"; + } + + model Eagle extends Bird { + kind: "eagle"; + friends?: Bird[]; + hate?: Record; + partner?: Bird; + } + `)) as { Bird: Model }; + + const visitedModels: Model[] = []; + navigateType( + Bird, + { + model(model) { + visitedModels.push(model); + }, + }, + { visitDerivedTypes: false }, + ); + + strictEqual(visitedModels.length, 1); + }); + it("finds models", async () => { const result = await runNavigator(` model Foo { From 117510f01a36219ad5e9f41546b5c187394c2662 Mon Sep 17 00:00:00 2001 From: Jose Manuel Heredia Hidalgo Date: Mon, 27 Jan 2025 16:30:11 -0800 Subject: [PATCH 2/2] Add change description --- ...er-semantic-walker-derived-models-2025-0-27-16-29-58.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .chronus/changes/feature-compiler-semantic-walker-derived-models-2025-0-27-16-29-58.md diff --git a/.chronus/changes/feature-compiler-semantic-walker-derived-models-2025-0-27-16-29-58.md b/.chronus/changes/feature-compiler-semantic-walker-derived-models-2025-0-27-16-29-58.md new file mode 100644 index 0000000000..4767aff027 --- /dev/null +++ b/.chronus/changes/feature-compiler-semantic-walker-derived-models-2025-0-27-16-29-58.md @@ -0,0 +1,7 @@ +--- +changeKind: feature +packages: + - "@typespec/compiler" +--- + +Add option for semantic walker to visit model derived types \ No newline at end of file