@azure-tools/typespec-java 0.19.3 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,10 @@
1
1
  import { AnySchema, ApiVersion, ArraySchema, BinaryResponse, BinarySchema, BooleanSchema, ByteArraySchema, ChoiceValue, DateSchema, DateTimeSchema, DictionarySchema, Discriminator, GroupProperty, GroupSchema, HttpHeader, HttpParameter, ImplementationLocation, KeySecurityScheme, Language, Metadata, NumberSchema, OAuth2SecurityScheme, ObjectSchema, OperationGroup, Parameter, ParameterLocation, Property, Relations, Response, SchemaResponse, SchemaType, Security, SerializationStyle, StringSchema, TimeSchema, UnixTimeSchema, UriSchema, VirtualParameter, } from "@autorest/codemodel";
2
2
  import { KnownMediaType } from "@azure-tools/codegen";
3
- import { getLroMetadata, getPagedResult, isPollingLocation } from "@azure-tools/typespec-azure-core";
4
- import { createSdkContext, getAllModels, getClientNameOverride, getClientType, getCrossLanguageDefinitionId, getDefaultApiVersion, getHttpOperationWithCache, getWireName, isApiVersion, isSdkBuiltInKind, isSdkIntKind, listClients, listOperationGroups, listOperationsInOperationGroup, shouldGenerateConvenient, shouldGenerateProtocol, getHttpOperationExamples, } from "@azure-tools/typespec-client-generator-core";
5
- import { getDoc, getEffectiveModelType, getEncode, getFriendlyName, getNamespaceFullName, getOverloadedOperation, getProjectedName, getSummary, getVisibility, isArrayModelType, isErrorModel, isRecordModelType, isVoidType, listServices, } from "@typespec/compiler";
6
- import { Visibility, getAuthentication, getHeaderFieldName, getPathParamName, getQueryParamName, getServers, getStatusCodeDescription, isBody, isBodyRoot, isHeader, isMultipartBodyProperty, isPathParam, isQueryParam, } from "@typespec/http";
7
- import { getResourceOperation, getSegment } from "@typespec/rest";
8
- import { getAddedOnVersions, getVersion } from "@typespec/versioning";
3
+ import { createSdkContext, getAllModels, getClientType, getWireName, isApiVersion, isSdkBuiltInKind, isSdkIntKind, } from "@azure-tools/typespec-client-generator-core";
4
+ import { getDoc, getEffectiveModelType, getNamespaceFullName, getOverloadedOperation, getSummary, getVisibility, isArrayModelType, isRecordModelType, listServices, } from "@typespec/compiler";
5
+ import { Visibility, getAuthentication, getHeaderFieldName, getPathParamName, getQueryParamName, isHeader, isPathParam, isQueryParam, } from "@typespec/http";
6
+ import { getSegment } from "@typespec/rest";
7
+ import { getAddedOnVersions } from "@typespec/versioning";
9
8
  import { fail } from "assert";
10
9
  import pkg from "lodash";
11
10
  import { Client as CodeModelClient } from "./common/client.js";
@@ -19,10 +18,10 @@ import { DurationSchema } from "./common/schemas/time.js";
19
18
  import { SchemaContext } from "./common/schemas/usage.js";
20
19
  import { createPollOperationDetailsSchema, getFileDetailsSchema } from "./external-schemas.js";
21
20
  import { ClientContext } from "./models.js";
22
- import { ORIGIN_API_VERSION, SPECIAL_HEADER_NAMES, cloneOperationParameter, getServiceVersion, isKnownContentType, isLroNewPollingStrategy, isPayloadProperty, operationIsJsonMergePatch, operationIsMultipart, operationIsMultipleContentTypes, } from "./operation-utils.js";
21
+ import { CONTENT_TYPE_KEY, ORIGIN_API_VERSION, SPECIAL_HEADER_NAMES, cloneOperationParameter, getServiceVersion, isKnownContentType, isLroNewPollingStrategy, isPayloadProperty, operationIsJsonMergePatch, operationIsMultipart, operationIsMultipleContentTypes, } from "./operation-utils.js";
23
22
  import { PreNamer } from "./prenamer/prenamer.js";
24
- import { ProcessingCache, getAccess, getDurationFormatFromSdkType, getNonNullSdkType, getUnionDescription, getUsage, hasScalarAsBase, isArmCommonType, isModelReferredInTemplate, isNullableType, isStable, modelIs, pushDistinct, } from "./type-utils.js";
25
- import { getNamespace, logWarning, pascalCase, stringArrayContainsIgnoreCase, trace } from "./utils.js";
23
+ import { ProcessingCache, getAccess, getDurationFormatFromSdkType, getNonNullSdkType, getUnionDescription, getUsage, isStable, modelIs, pushDistinct, } from "./type-utils.js";
24
+ import { getNamespace, logWarning, pascalCase, removeClientSuffix, stringArrayContainsIgnoreCase, trace, } from "./utils.js";
26
25
  const { isEqual } = pkg;
27
26
  export class CodeModelBuilder {
28
27
  constructor(program1, context) {
@@ -77,7 +76,9 @@ export class CodeModelBuilder {
77
76
  });
78
77
  }
79
78
  async build() {
80
- this.sdkContext = await createSdkContext(this.emitterContext, "@azure-tools/typespec-java");
79
+ this.sdkContext = await createSdkContext(this.emitterContext, "@azure-tools/typespec-java", {
80
+ versioning: { previewStringRegex: /$/ },
81
+ }); // include all versions and do the filter by ourselves
81
82
  // auth
82
83
  // TODO: it is not very likely, but different client could have different auth
83
84
  const auth = getAuthentication(this.program, this.serviceNamespace);
@@ -89,8 +90,8 @@ export class CodeModelBuilder {
89
90
  this.codeModel.arm = true;
90
91
  this.options["group-etag-headers"] = false;
91
92
  }
92
- const clients = this.processClients();
93
- this.processModels(clients);
93
+ this.processClients();
94
+ this.processModels();
94
95
  this.processSchemaUsage();
95
96
  if (this.options.namer) {
96
97
  this.codeModel = new PreNamer(this.codeModel).init().process();
@@ -98,64 +99,41 @@ export class CodeModelBuilder {
98
99
  this.deduplicateSchemaName();
99
100
  return this.codeModel;
100
101
  }
101
- processHost(server) {
102
+ processHostParameters(sdkPathParameters) {
102
103
  const hostParameters = [];
103
- if (server && !this.isArmSynthesizedServer(server)) {
104
- server.parameters.forEach((it) => {
105
- let parameter;
106
- if (isApiVersion(this.sdkContext, it)) {
107
- parameter = this.createApiVersionParameter(it.name, ParameterLocation.Uri);
108
- }
109
- else {
110
- const sdkType = getClientType(this.sdkContext, it.type);
111
- const schema = this.processSchemaFromSdkType(sdkType, it.name);
112
- this.trackSchemaUsage(schema, {
113
- usage: [SchemaContext.Input, SchemaContext.Output /*SchemaContext.Public*/],
114
- });
115
- parameter = new Parameter(this.getName(it), this.getDoc(it), schema, {
116
- implementation: ImplementationLocation.Client,
117
- origin: "modelerfour:synthesized/host",
118
- required: !it.optional,
119
- protocol: {
120
- http: new HttpParameter(ParameterLocation.Uri),
121
- },
122
- language: {
123
- default: {
124
- serializedName: it.name,
125
- },
126
- },
127
- extensions: {
128
- // TODO: deprecate this logic of string/url for x-ms-skip-url-encoding
129
- "x-ms-skip-url-encoding": schema instanceof UriSchema,
104
+ let parameter;
105
+ sdkPathParameters.forEach((arg) => {
106
+ var _a;
107
+ if (arg.isApiVersionParam) {
108
+ parameter = this.createApiVersionParameter(arg.name, ParameterLocation.Uri);
109
+ }
110
+ else {
111
+ const schema = this.processSchemaFromSdkType(arg.type, arg.name);
112
+ this.trackSchemaUsage(schema, {
113
+ usage: [SchemaContext.Input, SchemaContext.Output /*SchemaContext.Public*/],
114
+ });
115
+ parameter = new Parameter(arg.name, (_a = arg.description) !== null && _a !== void 0 ? _a : "", schema, {
116
+ implementation: ImplementationLocation.Client,
117
+ origin: "modelerfour:synthesized/host",
118
+ required: true,
119
+ protocol: {
120
+ http: new HttpParameter(ParameterLocation.Uri),
121
+ },
122
+ language: {
123
+ default: {
124
+ serializedName: arg.name,
130
125
  },
131
- // // make the logic same as TCGC, which takes the server-side default of host as client-side default
132
- // clientDefaultValue: getDefaultValue(it.defaultValue),
133
- });
134
- }
135
- hostParameters.push(this.codeModel.addGlobalParameter(parameter));
136
- });
137
- return hostParameters;
138
- }
139
- else {
140
- // use "endpoint"
141
- hostParameters.push(this.codeModel.addGlobalParameter(new Parameter("endpoint", "Server parameter", this.stringSchema, {
142
- implementation: ImplementationLocation.Client,
143
- origin: "modelerfour:synthesized/host",
144
- required: true,
145
- protocol: {
146
- http: new HttpParameter(ParameterLocation.Uri),
147
- },
148
- language: {
149
- default: {
150
- serializedName: "endpoint",
151
126
  },
152
- },
153
- extensions: {
154
- "x-ms-skip-url-encoding": true,
155
- },
156
- })));
157
- return hostParameters;
158
- }
127
+ // TODO: deprecate this logic of string/url for x-ms-skip-url-encoding
128
+ extensions: {
129
+ "x-ms-skip-url-encoding": schema instanceof UriSchema,
130
+ },
131
+ clientDefaultValue: arg.clientDefaultValue,
132
+ });
133
+ }
134
+ hostParameters.push(this.codeModel.addGlobalParameter(parameter));
135
+ });
136
+ return hostParameters;
159
137
  }
160
138
  processAuth(auth) {
161
139
  const securitySchemes = [];
@@ -210,16 +188,7 @@ export class CodeModelBuilder {
210
188
  isBranded() {
211
189
  return !this.options["flavor"] || this.options["flavor"].toLocaleLowerCase() === "azure";
212
190
  }
213
- isInternal(operation) {
214
- const access = getAccess(operation);
215
- if (access) {
216
- return access === "internal";
217
- }
218
- else {
219
- return false;
220
- }
221
- }
222
- processModels(clients) {
191
+ processModels() {
223
192
  const processedSdkModels = new Set();
224
193
  // lambda to mark model as public
225
194
  const modelAsPublic = (model) => {
@@ -305,33 +274,37 @@ export class CodeModelBuilder {
305
274
  schemaUsage.splice(index, 1);
306
275
  }
307
276
  }
308
- // Internal on Anonymous
309
- if (schemaUsage === null || schemaUsage === void 0 ? void 0 : schemaUsage.includes(SchemaContext.Anonymous)) {
310
- const index = schemaUsage.indexOf(SchemaContext.Internal);
311
- if (index < 0) {
312
- schemaUsage.push(SchemaContext.Internal);
277
+ // Internal on PublicSpread, but Public takes precedence
278
+ if (schemaUsage === null || schemaUsage === void 0 ? void 0 : schemaUsage.includes(SchemaContext.PublicSpread)) {
279
+ // remove PublicSpread as it now served its purpose
280
+ schemaUsage.splice(schemaUsage.indexOf(SchemaContext.PublicSpread), 1);
281
+ // Public would override PublicSpread, hence do nothing if this schema is Public
282
+ if (!(schemaUsage === null || schemaUsage === void 0 ? void 0 : schemaUsage.includes(SchemaContext.Public))) {
283
+ // set the model as Internal, so that it is not exposed to user
284
+ if (!schemaUsage.includes(SchemaContext.Internal)) {
285
+ schemaUsage.push(SchemaContext.Internal);
286
+ }
313
287
  }
314
288
  }
315
289
  }
316
290
  }
317
291
  processClients() {
318
- var _a, _b;
319
- const clients = listClients(this.sdkContext);
292
+ var _a, _b, _c;
320
293
  // preprocess group-etag-headers
321
294
  this.options["group-etag-headers"] = (_a = this.options["group-etag-headers"]) !== null && _a !== void 0 ? _a : true;
322
- for (const client of clients) {
295
+ const sdkPackage = this.sdkContext.sdkPackage;
296
+ for (const client of sdkPackage.clients) {
323
297
  let clientName = client.name;
324
- let clientSubNamespace = undefined;
325
298
  let javaNamespace = this.getJavaNamespace(this.namespace);
326
299
  const clientFullName = client.name;
327
300
  const clientNameSegments = clientFullName.split(".");
328
301
  if (clientNameSegments.length > 1) {
329
302
  clientName = clientNameSegments.at(-1);
330
- clientSubNamespace = clientNameSegments.slice(0, -1).join(".");
303
+ const clientSubNamespace = clientNameSegments.slice(0, -1).join(".");
331
304
  javaNamespace = this.getJavaNamespace(this.namespace + "." + clientSubNamespace);
332
305
  }
333
- const codeModelClient = new CodeModelClient(clientName, this.getDoc(client.type), {
334
- summary: this.getSummary(client.type),
306
+ const codeModelClient = new CodeModelClient(clientName, (_b = client.details) !== null && _b !== void 0 ? _b : "", {
307
+ summary: client.description,
335
308
  language: {
336
309
  default: {
337
310
  namespace: this.namespace,
@@ -345,111 +318,144 @@ export class CodeModelBuilder {
345
318
  });
346
319
  codeModelClient.crossLanguageDefinitionId = client.crossLanguageDefinitionId;
347
320
  // versioning
348
- const versioning = getVersion(this.program, client.service);
349
- if (versioning && versioning.getVersions()) {
350
- // @versioned in versioning
321
+ const versions = client.apiVersions;
322
+ if (versions && versions.length > 0) {
351
323
  if (!this.sdkContext.apiVersion || ["all", "latest"].includes(this.sdkContext.apiVersion)) {
352
- this.apiVersion = getDefaultApiVersion(this.sdkContext, client.service);
324
+ this.apiVersion = versions[versions.length - 1];
353
325
  }
354
326
  else {
355
- this.apiVersion = versioning.getVersions().find((it) => it.value === this.sdkContext.apiVersion);
327
+ this.apiVersion = versions.find((it) => it === this.sdkContext.apiVersion);
356
328
  if (!this.apiVersion) {
357
329
  throw new Error("Unrecognized api-version: " + this.sdkContext.apiVersion);
358
330
  }
359
331
  }
360
332
  codeModelClient.apiVersions = [];
361
- for (const version of this.getFilteredApiVersions(this.apiVersion, versioning.getVersions(), this.options["service-version-exclude-preview"])) {
333
+ for (const version of this.getFilteredApiVersions(this.apiVersion, versions, this.options["service-version-exclude-preview"])) {
362
334
  const apiVersion = new ApiVersion();
363
- apiVersion.version = version.value;
335
+ apiVersion.version = version;
364
336
  codeModelClient.apiVersions.push(apiVersion);
365
337
  }
366
338
  }
367
- // server
339
+ // client initialization
368
340
  let baseUri = "{endpoint}";
369
- const servers = getServers(this.program, client.service);
370
- if (servers && servers.length === 1 && !this.isArmSynthesizedServer(servers[0])) {
371
- baseUri = servers[0].url;
372
- }
373
- const hostParameters = this.processHost((servers === null || servers === void 0 ? void 0 : servers.length) === 1 ? servers[0] : undefined);
374
- codeModelClient.addGlobalParameters(hostParameters);
341
+ let hostParameters = [];
342
+ client.initialization.properties.forEach((initializationProperty) => {
343
+ if (initializationProperty.kind === "endpoint") {
344
+ let sdkPathParameters = [];
345
+ if (initializationProperty.type.kind === "union") {
346
+ if (initializationProperty.type.values.length === 2) {
347
+ // only get the sdkPathParameters from the endpoint whose serverUrl is not {"endpoint"}
348
+ for (const endpointType of initializationProperty.type.values) {
349
+ if (endpointType.kind === "endpoint" && endpointType.serverUrl !== "{endpoint}") {
350
+ sdkPathParameters = endpointType.templateArguments;
351
+ baseUri = endpointType.serverUrl;
352
+ }
353
+ }
354
+ }
355
+ else if (initializationProperty.type.values.length > 2) {
356
+ throw new Error("Multiple server url defined for one client is not supported yet.");
357
+ }
358
+ }
359
+ else if (initializationProperty.type.kind === "endpoint") {
360
+ sdkPathParameters = initializationProperty.type.templateArguments;
361
+ baseUri = initializationProperty.type.serverUrl;
362
+ }
363
+ hostParameters = this.processHostParameters(sdkPathParameters);
364
+ codeModelClient.addGlobalParameters(hostParameters);
365
+ }
366
+ });
375
367
  const clientContext = new ClientContext(baseUri, hostParameters, codeModelClient.globalParameters, codeModelClient.apiVersions);
376
- clientContext.preProcessOperations(this.sdkContext, client);
377
- const operationGroups = listOperationGroups(this.sdkContext, client, true);
378
- const operationWithoutGroup = listOperationsInOperationGroup(this.sdkContext, client);
368
+ // preprocess operation groups and operations
369
+ // operations without operation group
370
+ const serviceMethodsWithoutSubClient = this.listServiceMethodsUnderClient(client);
379
371
  let codeModelGroup = new OperationGroup("");
380
- for (const operation of operationWithoutGroup) {
381
- if (!this.needToSkipProcessingOperation(operation, clientContext)) {
382
- codeModelGroup.addOperation(this.processOperation("", operation, clientContext));
372
+ for (const serviceMethod of serviceMethodsWithoutSubClient) {
373
+ if (!this.needToSkipProcessingOperation(serviceMethod.__raw, clientContext)) {
374
+ codeModelGroup.addOperation(this.processOperation(serviceMethod, clientContext, ""));
383
375
  }
384
376
  }
385
- if (((_b = codeModelGroup.operations) === null || _b === void 0 ? void 0 : _b.length) > 0) {
377
+ if (((_c = codeModelGroup.operations) === null || _c === void 0 ? void 0 : _c.length) > 0) {
386
378
  codeModelClient.operationGroups.push(codeModelGroup);
387
379
  }
388
- for (const operationGroup of operationGroups) {
389
- const operations = listOperationsInOperationGroup(this.sdkContext, operationGroup);
380
+ // operations under operation groups
381
+ const subClients = this.listSubClientsUnderClient(client, true, true);
382
+ for (const subClient of subClients) {
383
+ const serviceMethods = this.listServiceMethodsUnderClient(subClient);
390
384
  // operation group with no operation is skipped
391
- if (operations.length > 0) {
392
- // groupPath would be in format of "[<SubNamespace>.]<ClientName>.Chat.Completions"
393
- let operationGroupPath = operationGroup.groupPath;
394
- if (clientSubNamespace && operationGroup.groupPath.startsWith(clientSubNamespace + ".")) {
395
- // remove SubNamespace
396
- operationGroupPath = operationGroupPath.slice((clientSubNamespace + ".").length);
397
- }
398
- const groupPath = operationGroupPath.split(".");
399
- let operationGroupName;
400
- if (groupPath.length > 1) {
401
- // remove ClientName
402
- operationGroupName = groupPath.slice(1).join("");
403
- }
404
- else {
405
- operationGroupName = groupPath[0];
406
- }
407
- codeModelGroup = new OperationGroup(operationGroupName);
408
- for (const operation of operations) {
409
- if (!this.needToSkipProcessingOperation(operation, clientContext)) {
410
- codeModelGroup.addOperation(this.processOperation(operationGroupName, operation, clientContext));
385
+ if (serviceMethods.length > 0) {
386
+ codeModelGroup = new OperationGroup(subClient.name);
387
+ for (const serviceMethod of serviceMethods) {
388
+ if (!this.needToSkipProcessingOperation(serviceMethod.__raw, clientContext)) {
389
+ codeModelGroup.addOperation(this.processOperation(serviceMethod, clientContext, subClient.name));
411
390
  }
412
391
  }
413
392
  codeModelClient.operationGroups.push(codeModelGroup);
414
393
  }
415
394
  }
416
395
  this.codeModel.clients.push(codeModelClient);
417
- }
418
- // postprocess for ServiceVersion
419
- let apiVersionSameForAllClients = true;
420
- let sharedApiVersions = undefined;
421
- for (const client of this.codeModel.clients) {
422
- const apiVersions = client.apiVersions;
423
- if (!apiVersions) {
424
- // client does not have apiVersions
425
- apiVersionSameForAllClients = false;
396
+ // postprocess for ServiceVersion
397
+ let apiVersionSameForAllClients = true;
398
+ let sharedApiVersions = undefined;
399
+ for (const client of this.codeModel.clients) {
400
+ const apiVersions = client.apiVersions;
401
+ if (!apiVersions) {
402
+ // client does not have apiVersions
403
+ apiVersionSameForAllClients = false;
404
+ }
405
+ else if (!sharedApiVersions) {
406
+ // first client, set it to sharedApiVersions
407
+ sharedApiVersions = apiVersions;
408
+ }
409
+ else {
410
+ apiVersionSameForAllClients = isEqual(sharedApiVersions, apiVersions);
411
+ }
412
+ if (!apiVersionSameForAllClients) {
413
+ break;
414
+ }
426
415
  }
427
- else if (!sharedApiVersions) {
428
- // first client, set it to sharedApiVersions
429
- sharedApiVersions = apiVersions;
416
+ if (apiVersionSameForAllClients) {
417
+ const serviceVersion = getServiceVersion(this.codeModel);
418
+ for (const client of this.codeModel.clients) {
419
+ client.serviceVersion = serviceVersion;
420
+ }
430
421
  }
431
422
  else {
432
- apiVersionSameForAllClients = isEqual(sharedApiVersions, apiVersions);
433
- }
434
- if (!apiVersionSameForAllClients) {
435
- break;
423
+ for (const client of this.codeModel.clients) {
424
+ const apiVersions = client.apiVersions;
425
+ if (apiVersions) {
426
+ client.serviceVersion = getServiceVersion(client);
427
+ }
428
+ }
436
429
  }
437
430
  }
438
- if (apiVersionSameForAllClients) {
439
- const serviceVersion = getServiceVersion(this.codeModel);
440
- for (const client of this.codeModel.clients) {
441
- client.serviceVersion = serviceVersion;
431
+ }
432
+ listSubClientsUnderClient(client, includeNestedOperationGroups, isRootClient) {
433
+ const operationGroups = [];
434
+ for (const method of client.methods) {
435
+ if (method.kind === "clientaccessor") {
436
+ const subClient = method.response;
437
+ if (!isRootClient) {
438
+ // if it is not root client, append the parent client's name
439
+ subClient.name = removeClientSuffix(client.name) + removeClientSuffix(pascalCase(subClient.name));
440
+ }
441
+ operationGroups.push(subClient);
442
+ if (includeNestedOperationGroups) {
443
+ for (const operationGroup of this.listSubClientsUnderClient(subClient, includeNestedOperationGroups, false)) {
444
+ operationGroups.push(operationGroup);
445
+ }
446
+ }
442
447
  }
443
448
  }
444
- else {
445
- for (const client of this.codeModel.clients) {
446
- const apiVersions = client.apiVersions;
447
- if (apiVersions) {
448
- client.serviceVersion = getServiceVersion(client);
449
- }
449
+ return operationGroups;
450
+ }
451
+ listServiceMethodsUnderClient(client) {
452
+ const methods = [];
453
+ for (const method of client.methods) {
454
+ if (method.kind !== "clientaccessor") {
455
+ methods.push(method);
450
456
  }
451
457
  }
452
- return clients;
458
+ return methods;
453
459
  }
454
460
  /**
455
461
  * Filter api-versions for "ServiceVersion".
@@ -467,20 +473,12 @@ export class CodeModelBuilder {
467
473
  .slice(0, versions.indexOf(pinnedApiVersion) + 1)
468
474
  .filter((version) => !excludePreview || !isStable(pinnedApiVersion) || isStable(version));
469
475
  }
470
- /**
471
- * `@armProviderNamespace` currently will add a default server if not defined globally:
472
- * https://github.com/Azure/typespec-azure/blob/8b8d7c05f168d9305a09691c4fedcb88f4a57652/packages/typespec-azure-resource-manager/src/namespace.ts#L121-L128
473
- * TODO: if the synthesized server has the right hostParameter, we can use that instead
474
- *
475
- * @param server returned by getServers
476
- * @returns whether it's synthesized by `@armProviderNamespace`
477
- */
478
- isArmSynthesizedServer(server) {
479
- return this.isArm() && (!server.parameters || server.parameters.size == 0);
480
- }
481
476
  needToSkipProcessingOperation(operation, clientContext) {
482
477
  // don't generate protocol and convenience method for overloaded operations
483
478
  // issue link: https://github.com/Azure/autorest.java/issues/1958#issuecomment-1562558219 we will support generate overload methods for non-union type in future (TODO issue: https://github.com/Azure/autorest.java/issues/2160)
479
+ if (operation === undefined) {
480
+ return true;
481
+ }
484
482
  if (getOverloadedOperation(this.program, operation)) {
485
483
  this.trace(`Operation '${operation.name}' is temporary skipped, as it is an overloaded operation`);
486
484
  return true;
@@ -493,9 +491,9 @@ export class CodeModelBuilder {
493
491
  supportsAdvancedVersioning() {
494
492
  return Boolean(this.options["advanced-versioning"]);
495
493
  }
496
- getOperationExample(operation) {
494
+ getOperationExample(sdkMethod) {
497
495
  var _a, _b;
498
- const httpOperationExamples = getHttpOperationExamples(this.sdkContext, operation);
496
+ const httpOperationExamples = sdkMethod.operation.examples;
499
497
  if (httpOperationExamples && httpOperationExamples.length > 0) {
500
498
  const operationExamples = {};
501
499
  for (const example of httpOperationExamples) {
@@ -503,8 +501,7 @@ export class CodeModelBuilder {
503
501
  // example.filePath is relative path from sdkContext.examplesDir
504
502
  // this is not a URL format (file:// or https://)
505
503
  operationExample["x-ms-original-file"] = example.filePath;
506
- operationExamples[(_b = (_a = operationExample.title) !== null && _a !== void 0 ? _a : operationExample.operationId) !== null && _b !== void 0 ? _b : operation.operation.name] =
507
- operationExample;
504
+ operationExamples[(_b = (_a = operationExample.title) !== null && _a !== void 0 ? _a : operationExample.operationId) !== null && _b !== void 0 ? _b : sdkMethod.name] = operationExample;
508
505
  }
509
506
  return operationExamples;
510
507
  }
@@ -512,58 +509,47 @@ export class CodeModelBuilder {
512
509
  return undefined;
513
510
  }
514
511
  }
515
- processOperation(groupName, operation, clientContext) {
512
+ processOperation(sdkMethod, clientContext, groupName) {
516
513
  var _a;
517
- const op = getHttpOperationWithCache(this.sdkContext, operation);
514
+ const operationName = sdkMethod.name;
515
+ const httpOperation = sdkMethod.operation;
516
+ const operationId = groupName ? `${groupName}_${operationName}` : `${operationName}`;
518
517
  const operationGroup = this.codeModel.getOperationGroup(groupName);
519
- const operationName = this.getName(operation);
520
- const opId = groupName ? `${groupName}_${operationName}` : `${operationName}`;
521
- const operationExamples = this.getOperationExample(op);
522
- const codeModelOperation = new CodeModelOperation(operationName, this.getDoc(operation), {
523
- operationId: opId,
524
- summary: this.getSummary(operation),
518
+ const operationExamples = this.getOperationExample(sdkMethod);
519
+ const codeModelOperation = new CodeModelOperation(operationName, (_a = sdkMethod.details) !== null && _a !== void 0 ? _a : "", {
520
+ operationId: operationId,
521
+ summary: sdkMethod.description,
525
522
  extensions: {
526
523
  "x-ms-examples": operationExamples,
527
524
  },
528
525
  });
529
- codeModelOperation.crossLanguageDefinitionId = getCrossLanguageDefinitionId(this.sdkContext, operation);
530
- codeModelOperation.internalApi = this.isInternal(operation);
531
- const convenienceApiName = this.getConvenienceApiName(operation);
532
- let generateConvenienceApi = Boolean(convenienceApiName);
533
- let generateProtocolApi = shouldGenerateProtocol(this.sdkContext, operation);
526
+ codeModelOperation.crossLanguageDefinitionId = sdkMethod.crossLanguageDefintionId;
527
+ codeModelOperation.internalApi = sdkMethod.access === "internal";
528
+ const convenienceApiName = this.getConvenienceApiName(sdkMethod);
529
+ let generateConvenienceApi = sdkMethod.generateConvenient;
530
+ let generateProtocolApi = sdkMethod.generateProtocol;
534
531
  let apiComment = undefined;
535
532
  if (generateConvenienceApi) {
536
533
  // check if the convenience API need to be disabled for some special cases
537
- if (operationIsMultipart(op)) {
534
+ if (operationIsMultipart(httpOperation)) {
538
535
  // do not generate protocol method for multipart/form-data, as it be very hard for user to prepare the request body as BinaryData
539
536
  generateProtocolApi = false;
540
- apiComment = `Protocol API requires serialization of parts with content-disposition and data, as operation '${op.operation.name}' is 'multipart/form-data'`;
537
+ apiComment = `Protocol API requires serialization of parts with content-disposition and data, as operation '${operationName}' is 'multipart/form-data'`;
541
538
  this.logWarning(apiComment);
542
539
  }
543
- else if (operationIsMultipleContentTypes(op)) {
540
+ else if (operationIsMultipleContentTypes(httpOperation)) {
544
541
  // and multiple content types
545
542
  // issue link: https://github.com/Azure/autorest.java/issues/1958#issuecomment-1562558219
546
543
  generateConvenienceApi = false;
547
- apiComment = `Convenience API is not generated, as operation '${op.operation.name}' is multiple content-type`;
544
+ apiComment = `Convenience API is not generated, as operation '${operationName}' is multiple content-type`;
548
545
  this.logWarning(apiComment);
549
546
  }
550
- else if (operationIsJsonMergePatch(op) && this.options["stream-style-serialization"] === false) {
547
+ else if (operationIsJsonMergePatch(httpOperation) && this.options["stream-style-serialization"] === false) {
551
548
  // do not generate convenient method for json merge patch operation if stream-style-serialization is not enabled
552
549
  generateConvenienceApi = false;
553
- apiComment = `Convenience API is not generated, as operation '${op.operation.name}' is 'application/merge-patch+json' and stream-style-serialization is not enabled`;
550
+ apiComment = `Convenience API is not generated, as operation '${operationName}' is 'application/merge-patch+json' and stream-style-serialization is not enabled`;
554
551
  this.logWarning(apiComment);
555
552
  }
556
- // else {
557
- // const union = operationRefersUnion(this.program, op, this.typeUnionRefCache);
558
- // if (union) {
559
- // // and Union
560
- // generateConvenienceApi = false;
561
- // apiComment = `Convenience API is not generated, as operation '${
562
- // op.operation.name
563
- // }' refers Union '${getUnionDescription(union, this.typeNameOptions)}'`;
564
- // this.logWarning(apiComment);
565
- // }
566
- // }
567
553
  }
568
554
  if (generateConvenienceApi && convenienceApiName) {
569
555
  codeModelOperation.convenienceApi = new ConvenienceApi(convenienceApiName);
@@ -577,75 +563,76 @@ export class CodeModelBuilder {
577
563
  codeModelOperation.addRequest(new Request({
578
564
  protocol: {
579
565
  http: {
580
- path: op.path,
581
- method: op.verb,
566
+ path: httpOperation.path,
567
+ method: httpOperation.verb,
582
568
  uri: clientContext.baseUri,
583
569
  },
584
570
  },
585
571
  }));
586
572
  // host
587
573
  clientContext.hostParameters.forEach((it) => codeModelOperation.addParameter(it));
588
- // parameters
589
- op.parameters.parameters.map((it) => this.processParameter(codeModelOperation, it, clientContext));
590
- // "accept" header
591
- this.addAcceptHeaderParameter(codeModelOperation, op.responses);
592
- // body
593
- if (op.parameters.body) {
594
- if (op.parameters.body.property) {
595
- if (!isVoidType(op.parameters.body.property.type)) {
596
- this.processParameterBody(codeModelOperation, op, op.parameters.body.property);
574
+ // path/query/header parameters
575
+ for (const param of httpOperation.parameters) {
576
+ // if it's paged operation with request body, skip content-type header added by TCGC, as next link call should not have content type header
577
+ if ((sdkMethod.kind === "paging" || sdkMethod.kind === "lropaging") &&
578
+ httpOperation.bodyParam &&
579
+ param.kind === "header") {
580
+ if (param.serializedName.toLocaleLowerCase() === CONTENT_TYPE_KEY) {
581
+ continue;
597
582
  }
598
583
  }
599
- else if (op.parameters.body.type) {
600
- let bodyType = op.parameters.body.type;
601
- if (bodyType.kind === "Model") {
602
- // try use resource type as round-trip model
603
- const resourceType = (_a = getResourceOperation(this.program, operation)) === null || _a === void 0 ? void 0 : _a.resourceType;
604
- if (resourceType && op.responses && op.responses.length > 0) {
605
- const resp = op.responses[0];
606
- if (resp.responses && resp.responses.length > 0 && resp.responses[0].body) {
607
- const responseBody = resp.responses[0].body;
608
- const bodyTypeInResponse = this.findResponseBody(responseBody.type);
609
- // response body type is resource type, and request body type (if templated) contains resource type
610
- if (bodyTypeInResponse === resourceType && isModelReferredInTemplate(bodyType, resourceType)) {
611
- bodyType = resourceType;
612
- }
613
- }
614
- }
615
- this.processParameterBody(codeModelOperation, op, bodyType);
584
+ // if the request body is optional, skip content-type header added by TCGC
585
+ // TODO: add optional content type to code-model, and support optional content-type from codegen, https://github.com/Azure/autorest.java/issues/2930
586
+ if (httpOperation.bodyParam && httpOperation.bodyParam.optional) {
587
+ if (param.serializedName.toLocaleLowerCase() === CONTENT_TYPE_KEY) {
588
+ continue;
616
589
  }
617
590
  }
591
+ this.processParameter(codeModelOperation, param, clientContext);
592
+ }
593
+ // body
594
+ if (httpOperation.bodyParam && httpOperation.__raw && httpOperation.bodyParam.type.__raw) {
595
+ this.processParameterBody(codeModelOperation, httpOperation.__raw, httpOperation, httpOperation.bodyParam);
618
596
  }
619
597
  // group ETag header parameters, if exists
620
598
  if (this.options["group-etag-headers"]) {
621
- this.processEtagHeaderParameters(codeModelOperation, op);
599
+ this.processEtagHeaderParameters(codeModelOperation, sdkMethod.operation);
622
600
  }
623
601
  // lro metadata
624
- const lroMetadata = this.processLroMetadata(codeModelOperation, op);
602
+ let lroMetadata = new LongRunningMetadata(false);
603
+ if (sdkMethod.kind === "lro" || sdkMethod.kind === "lropaging") {
604
+ lroMetadata = this.processLroMetadata(codeModelOperation, sdkMethod);
605
+ }
625
606
  // responses
626
- op.responses.map((it) => this.processResponse(codeModelOperation, it, lroMetadata.longRunning));
607
+ for (const [code, response] of sdkMethod.operation.responses) {
608
+ this.processResponse(codeModelOperation, code, response, lroMetadata.longRunning, false);
609
+ }
610
+ // exception
611
+ for (const [code, response] of sdkMethod.operation.exceptions) {
612
+ this.processResponse(codeModelOperation, code, response, lroMetadata.longRunning, true);
613
+ }
627
614
  // check for paged
628
- this.processRouteForPaged(codeModelOperation, op.responses);
615
+ this.processRouteForPaged(codeModelOperation, sdkMethod.operation.responses, sdkMethod);
629
616
  // check for long-running operation
630
- this.processRouteForLongRunning(codeModelOperation, operation, op.responses, lroMetadata);
617
+ this.processRouteForLongRunning(codeModelOperation, sdkMethod.operation.responses, lroMetadata);
631
618
  operationGroup.addOperation(codeModelOperation);
632
619
  return codeModelOperation;
633
620
  }
634
- processRouteForPaged(op, responses) {
635
- var _a, _b, _c, _d;
636
- for (const response of responses) {
637
- if (response.responses && response.responses.length > 0 && response.responses[0].body) {
638
- const responseBody = response.responses[0].body;
639
- const bodyType = this.findResponseBody(responseBody.type);
640
- if (bodyType.kind === "Model") {
641
- const pagedResult = getPagedResult(this.program, bodyType);
642
- if (pagedResult) {
621
+ processRouteForPaged(op, responses, sdkMethod) {
622
+ var _a, _b;
623
+ if (sdkMethod.kind === "paging" || sdkMethod.kind === "lropaging") {
624
+ for (const [_, response] of responses) {
625
+ const bodyType = response.type;
626
+ if (bodyType && bodyType.kind === "model") {
627
+ const itemName = sdkMethod.response.resultPath;
628
+ const nextLinkName = sdkMethod.nextLinkPath;
629
+ if (itemName && nextLinkName) {
643
630
  op.extensions = (_a = op.extensions) !== null && _a !== void 0 ? _a : {};
644
631
  op.extensions["x-ms-pageable"] = {
645
- itemName: (_b = pagedResult.itemsProperty) === null || _b === void 0 ? void 0 : _b.name,
646
- nextLinkName: (_c = pagedResult.nextLinkProperty) === null || _c === void 0 ? void 0 : _c.name,
632
+ itemName: itemName,
633
+ nextLinkName: nextLinkName,
647
634
  };
648
- (_d = op.responses) === null || _d === void 0 ? void 0 : _d.forEach((r) => {
635
+ (_b = op.responses) === null || _b === void 0 ? void 0 : _b.forEach((r) => {
649
636
  if (r instanceof SchemaResponse) {
650
637
  this.trackSchemaUsage(r.schema, { usage: [SchemaContext.Paged] });
651
638
  }
@@ -656,18 +643,17 @@ export class CodeModelBuilder {
656
643
  }
657
644
  }
658
645
  }
659
- processLroMetadata(op, httpOperation) {
660
- const operation = httpOperation.operation;
646
+ processLroMetadata(op, sdkMethod) {
661
647
  const trackConvenienceApi = Boolean(op.convenienceApi);
662
- const lroMetadata = getLroMetadata(this.program, operation);
648
+ const lroMetadata = sdkMethod.__raw_lro_metadata;
663
649
  // needs lroMetadata.statusMonitorStep, as getLroMetadata would return for @pollingOperation operation
664
650
  if (lroMetadata && lroMetadata.pollingInfo && lroMetadata.statusMonitorStep) {
665
651
  let pollingSchema = undefined;
666
652
  let finalSchema = undefined;
667
653
  let pollingStrategy = undefined;
668
654
  let finalResultPropertySerializedName = undefined;
669
- const verb = httpOperation.verb;
670
- const useNewPollStrategy = isLroNewPollingStrategy(httpOperation, lroMetadata);
655
+ const verb = sdkMethod.operation.verb;
656
+ const useNewPollStrategy = isLroNewPollingStrategy(sdkMethod.operation.__raw, lroMetadata);
671
657
  if (useNewPollStrategy) {
672
658
  // use OperationLocationPollingStrategy
673
659
  pollingStrategy = new Metadata({
@@ -728,24 +714,13 @@ export class CodeModelBuilder {
728
714
  }
729
715
  return new LongRunningMetadata(false);
730
716
  }
731
- processRouteForLongRunning(op, operation, responses, lroMetadata) {
732
- var _a, _b;
717
+ processRouteForLongRunning(op, responses, lroMetadata) {
718
+ var _a;
733
719
  if (lroMetadata.longRunning) {
734
720
  op.extensions = (_a = op.extensions) !== null && _a !== void 0 ? _a : {};
735
721
  op.extensions["x-ms-long-running-operation"] = true;
736
722
  return;
737
723
  }
738
- for (const resp of responses) {
739
- if (resp.responses && resp.responses.length > 0 && resp.responses[0].headers) {
740
- for (const [_, header] of Object.entries(resp.responses[0].headers)) {
741
- if (isPollingLocation(this.program, header)) {
742
- op.extensions = (_b = op.extensions) !== null && _b !== void 0 ? _b : {};
743
- op.extensions["x-ms-long-running-operation"] = true;
744
- break;
745
- }
746
- }
747
- }
748
- }
749
724
  }
750
725
  processParameter(op, param, clientContext) {
751
726
  var _a, _b;
@@ -754,65 +729,52 @@ export class CodeModelBuilder {
754
729
  if (this.isArm()) {
755
730
  // Currently we assume ARM tsp only have one client and one api-version.
756
731
  // TODO: How will service define mixed api-versions(like those in Compute RP)?
757
- const apiVersion = (_a = this.apiVersion) === null || _a === void 0 ? void 0 : _a.value;
732
+ const apiVersion = this.apiVersion;
758
733
  if (!this._armApiVersionParameter) {
759
- this._armApiVersionParameter = this.createApiVersionParameter("api-version", param.type === "query" ? ParameterLocation.Query : ParameterLocation.Path, apiVersion);
734
+ this._armApiVersionParameter = this.createApiVersionParameter("api-version", param.kind === "query" ? ParameterLocation.Query : ParameterLocation.Path, apiVersion);
760
735
  clientContext.addGlobalParameter(this._armApiVersionParameter);
761
736
  }
762
737
  op.addParameter(this._armApiVersionParameter);
763
738
  }
764
739
  else {
765
- const parameter = param.type === "query" ? this.apiVersionParameter : this.apiVersionParameterInPath;
740
+ const parameter = param.kind === "query" ? this.apiVersionParameter : this.apiVersionParameterInPath;
766
741
  op.addParameter(parameter);
767
742
  clientContext.addGlobalParameter(parameter);
768
743
  }
769
744
  }
770
- else if (this.isSubscriptionId(param)) {
745
+ else if (param.kind === "path" && param.onClient && this.isSubscriptionId(param)) {
771
746
  const parameter = this.subscriptionIdParameter(param);
772
747
  op.addParameter(parameter);
773
748
  clientContext.addGlobalParameter(parameter);
774
749
  }
775
- else if (SPECIAL_HEADER_NAMES.has(param.name.toLowerCase())) {
750
+ else if (param.kind === "header" && SPECIAL_HEADER_NAMES.has(param.serializedName.toLowerCase())) {
776
751
  // special headers
777
- op.specialHeaders = (_b = op.specialHeaders) !== null && _b !== void 0 ? _b : [];
778
- if (!stringArrayContainsIgnoreCase(op.specialHeaders, param.name)) {
779
- op.specialHeaders.push(param.name);
752
+ op.specialHeaders = (_a = op.specialHeaders) !== null && _a !== void 0 ? _a : [];
753
+ if (!stringArrayContainsIgnoreCase(op.specialHeaders, param.serializedName)) {
754
+ op.specialHeaders.push(param.serializedName);
780
755
  }
781
756
  }
782
757
  else {
783
758
  // schema
784
- let schema;
785
- const sdkType = getNonNullSdkType(getClientType(this.sdkContext, param.param));
786
- if (param.type === "header" &&
787
- param.param.type.kind === "Scalar" &&
788
- getEncode(this.program, param.param) === undefined &&
789
- getEncode(this.program, param.param.type) === undefined &&
790
- (hasScalarAsBase(param.param.type, "utcDateTime") || hasScalarAsBase(param.param.type, "offsetDateTime")) &&
791
- (sdkType.kind === "utcDateTime" || sdkType.kind === "offsetDateTime")) {
792
- // utcDateTime in header maps to rfc7231
793
- schema = this.processDateTimeSchemaFromSdkType(sdkType, param.param.name, true);
794
- }
795
- else {
796
- schema = this.processSchemaFromSdkType(sdkType, param.param.name);
797
- }
759
+ const sdkType = getNonNullSdkType(param.type);
760
+ const schema = this.processSchemaFromSdkType(sdkType, param.name);
798
761
  let extensions = undefined;
799
- // skip-url-encoding
800
- if (param.type === "path") {
762
+ if (param.kind === "path") {
801
763
  if (param.allowReserved) {
802
764
  extensions = extensions !== null && extensions !== void 0 ? extensions : {};
803
765
  extensions["x-ms-skip-url-encoding"] = true;
804
766
  }
805
767
  }
806
768
  // TODO: deprecate this logic of string/url for x-ms-skip-url-encoding
807
- if ((param.type === "query" || param.type === "path") &&
808
- param.param.type.kind === "Scalar" &&
769
+ if ((param.kind === "query" || param.kind === "path") &&
770
+ isSdkBuiltInKind(sdkType.kind) &&
809
771
  schema instanceof UriSchema) {
810
772
  extensions = extensions !== null && extensions !== void 0 ? extensions : {};
811
773
  extensions["x-ms-skip-url-encoding"] = true;
812
774
  }
813
- if (this.supportsAdvancedVersioning()) {
775
+ if (this.supportsAdvancedVersioning() && param.__raw) {
814
776
  // versioning
815
- const addedOn = getAddedOnVersions(this.program, param.param);
777
+ const addedOn = getAddedOnVersions(this.program, param.__raw);
816
778
  if (addedOn) {
817
779
  extensions = extensions !== null && extensions !== void 0 ? extensions : {};
818
780
  extensions["x-ms-versioning-added"] = clientContext.getAddedVersions(addedOn);
@@ -821,62 +783,59 @@ export class CodeModelBuilder {
821
783
  // format if array
822
784
  let style = undefined;
823
785
  let explode = undefined;
824
- if (param.param.type.kind === "Model" && isArrayModelType(this.program, param.param.type)) {
825
- if (param.type === "query") {
826
- // eslint-disable-next-line deprecation/deprecation
827
- const queryParamFormat = param === null || param === void 0 ? void 0 : param.format;
828
- if (queryParamFormat) {
829
- switch (queryParamFormat) {
830
- case "csv":
831
- style = SerializationStyle.Simple;
832
- break;
833
- case "ssv":
834
- style = SerializationStyle.SpaceDelimited;
835
- break;
836
- case "tsv":
837
- style = SerializationStyle.TabDelimited;
838
- break;
839
- case "pipes":
840
- style = SerializationStyle.PipeDelimited;
841
- break;
842
- case "multi":
843
- style = SerializationStyle.Form;
844
- explode = true;
845
- break;
846
- default:
847
- this.logWarning(`Unrecognized query parameter format: '${queryParamFormat}'.`);
848
- break;
849
- }
786
+ if (sdkType.kind === "array") {
787
+ if (param.kind === "query") {
788
+ const format = param.collectionFormat;
789
+ switch (format) {
790
+ case "csv":
791
+ case "simple":
792
+ style = SerializationStyle.Simple;
793
+ break;
794
+ case "ssv":
795
+ style = SerializationStyle.SpaceDelimited;
796
+ break;
797
+ case "tsv":
798
+ style = SerializationStyle.TabDelimited;
799
+ break;
800
+ case "pipes":
801
+ style = SerializationStyle.PipeDelimited;
802
+ break;
803
+ case "multi":
804
+ case "form":
805
+ style = SerializationStyle.Form;
806
+ explode = true;
807
+ break;
850
808
  }
851
809
  }
852
- else if (param.type === "header") {
853
- if (param.format) {
854
- switch (param.format) {
855
- case "csv":
856
- style = SerializationStyle.Simple;
857
- break;
858
- default:
859
- this.logWarning(`Unrecognized header parameter format: '${param.format}'.`);
860
- break;
861
- }
810
+ else if (param.kind === "header") {
811
+ const format = param.collectionFormat;
812
+ switch (format) {
813
+ case "csv":
814
+ style = SerializationStyle.Simple;
815
+ break;
816
+ default:
817
+ if (format) {
818
+ this.logWarning(`Unrecognized header parameter format: '${format}'.`);
819
+ }
820
+ break;
862
821
  }
863
822
  }
864
823
  }
865
- const nullable = isNullableType(param.param.type);
866
- const parameter = new Parameter(this.getName(param.param), this.getDoc(param.param), schema, {
867
- summary: this.getSummary(param.param),
824
+ const nullable = param.type.kind === "nullable";
825
+ const parameter = new Parameter(param.name, (_b = param.details) !== null && _b !== void 0 ? _b : "", schema, {
826
+ summary: param.description,
868
827
  implementation: ImplementationLocation.Method,
869
- required: !param.param.optional,
828
+ required: !param.optional,
870
829
  nullable: nullable,
871
830
  protocol: {
872
- http: new HttpParameter(param.type, {
831
+ http: new HttpParameter(param.kind, {
873
832
  style: style,
874
833
  explode: explode,
875
834
  }),
876
835
  },
877
836
  language: {
878
837
  default: {
879
- serializedName: this.getSerializedName(param.param),
838
+ serializedName: param.serializedName, // it uses param.name previously, but better to use param.serializedName directly
880
839
  },
881
840
  },
882
841
  extensions: extensions,
@@ -888,43 +847,6 @@ export class CodeModelBuilder {
888
847
  }
889
848
  }
890
849
  }
891
- addAcceptHeaderParameter(op, responses) {
892
- var _a, _b, _c;
893
- if ((_a = op.parameters) === null || _a === void 0 ? void 0 : _a.some((it) => { var _a; return ((_a = it.language.default.serializedName) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === "accept"; })) {
894
- // parameters already include "accept" header
895
- return;
896
- }
897
- const produces = new Set();
898
- for (const resp of responses) {
899
- if (resp.responses && resp.responses.length > 0) {
900
- for (const response of resp.responses) {
901
- (_b = response.body) === null || _b === void 0 ? void 0 : _b.contentTypes.forEach((it) => produces.add(it));
902
- }
903
- }
904
- }
905
- if (produces.size === 0) {
906
- produces.add("application/json");
907
- }
908
- const acceptTypes = Array.from(produces.values()).join(", ");
909
- const acceptSchema = ((_c = this.codeModel.schemas.constants) === null || _c === void 0 ? void 0 : _c.find((it) => it.language.default.name === "accept" && it.value.value === acceptTypes)) ||
910
- this.codeModel.schemas.add(new ConstantSchema("accept", `Accept: ${acceptTypes}`, {
911
- valueType: this.stringSchema,
912
- value: new ConstantValue(acceptTypes),
913
- }));
914
- op.addParameter(new Parameter("accept", "Accept header", acceptSchema, {
915
- implementation: ImplementationLocation.Method,
916
- origin: "modelerfour:synthesized/accept",
917
- required: true,
918
- protocol: {
919
- http: new HttpParameter(ParameterLocation.Header),
920
- },
921
- language: {
922
- default: {
923
- serializedName: "accept",
924
- },
925
- },
926
- }));
927
- }
928
850
  processEtagHeaderParameters(op, httpOperation) {
929
851
  if (op.convenienceApi && op.parameters && op.signatureParameters) {
930
852
  const etagHeadersNames = new Set([
@@ -975,7 +897,7 @@ export class CodeModelBuilder {
975
897
  request.signatureParameters.push(clonedParameter);
976
898
  }
977
899
  }
978
- const namespace = getNamespace(httpOperation.operation);
900
+ const namespace = getNamespace(httpOperation.__raw.operation); // TODO: SdkHttpOperation does not have namespace
979
901
  const schemaName = groupToRequestConditions ? "RequestConditions" : "MatchConditions";
980
902
  const schemaDescription = groupToRequestConditions
981
903
  ? "Specifies HTTP options for conditional requests based on modification time."
@@ -1026,274 +948,272 @@ export class CodeModelBuilder {
1026
948
  }
1027
949
  }
1028
950
  }
1029
- processParameterBody(op, httpOperation, body) {
951
+ processParameterBody(op, rawHttpOperation, sdkHttpOperation, sdkBody) {
1030
952
  var _a, _b, _c;
1031
953
  // set contentTypes to mediaTypes
1032
- op.requests[0].protocol.http.mediaTypes = httpOperation.parameters.body.contentTypes;
1033
- const parameters = httpOperation.operation.parameters;
954
+ op.requests[0].protocol.http.mediaTypes = sdkBody.contentTypes;
1034
955
  const unknownRequestBody = op.requests[0].protocol.http.mediaTypes &&
1035
956
  op.requests[0].protocol.http.mediaTypes.length > 0 &&
1036
957
  !isKnownContentType(op.requests[0].protocol.http.mediaTypes);
1037
- const sdkType = getClientType(this.sdkContext, body, httpOperation.operation);
958
+ const sdkType = sdkBody.type;
1038
959
  let schema;
1039
- if (unknownRequestBody &&
1040
- body.kind === "ModelProperty" &&
1041
- body.type.kind === "Scalar" &&
1042
- body.type.name === "bytes") {
1043
- // handle binary request body
1044
- schema = this.processBinarySchema(body.type);
960
+ if (unknownRequestBody && sdkType.kind === "bytes") {
961
+ // if it's unknown request body, handle binary request body
962
+ schema = this.processBinarySchemaFromSdkType(sdkType);
1045
963
  }
1046
964
  else {
1047
- schema = this.processSchemaFromSdkType(sdkType, body.name);
1048
- }
1049
- // Explicit body parameter @body or @bodyRoot would result to body.kind === "ModelProperty"
1050
- // Implicit body parameter would result to body.kind === "Model"
1051
- // see https://typespec.io/docs/libraries/http/cheat-sheet#data-types
1052
- const bodyParameterFlatten = sdkType.kind === "model" && body.kind === "Model" && !this.isArm();
1053
- const parameterName = body.kind === "Model" ? (sdkType.kind === "model" ? sdkType.name : "") : this.getName(body);
1054
- const parameter = new Parameter(parameterName, this.getDoc(body), schema, {
1055
- summary: this.getSummary(body),
965
+ schema = this.processSchemaFromSdkType(getNonNullSdkType(sdkType), sdkBody.name);
966
+ }
967
+ const parameterName = sdkBody.name;
968
+ const parameter = new Parameter(parameterName, (_a = sdkBody.description) !== null && _a !== void 0 ? _a : "", schema, {
969
+ summary: sdkBody.details,
1056
970
  implementation: ImplementationLocation.Method,
1057
- required: body.kind === "Model" || !body.optional,
971
+ required: !sdkBody.optional,
1058
972
  protocol: {
1059
973
  http: new HttpParameter(ParameterLocation.Body),
1060
974
  },
1061
975
  });
1062
976
  op.addParameter(parameter);
977
+ const jsonMergePatch = operationIsJsonMergePatch(sdkHttpOperation);
978
+ const schemaIsPublicBeforeProcess = schema instanceof ObjectSchema && ((_b = schema.usage) === null || _b === void 0 ? void 0 : _b.includes(SchemaContext.Public));
1063
979
  this.trackSchemaUsage(schema, { usage: [SchemaContext.Input] });
1064
980
  if (op.convenienceApi) {
1065
981
  // model/schema does not need to be Public or Internal, if it is not to be used in convenience API
1066
982
  this.trackSchemaUsage(schema, { usage: [op.internalApi ? SchemaContext.Internal : SchemaContext.Public] });
1067
983
  }
1068
- if (operationIsJsonMergePatch(httpOperation)) {
984
+ if (jsonMergePatch) {
1069
985
  this.trackSchemaUsage(schema, { usage: [SchemaContext.JsonMergePatch] });
1070
986
  }
1071
- if (op.convenienceApi && operationIsMultipart(httpOperation)) {
987
+ if (op.convenienceApi && operationIsMultipart(sdkHttpOperation)) {
1072
988
  this.trackSchemaUsage(schema, { serializationFormats: [KnownMediaType.Multipart] });
1073
989
  }
1074
- if (schema instanceof ObjectSchema && bodyParameterFlatten) {
1075
- // flatten body parameter
1076
- // name the schema for documentation
1077
- schema.language.default.name = pascalCase(op.language.default.name) + "Request";
1078
- if (!parameter.language.default.name) {
1079
- // name the parameter for documentation
1080
- parameter.language.default.name = "request";
1081
- }
1082
- if (operationIsJsonMergePatch(httpOperation)) {
1083
- // skip model flatten, if "application/merge-patch+json"
1084
- schema.language.default.name = pascalCase(op.language.default.name) + "PatchRequest";
1085
- return;
1086
- }
1087
- this.trackSchemaUsage(schema, { usage: [SchemaContext.Anonymous] });
1088
- if (op.convenienceApi && op.parameters) {
1089
- op.convenienceApi.requests = [];
1090
- const request = new Request({
1091
- protocol: op.requests[0].protocol,
1092
- });
1093
- request.parameters = [];
1094
- op.convenienceApi.requests.push(request);
1095
- for (const [_, opParameter] of parameters.properties) {
1096
- const serializedName = this.getSerializedName(opParameter);
1097
- const paramLocation = this.getParameterLocation(opParameter);
1098
- let existParameter;
1099
- if (paramLocation === "BodyProperty") {
1100
- // property of body, it won't match existing parameter (whose paramLocation be body, path, query, header)
1101
- existParameter = undefined;
990
+ if (op.convenienceApi) {
991
+ // Explicit body parameter @body or @bodyRoot would result to the existance of rawHttpOperation.parameters.body.property
992
+ // Implicit body parameter would result to rawHttpOperation.parameters.body.property be undefined
993
+ // see https://typespec.io/docs/libraries/http/cheat-sheet#data-types
994
+ const bodyParameterFlatten = schema instanceof ObjectSchema &&
995
+ sdkType.kind === "model" &&
996
+ !((_c = rawHttpOperation.parameters.body) === null || _c === void 0 ? void 0 : _c.property) &&
997
+ !this.isArm();
998
+ if (schema instanceof ObjectSchema && bodyParameterFlatten) {
999
+ // flatten body parameter
1000
+ const parameters = sdkHttpOperation.parameters;
1001
+ const bodyParameter = sdkHttpOperation.bodyParam;
1002
+ if (!parameter.language.default.name) {
1003
+ // name the parameter for documentation
1004
+ parameter.language.default.name = "request";
1005
+ }
1006
+ if (jsonMergePatch) {
1007
+ // skip model flatten, if "application/merge-patch+json"
1008
+ if (sdkType.isGeneratedName) {
1009
+ schema.language.default.name = pascalCase(op.language.default.name) + "PatchRequest";
1102
1010
  }
1103
- else {
1104
- existParameter = op.parameters.find((it) => {
1105
- var _a;
1106
- const sameParamLocation = paramLocation === ((_a = it.protocol.http) === null || _a === void 0 ? void 0 : _a.in);
1107
- const sameSerializedName = it.language.default.serializedName === serializedName;
1108
- if (paramLocation === ParameterLocation.Body) {
1109
- // body, same paramLocation, as there could only be 1 body in operation
1110
- return sameParamLocation;
1111
- }
1112
- else {
1113
- // path, query, header, require same serializedName and same paramLocation
1114
- return sameParamLocation && sameSerializedName;
1115
- }
1116
- });
1011
+ return;
1012
+ }
1013
+ const schemaUsage = schema.usage;
1014
+ if (!schemaIsPublicBeforeProcess && (schemaUsage === null || schemaUsage === void 0 ? void 0 : schemaUsage.includes(SchemaContext.Public))) {
1015
+ // Public added in this op, change it to PublicSpread
1016
+ // This means that if this op would originally add Public to this schema, it adds PublicSpread instead
1017
+ schemaUsage === null || schemaUsage === void 0 ? void 0 : schemaUsage.splice(schemaUsage === null || schemaUsage === void 0 ? void 0 : schemaUsage.indexOf(SchemaContext.Public), 1);
1018
+ this.trackSchemaUsage(schema, { usage: [SchemaContext.PublicSpread] });
1019
+ }
1020
+ if (op.convenienceApi && op.parameters) {
1021
+ op.convenienceApi.requests = [];
1022
+ const request = new Request({
1023
+ protocol: op.requests[0].protocol,
1024
+ });
1025
+ request.parameters = [];
1026
+ op.convenienceApi.requests.push(request);
1027
+ // header/query/path params
1028
+ for (const opParameter of parameters) {
1029
+ this.addParameterOrBodyPropertyToCodeModelRequest(opParameter, op, request, schema, parameter);
1117
1030
  }
1118
- if (existParameter) {
1119
- // parameter
1120
- if (existParameter.implementation === ImplementationLocation.Method &&
1121
- ((_b = (_a = existParameter.origin) === null || _a === void 0 ? void 0 : _a.startsWith("modelerfour:synthesized/")) !== null && _b !== void 0 ? _b : true) &&
1122
- !(existParameter.schema instanceof ConstantSchema)) {
1123
- request.parameters.push(cloneOperationParameter(existParameter));
1031
+ // body param
1032
+ if (bodyParameter) {
1033
+ if (bodyParameter.type.kind === "model") {
1034
+ for (const bodyProperty of bodyParameter.type.properties) {
1035
+ if (bodyProperty.kind === "property") {
1036
+ this.addParameterOrBodyPropertyToCodeModelRequest(bodyProperty, op, request, schema, parameter);
1037
+ }
1038
+ }
1124
1039
  }
1125
1040
  }
1126
- else {
1127
- // property from anonymous model
1128
- const existBodyProperty = (_c = schema.properties) === null || _c === void 0 ? void 0 : _c.find((it) => it.serializedName === serializedName);
1129
- if (existBodyProperty &&
1130
- !existBodyProperty.readOnly &&
1131
- !(existBodyProperty.schema instanceof ConstantSchema)) {
1132
- request.parameters.push(new VirtualParameter(existBodyProperty.language.default.name, existBodyProperty.language.default.description, existBodyProperty.schema, {
1133
- originalParameter: parameter,
1134
- targetProperty: existBodyProperty,
1135
- language: {
1136
- default: {
1137
- serializedName: existBodyProperty.serializedName,
1138
- },
1041
+ request.signatureParameters = request.parameters;
1042
+ if (request.signatureParameters.length > 6) {
1043
+ // create an option bag
1044
+ const name = op.language.default.name + "Options";
1045
+ const namespace = getNamespace(rawHttpOperation.operation);
1046
+ // option bag schema
1047
+ const optionBagSchema = this.codeModel.schemas.add(new GroupSchema(name, `Options for ${op.language.default.name} API`, {
1048
+ language: {
1049
+ default: {
1050
+ namespace: namespace,
1051
+ },
1052
+ java: {
1053
+ namespace: this.getJavaNamespace(namespace),
1139
1054
  },
1140
- summary: existBodyProperty.summary,
1141
- implementation: ImplementationLocation.Method,
1142
- required: existBodyProperty.required,
1143
- nullable: existBodyProperty.nullable,
1144
- }));
1145
- }
1146
- }
1147
- }
1148
- request.signatureParameters = request.parameters;
1149
- if (request.signatureParameters.length > 6) {
1150
- // create an option bag
1151
- const name = op.language.default.name + "Options";
1152
- const namespace = getNamespace(httpOperation.operation);
1153
- // option bag schema
1154
- const optionBagSchema = this.codeModel.schemas.add(new GroupSchema(name, `Options for ${op.language.default.name} API`, {
1155
- language: {
1156
- default: {
1157
- namespace: namespace,
1158
- },
1159
- java: {
1160
- namespace: this.getJavaNamespace(namespace),
1161
1055
  },
1162
- },
1163
- }));
1164
- request.parameters.forEach((it) => {
1165
- optionBagSchema.add(new GroupProperty(it.language.default.name, it.language.default.description, it.schema, {
1166
- originalParameter: [it],
1167
- summary: it.summary,
1168
- required: it.required,
1169
- nullable: it.nullable,
1170
- readOnly: false,
1171
- serializedName: it.language.default.serializedName,
1172
1056
  }));
1173
- });
1174
- this.trackSchemaUsage(optionBagSchema, { usage: [SchemaContext.Input] });
1175
- if (op.convenienceApi) {
1176
- this.trackSchemaUsage(optionBagSchema, {
1177
- usage: [op.internalApi ? SchemaContext.Internal : SchemaContext.Public],
1057
+ request.parameters.forEach((it) => {
1058
+ optionBagSchema.add(new GroupProperty(it.language.default.name, it.language.default.description, it.schema, {
1059
+ originalParameter: [it],
1060
+ summary: it.summary,
1061
+ required: it.required,
1062
+ nullable: it.nullable,
1063
+ readOnly: false,
1064
+ serializedName: it.language.default.serializedName,
1065
+ }));
1066
+ });
1067
+ this.trackSchemaUsage(optionBagSchema, { usage: [SchemaContext.Input] });
1068
+ if (op.convenienceApi) {
1069
+ this.trackSchemaUsage(optionBagSchema, {
1070
+ usage: [op.internalApi ? SchemaContext.Internal : SchemaContext.Public],
1071
+ });
1072
+ }
1073
+ // option bag parameter
1074
+ const optionBagParameter = new Parameter("options", optionBagSchema.language.default.description, optionBagSchema, {
1075
+ implementation: ImplementationLocation.Method,
1076
+ required: true,
1077
+ nullable: false,
1178
1078
  });
1079
+ request.signatureParameters = [optionBagParameter];
1080
+ request.parameters.forEach((it) => (it.groupedBy = optionBagParameter));
1081
+ request.parameters.push(optionBagParameter);
1179
1082
  }
1180
- // option bag parameter
1181
- const optionBagParameter = new Parameter("options", optionBagSchema.language.default.description, optionBagSchema, {
1182
- implementation: ImplementationLocation.Method,
1183
- required: true,
1184
- nullable: false,
1185
- });
1186
- request.signatureParameters = [optionBagParameter];
1187
- request.parameters.forEach((it) => (it.groupedBy = optionBagParameter));
1188
- request.parameters.push(optionBagParameter);
1189
1083
  }
1190
1084
  }
1191
1085
  }
1192
1086
  }
1087
+ addParameterOrBodyPropertyToCodeModelRequest(opParameter, op, request, schema, originalParameter) {
1088
+ var _a, _b, _c, _d, _e;
1089
+ const serializedName = opParameter.serializedName;
1090
+ let existParameter;
1091
+ if (opParameter.kind !== "property") {
1092
+ // not body property
1093
+ // header/query/path, same location and same serializedName
1094
+ existParameter = (_a = op.parameters) === null || _a === void 0 ? void 0 : _a.find((it) => { var _a; return ((_a = it.protocol.http) === null || _a === void 0 ? void 0 : _a.in) === opParameter.kind && it.language.default.serializedName === serializedName; });
1095
+ }
1096
+ request.parameters = (_b = request.parameters) !== null && _b !== void 0 ? _b : [];
1097
+ if (existParameter) {
1098
+ // parameter
1099
+ if (existParameter.implementation === ImplementationLocation.Method &&
1100
+ ((_d = (_c = existParameter.origin) === null || _c === void 0 ? void 0 : _c.startsWith("modelerfour:synthesized/")) !== null && _d !== void 0 ? _d : true) &&
1101
+ !(existParameter.schema instanceof ConstantSchema)) {
1102
+ request.parameters.push(cloneOperationParameter(existParameter));
1103
+ }
1104
+ }
1105
+ else {
1106
+ // property from anonymous model
1107
+ const existBodyProperty = (_e = schema.properties) === null || _e === void 0 ? void 0 : _e.find((it) => it.serializedName === serializedName);
1108
+ if (existBodyProperty && !existBodyProperty.readOnly && !(existBodyProperty.schema instanceof ConstantSchema)) {
1109
+ request.parameters.push(new VirtualParameter(existBodyProperty.language.default.name, existBodyProperty.language.default.description, existBodyProperty.schema, {
1110
+ originalParameter: originalParameter,
1111
+ targetProperty: existBodyProperty,
1112
+ language: {
1113
+ default: {
1114
+ serializedName: existBodyProperty.serializedName,
1115
+ },
1116
+ },
1117
+ summary: existBodyProperty.summary,
1118
+ implementation: ImplementationLocation.Method,
1119
+ required: existBodyProperty.required,
1120
+ nullable: existBodyProperty.nullable,
1121
+ }));
1122
+ }
1123
+ }
1124
+ }
1193
1125
  findResponseBody(bodyType) {
1194
1126
  // find a type that possibly without http metadata like @statusCode
1195
1127
  return this.getEffectiveSchemaType(bodyType);
1196
1128
  }
1197
- processResponse(op, resp, longRunning) {
1129
+ processResponse(op, statusCode, sdkResponse, longRunning, isErrorResponse) {
1130
+ var _a;
1198
1131
  // TODO: what to do if more than 1 response?
1199
1132
  // It happens when the response type is Union, on one status code.
1200
- let response;
1133
+ // let response: Response;
1201
1134
  let headers = undefined;
1202
- if (resp.responses && resp.responses.length > 0) {
1203
- // headers
1204
- headers = [];
1205
- for (const response of resp.responses.values()) {
1206
- if (response.headers) {
1207
- for (const [key, header] of Object.entries(response.headers)) {
1208
- const sdkType = getClientType(this.sdkContext, header);
1209
- const schema = this.processSchemaFromSdkType(sdkType, key);
1210
- headers.push(new HttpHeader(key, schema, {
1211
- language: {
1212
- default: {
1213
- name: key,
1214
- description: this.getDoc(header),
1215
- },
1216
- },
1217
- }));
1218
- }
1219
- }
1220
- }
1221
- }
1222
- let responseBody = undefined;
1223
- let bodyType = undefined;
1224
- let trackConvenienceApi = Boolean(op.convenienceApi);
1225
- if (resp.responses && resp.responses.length > 0 && resp.responses[0].body) {
1226
- responseBody = resp.responses[0].body;
1227
- }
1228
- if (responseBody) {
1229
- const unknownResponseBody = responseBody.contentTypes.length > 0 && !isKnownContentType(responseBody.contentTypes);
1230
- bodyType = this.findResponseBody(responseBody.type);
1231
- if (unknownResponseBody && bodyType.kind === "Scalar" && bodyType.name === "bytes") {
1232
- // binary
1233
- response = new BinaryResponse({
1234
- protocol: {
1235
- http: {
1236
- statusCodes: this.getStatusCodes(resp.statusCodes),
1237
- headers: headers,
1238
- mediaTypes: responseBody.contentTypes,
1239
- knownMediaType: KnownMediaType.Binary,
1240
- },
1241
- },
1135
+ // headers
1136
+ headers = [];
1137
+ if (sdkResponse.headers) {
1138
+ for (const header of sdkResponse.headers) {
1139
+ const schema = this.processSchemaFromSdkType(header.type, header.serializedName);
1140
+ headers.push(new HttpHeader(header.serializedName, schema, {
1242
1141
  language: {
1243
1142
  default: {
1244
- name: op.language.default.name + "Response",
1245
- description: this.getResponseDescription(resp),
1143
+ name: header.serializedName,
1144
+ description: (_a = header.description) !== null && _a !== void 0 ? _a : header.details,
1246
1145
  },
1247
1146
  },
1248
- });
1147
+ }));
1249
1148
  }
1250
- else {
1251
- // schema (usually JSON)
1252
- let schema = undefined;
1253
- if (longRunning) {
1254
- // LRO uses the LroMetadata for poll/final result, not the response of activation request
1255
- trackConvenienceApi = false;
1256
- }
1257
- if (!schema) {
1258
- const sdkType = getClientType(this.sdkContext, bodyType);
1259
- schema = this.processSchemaFromSdkType(sdkType, op.language.default.name + "Response");
1260
- }
1261
- response = new SchemaResponse(schema, {
1262
- protocol: {
1263
- http: {
1264
- statusCodes: this.getStatusCodes(resp.statusCodes),
1265
- headers: headers,
1266
- mediaTypes: responseBody.contentTypes,
1267
- },
1149
+ }
1150
+ const bodyType = sdkResponse.type;
1151
+ let trackConvenienceApi = Boolean(op.convenienceApi);
1152
+ const unknownResponseBody = sdkResponse.contentTypes && sdkResponse.contentTypes.length > 0 && !isKnownContentType(sdkResponse.contentTypes);
1153
+ let response;
1154
+ if (unknownResponseBody && bodyType && bodyType.kind === "bytes") {
1155
+ // binary
1156
+ response = new BinaryResponse({
1157
+ protocol: {
1158
+ http: {
1159
+ statusCodes: this.getStatusCodes(statusCode),
1160
+ headers: headers,
1161
+ mediaTypes: sdkResponse.contentTypes,
1162
+ knownMediaType: KnownMediaType.Binary,
1268
1163
  },
1269
- language: {
1270
- default: {
1271
- name: op.language.default.name + "Response",
1272
- description: this.getResponseDescription(resp),
1273
- },
1164
+ },
1165
+ language: {
1166
+ default: {
1167
+ name: op.language.default.name + "Response",
1168
+ description: sdkResponse.description,
1274
1169
  },
1275
- });
1170
+ },
1171
+ });
1172
+ }
1173
+ else if (bodyType) {
1174
+ // schema (usually JSON)
1175
+ let schema = undefined;
1176
+ if (longRunning) {
1177
+ // LRO uses the LroMetadata for poll/final result, not the response of activation request
1178
+ trackConvenienceApi = false;
1179
+ }
1180
+ if (!schema) {
1181
+ schema = this.processSchemaFromSdkType(bodyType, op.language.default.name + "Response");
1276
1182
  }
1183
+ response = new SchemaResponse(schema, {
1184
+ protocol: {
1185
+ http: {
1186
+ statusCodes: this.getStatusCodes(statusCode),
1187
+ headers: headers,
1188
+ mediaTypes: sdkResponse.contentTypes,
1189
+ },
1190
+ },
1191
+ language: {
1192
+ default: {
1193
+ name: op.language.default.name + "Response",
1194
+ description: sdkResponse.description,
1195
+ },
1196
+ },
1197
+ });
1277
1198
  }
1278
1199
  else {
1279
1200
  // not binary nor schema, usually NoContent
1280
1201
  response = new Response({
1281
1202
  protocol: {
1282
1203
  http: {
1283
- statusCodes: this.getStatusCodes(resp.statusCodes),
1204
+ statusCodes: this.getStatusCodes(statusCode),
1284
1205
  headers: headers,
1285
1206
  },
1286
1207
  },
1287
1208
  language: {
1288
1209
  default: {
1289
1210
  name: op.language.default.name + "Response",
1290
- description: this.getResponseDescription(resp),
1211
+ description: sdkResponse.description,
1291
1212
  },
1292
1213
  },
1293
1214
  });
1294
1215
  }
1295
- if (resp.statusCodes === "*" || (bodyType && isErrorModel(this.program, bodyType))) {
1296
- // "*", or the model is @error
1216
+ if (isErrorResponse) {
1297
1217
  op.addException(response);
1298
1218
  if (response instanceof SchemaResponse) {
1299
1219
  this.trackSchemaUsage(response.schema, { usage: [SchemaContext.Exception] });
@@ -1327,11 +1247,6 @@ export class CodeModelBuilder {
1327
1247
  .map((it) => it.toString());
1328
1248
  }
1329
1249
  }
1330
- getResponseDescription(resp) {
1331
- return (resp.description ||
1332
- (resp.statusCodes === "*" ? "An unexpected error response" : getStatusCodeDescription(resp.statusCodes)) ||
1333
- "");
1334
- }
1335
1250
  processSchemaFromSdkType(type, nameHint) {
1336
1251
  return this.schemaCache.process(type, nameHint) || fail("Unable to process schema.");
1337
1252
  }
@@ -1744,9 +1659,10 @@ export class CodeModelBuilder {
1744
1659
  });
1745
1660
  return this.codeModel.schemas.add(unionSchema);
1746
1661
  }
1747
- processBinarySchema(type) {
1748
- return this.codeModel.schemas.add(new BinarySchema(this.getDoc(type), {
1749
- summary: this.getSummary(type),
1662
+ processBinarySchemaFromSdkType(type) {
1663
+ var _a;
1664
+ return this.codeModel.schemas.add(new BinarySchema((_a = type.description) !== null && _a !== void 0 ? _a : "", {
1665
+ summary: type.details,
1750
1666
  }));
1751
1667
  }
1752
1668
  getUnionVariantName(type, option) {
@@ -1834,30 +1750,6 @@ export class CodeModelBuilder {
1834
1750
  getSummary(target) {
1835
1751
  return target ? getSummary(this.program, target) : undefined;
1836
1752
  }
1837
- getName(target, nameHint = undefined) {
1838
- // TODO: once getLibraryName API in typespec-client-generator-core can get projected name from language and client, as well as can handle template case, use getLibraryName API
1839
- const emitterClientName = getClientNameOverride(this.sdkContext, target);
1840
- if (emitterClientName && typeof emitterClientName === "string") {
1841
- return emitterClientName;
1842
- }
1843
- // TODO: deprecate getProjectedName
1844
- const languageProjectedName = getProjectedName(this.program, target, "java");
1845
- if (languageProjectedName) {
1846
- return languageProjectedName;
1847
- }
1848
- const clientProjectedName = getProjectedName(this.program, target, "client");
1849
- if (clientProjectedName) {
1850
- return clientProjectedName;
1851
- }
1852
- const friendlyName = getFriendlyName(this.program, target);
1853
- if (friendlyName) {
1854
- return friendlyName;
1855
- }
1856
- if (typeof target.name === "symbol") {
1857
- return "";
1858
- }
1859
- return target.name || "";
1860
- }
1861
1753
  getSerializedName(target) {
1862
1754
  if (isHeader(this.program, target)) {
1863
1755
  return getHeaderFieldName(this.program, target);
@@ -1873,25 +1765,6 @@ export class CodeModelBuilder {
1873
1765
  return getWireName(this.sdkContext, target);
1874
1766
  }
1875
1767
  }
1876
- getParameterLocation(target) {
1877
- if (isHeader(this.program, target)) {
1878
- return ParameterLocation.Header;
1879
- }
1880
- else if (isQueryParam(this.program, target)) {
1881
- return ParameterLocation.Query;
1882
- }
1883
- else if (isPathParam(this.program, target)) {
1884
- return ParameterLocation.Path;
1885
- }
1886
- else if (isBody(this.program, target) ||
1887
- isBodyRoot(this.program, target) ||
1888
- isMultipartBodyProperty(this.program, target)) {
1889
- return ParameterLocation.Body;
1890
- }
1891
- else {
1892
- return "BodyProperty";
1893
- }
1894
- }
1895
1768
  isReadOnly(target) {
1896
1769
  const segment = target.__raw ? getSegment(this.program, target.__raw) !== undefined : false;
1897
1770
  if (segment) {
@@ -1943,10 +1816,10 @@ export class CodeModelBuilder {
1943
1816
  return undefined;
1944
1817
  }
1945
1818
  }
1946
- getConvenienceApiName(op) {
1947
- // check @convenienceMethod
1948
- if (shouldGenerateConvenient(this.sdkContext, op)) {
1949
- return this.getName(op);
1819
+ getConvenienceApiName(sdkMethod) {
1820
+ // check @convenienceAPI
1821
+ if (sdkMethod.generateConvenient) {
1822
+ return sdkMethod.name;
1950
1823
  }
1951
1824
  else {
1952
1825
  return undefined;
@@ -2028,16 +1901,11 @@ export class CodeModelBuilder {
2028
1901
  (this._apiVersionParameterInPath = this.createApiVersionParameter("apiVersion", ParameterLocation.Path)));
2029
1902
  }
2030
1903
  isSubscriptionId(param) {
2031
- var _a;
2032
- return ("subscriptionId".toLocaleLowerCase() === ((_a = param === null || param === void 0 ? void 0 : param.name) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase()) &&
2033
- param.param &&
2034
- isArmCommonType(param.param) &&
2035
- isPathParam(this.program, param.param));
1904
+ return "subscriptionId".toLocaleLowerCase() === param.serializedName.toLocaleLowerCase();
2036
1905
  }
2037
1906
  subscriptionIdParameter(parameter) {
2038
1907
  if (!this._subscriptionParameter) {
2039
- const param = parameter.param;
2040
- const description = getDoc(this.program, param);
1908
+ const description = parameter.description;
2041
1909
  this._subscriptionParameter = new Parameter("subscriptionId", description ? description : "The ID of the target subscription.", this.stringSchema, {
2042
1910
  implementation: ImplementationLocation.Client,
2043
1911
  required: true,
@@ -2054,7 +1922,7 @@ export class CodeModelBuilder {
2054
1922
  return this._subscriptionParameter;
2055
1923
  }
2056
1924
  propagateSchemaUsage(schema) {
2057
- var _a, _b;
1925
+ var _a, _b, _c, _d;
2058
1926
  const processedSchemas = new Set();
2059
1927
  const innerApplySchemaUsage = (schema, schemaUsage) => {
2060
1928
  this.trackSchemaUsage(schema, schemaUsage);
@@ -2110,9 +1978,18 @@ export class CodeModelBuilder {
2110
1978
  }
2111
1979
  };
2112
1980
  // Exclude context that not to be propagated
1981
+ const updatedSchemaUsage = (_a = schema.usage) === null || _a === void 0 ? void 0 : _a.filter((it) => it !== SchemaContext.Paged && it !== SchemaContext.PublicSpread);
1982
+ const indexSpread = (_b = schema.usage) === null || _b === void 0 ? void 0 : _b.indexOf(SchemaContext.PublicSpread);
1983
+ if (updatedSchemaUsage &&
1984
+ indexSpread &&
1985
+ indexSpread >= 0 &&
1986
+ !((_c = schema.usage) === null || _c === void 0 ? void 0 : _c.includes(SchemaContext.Public))) {
1987
+ // Propagate Public, if schema is PublicSpread
1988
+ updatedSchemaUsage.push(SchemaContext.Public);
1989
+ }
2113
1990
  const schemaUsage = {
2114
- usage: (_a = schema.usage) === null || _a === void 0 ? void 0 : _a.filter((it) => it !== SchemaContext.Paged && it !== SchemaContext.Anonymous),
2115
- serializationFormats: (_b = schema.serializationFormats) === null || _b === void 0 ? void 0 : _b.filter((it) => it !== KnownMediaType.Multipart),
1991
+ usage: updatedSchemaUsage,
1992
+ serializationFormats: (_d = schema.serializationFormats) === null || _d === void 0 ? void 0 : _d.filter((it) => it !== KnownMediaType.Multipart),
2116
1993
  };
2117
1994
  // Propagate the usage of the initial schema itself
2118
1995
  innerPropagateSchemaUsage(schema, schemaUsage);