Skip to content

Commit 0926da1

Browse files
tsp, internalApi generate model classes (#2300)
1 parent 0d85c55 commit 0926da1

39 files changed

+1068
-104
lines changed

extension-base/src/main/java/com/azure/autorest/extension/base/model/codemodel/Operation.java

+10-3
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,10 @@ public class Operation extends Metadata {
6767

6868
private ConvenienceApi convenienceApi;
6969

70-
/**
71-
* a boolean to represent should generate protocol api or not, default is true
72-
*/
7370
private Boolean generateProtocolApi;
7471

72+
private Boolean internalApi;
73+
7574
// internal
7675
private OperationGroup operationGroup;
7776

@@ -292,4 +291,12 @@ public Boolean getGenerateProtocolApi() {
292291
public void setGenerateProtocolApi(Boolean generateProtocolApi) {
293292
this.generateProtocolApi = generateProtocolApi;
294293
}
294+
295+
public Boolean getInternalApi() {
296+
return internalApi;
297+
}
298+
299+
public void setInternalApi(Boolean internalApi) {
300+
this.internalApi = internalApi;
301+
}
295302
}

javagen/src/main/java/com/azure/autorest/mapper/ClientMethodMapper.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -296,11 +296,18 @@ private List<ClientMethod> createClientMethods(Operation operation, boolean isPr
296296
final MethodOverloadType defaultOverloadType = hasNonRequiredParameters(parameters) ? MethodOverloadType.OVERLOAD_MAXIMUM : MethodOverloadType.OVERLOAD_MINIMUM_MAXIMUM;
297297
final boolean generateOnlyRequiredParameters = settings.isRequiredParameterClientMethods() && defaultOverloadType == MethodOverloadType.OVERLOAD_MAXIMUM;
298298

299+
JavaVisibility methodVisibilityInWrapperClient = JavaVisibility.Public;
300+
if ((isProtocolMethod && operation.getGenerateProtocolApi() == Boolean.FALSE)
301+
|| (!isProtocolMethod && operation.getInternalApi() == Boolean.TRUE)) {
302+
// Client method is package private in wrapper client, so that the client or developer can still invoke it.
303+
methodVisibilityInWrapperClient = JavaVisibility.PackagePrivate;
304+
}
305+
299306
builder.parameters(parameters)
300307
.requiredNullableParameterExpressions(requiredParameterExpressions)
301308
.validateExpressions(validateExpressions)
302309
.methodTransformationDetails(methodTransformationDetails)
303-
.methodVisibilityInWrapperClient(isProtocolMethod && operation.getGenerateProtocolApi() == Boolean.FALSE ? JavaVisibility.PackagePrivate : JavaVisibility.Public)
310+
.methodVisibilityInWrapperClient(methodVisibilityInWrapperClient)
304311
.methodPageDetails(null);
305312

306313
if (isPageable) {

javagen/src/main/java/com/azure/autorest/template/ConvenienceMethodTemplateBase.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,11 @@ public void write(ConvenienceMethod convenienceMethodObj, JavaClass classBlock,
6868
addGeneratedAnnotation(classBlock);
6969
TemplateUtil.writeClientMethodServiceMethodAnnotation(convenienceMethod, classBlock);
7070

71+
JavaVisibility methodVisibility = convenienceMethod.getMethodVisibilityInWrapperClient();
72+
7173
// convenience method
7274
String methodDeclaration = String.format("%1$s %2$s(%3$s)", convenienceMethod.getReturnValue().getType(), getMethodName(convenienceMethod), convenienceMethod.getParametersDeclaration());
73-
classBlock.publicMethod(methodDeclaration, methodBlock -> {
75+
classBlock.method(methodVisibility, null, methodDeclaration, methodBlock -> {
7476
methodBlock.line("// Generated convenience method for " + getMethodName(protocolMethod));
7577

7678
writeMethodImplementation(protocolMethod, convenienceMethod, methodBlock, typeReferenceStaticClasses);

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
],
4141
"devDependencies": {
4242
"autorest": "^3.0.0",
43-
"@microsoft.azure/autorest.testserver": "3.3.45"
43+
"@microsoft.azure/autorest.testserver": "3.3.45",
44+
"functions-have-names": "~1.2.3"
4445
}
4546
}

typespec-extension/changelog.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Release History
22

3+
## 0.8.13 (Unreleased)
4+
5+
Compatible with compiler 0.48.
6+
7+
- Supported `@include` from typespec-client-generator-core.
8+
- Supported generate model classes to implementation package, for API of `@access(Access.internal)` or `@internal`.
9+
310
## 0.8.12 (2023-09-12)
411

512
Compatible with compiler 0.47.

typespec-extension/package.json

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@azure-tools/typespec-java",
3-
"version": "0.8.12",
3+
"version": "0.8.13",
44
"description": "TypeSpec library for emitting Java client from the TypeSpec REST protocol binding",
55
"keywords": [
66
"TypeSpec"
@@ -58,18 +58,18 @@
5858
"js-yaml": "~4.1.0"
5959
},
6060
"devDependencies": {
61-
"@types/lodash": "~4.14.196",
61+
"@types/lodash": "~4.14.198",
6262
"@types/js-yaml": "~4.0.5",
6363
"@types/mocha": "~10.0.1",
64-
"@types/node": "~20.4.9",
64+
"@types/node": "~20.6.0",
6565
"@types/prettier": "~2.7.3",
6666
"c8": "~8.0.1",
67-
"eslint": "~8.46.0",
67+
"eslint": "~8.49.0",
6868
"mocha": "~10.2.0",
6969
"rimraf": "~5.0.1",
70-
"typescript": "~5.1.6",
71-
"@typescript-eslint/parser": "~6.3.0",
72-
"@typescript-eslint/eslint-plugin": "~6.3.0",
70+
"typescript": "~5.2.2",
71+
"@typescript-eslint/parser": "~6.7.0",
72+
"@typescript-eslint/eslint-plugin": "~6.7.0",
7373
"eslint-plugin-deprecation": "~1.5.0"
7474
}
7575
}

typespec-extension/src/code-model-builder.ts

+33-21
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ import {
6868
shouldGenerateProtocol,
6969
isInternal,
7070
SdkClient,
71+
isInclude,
7172
} from "@azure-tools/typespec-client-generator-core";
7273
import { fail } from "assert";
7374
import {
@@ -366,7 +367,7 @@ export class CodeModelBuilder {
366367
if (access) {
367368
return access === "internal";
368369
} else {
369-
// fallback to "internal", it will be
370+
// TODO: deprecate "internal"
370371
return isInternal(context, operation);
371372
}
372373
}
@@ -377,31 +378,39 @@ export class CodeModelBuilder {
377378
const models: (Model | Enum)[] = Array.from(client.service.models.values());
378379
Array.from(client.service.enums.values()).forEach((it) => models.push(it));
379380

381+
// lambda to mark model as public
382+
const modelAsPublic = (model: Model | Enum) => {
383+
// check it does not contain Union
384+
const union = unionReferredByType(this.program, model, this.typeUnionRefCache);
385+
if (union) {
386+
const errorMsg = `Model '${getTypeName(
387+
model,
388+
this.typeNameOptions,
389+
)}' cannot be set as access=public, as it refers Union '${getUnionName(union, this.typeNameOptions)}'`;
390+
throw new Error(errorMsg);
391+
}
392+
393+
const schema = this.processSchema(model, model.name);
394+
395+
this.trackSchemaUsage(schema, {
396+
usage: [SchemaContext.Public],
397+
});
398+
};
399+
380400
for (const model of models) {
381401
if (!processedModels.has(model)) {
382402
const access = getAccess(model);
383403
if (access === "public") {
384-
// check it does not contain Union
385-
const union = unionReferredByType(this.program, model, this.typeUnionRefCache);
386-
if (union) {
387-
const errorMsg = `Model '${getTypeName(
388-
model,
389-
this.typeNameOptions,
390-
)}' cannot be set as access=public, as it refers Union '${getUnionName(union, this.typeNameOptions)}'`;
391-
throw new Error(errorMsg);
392-
}
393-
394-
const schema = this.processSchema(model, model.name);
395-
396-
this.trackSchemaUsage(schema, {
397-
usage: [SchemaContext.Public],
398-
});
404+
modelAsPublic(model);
399405
} else if (access === "internal") {
400406
const schema = this.processSchema(model, model.name);
401407

402408
this.trackSchemaUsage(schema, {
403409
usage: [SchemaContext.Internal],
404410
});
411+
} else if (model.kind === "Model" && isInclude(this.sdkContext, model)) {
412+
// TODO: deprecate "include"
413+
modelAsPublic(model);
405414
}
406415

407416
const usage = getUsage(model);
@@ -596,12 +605,10 @@ export class CodeModelBuilder {
596605
},
597606
});
598607

599-
// TODO (weidxu): temporary disable codeModelOperation.internalApi
600-
// codeModelOperation.internalApi = this.isInternal(this.sdkContext, operation);
601-
const internalApi = this.isInternal(this.sdkContext, operation);
608+
codeModelOperation.internalApi = this.isInternal(this.sdkContext, operation);
602609

603610
const convenienceApiName = this.getConvenienceApiName(operation);
604-
let generateConvenienceApi: boolean = !!convenienceApiName && !internalApi; // at present, internalApi means not convenienceApi. this could change.
611+
let generateConvenienceApi: boolean = !!convenienceApiName;
605612

606613
let apiComment: string | undefined = undefined;
607614
if (generateConvenienceApi) {
@@ -1259,7 +1266,12 @@ export class CodeModelBuilder {
12591266
);
12601267
});
12611268

1262-
this.trackSchemaUsage(optionBagSchema, { usage: [SchemaContext.Input, SchemaContext.Public] });
1269+
this.trackSchemaUsage(optionBagSchema, { usage: [SchemaContext.Input] });
1270+
if (op.internalApi) {
1271+
this.trackSchemaUsage(optionBagSchema, { usage: [SchemaContext.Internal] });
1272+
} else if (op.convenienceApi) {
1273+
this.trackSchemaUsage(optionBagSchema, { usage: [SchemaContext.Public] });
1274+
}
12631275

12641276
// option bag parameter
12651277
const optionBagParameter = new Parameter(

typespec-tests/package.json

+14-13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "typespec-java-tests",
2+
"name": "@azure-tools/typespec-java-tests",
33
"version": "0.0.1",
44
"type": "module",
55
"scripts": {
@@ -9,23 +9,24 @@
99
"testserver-run": "npx cadl-ranch serve ./node_modules/@azure-tools/cadl-ranch-specs/http --coverageFile ./cadl-ranch-coverage-java.json"
1010
},
1111
"dependencies": {
12-
"@typespec/openapi": ">=0.45.0 <1.0.0",
13-
"@azure-tools/typespec-autorest": ">=0.31.0 <1.0.0",
14-
"@azure-tools/cadl-ranch-specs": "0.21.0",
15-
"@azure-tools/typespec-java": "file:/../typespec-extension/azure-tools-typespec-java-0.8.12.tgz"
12+
"@typespec/openapi": ">=0.48.0 <1.0.0",
13+
"@azure-tools/typespec-autorest": ">=0.34.0 <1.0.0",
14+
"@azure-tools/cadl-ranch-specs": "0.22.0",
15+
"@azure-tools/typespec-java": "file:/../typespec-extension/azure-tools-typespec-java-0.8.13.tgz"
1616
},
1717
"devDependencies": {
18-
"@typespec/prettier-plugin-typespec": ">=0.45.0 <1.0.0",
18+
"@typespec/prettier-plugin-typespec": "~0.48.0",
1919
"prettier-plugin-organize-imports": "3.2.3",
20-
"prettier": "~3.0.1"
20+
"prettier": "~3.0.3",
21+
"functions-have-names": "~1.2.3"
2122
},
2223
"overrides": {
23-
"@typespec/compiler": ">=0.45.0 <1.0.0",
24-
"@typespec/http": ">=0.45.0 <1.0.0",
25-
"@typespec/rest": ">=0.45.0 <1.0.0",
26-
"@typespec/versioning": ">=0.45.0 <1.0.0",
27-
"@azure-tools/typespec-azure-core": ">=0.31.0 <1.0.0",
28-
"@azure-tools/typespec-client-generator-core": "0.34.0-dev.6"
24+
"@typespec/compiler": ">=0.48.0 <1.0.0",
25+
"@typespec/http": ">=0.48.0 <1.0.0",
26+
"@typespec/rest": ">=0.48.0 <1.0.0",
27+
"@typespec/versioning": ">=0.48.0 <1.0.0",
28+
"@azure-tools/typespec-azure-core": ">=0.34.0 <1.0.0",
29+
"@azure-tools/typespec-client-generator-core": ">=0.34.0 <1.0.0"
2930
},
3031
"private": true
3132
}

typespec-tests/src/main/java/com/_specs_/azure/clientgenerator/core/access/InternalOperationAsyncClient.java

+73
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
package com._specs_.azure.clientgenerator.core.access;
66

77
import com._specs_.azure.clientgenerator.core.access.implementation.InternalOperationsImpl;
8+
import com._specs_.azure.clientgenerator.core.access.implementation.models.InternalDecoratorModelInInternal;
9+
import com._specs_.azure.clientgenerator.core.access.implementation.models.NoDecoratorModelInInternal;
10+
import com._specs_.azure.clientgenerator.core.access.implementation.models.PublicDecoratorModelInInternal;
811
import com.azure.core.annotation.Generated;
912
import com.azure.core.annotation.ReturnType;
1013
import com.azure.core.annotation.ServiceClient;
@@ -16,6 +19,7 @@
1619
import com.azure.core.http.rest.RequestOptions;
1720
import com.azure.core.http.rest.Response;
1821
import com.azure.core.util.BinaryData;
22+
import com.azure.core.util.FluxUtil;
1923
import reactor.core.publisher.Mono;
2024

2125
/** Initializes a new instance of the asynchronous AccessClient type. */
@@ -110,4 +114,73 @@ Mono<Response<BinaryData>> internalDecoratorInInternalWithResponse(String name,
110114
Mono<Response<BinaryData>> publicDecoratorInInternalWithResponse(String name, RequestOptions requestOptions) {
111115
return this.serviceClient.publicDecoratorInInternalWithResponseAsync(name, requestOptions);
112116
}
117+
118+
/**
119+
* The noDecoratorInInternal operation.
120+
*
121+
* @param name A sequence of textual characters.
122+
* @throws IllegalArgumentException thrown if parameters fail the validation.
123+
* @throws HttpResponseException thrown if the request is rejected by server.
124+
* @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401.
125+
* @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404.
126+
* @throws ResourceModifiedException thrown if the request is rejected by server on status code 409.
127+
* @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
128+
* @return used in an internal operation, should be generated but not exported on successful completion of {@link
129+
* Mono}.
130+
*/
131+
@Generated
132+
@ServiceMethod(returns = ReturnType.SINGLE)
133+
Mono<NoDecoratorModelInInternal> noDecoratorInInternal(String name) {
134+
// Generated convenience method for noDecoratorInInternalWithResponse
135+
RequestOptions requestOptions = new RequestOptions();
136+
return noDecoratorInInternalWithResponse(name, requestOptions)
137+
.flatMap(FluxUtil::toMono)
138+
.map(protocolMethodData -> protocolMethodData.toObject(NoDecoratorModelInInternal.class));
139+
}
140+
141+
/**
142+
* The internalDecoratorInInternal operation.
143+
*
144+
* @param name A sequence of textual characters.
145+
* @throws IllegalArgumentException thrown if parameters fail the validation.
146+
* @throws HttpResponseException thrown if the request is rejected by server.
147+
* @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401.
148+
* @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404.
149+
* @throws ResourceModifiedException thrown if the request is rejected by server on status code 409.
150+
* @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
151+
* @return used in an internal operation, should be generated but not exported on successful completion of {@link
152+
* Mono}.
153+
*/
154+
@Generated
155+
@ServiceMethod(returns = ReturnType.SINGLE)
156+
Mono<InternalDecoratorModelInInternal> internalDecoratorInInternal(String name) {
157+
// Generated convenience method for internalDecoratorInInternalWithResponse
158+
RequestOptions requestOptions = new RequestOptions();
159+
return internalDecoratorInInternalWithResponse(name, requestOptions)
160+
.flatMap(FluxUtil::toMono)
161+
.map(protocolMethodData -> protocolMethodData.toObject(InternalDecoratorModelInInternal.class));
162+
}
163+
164+
/**
165+
* The publicDecoratorInInternal operation.
166+
*
167+
* @param name A sequence of textual characters.
168+
* @throws IllegalArgumentException thrown if parameters fail the validation.
169+
* @throws HttpResponseException thrown if the request is rejected by server.
170+
* @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401.
171+
* @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404.
172+
* @throws ResourceModifiedException thrown if the request is rejected by server on status code 409.
173+
* @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
174+
* @return used in an internal operation but with public decorator, should be generated and exported on successful
175+
* completion of {@link Mono}.
176+
*/
177+
@Generated
178+
@ServiceMethod(returns = ReturnType.SINGLE)
179+
Mono<PublicDecoratorModelInInternal> publicDecoratorInInternal(String name) {
180+
// Generated convenience method for publicDecoratorInInternalWithResponse
181+
RequestOptions requestOptions = new RequestOptions();
182+
return publicDecoratorInInternalWithResponse(name, requestOptions)
183+
.flatMap(FluxUtil::toMono)
184+
.map(protocolMethodData -> protocolMethodData.toObject(PublicDecoratorModelInInternal.class));
185+
}
113186
}

0 commit comments

Comments
 (0)