Skip to content

Commit

Permalink
[tcgc] don't set mfd model properties that are models to be used as m…
Browse files Browse the repository at this point in the history
…fd models (#569)
  • Loading branch information
iscai-msft authored Apr 2, 2024
1 parent 923625f commit 257e7ad
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 15 deletions.
7 changes: 7 additions & 0 deletions .chronus/changes/prop_not_set_multipart-2024-3-1-16-13-0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
changeKind: fix
packages:
- "@azure-tools/typespec-client-generator-core"
---

don't recursively set `MultipartFormData` usage for models that are properties on a `MultipartFormData` model
41 changes: 26 additions & 15 deletions packages/typespec-client-generator-core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1119,33 +1119,40 @@ function checkAndGetClientType(
return diagnostics.wrap([clientType]);
}

interface ModelUsageOptions {
seenModelNames?: Set<SdkType>;
recurseThroughProperties?: boolean;
}

function updateUsageOfModel(
context: TCGCContext,
usage: UsageFlags,
type?: SdkType,
seenModelNames?: Set<SdkType>
options?: ModelUsageOptions
): void {
options = options ?? {};
options.recurseThroughProperties = options?.recurseThroughProperties ?? true;
if (!type || !["model", "enum", "array", "dict", "union", "enumvalue"].includes(type.kind))
return;
if (seenModelNames === undefined) {
seenModelNames = new Set<SdkType>();
if (options?.seenModelNames === undefined) {
options.seenModelNames = new Set<SdkType>();
}
if (type.kind === "model" && seenModelNames.has(type)) return; // avoid circular references
if (type.kind === "model" && options.seenModelNames.has(type)) return; // avoid circular references
if (type.kind === "array" || type.kind === "dict") {
return updateUsageOfModel(context, usage, type.valueType, seenModelNames);
return updateUsageOfModel(context, usage, type.valueType, options);
}
if (type.kind === "union") {
for (const unionType of type.values) {
updateUsageOfModel(context, usage, unionType, seenModelNames);
updateUsageOfModel(context, usage, unionType, options);
}
return;
}
if (type.kind === "enumvalue") {
updateUsageOfModel(context, usage, type.enumType, seenModelNames);
updateUsageOfModel(context, usage, type.enumType, options);
return;
}
if (type.kind !== "model" && type.kind !== "enum") return;
seenModelNames.add(type);
options.seenModelNames.add(type);

const usageOverride = getUsageOverride(context, type.__raw as any);
if (usageOverride) {
Expand All @@ -1160,18 +1167,20 @@ function updateUsageOfModel(
type.baseModel.usage |= usage;
}
if (type.baseModel) {
updateUsageOfModel(context, usage, type.baseModel, seenModelNames);
updateUsageOfModel(context, usage, type.baseModel, options);
}
if (type.discriminatedSubtypes) {
for (const discriminatedSubtype of Object.values(type.discriminatedSubtypes)) {
updateUsageOfModel(context, usage, discriminatedSubtype, seenModelNames);
updateUsageOfModel(context, usage, discriminatedSubtype, options);
}
}
if (type.additionalProperties) {
updateUsageOfModel(context, usage, type.additionalProperties, seenModelNames);
if (type.additionalProperties && options.recurseThroughProperties) {
updateUsageOfModel(context, usage, type.additionalProperties, options);
}
for (const property of type.properties) {
updateUsageOfModel(context, usage, property.type, seenModelNames);
if (options.recurseThroughProperties) {
for (const property of type.properties) {
updateUsageOfModel(context, usage, property.type, options);
}
}
}

Expand Down Expand Up @@ -1216,7 +1225,9 @@ function updateTypesFromOperation(
}
if (isMultipartFormData(context, httpBody.type, operation)) {
bodies.forEach((body) => {
updateUsageOfModel(context, UsageFlags.MultipartFormData, body);
updateUsageOfModel(context, UsageFlags.MultipartFormData, body, {
recurseThroughProperties: false,
});
});
}
}
Expand Down
26 changes: 26 additions & 0 deletions packages/typespec-client-generator-core/test/types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3000,6 +3000,32 @@ describe("typespec-client-generator-core: types", () => {
["color", "description", "displayName", "name"].sort()
);
});

it("usage doesn't apply to properties of a form data", async function () {
await runner.compileWithBuiltInService(`
model MultiPartRequest {
id: string;
profileImage: bytes;
address: Address;
}
model Address {
city: string;
}
@post
op upload(@header contentType: "multipart/form-data", @body body: MultiPartRequest): void;
`);
const models = runner.context.sdkPackage.models;
strictEqual(models.length, 2);
const multiPartRequest = models.find((x) => x.name === "MultiPartRequest");
ok(multiPartRequest);
ok(multiPartRequest.usage & UsageFlags.MultipartFormData);

const address = models.find((x) => x.name === "Address");
ok(address);
strictEqual(address.usage & UsageFlags.MultipartFormData, 0);
});
});
describe("SdkTupleType", () => {
it("model with tupled properties", async function () {
Expand Down

0 comments on commit 257e7ad

Please sign in to comment.