Skip to content

Commit

Permalink
tsp, fix projectedName json on spread/flatten (#2462)
Browse files Browse the repository at this point in the history
* fix projectedName on spread/flatten

* handle projectedName(json) for discriminator property
  • Loading branch information
weidongxu-microsoft authored Dec 13, 2023
1 parent 72a8f24 commit 88aa774
Show file tree
Hide file tree
Showing 14 changed files with 423 additions and 22 deletions.
1 change: 1 addition & 0 deletions eng/pipelines/ci-typespec-java-dev-nightly.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ jobs:
workingDirectory: ./typespec-extension
- task: PowerShell@2
retryCountOnTaskFailure: 1
displayName: 'Generate Code'
inputs:
pwsh: true
Expand Down
1 change: 1 addition & 0 deletions eng/pipelines/ci-typespec-java.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ jobs:
publishJUnitResults: false

- task: PowerShell@2
retryCountOnTaskFailure: 1
displayName: 'Generate Code'
inputs:
pwsh: true
Expand Down
6 changes: 5 additions & 1 deletion typespec-extension/changelog.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
# Release History

## 0.12.0 (Unreleased)
## 0.12.1 (Unreleased)

Compatible with compiler 0.51.

- Supported convenience API for "multipart/form-data".

## 0.12.0 (2023-12-13)

Compatible with compiler 0.51.

## 0.11.3 (2023-12-06)

Compatible with compiler 0.50.
Expand Down
50 changes: 40 additions & 10 deletions typespec-extension/src/code-model-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ export class CodeModelBuilder {
const keyScheme = new KeySecurityScheme({
name: "authorization",
});
(keyScheme as any).prefix = schemeOrApiKeyPrefix; // TODO (weidxu): modify KeySecurityScheme, after design stable
(keyScheme as any).prefix = schemeOrApiKeyPrefix; // TODO: modify KeySecurityScheme, after design stable
securitySchemes.push(keyScheme);
}
break;
Expand Down Expand Up @@ -1279,8 +1279,9 @@ export class CodeModelBuilder {
request.parameters = [];
op.convenienceApi.requests.push(request);

for (const [key, _] of parameters.properties) {
const existParameter = op.parameters.find((it) => it.language.default.serializedName === key);
for (const [_, opParameter] of parameters.properties) {
const serializedName = this.getSerializedName(opParameter);
const existParameter = op.parameters.find((it) => it.language.default.serializedName === serializedName);
if (existParameter) {
// parameter
if (
Expand All @@ -1291,7 +1292,7 @@ export class CodeModelBuilder {
}
} else {
// property from anonymous model
const existBodyProperty = schema.properties?.find((it) => it.serializedName === key);
const existBodyProperty = schema.properties?.find((it) => it.serializedName === serializedName);
if (existBodyProperty) {
request.parameters.push(
new VirtualParameter(
Expand Down Expand Up @@ -1990,15 +1991,42 @@ export class CodeModelBuilder {

// discriminator
let discriminatorPropertyName: string | undefined = undefined;
type discriminatorTypeWithPropertyName = Partial<Discriminator> & { propertyName: string };
const discriminator = getDiscriminator(this.program, type);
if (discriminator) {
discriminatorPropertyName = discriminator.propertyName;
objectSchema.discriminator = new Discriminator(
new Property(discriminatorPropertyName, discriminatorPropertyName, this.stringSchema, {
required: true,
serializedName: discriminatorPropertyName,
}),
// find the discriminator property from model
// the property is required for getting its serializedName
let discriminatorProperty = Array.from(type.properties.values()).find(
(it) => it.name === discriminatorPropertyName,
);
if (!discriminatorProperty) {
// try find the discriminator property from any of its derived models
for (const deriveModel of type.derivedModels) {
discriminatorProperty = Array.from(deriveModel.properties.values()).find(
(it) => it.name === discriminatorPropertyName,
);
if (discriminatorProperty) {
// found
break;
}
}
}
if (discriminatorProperty) {
objectSchema.discriminator = new Discriminator(this.processModelProperty(discriminatorProperty));
// as we do not expose the discriminator property, its schema is fine to be just a string (and we do not want to generate an enum that not used anywhere)
// TODO: support enum schema, if we expose the discriminator property
objectSchema.discriminator.property.schema = this.stringSchema;
} else {
// fallback to property name, if cannot find the discriminator property
objectSchema.discriminator = new Discriminator(
new Property(discriminatorPropertyName, discriminatorPropertyName, this.stringSchema, {
required: true,
serializedName: discriminatorPropertyName,
}),
);
}
(objectSchema.discriminator as discriminatorTypeWithPropertyName).propertyName = discriminatorPropertyName;
}

// parent
Expand Down Expand Up @@ -2042,7 +2070,9 @@ export class CodeModelBuilder {
(it) => it instanceof ObjectSchema && it.discriminator,
);
if (parentWithDiscriminator) {
discriminatorPropertyName = (parentWithDiscriminator as ObjectSchema).discriminator!.property.serializedName;
discriminatorPropertyName = (
(parentWithDiscriminator as ObjectSchema).discriminator as discriminatorTypeWithPropertyName
).propertyName;

const discriminatorProperty = Array.from(type.properties.values()).find(
(it) => it.name === discriminatorPropertyName && (it.type.kind === "String" || it.type.kind === "EnumMember"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,33 @@ public Mono<Response<Void>> sendWithResponse(String id, BinaryData request, Requ
return this.serviceClient.sendWithResponseAsync(id, request, requestOptions);
}

/**
* The sendProjectedName operation.
* <p>
* <strong>Request Body Schema</strong>
* </p>
* <pre>{@code
* {
* file_id: String (Required)
* }
* }</pre>
*
* @param id A sequence of textual characters.
* @param request The request parameter.
* @param requestOptions The options to configure the HTTP request before HTTP client sends it.
* @throws HttpResponseException thrown if the request is rejected by server.
* @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401.
* @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404.
* @throws ResourceModifiedException thrown if the request is rejected by server on status code 409.
* @return the {@link Response} on successful completion of {@link Mono}.
*/
@Generated
@ServiceMethod(returns = ReturnType.SINGLE)
public Mono<Response<Void>> sendProjectedNameWithResponse(String id, BinaryData request,
RequestOptions requestOptions) {
return this.serviceClient.sendProjectedNameWithResponseAsync(id, request, requestOptions);
}

/**
* The sendLong operation.
* <p>
Expand Down Expand Up @@ -172,6 +199,30 @@ public Mono<Void> send(String id, String input) {
return sendWithResponse(id, request, requestOptions).flatMap(FluxUtil::toMono);
}

/**
* The sendProjectedName operation.
*
* @param id A sequence of textual characters.
* @param fileIdentifier A sequence of textual characters.
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @throws HttpResponseException thrown if the request is rejected by server.
* @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401.
* @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404.
* @throws ResourceModifiedException thrown if the request is rejected by server on status code 409.
* @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
* @return A {@link Mono} that completes when a successful response is received.
*/
@Generated
@ServiceMethod(returns = ReturnType.SINGLE)
public Mono<Void> sendProjectedName(String id, String fileIdentifier) {
// Generated convenience method for sendProjectedNameWithResponse
RequestOptions requestOptions = new RequestOptions();
Map<String, Object> requestObj = new HashMap<>();
requestObj.put("file_id", fileIdentifier);
BinaryData request = BinaryData.fromObject(requestObj);
return sendProjectedNameWithResponse(id, request, requestOptions).flatMap(FluxUtil::toMono);
}

/**
* The sendLong operation.
*
Expand Down
49 changes: 49 additions & 0 deletions typespec-tests/src/main/java/com/cadl/flatten/FlattenClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,32 @@ public Response<Void> sendWithResponse(String id, BinaryData request, RequestOpt
return this.serviceClient.sendWithResponse(id, request, requestOptions);
}

/**
* The sendProjectedName operation.
* <p>
* <strong>Request Body Schema</strong>
* </p>
* <pre>{@code
* {
* file_id: String (Required)
* }
* }</pre>
*
* @param id A sequence of textual characters.
* @param request The request parameter.
* @param requestOptions The options to configure the HTTP request before HTTP client sends it.
* @throws HttpResponseException thrown if the request is rejected by server.
* @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401.
* @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404.
* @throws ResourceModifiedException thrown if the request is rejected by server on status code 409.
* @return the {@link Response}.
*/
@Generated
@ServiceMethod(returns = ReturnType.SINGLE)
public Response<Void> sendProjectedNameWithResponse(String id, BinaryData request, RequestOptions requestOptions) {
return this.serviceClient.sendProjectedNameWithResponse(id, request, requestOptions);
}

/**
* The sendLong operation.
* <p>
Expand Down Expand Up @@ -168,6 +194,29 @@ public void send(String id, String input) {
sendWithResponse(id, request, requestOptions).getValue();
}

/**
* The sendProjectedName operation.
*
* @param id A sequence of textual characters.
* @param fileIdentifier A sequence of textual characters.
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @throws HttpResponseException thrown if the request is rejected by server.
* @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401.
* @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404.
* @throws ResourceModifiedException thrown if the request is rejected by server on status code 409.
* @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
*/
@Generated
@ServiceMethod(returns = ReturnType.SINGLE)
public void sendProjectedName(String id, String fileIdentifier) {
// Generated convenience method for sendProjectedNameWithResponse
RequestOptions requestOptions = new RequestOptions();
Map<String, Object> requestObj = new HashMap<>();
requestObj.put("file_id", fileIdentifier);
BinaryData request = BinaryData.fromObject(requestObj);
sendProjectedNameWithResponse(id, request, requestOptions).getValue();
}

/**
* The sendLong operation.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,26 @@ Response<Void> sendSync(@HostParam("endpoint") String endpoint, @QueryParam("id"
@QueryParam("api-version") String apiVersion, @HeaderParam("accept") String accept,
@BodyParam("application/json") BinaryData request, RequestOptions requestOptions, Context context);

@Post("/flatten/send-projected-name")
@ExpectedResponses({ 200 })
@UnexpectedResponseExceptionType(value = ClientAuthenticationException.class, code = { 401 })
@UnexpectedResponseExceptionType(value = ResourceNotFoundException.class, code = { 404 })
@UnexpectedResponseExceptionType(value = ResourceModifiedException.class, code = { 409 })
@UnexpectedResponseExceptionType(HttpResponseException.class)
Mono<Response<Void>> sendProjectedName(@HostParam("endpoint") String endpoint, @QueryParam("id") String id,
@HeaderParam("accept") String accept, @BodyParam("application/json") BinaryData request,
RequestOptions requestOptions, Context context);

@Post("/flatten/send-projected-name")
@ExpectedResponses({ 200 })
@UnexpectedResponseExceptionType(value = ClientAuthenticationException.class, code = { 401 })
@UnexpectedResponseExceptionType(value = ResourceNotFoundException.class, code = { 404 })
@UnexpectedResponseExceptionType(value = ResourceModifiedException.class, code = { 409 })
@UnexpectedResponseExceptionType(HttpResponseException.class)
Response<Void> sendProjectedNameSync(@HostParam("endpoint") String endpoint, @QueryParam("id") String id,
@HeaderParam("accept") String accept, @BodyParam("application/json") BinaryData request,
RequestOptions requestOptions, Context context);

@Post("/flatten/send-long")
@ExpectedResponses({ 200 })
@UnexpectedResponseExceptionType(value = ClientAuthenticationException.class, code = { 401 })
Expand Down Expand Up @@ -244,6 +264,60 @@ public Response<Void> sendWithResponse(String id, BinaryData request, RequestOpt
requestOptions, Context.NONE);
}

/**
* The sendProjectedName operation.
* <p>
* <strong>Request Body Schema</strong>
* </p>
* <pre>{@code
* {
* file_id: String (Required)
* }
* }</pre>
*
* @param id A sequence of textual characters.
* @param request The request parameter.
* @param requestOptions The options to configure the HTTP request before HTTP client sends it.
* @throws HttpResponseException thrown if the request is rejected by server.
* @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401.
* @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404.
* @throws ResourceModifiedException thrown if the request is rejected by server on status code 409.
* @return the {@link Response} on successful completion of {@link Mono}.
*/
@ServiceMethod(returns = ReturnType.SINGLE)
public Mono<Response<Void>> sendProjectedNameWithResponseAsync(String id, BinaryData request,
RequestOptions requestOptions) {
final String accept = "application/json";
return FluxUtil.withContext(
context -> service.sendProjectedName(this.getEndpoint(), id, accept, request, requestOptions, context));
}

/**
* The sendProjectedName operation.
* <p>
* <strong>Request Body Schema</strong>
* </p>
* <pre>{@code
* {
* file_id: String (Required)
* }
* }</pre>
*
* @param id A sequence of textual characters.
* @param request The request parameter.
* @param requestOptions The options to configure the HTTP request before HTTP client sends it.
* @throws HttpResponseException thrown if the request is rejected by server.
* @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401.
* @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404.
* @throws ResourceModifiedException thrown if the request is rejected by server on status code 409.
* @return the {@link Response}.
*/
@ServiceMethod(returns = ReturnType.SINGLE)
public Response<Void> sendProjectedNameWithResponse(String id, BinaryData request, RequestOptions requestOptions) {
final String accept = "application/json";
return service.sendProjectedNameSync(this.getEndpoint(), id, accept, request, requestOptions, Context.NONE);
}

/**
* The sendLong operation.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ public final class NamingAsyncClient {
* {
* name: String (Required)
* data (Required): {
* data: byte[] (Required)
* data (Required): {
* kind_id: String (Optional)
* }
* }
* type: String(Blob/File) (Required)
* status: String(Running/Completed/Failed) (Required)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,9 @@ Response<BinaryData> getAnonymouseSync(@HostParam("endpoint") String endpoint,
* {
* name: String (Required)
* data (Required): {
* data: byte[] (Required)
* data (Required): {
* kind_id: String (Optional)
* }
* }
* type: String(Blob/File) (Required)
* status: String(Running/Completed/Failed) (Required)
Expand Down Expand Up @@ -211,7 +213,9 @@ public Mono<Response<BinaryData>> postWithResponseAsync(String name, BinaryData
* {
* name: String (Required)
* data (Required): {
* data: byte[] (Required)
* data (Required): {
* kind_id: String (Optional)
* }
* }
* type: String(Blob/File) (Required)
* status: String(Running/Completed/Failed) (Required)
Expand Down
Loading

0 comments on commit 88aa774

Please sign in to comment.