Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .chronus/changes/main-2025-9-7-12-33-46.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
changeKind: fix
packages:
- "@typespec/compiler"
---

Addressed an issue where applying the `Update` visibility transform would not correctly rename nested models.
4 changes: 3 additions & 1 deletion packages/compiler/src/lib/visibility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,9 @@ export const $withLifecycleUpdate: WithLifecycleUpdateDecorator = (
any: new Set([lifecycle.members.get("Create")!, lifecycle.members.get("Update")!]),
};

const createOrUpdateMutator = createVisibilityFilterMutator(lifecycleCreateOrUpdate);
const createOrUpdateMutator = createVisibilityFilterMutator(lifecycleCreateOrUpdate, {
nameTemplate,
});

mutator = createVisibilityFilterMutator(lifecycleUpdate, {
recur: createOrUpdateMutator,
Expand Down
96 changes: 51 additions & 45 deletions packages/compiler/test/visibility.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ describe("compiler: visibility core", () => {
removeVisibilityModifiers(runner.program, x, [Create]);
clearVisibilityModifiersForClass(runner.program, x, Lifecycle);

ok(runner.program.diagnostics.length === 3);
strictEqual(runner.program.diagnostics.length, 3);

expectDiagnostics(runner.program.diagnostics, [
{
Expand Down Expand Up @@ -737,31 +737,33 @@ describe("compiler: visibility core", () => {
@invisible(Lifecycle)
invisible: string;

nested: {
@visibility(${Lifecycle.Read})
r: string;
nested: Nested;
}

cru: string;
model Nested {
@visibility(${Lifecycle.Read})
r: string;

@visibility(${Lifecycle.Create}, ${Lifecycle.Read})
cr: string;
cru: string;

@visibility(${Lifecycle.Create}, ${Lifecycle.Update})
cu: string;
@visibility(${Lifecycle.Create}, ${Lifecycle.Read})
cr: string;

@visibility(${Lifecycle.Create})
c: string;
@visibility(${Lifecycle.Create}, ${Lifecycle.Update})
cu: string;

@visibility(${Lifecycle.Update}, ${Lifecycle.Read})
ru: string;
@visibility(${Lifecycle.Create})
c: string;

@visibility(${Lifecycle.Update})
u: string;
@visibility(${Lifecycle.Update}, ${Lifecycle.Read})
ru: string;

@invisible(Lifecycle)
invisible: string;
};
}
@visibility(${Lifecycle.Update})
u: string;

@invisible(Lifecycle)
invisible: string;
};

// This ensures the transforms are non-side-effecting.
model ReadExample is Read<Example>;
Expand Down Expand Up @@ -888,7 +890,7 @@ describe("compiler: visibility core", () => {

const A = ref.type;

ok(A.kind === "Model");
strictEqual(A.kind, "Model");

const a = A.properties.get("a");
const b = A.properties.get("b");
Expand Down Expand Up @@ -1011,14 +1013,14 @@ describe("compiler: visibility core", () => {
const dataA = DataA.properties.get("data_a")!;
const dataB = DataB.properties.get("data_b")!;

ok(dataA.type.kind === "Model");
ok(dataB.type.kind === "Model");
strictEqual(dataA.type.kind, "Model");
strictEqual(dataB.type.kind, "Model");

const FooA = dataA.type as Model;
const FooB = dataB.type as Model;

ok(FooA.name === "FooA");
ok(FooB.name === "FooB");
strictEqual(FooA.name, "FooA");
strictEqual(FooB.name, "FooB");

ok(FooA.properties.has("foo_a"));
ok(!FooA.properties.has("foo_b"));
Expand Down Expand Up @@ -1070,8 +1072,8 @@ describe("compiler: visibility core", () => {
ok(a);
ok(b);

ok(a.type.kind === "Model");
ok(b.type.kind === "Model");
strictEqual(a.type.kind, "Model");
strictEqual(b.type.kind, "Model");

const A = a.type as Model;
const B = b.type as Model;
Expand All @@ -1091,20 +1093,20 @@ describe("compiler: visibility core", () => {
ok(aC);
ok(bC);

ok(aC.type === bC.type);
strictEqual(aC.type, bC.type);

let C = aC.type as Model;

ok(C.kind === "Model");
ok(C.name === "ReadC");
strictEqual(C.kind, "Model");
strictEqual(C.name, "ReadC");

ok(!C.properties.has("invisible"));
ok(C.properties.has("c"));

C = bC.type as Model;

ok(C.kind === "Model");
ok(C.name === "ReadC");
strictEqual(C.kind, "Model");
strictEqual(C.name, "ReadC");

ok(!C.properties.has("invisible"));
ok(C.properties.has("c"));
Expand Down Expand Up @@ -1135,7 +1137,7 @@ describe("compiler: visibility core", () => {

strictEqual(aB.kind, "Model");

ok(aB === B);
strictEqual(aB, B);
});

it("correctly transforms arrays and records", async () => {
Expand Down Expand Up @@ -1166,22 +1168,22 @@ describe("compiler: visibility core", () => {
const arrayType = array.type;
const recordType = record.type;

ok(arrayType.kind === "Model");
ok(recordType.kind === "Model");
strictEqual(arrayType.kind, "Model");
strictEqual(recordType.kind, "Model");

ok($(runner.program).array.is(arrayType));
ok($(runner.program).record.is(recordType));

const arrayA = (arrayType as Model).indexer!.value as Model;
const recordA = (recordType as Model).indexer!.value as Model;

ok(arrayA.kind === "Model");
ok(recordA.kind === "Model");
strictEqual(arrayA.kind, "Model");
strictEqual(recordA.kind, "Model");

ok(arrayA.name === "ATransform");
ok(recordA.name === "ATransform");
strictEqual(arrayA.name, "ATransform");
strictEqual(recordA.name, "ATransform");

ok(arrayA === recordA);
strictEqual(arrayA, recordA);

ok(arrayA.properties.has("a"));
ok(!arrayA.properties.has("invisible"));
Expand Down Expand Up @@ -1219,8 +1221,8 @@ describe("compiler: visibility core", () => {
const arrType = arr.type;
const recType = rec.type;

ok(arrType.kind === "Model");
ok(recType.kind === "Model");
strictEqual(arrType.kind, "Model");
strictEqual(recType.kind, "Model");

ok($(runner.program).array.is(arrType));
ok($(runner.program).record.is(recType));
Expand Down Expand Up @@ -1279,7 +1281,8 @@ function validateCreateOrUpdateTransform(
const nested = Result.properties.get("nested");

ok(nested);
ok(nested.type.kind === "Model");
strictEqual(nested.type.kind, "Model");
strictEqual(nested.type.name, "CreateOrUpdateNested");

const nestedProps = getProperties(nested.type);

Expand Down Expand Up @@ -1332,7 +1335,8 @@ function validateUpdateTransform(
const nested = Result.properties.get("nested");

ok(nested);
ok(nested.type.kind === "Model");
strictEqual(nested.type.kind, "Model");
strictEqual(nested.type.name, "UpdateNested");

// Nested properties work differently in Lifecycle Update transforms, requiring nested create-only properties to
// additionally be visible
Expand Down Expand Up @@ -1387,7 +1391,8 @@ function validateCreateTransform(
const nested = Result.properties.get("nested");

ok(nested);
ok(nested.type.kind === "Model");
strictEqual(nested.type.kind, "Model");
strictEqual(nested.type.name, "CreateNested");

const nestedProps = getProperties(nested.type);

Expand Down Expand Up @@ -1441,7 +1446,8 @@ function validateReadTransform(
const nested = Result.properties.get("nested");

ok(nested);
ok(nested.type.kind === "Model");
strictEqual(nested.type.kind, "Model");
strictEqual(nested.type.name, "ReadNested");

const nestedProps = getProperties(nested.type);

Expand Down
Loading