@azure-tools/typespec-go 0.1.0

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.
Files changed (119) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +16 -0
  3. package/dist/codegen.go/src/clientFactory.d.ts +3 -0
  4. package/dist/codegen.go/src/clientFactory.d.ts.map +1 -0
  5. package/dist/codegen.go/src/clientFactory.js +77 -0
  6. package/dist/codegen.go/src/clientFactory.js.map +1 -0
  7. package/dist/codegen.go/src/constants.d.ts +3 -0
  8. package/dist/codegen.go/src/constants.d.ts.map +1 -0
  9. package/dist/codegen.go/src/constants.js +59 -0
  10. package/dist/codegen.go/src/constants.js.map +1 -0
  11. package/dist/codegen.go/src/fake/factory.d.ts +3 -0
  12. package/dist/codegen.go/src/fake/factory.d.ts.map +1 -0
  13. package/dist/codegen.go/src/fake/factory.js +69 -0
  14. package/dist/codegen.go/src/fake/factory.js.map +1 -0
  15. package/dist/codegen.go/src/fake/internal.d.ts +14 -0
  16. package/dist/codegen.go/src/fake/internal.d.ts.map +1 -0
  17. package/dist/codegen.go/src/fake/internal.js +197 -0
  18. package/dist/codegen.go/src/fake/internal.js.map +1 -0
  19. package/dist/codegen.go/src/fake/servers.d.ts +14 -0
  20. package/dist/codegen.go/src/fake/servers.d.ts.map +1 -0
  21. package/dist/codegen.go/src/fake/servers.js +1255 -0
  22. package/dist/codegen.go/src/fake/servers.js.map +1 -0
  23. package/dist/codegen.go/src/gomod.d.ts +3 -0
  24. package/dist/codegen.go/src/gomod.d.ts.map +1 -0
  25. package/dist/codegen.go/src/gomod.js +55 -0
  26. package/dist/codegen.go/src/gomod.js.map +1 -0
  27. package/dist/codegen.go/src/helpers.d.ts +32 -0
  28. package/dist/codegen.go/src/helpers.d.ts.map +1 -0
  29. package/dist/codegen.go/src/helpers.js +586 -0
  30. package/dist/codegen.go/src/helpers.js.map +1 -0
  31. package/dist/codegen.go/src/imports.d.ts +11 -0
  32. package/dist/codegen.go/src/imports.d.ts.map +1 -0
  33. package/dist/codegen.go/src/imports.js +65 -0
  34. package/dist/codegen.go/src/imports.js.map +1 -0
  35. package/dist/codegen.go/src/interfaces.d.ts +3 -0
  36. package/dist/codegen.go/src/interfaces.d.ts.map +1 -0
  37. package/dist/codegen.go/src/interfaces.js +36 -0
  38. package/dist/codegen.go/src/interfaces.js.map +1 -0
  39. package/dist/codegen.go/src/models.d.ts +9 -0
  40. package/dist/codegen.go/src/models.d.ts.map +1 -0
  41. package/dist/codegen.go/src/models.js +849 -0
  42. package/dist/codegen.go/src/models.js.map +1 -0
  43. package/dist/codegen.go/src/operations.d.ts +9 -0
  44. package/dist/codegen.go/src/operations.d.ts.map +1 -0
  45. package/dist/codegen.go/src/operations.js +1337 -0
  46. package/dist/codegen.go/src/operations.js.map +1 -0
  47. package/dist/codegen.go/src/options.d.ts +3 -0
  48. package/dist/codegen.go/src/options.d.ts.map +1 -0
  49. package/dist/codegen.go/src/options.js +64 -0
  50. package/dist/codegen.go/src/options.js.map +1 -0
  51. package/dist/codegen.go/src/polymorphics.d.ts +3 -0
  52. package/dist/codegen.go/src/polymorphics.d.ts.map +1 -0
  53. package/dist/codegen.go/src/polymorphics.js +169 -0
  54. package/dist/codegen.go/src/polymorphics.js.map +1 -0
  55. package/dist/codegen.go/src/responses.d.ts +7 -0
  56. package/dist/codegen.go/src/responses.d.ts.map +1 -0
  57. package/dist/codegen.go/src/responses.js +167 -0
  58. package/dist/codegen.go/src/responses.js.map +1 -0
  59. package/dist/codegen.go/src/time.d.ts +8 -0
  60. package/dist/codegen.go/src/time.d.ts.map +1 -0
  61. package/dist/codegen.go/src/time.js +511 -0
  62. package/dist/codegen.go/src/time.js.map +1 -0
  63. package/dist/codemodel.go/src/client.d.ts +96 -0
  64. package/dist/codemodel.go/src/client.d.ts.map +1 -0
  65. package/dist/codemodel.go/src/client.js +114 -0
  66. package/dist/codemodel.go/src/client.js.map +1 -0
  67. package/dist/codemodel.go/src/index.d.ts +6 -0
  68. package/dist/codemodel.go/src/index.d.ts.map +1 -0
  69. package/dist/codemodel.go/src/index.js +10 -0
  70. package/dist/codemodel.go/src/index.js.map +1 -0
  71. package/dist/codemodel.go/src/package.d.ts +49 -0
  72. package/dist/codemodel.go/src/package.d.ts.map +1 -0
  73. package/dist/codemodel.go/src/package.js +86 -0
  74. package/dist/codemodel.go/src/package.js.map +1 -0
  75. package/dist/codemodel.go/src/param.d.ts +162 -0
  76. package/dist/codemodel.go/src/param.d.ts.map +1 -0
  77. package/dist/codemodel.go/src/param.js +189 -0
  78. package/dist/codemodel.go/src/param.js.map +1 -0
  79. package/dist/codemodel.go/src/result.d.ts +102 -0
  80. package/dist/codemodel.go/src/result.d.ts.map +1 -0
  81. package/dist/codemodel.go/src/result.js +119 -0
  82. package/dist/codemodel.go/src/result.js.map +1 -0
  83. package/dist/codemodel.go/src/type.d.ts +181 -0
  84. package/dist/codemodel.go/src/type.d.ts.map +1 -0
  85. package/dist/codemodel.go/src/type.js +242 -0
  86. package/dist/codemodel.go/src/type.js.map +1 -0
  87. package/dist/naming.go/src/mappings.d.ts +3 -0
  88. package/dist/naming.go/src/mappings.d.ts.map +1 -0
  89. package/dist/naming.go/src/mappings.js +128 -0
  90. package/dist/naming.go/src/mappings.js.map +1 -0
  91. package/dist/naming.go/src/naming.d.ts +10 -0
  92. package/dist/naming.go/src/naming.d.ts.map +1 -0
  93. package/dist/naming.go/src/naming.js +114 -0
  94. package/dist/naming.go/src/naming.js.map +1 -0
  95. package/dist/typespec-go/src/emitter.d.ts +5 -0
  96. package/dist/typespec-go/src/emitter.d.ts.map +1 -0
  97. package/dist/typespec-go/src/emitter.js +122 -0
  98. package/dist/typespec-go/src/emitter.js.map +1 -0
  99. package/dist/typespec-go/src/index.d.ts +3 -0
  100. package/dist/typespec-go/src/index.d.ts.map +1 -0
  101. package/dist/typespec-go/src/index.js +7 -0
  102. package/dist/typespec-go/src/index.js.map +1 -0
  103. package/dist/typespec-go/src/lib.d.ts +25 -0
  104. package/dist/typespec-go/src/lib.d.ts.map +1 -0
  105. package/dist/typespec-go/src/lib.js +36 -0
  106. package/dist/typespec-go/src/lib.js.map +1 -0
  107. package/dist/typespec-go/src/tcgcadapter/adapter.d.ts +5 -0
  108. package/dist/typespec-go/src/tcgcadapter/adapter.d.ts.map +1 -0
  109. package/dist/typespec-go/src/tcgcadapter/adapter.js +119 -0
  110. package/dist/typespec-go/src/tcgcadapter/adapter.js.map +1 -0
  111. package/dist/typespec-go/src/tcgcadapter/clients.d.ts +26 -0
  112. package/dist/typespec-go/src/tcgcadapter/clients.d.ts.map +1 -0
  113. package/dist/typespec-go/src/tcgcadapter/clients.js +621 -0
  114. package/dist/typespec-go/src/tcgcadapter/clients.js.map +1 -0
  115. package/dist/typespec-go/src/tcgcadapter/types.d.ts +29 -0
  116. package/dist/typespec-go/src/tcgcadapter/types.d.ts.map +1 -0
  117. package/dist/typespec-go/src/tcgcadapter/types.js +975 -0
  118. package/dist/typespec-go/src/tcgcadapter/types.js.map +1 -0
  119. package/package.json +77 -0
@@ -0,0 +1,1255 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License. See License.txt in the project root for license information.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import * as go from '../../../codemodel.go/src/index.js';
6
+ import { capitalize, uncapitalize } from '@azure-tools/codegen';
7
+ import { values } from '@azure-tools/linq';
8
+ import * as helpers from '../helpers.js';
9
+ import { fixUpMethodName } from '../operations.js';
10
+ import { ImportManager } from '../imports.js';
11
+ import { generateServerInternal, RequiredHelpers } from './internal.js';
12
+ // contains the generated content for all servers and the required helpers
13
+ export class ServerContent {
14
+ constructor(servers, internals) {
15
+ this.servers = servers;
16
+ this.internals = internals;
17
+ }
18
+ }
19
+ // represents the generated content for an operation group
20
+ export class OperationGroupContent {
21
+ constructor(name, content) {
22
+ this.name = name;
23
+ this.content = content;
24
+ }
25
+ }
26
+ // used to track the helpers we need to emit. they're all false by default.
27
+ const requiredHelpers = new RequiredHelpers();
28
+ export function getServerName(client) {
29
+ // for the fake server, we use the suffix Server instead of Client
30
+ return capitalize(client.name.replace(/[C|c]lient$/, 'Server'));
31
+ }
32
+ function isMethodInternal(method) {
33
+ return !!method.name.match(/^[a-z]{1}/);
34
+ }
35
+ export async function generateServers(codeModel) {
36
+ const operations = new Array();
37
+ const clientPkg = codeModel.packageName;
38
+ for (const client of values(codeModel.clients)) {
39
+ if (client.clientAccessors.length === 0 && values(client.methods).all(method => { return isMethodInternal(method); })) {
40
+ // client has no client accessors and no exported methods, skip it
41
+ continue;
42
+ }
43
+ // the list of packages to import
44
+ const imports = new ImportManager();
45
+ // add standard imports
46
+ imports.add('errors');
47
+ imports.add('fmt');
48
+ imports.add('net/http');
49
+ imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime');
50
+ const serverName = getServerName(client);
51
+ let content;
52
+ content = `// ${serverName} is a fake server for instances of the ${clientPkg}.${client.name} type.\n`;
53
+ content += `type ${serverName} struct{\n`;
54
+ // we might remove some operations from the list
55
+ const finalMethods = new Array();
56
+ let countLROs = 0;
57
+ let countPagers = 0;
58
+ // add server transports for client accessors
59
+ // we might remove some clients from the list
60
+ const finalSubClients = new Array();
61
+ for (const clientAccessor of client.clientAccessors) {
62
+ if (values(clientAccessor.subClient.methods).all(method => { return isMethodInternal(method); })) {
63
+ // client has no exported methods, skip it
64
+ continue;
65
+ }
66
+ const serverName = getServerName(clientAccessor.subClient);
67
+ content += `\t// ${serverName} contains the fakes for client ${clientAccessor.subClient.name}\n`;
68
+ content += `\t${serverName} ${serverName}\n\n`;
69
+ finalSubClients.push(clientAccessor.subClient);
70
+ }
71
+ for (const method of values(client.methods)) {
72
+ if (isMethodInternal(method)) {
73
+ // method isn't exported, don't create a fake for it
74
+ continue;
75
+ }
76
+ let serverResponse;
77
+ if (go.isLROMethod(method)) {
78
+ let respType = `${clientPkg}.${method.responseEnvelope.name}`;
79
+ if (go.isPageableMethod(method)) {
80
+ respType = `azfake.PagerResponder[${clientPkg}.${method.responseEnvelope.name}]`;
81
+ }
82
+ serverResponse = `resp azfake.PollerResponder[${respType}], errResp azfake.ErrorResponder`;
83
+ }
84
+ else if (go.isPageableMethod(method)) {
85
+ serverResponse = `resp azfake.PagerResponder[${clientPkg}.${method.responseEnvelope.name}]`;
86
+ }
87
+ else {
88
+ serverResponse = `resp azfake.Responder[${clientPkg}.${method.responseEnvelope.name}], errResp azfake.ErrorResponder`;
89
+ }
90
+ const operationName = fixUpMethodName(method);
91
+ content += `\t// ${operationName} is the fake for method ${client.name}.${operationName}\n`;
92
+ const successCodes = new Array();
93
+ if (method.responseEnvelope.result && go.isAnyResult(method.responseEnvelope.result)) {
94
+ for (const httpStatus of values(method.httpStatusCodes)) {
95
+ const result = method.responseEnvelope.result.httpStatusCodeType[httpStatus];
96
+ if (!result) {
97
+ // the operation contains a mix of schemas and non-schema responses
98
+ successCodes.push(`${helpers.formatStatusCode(httpStatus)} (no return type)`);
99
+ continue;
100
+ }
101
+ successCodes.push(`${helpers.formatStatusCode(httpStatus)} (returns ${go.getTypeDeclaration(result, clientPkg)})`);
102
+ }
103
+ content += '\t// HTTP status codes to indicate success:\n';
104
+ for (const successCode of successCodes) {
105
+ content += `\t// - ${successCode}\n`;
106
+ }
107
+ }
108
+ else {
109
+ for (const statusCode of values(method.httpStatusCodes)) {
110
+ successCodes.push(`${helpers.formatStatusCode(statusCode)}`);
111
+ }
112
+ content += `\t// HTTP status codes to indicate success: ${successCodes.join(', ')}\n`;
113
+ }
114
+ content += `\t${operationName} func(${getAPIParametersSig(method, imports, clientPkg)}) (${serverResponse})\n\n`;
115
+ finalMethods.push(method);
116
+ if (go.isLROMethod(method)) {
117
+ ++countLROs;
118
+ }
119
+ else if (go.isPageableMethod(method)) {
120
+ ++countPagers;
121
+ }
122
+ }
123
+ content += '}\n\n';
124
+ ///////////////////////////////////////////////////////////////////////////
125
+ const serverTransport = `${serverName}Transport`;
126
+ content += `// New${serverTransport} creates a new instance of ${serverTransport} with the provided implementation.\n`;
127
+ content += `// The returned ${serverTransport} instance is connected to an instance of ${clientPkg}.${client.name} via the\n`;
128
+ content += '// azcore.ClientOptions.Transporter field in the client\'s constructor parameters.\n';
129
+ content += `func New${serverTransport}(srv *${serverName}) *${serverTransport} {\n`;
130
+ if (countLROs === 0 && countPagers === 0) {
131
+ content += `\treturn &${serverTransport}{srv: srv}\n}\n\n`;
132
+ }
133
+ else {
134
+ content += `\treturn &${serverTransport}{\n\t\tsrv: srv,\n`;
135
+ for (const method of values(finalMethods)) {
136
+ let respType = `${clientPkg}.${method.responseEnvelope.name}`;
137
+ if (go.isLROMethod(method)) {
138
+ if (go.isPageableMethod(method)) {
139
+ respType = `azfake.PagerResponder[${clientPkg}.${method.responseEnvelope.name}]`;
140
+ }
141
+ requiredHelpers.tracker = true;
142
+ content += `\t\t${uncapitalize(fixUpMethodName(method))}: newTracker[azfake.PollerResponder[${respType}]](),\n`;
143
+ }
144
+ else if (go.isPageableMethod(method)) {
145
+ requiredHelpers.tracker = true;
146
+ content += `\t\t${uncapitalize(fixUpMethodName(method))}: newTracker[azfake.PagerResponder[${respType}]](),\n`;
147
+ }
148
+ }
149
+ content += '\t}\n}\n\n';
150
+ }
151
+ content += `// ${serverTransport} connects instances of ${clientPkg}.${client.name} to instances of ${serverName}.\n`;
152
+ content += `// Don't use this type directly, use New${serverTransport} instead.\n`;
153
+ content += `type ${serverTransport} struct {\n`;
154
+ content += `\tsrv *${serverName}\n`;
155
+ // add server transports for client accessors
156
+ if (finalSubClients.length > 0) {
157
+ requiredHelpers.initServer = true;
158
+ imports.add('sync');
159
+ content += '\ttrMu sync.Mutex\n';
160
+ for (const subClient of finalSubClients) {
161
+ const serverName = getServerName(subClient);
162
+ content += `\ttr${serverName} *${serverName}Transport\n`;
163
+ }
164
+ }
165
+ for (const method of values(finalMethods)) {
166
+ // create state machines for any pager/poller operations
167
+ let respType = `${clientPkg}.${method.responseEnvelope.name}`;
168
+ if (go.isLROMethod(method)) {
169
+ if (go.isPageableMethod(method)) {
170
+ respType = `azfake.PagerResponder[${clientPkg}.${method.responseEnvelope.name}]`;
171
+ }
172
+ requiredHelpers.tracker = true;
173
+ content += `\t${uncapitalize(fixUpMethodName(method))} *tracker[azfake.PollerResponder[${respType}]]\n`;
174
+ }
175
+ else if (go.isPageableMethod(method)) {
176
+ requiredHelpers.tracker = true;
177
+ content += `\t${uncapitalize(fixUpMethodName(method))} *tracker[azfake.PagerResponder[${clientPkg}.${method.responseEnvelope.name}]]\n`;
178
+ }
179
+ }
180
+ content += '}\n\n';
181
+ content += generateServerTransportDo(serverTransport, client, finalSubClients, finalMethods);
182
+ content += generateServerTransportClientDispatch(serverTransport, finalSubClients, imports);
183
+ content += generateServerTransportMethodDispatch(serverTransport, client, finalMethods);
184
+ content += generateServerTransportMethods(codeModel, serverTransport, finalMethods, imports);
185
+ ///////////////////////////////////////////////////////////////////////////
186
+ // stitch everything together
187
+ let text = helpers.contentPreamble(codeModel, 'fake');
188
+ text += imports.text();
189
+ text += content;
190
+ operations.push(new OperationGroupContent(serverName, text));
191
+ }
192
+ return new ServerContent(operations, generateServerInternal(codeModel, requiredHelpers));
193
+ }
194
+ // method names for fakes dispatching
195
+ const dispatchMethodFake = 'dispatchToMethodFake';
196
+ const dispatchToClientFake = 'dispatchToClientFake';
197
+ function generateServerTransportDo(serverTransport, client, finalSubClients, finalMethods) {
198
+ const receiverName = serverTransport[0].toLowerCase();
199
+ let content = `// Do implements the policy.Transporter interface for ${serverTransport}.\n`;
200
+ content += `func (${receiverName} *${serverTransport}) Do(req *http.Request) (*http.Response, error) {\n`;
201
+ content += '\trawMethod := req.Context().Value(runtime.CtxAPINameKey{})\n';
202
+ content += '\tmethod, ok := rawMethod.(string)\n';
203
+ content += '\tif !ok {\n\t\treturn nil, nonRetriableError{errors.New("unable to dispatch request, missing value for CtxAPINameKey")}\n\t}\n\n';
204
+ if (finalSubClients.length > 0 && finalMethods.length > 0) {
205
+ // client contains client accessors and methods.
206
+ // if the method isn't for this client, dispatch to the correct client
207
+ content += `\tif client := method[:strings.Index(method, ".")]; client != "${client.name}" {\n`;
208
+ content += `\t\treturn ${receiverName}.${dispatchToClientFake}(req, client)\n\t}\n`;
209
+ // else dispatch to our method fakes
210
+ content += `\treturn ${receiverName}.${dispatchMethodFake}(req, method)\n`;
211
+ }
212
+ else if (finalSubClients.length > 0) {
213
+ content += `\treturn ${receiverName}.${dispatchToClientFake}(req, method[:strings.Index(method, ".")])\n`;
214
+ }
215
+ else {
216
+ content += `\treturn ${receiverName}.${dispatchMethodFake}(req, method)\n`;
217
+ }
218
+ content += '}\n\n'; // end Do
219
+ return content;
220
+ }
221
+ function generateServerTransportClientDispatch(serverTransport, subClients, imports) {
222
+ if (subClients.length === 0) {
223
+ return '';
224
+ }
225
+ const receiverName = serverTransport[0].toLowerCase();
226
+ imports.add('strings');
227
+ let content = `func (${receiverName} *${serverTransport}) ${dispatchToClientFake}(req *http.Request, client string) (*http.Response, error) {\n`;
228
+ content += '\tvar resp *http.Response\n\tvar err error\n\n';
229
+ content += '\tswitch client {\n';
230
+ for (const subClient of subClients) {
231
+ content += `\tcase "${subClient.name}":\n`;
232
+ const serverName = getServerName(subClient);
233
+ content += `\t\tinitServer(&${receiverName}.trMu, &${receiverName}.tr${serverName}, func() *${serverName}Transport {\n\t\treturn New${serverName}Transport(&${receiverName}.srv.${serverName}) })\n`;
234
+ content += `\t\tresp, err = ${receiverName}.tr${serverName}.Do(req)\n`;
235
+ }
236
+ content += '\tdefault:\n\t\terr = fmt.Errorf("unhandled client %s", client)\n';
237
+ content += '\t}\n\n'; // end switch
238
+ content += '\treturn resp, err\n}\n\n';
239
+ return content;
240
+ }
241
+ function generateServerTransportMethodDispatch(serverTransport, client, finalMethods) {
242
+ if (finalMethods.length === 0) {
243
+ return '';
244
+ }
245
+ const receiverName = serverTransport[0].toLowerCase();
246
+ let content = `func (${receiverName} *${serverTransport}) ${dispatchMethodFake}(req *http.Request, method string) (*http.Response, error) {\n`;
247
+ content += '\tvar resp *http.Response\n';
248
+ content += '\tvar err error\n\n';
249
+ content += '\tswitch method {\n';
250
+ for (const method of values(finalMethods)) {
251
+ const operationName = fixUpMethodName(method);
252
+ content += `\tcase "${client.name}.${operationName}":\n`;
253
+ content += `\t\tresp, err = ${receiverName}.dispatch${operationName}(req)\n`;
254
+ }
255
+ content += '\tdefault:\n\t\terr = fmt.Errorf("unhandled API %s", method)\n';
256
+ content += '\t}\n\n'; // end switch
257
+ content += '\treturn resp, err\n}\n\n';
258
+ return content;
259
+ }
260
+ function generateServerTransportMethods(codeModel, serverTransport, finalMethods, imports) {
261
+ if (finalMethods.length === 0) {
262
+ return '';
263
+ }
264
+ imports.add(helpers.getParentImport(codeModel));
265
+ imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/fake', 'azfake');
266
+ imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/fake/server');
267
+ const receiverName = serverTransport[0].toLowerCase();
268
+ let content = '';
269
+ for (const method of values(finalMethods)) {
270
+ content += `func (${receiverName} *${serverTransport}) dispatch${fixUpMethodName(method)}(req *http.Request) (*http.Response, error) {\n`;
271
+ content += `\tif ${receiverName}.srv.${fixUpMethodName(method)} == nil {\n`;
272
+ content += `\t\treturn nil, &nonRetriableError{errors.New("fake for method ${fixUpMethodName(method)} not implemented")}\n\t}\n`;
273
+ if (go.isLROMethod(method)) {
274
+ // must check LRO before pager as you can have paged LROs
275
+ content += dispatchForLROBody(codeModel.packageName, receiverName, method, imports);
276
+ }
277
+ else if (go.isPageableMethod(method)) {
278
+ content += dispatchForPagerBody(codeModel.packageName, receiverName, method, imports);
279
+ }
280
+ else {
281
+ content += dispatchForOperationBody(codeModel.packageName, receiverName, method, imports);
282
+ content += '\trespContent := server.GetResponseContent(respr)\n';
283
+ const formattedStatusCodes = helpers.formatStatusCodes(method.httpStatusCodes);
284
+ content += `\tif !contains([]int{${formattedStatusCodes}}, respContent.HTTPStatus) {\n`;
285
+ content += `\t\treturn nil, &nonRetriableError{fmt.Errorf("unexpected status code %d. acceptable values are ${formattedStatusCodes}", respContent.HTTPStatus)}\n\t}\n`;
286
+ if (!method.responseEnvelope.result || go.isHeadAsBooleanResult(method.responseEnvelope.result)) {
287
+ content += '\tresp, err := server.NewResponse(respContent, req, nil)\n';
288
+ }
289
+ else if (go.isAnyResult(method.responseEnvelope.result)) {
290
+ content += `\tresp, err := server.MarshalResponseAs${method.responseEnvelope.result.format}(respContent, server.GetResponse(respr).${getResultFieldName(method.responseEnvelope.result)}, req)\n`;
291
+ }
292
+ else if (go.isBinaryResult(method.responseEnvelope.result)) {
293
+ content += '\tresp, err := server.NewResponse(respContent, req, &server.ResponseOptions{\n';
294
+ content += `\t\tBody: server.GetResponse(respr).${getResultFieldName(method.responseEnvelope.result)},\n`;
295
+ content += '\t\tContentType: req.Header.Get("Content-Type"),\n';
296
+ content += '\t})\n';
297
+ }
298
+ else if (go.isMonomorphicResult(method.responseEnvelope.result)) {
299
+ if (go.isBytesType(method.responseEnvelope.result.monomorphicType)) {
300
+ const encoding = method.responseEnvelope.result.monomorphicType.encoding;
301
+ content += `\tresp, err := server.MarshalResponseAsByteArray(respContent, server.GetResponse(respr).${getResultFieldName(method.responseEnvelope.result)}, runtime.Base64${encoding}Format, req)\n`;
302
+ }
303
+ else if (go.isSliceType(method.responseEnvelope.result.monomorphicType) && method.responseEnvelope.result.monomorphicType.rawJSONAsBytes) {
304
+ imports.add('bytes');
305
+ imports.add('io');
306
+ content += '\tresp, err := server.NewResponse(respContent, req, &server.ResponseOptions{\n';
307
+ content += '\t\tBody: io.NopCloser(bytes.NewReader(server.GetResponse(respr).RawJSON)),\n';
308
+ content += '\t\tContentType: "application/json",\n\t})\n';
309
+ }
310
+ else {
311
+ let respField = `.${getResultFieldName(method.responseEnvelope.result)}`;
312
+ if (method.responseEnvelope.result.format === 'XML' && go.isSliceType(method.responseEnvelope.result.monomorphicType)) {
313
+ // for XML array responses we use the response type directly as it has the necessary XML tag for proper marshalling
314
+ respField = '';
315
+ }
316
+ let responseField = `server.GetResponse(respr)${respField}`;
317
+ if (go.isTimeType(method.responseEnvelope.result.monomorphicType)) {
318
+ responseField = `(*${method.responseEnvelope.result.monomorphicType.dateTimeFormat})(${responseField})`;
319
+ }
320
+ content += `\tresp, err := server.MarshalResponseAs${method.responseEnvelope.result.format}(respContent, ${responseField}, req)\n`;
321
+ }
322
+ }
323
+ else if (go.isModelResult(method.responseEnvelope.result) || go.isPolymorphicResult(method.responseEnvelope.result)) {
324
+ const respField = `.${getResultFieldName(method.responseEnvelope.result)}`;
325
+ const responseField = `server.GetResponse(respr)${respField}`;
326
+ content += `\tresp, err := server.MarshalResponseAs${method.responseEnvelope.result.format}(respContent, ${responseField}, req)\n`;
327
+ }
328
+ content += '\tif err != nil {\n\t\treturn nil, err\n\t}\n';
329
+ // propagate any header response values into the *http.Response
330
+ for (const header of values(method.responseEnvelope.headers)) {
331
+ if (go.isHeaderMapResponse(header)) {
332
+ content += `\tfor k, v := range server.GetResponse(respr).${header.fieldName} {\n`;
333
+ content += '\t\tif v != nil {\n';
334
+ content += `\t\t\tresp.Header.Set("${header.collectionPrefix}"+k, *v)\n`;
335
+ content += '\t\t}\n';
336
+ content += '\t}\n';
337
+ }
338
+ else {
339
+ content += `\tif val := server.GetResponse(respr).${header.fieldName}; val != nil {\n`;
340
+ content += `\t\tresp.Header.Set("${header.headerName}", ${helpers.formatValue('val', header.type, imports, true)})\n\t}\n`;
341
+ }
342
+ }
343
+ content += '\treturn resp, nil\n';
344
+ }
345
+ content += '}\n\n';
346
+ }
347
+ return content;
348
+ }
349
+ function dispatchForOperationBody(clientPkg, receiverName, method, imports) {
350
+ const numPathParams = values(method.parameters).where((each) => { return go.isPathParameter(each) && !go.isLiteralParameter(each); }).count();
351
+ let content = '';
352
+ if (numPathParams > 0) {
353
+ imports.add('regexp');
354
+ content += `\tconst regexStr = \`${createPathParamsRegex(method)}\`\n`;
355
+ content += '\tregex := regexp.MustCompile(regexStr)\n';
356
+ content += '\tmatches := regex.FindStringSubmatch(req.URL.EscapedPath())\n';
357
+ content += `\tif matches == nil || len(matches) < ${numPathParams} {\n`;
358
+ content += '\t\treturn nil, fmt.Errorf("failed to parse path %s", req.URL.Path)\n\t}\n';
359
+ }
360
+ if (values(method.parameters).where((each) => { return go.isQueryParameter(each) && each.location === 'method' && !go.isLiteralParameter(each); }).any()) {
361
+ content += '\tqp := req.URL.Query()\n';
362
+ }
363
+ const bodyParam = values(method.parameters).where((each) => {
364
+ return go.isBodyParameter(each) || go.isFormBodyParameter(each) || go.isMultipartFormBodyParameter(each) || go.isPartialBodyParameter(each);
365
+ }).first();
366
+ if (!bodyParam) {
367
+ // no body, just headers and/or query params
368
+ }
369
+ else if (go.isMultipartFormBodyParameter(bodyParam)) {
370
+ imports.add('io');
371
+ imports.add('mime');
372
+ imports.add('mime/multipart');
373
+ content += '\t_, params, err := mime.ParseMediaType(req.Header.Get("Content-Type"))\n';
374
+ content += '\tif err != nil {\n\t\treturn nil, err\n\t}\n';
375
+ content += '\treader := multipart.NewReader(req.Body, params["boundary"])\n';
376
+ for (const param of values(method.parameters)) {
377
+ if (go.isMultipartFormBodyParameter(param)) {
378
+ let pkgPrefix = '';
379
+ if (go.isConstantType(param.type) || go.isModelType(param.type)) {
380
+ pkgPrefix = clientPkg + '.';
381
+ }
382
+ content += `\tvar ${param.name} ${pkgPrefix}${go.getTypeDeclaration(param.type)}\n`;
383
+ }
384
+ }
385
+ content += '\tfor {\n';
386
+ content += '\t\tvar part *multipart.Part\n';
387
+ content += '\t\tpart, err = reader.NextPart()\n';
388
+ content += '\t\tif errors.Is(err, io.EOF) {\n\t\t\tbreak\n';
389
+ content += '\t\t} else if err != nil {\n\t\t\treturn nil, err\n\t\t}\n';
390
+ content += '\t\tvar content []byte\n';
391
+ content += '\t\tswitch fn := part.FormName(); fn {\n';
392
+ // specify boolTarget if parsing bools happens in place.
393
+ // in this case, the err check is omitted and assumed to happen elsewhere.
394
+ // the parsed value is in a local var named parsed.
395
+ const parsePrimitiveType = function (typeName, boolTarget) {
396
+ const parseResults = 'parsed, parseErr';
397
+ let parsingCode = '';
398
+ imports.add('strconv');
399
+ switch (typeName) {
400
+ case 'bool':
401
+ if (boolTarget) {
402
+ parsingCode = `\t\t\t${boolTarget} = strconv.ParseBool(string(content))\n`;
403
+ }
404
+ else {
405
+ parsingCode = `\t\t\t${parseResults} := strconv.ParseBool(string(content))\n`;
406
+ }
407
+ break;
408
+ case 'float32':
409
+ case 'float64':
410
+ parsingCode = `\t\t\t${parseResults} := strconv.ParseFloat(string(content), ${helpers.getBitSizeForNumber(typeName)})\n`;
411
+ break;
412
+ case 'int8':
413
+ case 'int16':
414
+ case 'int32':
415
+ case 'int64':
416
+ parsingCode = `\t\t\t${parseResults} := strconv.ParseInt(string(content), 10, ${helpers.getBitSizeForNumber(typeName)})\n`;
417
+ break;
418
+ default:
419
+ throw new Error(`unhandled multipart parameter primitive type ${typeName}`);
420
+ }
421
+ if (!boolTarget) {
422
+ parsingCode += '\t\t\tif parseErr != nil {\n\t\t\t\treturn nil, parseErr\n\t\t\t}\n';
423
+ }
424
+ return parsingCode;
425
+ };
426
+ const isMultipartContentType = function (type) {
427
+ type = helpers.recursiveUnwrapMapSlice(type);
428
+ return (go.isQualifiedType(type) && type.exportName === 'MultipartContent');
429
+ };
430
+ const emitCase = function (caseValue, paramVar, type) {
431
+ let caseContent = `\t\tcase "${caseValue}":\n`;
432
+ caseContent += '\t\t\tcontent, err = io.ReadAll(part)\n';
433
+ caseContent += '\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n';
434
+ let assignedValue;
435
+ if (go.isModelType(helpers.recursiveUnwrapMapSlice(type))) {
436
+ imports.add('encoding/json');
437
+ caseContent += `\t\t\tif err = json.Unmarshal(content, &${paramVar}); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n`;
438
+ }
439
+ else if (go.isQualifiedType(type) && type.exportName === 'ReadSeekCloser') {
440
+ imports.add('bytes');
441
+ imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming');
442
+ assignedValue = 'streaming.NopCloser(bytes.NewReader(content))';
443
+ }
444
+ else if (go.isConstantType(type)) {
445
+ let from;
446
+ switch (type.type) {
447
+ case 'bool':
448
+ case 'float32':
449
+ case 'float64':
450
+ case 'int32':
451
+ case 'int64':
452
+ caseContent += parsePrimitiveType(type.type);
453
+ from = 'parsed';
454
+ break;
455
+ case 'string':
456
+ from = 'content';
457
+ break;
458
+ }
459
+ assignedValue = `${clientPkg}.${type.name}(${from})`;
460
+ }
461
+ else if (go.isPrimitiveType(type)) {
462
+ switch (type.typeName) {
463
+ case 'bool':
464
+ imports.add('strconv');
465
+ // ParseBool happens in place, so no need to set assignedValue
466
+ caseContent += parsePrimitiveType(type.typeName, `${paramVar}, err`);
467
+ break;
468
+ case 'float32':
469
+ case 'float64':
470
+ case 'int8':
471
+ case 'int16':
472
+ case 'int32':
473
+ case 'int64':
474
+ caseContent += parsePrimitiveType(type.typeName);
475
+ assignedValue = `${type.typeName}(parsed)`;
476
+ break;
477
+ case 'string':
478
+ assignedValue = 'string(content)';
479
+ break;
480
+ default:
481
+ throw new Error(`unhandled multipart parameter primitive type ${type.typeName}`);
482
+ }
483
+ }
484
+ else if (isMultipartContentType(type)) {
485
+ imports.add('bytes');
486
+ imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming');
487
+ const bodyContent = 'streaming.NopCloser(bytes.NewReader(content))';
488
+ const contentType = 'part.Header.Get("Content-Type")';
489
+ const filename = 'part.FileName()';
490
+ if (go.isSliceType(type)) {
491
+ caseContent += `\t\t\t${paramVar} = append(${paramVar}, streaming.MultipartContent{\n`;
492
+ caseContent += `\t\t\t\tBody: ${bodyContent},\n`;
493
+ caseContent += `\t\t\t\tContentType: ${contentType},\n`;
494
+ caseContent += `\t\t\t\tFilename: ${filename},\n`;
495
+ caseContent += '\t\t\t})\n';
496
+ }
497
+ else {
498
+ caseContent += `\t\t\t${paramVar}.Body = ${bodyContent}\n`;
499
+ caseContent += `\t\t\t${paramVar}.ContentType = ${contentType}\n`;
500
+ caseContent += `\t\t\t${paramVar}.Filename = ${filename}\n`;
501
+ }
502
+ }
503
+ else if (go.isSliceType(type)) {
504
+ if (go.isQualifiedType(type.elementType) && type.elementType.exportName === 'ReadSeekCloser') {
505
+ imports.add('bytes');
506
+ imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming');
507
+ assignedValue = `append(${paramVar}, streaming.NopCloser(bytes.NewReader(content)))`;
508
+ }
509
+ else {
510
+ throw new Error(`uhandled multipart parameter array element type ${go.getTypeDeclaration(type.elementType)}`);
511
+ }
512
+ }
513
+ else {
514
+ throw new Error(`uhandled multipart parameter type ${go.getTypeDeclaration(type)}`);
515
+ }
516
+ if (assignedValue) {
517
+ caseContent += `\t\t\t${paramVar} = ${assignedValue}\n`;
518
+ }
519
+ return caseContent;
520
+ };
521
+ for (const param of values(method.parameters)) {
522
+ if (go.isMultipartFormBodyParameter(param)) {
523
+ if (go.isModelType(param.type)) {
524
+ for (const field of param.type.fields) {
525
+ content += emitCase(field.serializedName, `${param.name}.${field.name}`, field.type);
526
+ }
527
+ }
528
+ else {
529
+ content += emitCase(param.name, param.name, param.type);
530
+ }
531
+ }
532
+ }
533
+ content += '\t\tdefault:\n\t\t\treturn nil, fmt.Errorf("unexpected part %s", fn)\n';
534
+ content += '\t\t}\n'; // end switch
535
+ content += '\t}\n'; // end for
536
+ }
537
+ else if (go.isFormBodyParameter(bodyParam)) {
538
+ for (const param of values(method.parameters)) {
539
+ if (go.isFormBodyParameter(param)) {
540
+ let pkgPrefix = '';
541
+ if (go.isConstantType(param.type)) {
542
+ pkgPrefix = clientPkg + '.';
543
+ }
544
+ content += `\tvar ${param.name} ${pkgPrefix}${go.getTypeDeclaration(param.type)}\n`;
545
+ }
546
+ }
547
+ content += '\tif err := req.ParseForm(); err != nil {\n\t\treturn nil, &nonRetriableError{fmt.Errorf("failed parsing form data: %v", err)}\n\t}\n';
548
+ content += '\tfor key := range req.Form {\n';
549
+ content += '\t\tswitch key {\n';
550
+ for (const param of values(method.parameters)) {
551
+ if (go.isFormBodyParameter(param)) {
552
+ content += `\t\tcase "${param.formDataName}":\n`;
553
+ let assignedValue;
554
+ if (go.isConstantType(param.type)) {
555
+ assignedValue = `${go.getTypeDeclaration(param.type, clientPkg)}(req.FormValue(key))`;
556
+ }
557
+ else if (go.isPrimitiveType(param.type) && param.type.typeName === 'string') {
558
+ assignedValue = 'req.FormValue(key)';
559
+ }
560
+ else {
561
+ throw new Error(`uhandled form parameter type ${go.getTypeDeclaration(param.type)}`);
562
+ }
563
+ content += `\t\t\t${param.name} = ${assignedValue}\n`;
564
+ }
565
+ }
566
+ content += '\t\t}\n'; // end switch
567
+ content += '\t}\n'; // end for
568
+ }
569
+ else if (bodyParam.bodyFormat === 'binary') {
570
+ // nothing to do for binary media type
571
+ }
572
+ else if (bodyParam.bodyFormat === 'Text') {
573
+ if (bodyParam && !go.isLiteralParameter(bodyParam)) {
574
+ imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/fake', 'azfake');
575
+ content += '\tbody, err := server.UnmarshalRequestAsText(req)\n';
576
+ content += '\tif err != nil {\n\t\treturn nil, err\n\t}\n';
577
+ }
578
+ }
579
+ else if (bodyParam.bodyFormat === 'JSON' || bodyParam.bodyFormat === 'XML') {
580
+ if (bodyParam && !go.isLiteralParameter(bodyParam)) {
581
+ imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/fake', 'azfake');
582
+ if (go.isBytesType(bodyParam.type)) {
583
+ content += `\tbody, err := server.UnmarshalRequestAsByteArray(req, runtime.Base64${bodyParam.type.encoding}Format)\n`;
584
+ content += '\tif err != nil {\n\t\treturn nil, err\n\t}\n';
585
+ }
586
+ else if (go.isSliceType(bodyParam.type) && bodyParam.type.rawJSONAsBytes) {
587
+ content += '\tbody, err := io.ReadAll(req.Body)\n';
588
+ content += '\tif err != nil {\n\t\treturn nil, err\n\t}\n';
589
+ content += '\treq.Body.Close()\n';
590
+ }
591
+ else if (go.isInterfaceType(bodyParam.type)) {
592
+ requiredHelpers.readRequestBody = true;
593
+ content += '\traw, err := readRequestBody(req)\n';
594
+ content += '\tif err != nil {\n\t\treturn nil, err\n\t}\n';
595
+ content += `\tbody, err := unmarshal${bodyParam.type.name}(raw)\n`;
596
+ content += '\tif err != nil {\n\t\treturn nil, err\n\t}\n';
597
+ }
598
+ else {
599
+ let bodyTypeName = go.getTypeDeclaration(bodyParam.type, clientPkg);
600
+ if (go.isTimeType(bodyParam.type)) {
601
+ bodyTypeName = bodyParam.type.dateTimeFormat;
602
+ }
603
+ content += `\tbody, err := server.UnmarshalRequestAs${bodyParam.bodyFormat}[${bodyTypeName}](req)\n`;
604
+ content += '\tif err != nil {\n\t\treturn nil, err\n\t}\n';
605
+ }
606
+ }
607
+ }
608
+ const partialBodyParams = values(method.parameters).where((param) => { return go.isPartialBodyParameter(param); }).toArray();
609
+ if (partialBodyParams.length > 0) {
610
+ // construct the partial body params type and unmarshal it
611
+ content += '\ttype partialBodyParams struct {\n';
612
+ for (const partialBodyParam of partialBodyParams) {
613
+ content += `\t\t${capitalize(partialBodyParam.name)} ${helpers.star(partialBodyParam)}${go.getTypeDeclaration(partialBodyParam.type)} \`json:"${partialBodyParam.serializedName}"\`\n`;
614
+ }
615
+ content += '\t}\n';
616
+ content += `\tbody, err := server.UnmarshalRequestAs${partialBodyParams[0].format}[partialBodyParams](req)\n`;
617
+ content += '\tif err != nil {\n\t\treturn nil, err\n\t}\n';
618
+ }
619
+ const result = parseHeaderPathQueryParams(clientPkg, method, imports);
620
+ content += result.content;
621
+ // translate each partial body param to its field within the unmarshalled body
622
+ for (const partialBodyParam of partialBodyParams) {
623
+ result.params.set(partialBodyParam.name, `${helpers.star(partialBodyParam)}body.${capitalize(partialBodyParam.name)}`);
624
+ }
625
+ const apiCall = `:= ${receiverName}.srv.${fixUpMethodName(method)}(${populateApiParams(clientPkg, method, result.params, imports)})`;
626
+ if (go.isPageableMethod(method) && !go.isLROMethod(method)) {
627
+ content += `resp ${apiCall}\n`;
628
+ return content;
629
+ }
630
+ content += `\trespr, errRespr ${apiCall}\n`;
631
+ content += '\tif respErr := server.GetError(errRespr, req); respErr != nil {\n';
632
+ content += '\t\treturn nil, respErr\n\t}\n';
633
+ return content;
634
+ }
635
+ function dispatchForLROBody(clientPkg, receiverName, method, imports) {
636
+ const operationName = fixUpMethodName(method);
637
+ const localVarName = uncapitalize(operationName);
638
+ const operationStateMachine = `${receiverName}.${uncapitalize(operationName)}`;
639
+ let content = `\t${localVarName} := ${operationStateMachine}.get(req)\n`;
640
+ content += `\tif ${localVarName} == nil {\n`;
641
+ content += dispatchForOperationBody(clientPkg, receiverName, method, imports);
642
+ content += `\t\t${localVarName} = &respr\n`;
643
+ content += `\t\t${operationStateMachine}.add(req, ${localVarName})\n`;
644
+ content += '\t}\n\n';
645
+ content += `\tresp, err := server.PollerResponderNext(${localVarName}, req)\n`;
646
+ content += '\tif err != nil {\n\t\treturn nil, err\n\t}\n\n';
647
+ const formattedStatusCodes = helpers.formatStatusCodes(method.httpStatusCodes);
648
+ content += `\tif !contains([]int{${formattedStatusCodes}}, resp.StatusCode) {\n`;
649
+ content += `\t\t${operationStateMachine}.remove(req)\n`;
650
+ content += `\t\treturn nil, &nonRetriableError{fmt.Errorf("unexpected status code %d. acceptable values are ${formattedStatusCodes}", resp.StatusCode)}\n\t}\n`;
651
+ content += `\tif !server.PollerResponderMore(${localVarName}) {\n`;
652
+ content += `\t\t${operationStateMachine}.remove(req)\n\t}\n\n`;
653
+ content += '\treturn resp, nil\n';
654
+ return content;
655
+ }
656
+ function dispatchForPagerBody(clientPkg, receiverName, method, imports) {
657
+ const operationName = fixUpMethodName(method);
658
+ const localVarName = uncapitalize(operationName);
659
+ const operationStateMachine = `${receiverName}.${uncapitalize(operationName)}`;
660
+ let content = `\t${localVarName} := ${operationStateMachine}.get(req)\n`;
661
+ content += `\tif ${localVarName} == nil {\n`;
662
+ content += dispatchForOperationBody(clientPkg, receiverName, method, imports);
663
+ content += `\t\t${localVarName} = &resp\n`;
664
+ content += `\t\t${operationStateMachine}.add(req, ${localVarName})\n`;
665
+ if (method.nextLinkName) {
666
+ imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/to');
667
+ content += `\t\tserver.PagerResponderInjectNextLinks(${localVarName}, req, func(page *${clientPkg}.${method.responseEnvelope.name}, createLink func() string) {\n`;
668
+ content += `\t\t\tpage.${method.nextLinkName} = to.Ptr(createLink())\n`;
669
+ content += '\t\t})\n';
670
+ }
671
+ content += '\t}\n'; // end if
672
+ content += `\tresp, err := server.PagerResponderNext(${localVarName}, req)\n`;
673
+ content += '\tif err != nil {\n\t\treturn nil, err\n\t}\n';
674
+ const formattedStatusCodes = helpers.formatStatusCodes(method.httpStatusCodes);
675
+ content += `\tif !contains([]int{${formattedStatusCodes}}, resp.StatusCode) {\n`;
676
+ content += `\t\t${operationStateMachine}.remove(req)\n`;
677
+ content += `\t\treturn nil, &nonRetriableError{fmt.Errorf("unexpected status code %d. acceptable values are ${formattedStatusCodes}", resp.StatusCode)}\n\t}\n`;
678
+ content += `\tif !server.PagerResponderMore(${localVarName}) {\n`;
679
+ content += `\t\t${operationStateMachine}.remove(req)\n\t}\n`;
680
+ content += '\treturn resp, nil\n';
681
+ return content;
682
+ }
683
+ function sanitizeRegexpCaptureGroupName(name) {
684
+ // dash '-' characters are not allowed so replace them with '_'
685
+ return name.replace('-', '_');
686
+ }
687
+ function createPathParamsRegex(method) {
688
+ // "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{parentResourcePath}/{resourceType}/{resourceName}"
689
+ // each path param will replaced with a regex capture.
690
+ // note that some path params are optional.
691
+ let urlPath = method.httpPath;
692
+ // escape any characters in the path that could be interpreted as regex tokens
693
+ // per RFC3986, these are the pchars that also double as regex tokens
694
+ // . $ * + ()
695
+ urlPath = urlPath.replace(/([.$*+()])/g, '\\$1');
696
+ for (const param of values(method.parameters)) {
697
+ if (!go.isPathParameter(param)) {
698
+ continue;
699
+ }
700
+ const toReplace = `{${param.pathSegment}}`;
701
+ let replaceWith = `(?P<${sanitizeRegexpCaptureGroupName(param.pathSegment)}>[!#&$-;=?-\\[\\]_a-zA-Z0-9~%@]+)`;
702
+ if (param.kind === 'optional' || param.kind === 'flag') {
703
+ replaceWith += '?';
704
+ }
705
+ urlPath = urlPath.replace(toReplace, replaceWith);
706
+ }
707
+ return urlPath;
708
+ }
709
+ // parses header/path/query params as required.
710
+ // returns the parsing code and the params that contain the parsed values.
711
+ function parseHeaderPathQueryParams(clientPkg, method, imports) {
712
+ let content = '';
713
+ const paramValues = new Map();
714
+ const createLocalVariableName = function (param, suffix) {
715
+ const paramName = `${uncapitalize(param.name)}${suffix}`;
716
+ paramValues.set(param.name, paramName);
717
+ return paramName;
718
+ };
719
+ const emitNumericConversion = function (src, type) {
720
+ imports.add('strconv');
721
+ let precision = '32';
722
+ if (type === 'float64' || type === 'int64') {
723
+ precision = '64';
724
+ }
725
+ let parseType = 'Int';
726
+ let base = '10, ';
727
+ if (type === 'float32' || type === 'float64') {
728
+ parseType = 'Float';
729
+ base = '';
730
+ }
731
+ return `strconv.Parse${parseType}(${src}, ${base}${precision})`;
732
+ };
733
+ // track the param groups that need to be instantiated/populated.
734
+ // we track the params separately as it might be a subset of ParameterGroup.params
735
+ const paramGroups = new Map();
736
+ for (const param of values(consolidateHostParams(method.parameters))) {
737
+ if (param.location === 'client' || go.isLiteralParameter(param)) {
738
+ // client params and parameter literals aren't passed to APIs
739
+ continue;
740
+ }
741
+ if (go.isResumeTokenParameter(param)) {
742
+ // skip the ResumeToken param as we don't send that back to the caller
743
+ continue;
744
+ }
745
+ // NOTE: param group check must happen before skipping body params.
746
+ // this is to handle the case where the body param is grouped/optional
747
+ if (param.group) {
748
+ if (!paramGroups.has(param.group)) {
749
+ paramGroups.set(param.group, new Array());
750
+ }
751
+ const params = paramGroups.get(param.group);
752
+ params.push(param);
753
+ }
754
+ if (go.isBodyParameter(param) || go.isFormBodyParameter(param) || go.isMultipartFormBodyParameter(param)) {
755
+ // body params will be unmarshalled, no need for parsing.
756
+ continue;
757
+ }
758
+ // paramValue is initialized with the "raw" source value.
759
+ // e.g. getHeaderValue(...), qp.Get("foo") etc
760
+ // since path/query params need to be unescaped, the value
761
+ // of paramValue will be updated with the var name that
762
+ // contains the unescaped value.
763
+ let paramValue = getRawParamValue(param);
764
+ // path/query params might be escaped, so we need to unescape them first.
765
+ // must handle query collections first as it's a superset of query param.
766
+ if (go.isQueryCollectionParameter(param) && param.collectionFormat === 'multi') {
767
+ imports.add('net/url');
768
+ const escapedParam = createLocalVariableName(param, 'Escaped');
769
+ content += `\t${escapedParam} := ${paramValue}\n`;
770
+ let paramVar = createLocalVariableName(param, 'Unescaped');
771
+ if (go.isPrimitiveType(param.type.elementType) && param.type.elementType.typeName === 'string') {
772
+ // by convention, if the value is in its "final form" (i.e. no parsing required)
773
+ // then its var is to have the "Param" suffix. the only case is string, everything
774
+ // else requires some amount of parsing/conversion.
775
+ paramVar = createLocalVariableName(param, 'Param');
776
+ }
777
+ content += `\t${paramVar} := make([]string, len(${escapedParam}))\n`;
778
+ content += `\tfor i, v := range ${escapedParam} {\n`;
779
+ content += '\t\tu, unescapeErr := url.QueryUnescape(v)\n';
780
+ content += '\t\tif unescapeErr != nil {\n\t\t\treturn nil, unescapeErr\n\t\t}\n';
781
+ content += `\t\t${paramVar}[i] = u\n\t}\n`;
782
+ paramValue = paramVar;
783
+ }
784
+ else if (go.isPathParameter(param) || go.isQueryParameter(param)) {
785
+ imports.add('net/url');
786
+ let where;
787
+ if (go.isPathParameter(param)) {
788
+ where = 'Path';
789
+ }
790
+ else {
791
+ where = 'Query';
792
+ }
793
+ let paramVar = createLocalVariableName(param, 'Unescaped');
794
+ if (go.isRequiredParameter(param) && go.isConstantType(param.type) && param.type.type === 'string') {
795
+ // for string-based enums, we perform the conversion as part of unescaping
796
+ requiredHelpers.parseWithCast = true;
797
+ paramVar = createLocalVariableName(param, 'Param');
798
+ content += `\t${paramVar}, err := parseWithCast(${paramValue}, func (v string) (${go.getTypeDeclaration(param.type, clientPkg)}, error) {\n`;
799
+ content += `\t\tp, unescapeErr := url.${where}Unescape(v)\n`;
800
+ content += '\t\tif unescapeErr != nil {\n\t\t\treturn "", unescapeErr\n\t\t}\n';
801
+ content += `\t\treturn ${go.getTypeDeclaration(param.type, clientPkg)}(p), nil\n\t})\n`;
802
+ }
803
+ else {
804
+ if (go.isRequiredParameter(param) &&
805
+ ((go.isPrimitiveType(param.type) && param.type.typeName === 'string') ||
806
+ (go.isSliceType(param.type) && go.isPrimitiveType(param.type.elementType) && param.type.elementType.typeName === 'string'))) {
807
+ // by convention, if the value is in its "final form" (i.e. no parsing required)
808
+ // then its var is to have the "Param" suffix. the only case is string, everything
809
+ // else requires some amount of parsing/conversion.
810
+ paramVar = createLocalVariableName(param, 'Param');
811
+ }
812
+ content += `\t${paramVar}, err := url.${where}Unescape(${paramValue})\n`;
813
+ }
814
+ content += '\tif err != nil {\n\t\treturn nil, err\n\t}\n';
815
+ paramValue = paramVar;
816
+ }
817
+ // parse params as required
818
+ if (go.isHeaderCollectionParameter(param) || go.isPathCollectionParameter(param) || go.isQueryCollectionParameter(param)) {
819
+ // any element type other than string will require some form of conversion/parsing
820
+ if (!(go.isPrimitiveType(param.type.elementType) && param.type.elementType.typeName === 'string')) {
821
+ if (param.collectionFormat !== 'multi') {
822
+ requiredHelpers.splitHelper = true;
823
+ const elementsParam = createLocalVariableName(param, 'Elements');
824
+ content += `\t${elementsParam} := splitHelper(${paramValue}, "${helpers.getDelimiterForCollectionFormat(param.collectionFormat)}")\n`;
825
+ paramValue = elementsParam;
826
+ }
827
+ const paramVar = createLocalVariableName(param, 'Param');
828
+ let elementFormat;
829
+ if (go.isConstantType(param.type.elementType)) {
830
+ elementFormat = param.type.elementType.type;
831
+ }
832
+ else if (go.isPrimitiveType(param.type.elementType)) {
833
+ elementFormat = param.type.elementType.typeName;
834
+ }
835
+ else if (go.isBytesType(param.type.elementType)) {
836
+ elementFormat = param.type.elementType.encoding;
837
+ }
838
+ else if (go.isTimeType(param.type.elementType)) {
839
+ elementFormat = param.type.elementType.dateTimeFormat;
840
+ }
841
+ else {
842
+ throw new Error(`unhandled element type ${go.getTypeDeclaration(param.type.elementType)}`);
843
+ }
844
+ let toType = go.getTypeDeclaration(param.type.elementType);
845
+ if (go.isConstantType(param.type.elementType)) {
846
+ toType = `${clientPkg}.${toType}`;
847
+ }
848
+ content += `\t${paramVar} := make([]${toType}, len(${paramValue}))\n`;
849
+ content += `\tfor i := 0; i < len(${paramValue}); i++ {\n`;
850
+ let fromVar;
851
+ // TODO: consolidate with non-collection parsing code
852
+ if (elementFormat === 'bool') {
853
+ imports.add('strconv');
854
+ fromVar = 'parsedBool';
855
+ content += `\t\t${fromVar}, parseErr := strconv.ParseBool(${paramValue}[i])\n`;
856
+ content += '\t\tif parseErr != nil {\n\t\t\treturn nil, parseErr\n\t\t}\n';
857
+ }
858
+ else if (elementFormat === 'float32' || elementFormat === 'float64' || elementFormat === 'int32' || elementFormat === 'int64') {
859
+ fromVar = `parsed${capitalize(elementFormat)}`;
860
+ content += `\t\t${fromVar}, parseErr := ${emitNumericConversion(`${paramValue}[i]`, elementFormat)}\n`;
861
+ content += '\t\tif parseErr != nil {\n\t\t\treturn nil, parseErr\n\t\t}\n';
862
+ }
863
+ else if (elementFormat === 'string') {
864
+ // we're casting an enum string value to its const type
865
+ // TODO: what about enums that aren't strings?
866
+ fromVar = `${paramValue}[i]`;
867
+ }
868
+ else if (elementFormat === 'Std' || elementFormat === 'URL') {
869
+ imports.add('encoding/base64');
870
+ fromVar = `parsed${capitalize(elementFormat)}`;
871
+ content += `\t\t${fromVar}, parseErr := base64.${elementFormat}Encoding.DecodeString(${paramValue}[i])\n`;
872
+ content += '\t\tif parseErr != nil {\n\t\t\treturn nil, parseErr\n\t\t}\n';
873
+ }
874
+ else if (elementFormat === 'dateTimeRFC1123' || elementFormat === 'dateTimeRFC3339' || elementFormat === 'timeUnix') {
875
+ imports.add('time');
876
+ fromVar = `parsed${capitalize(elementFormat)}`;
877
+ if (elementFormat === 'timeUnix') {
878
+ imports.add('strconv');
879
+ content += `\t\tp, parseErr := strconv.ParseInt(${paramValue}[i], 10, 64)\n`;
880
+ content += '\t\tif parseErr != nil {\n\t\t\treturn nil, parseErr\n\t\t}\n';
881
+ content += `\t\t${fromVar} := time.Unix(p, 0).UTC()\n`;
882
+ }
883
+ else {
884
+ let format = 'time.RFC3339Nano';
885
+ if (elementFormat === 'dateTimeRFC1123') {
886
+ format = 'time.RFC1123';
887
+ }
888
+ content += `\t\t${fromVar}, parseErr := time.Parse(${format}, ${paramValue}[i])\n`;
889
+ content += '\t\tif parseErr != nil {\n\t\t\treturn nil, parseErr\n\t\t}\n';
890
+ }
891
+ }
892
+ else {
893
+ throw new Error(`unhandled element format ${elementFormat}`);
894
+ }
895
+ // TODO: remove cast in some cases
896
+ content += `\t\t${paramVar}[i] = ${toType}(${fromVar})\n\t}\n`;
897
+ }
898
+ else if (!go.isRequiredParameter(param) && param.collectionFormat !== 'multi') {
899
+ // for slices of strings that are required, the call to splitHelper(...) is inlined into
900
+ // the invocation of the fake e.g. srv.FakeFunc(splitHelper...). but if it's optional, we
901
+ // need to create a local first which will later be copied into the optional param group.
902
+ requiredHelpers.splitHelper = true;
903
+ content += `\t${createLocalVariableName(param, 'Param')} := splitHelper(${paramValue}, "${helpers.getDelimiterForCollectionFormat(param.collectionFormat)}")\n`;
904
+ }
905
+ }
906
+ else if (go.isPrimitiveType(param.type) && param.type.typeName === 'bool') {
907
+ imports.add('strconv');
908
+ let from = `strconv.ParseBool(${paramValue})`;
909
+ if (!go.isRequiredParameter(param)) {
910
+ requiredHelpers.parseOptional = true;
911
+ from = `parseOptional(${paramValue}, strconv.ParseBool)`;
912
+ }
913
+ content += `\t${createLocalVariableName(param, 'Param')}, err := ${from}\n`;
914
+ content += '\tif err != nil {\n\t\treturn nil, err\n\t}\n';
915
+ }
916
+ else if (go.isBytesType(param.type)) {
917
+ imports.add('encoding/base64');
918
+ content += `\t${createLocalVariableName(param, 'Param')}, err := base64.${param.type.encoding}Encoding.DecodeString(${paramValue})\n`;
919
+ content += '\tif err != nil {\n\t\treturn nil, err\n\t}\n';
920
+ }
921
+ else if (go.isTimeType(param.type)) {
922
+ if (param.type.dateTimeFormat === 'dateType' || param.type.dateTimeFormat === 'timeRFC3339') {
923
+ imports.add('time');
924
+ let format = helpers.dateFormat;
925
+ if (param.type.dateTimeFormat === 'timeRFC3339') {
926
+ format = helpers.timeRFC3339Format;
927
+ }
928
+ let from = `time.Parse("${format}", ${paramValue})`;
929
+ if (!go.isRequiredParameter(param)) {
930
+ requiredHelpers.parseOptional = true;
931
+ from = `parseOptional(${paramValue}, func(v string) (time.Time, error) { return time.Parse("${format}", v) })`;
932
+ }
933
+ content += `\t${createLocalVariableName(param, 'Param')}, err := ${from}\n`;
934
+ content += '\tif err != nil {\n\t\treturn nil, err\n\t}\n';
935
+ }
936
+ else if (param.type.dateTimeFormat === 'dateTimeRFC1123' || param.type.dateTimeFormat === 'dateTimeRFC3339') {
937
+ imports.add('time');
938
+ let format = 'time.RFC3339Nano';
939
+ if (param.type.dateTimeFormat === 'dateTimeRFC1123') {
940
+ format = 'time.RFC1123';
941
+ }
942
+ let from = `time.Parse(${format}, ${paramValue})`;
943
+ if (!go.isRequiredParameter(param)) {
944
+ requiredHelpers.parseOptional = true;
945
+ from = `parseOptional(${paramValue}, func(v string) (time.Time, error) { return time.Parse(${format}, v) })`;
946
+ }
947
+ content += `\t${createLocalVariableName(param, 'Param')}, err := ${from}\n`;
948
+ content += '\tif err != nil {\n\t\treturn nil, err\n\t}\n';
949
+ }
950
+ else {
951
+ imports.add('strconv');
952
+ let parser;
953
+ if (!go.isRequiredParameter(param)) {
954
+ requiredHelpers.parseOptional = true;
955
+ parser = 'parseOptional';
956
+ }
957
+ else {
958
+ requiredHelpers.parseWithCast = true;
959
+ parser = 'parseWithCast';
960
+ }
961
+ content += `\t${createLocalVariableName(param, 'Param')}, err := ${parser}(${paramValue}, func (v string) (time.Time, error) {\n`;
962
+ content += '\t\tp, parseErr := strconv.ParseInt(v, 10, 64)\n';
963
+ content += '\t\tif parseErr != nil {\n\t\t\treturn time.Time{}, parseErr\n\t\t}\n';
964
+ content += '\t\treturn time.Unix(p, 0).UTC(), nil\n\t})\n';
965
+ content += '\tif err != nil {\n\t\treturn nil, err\n\t}\n';
966
+ }
967
+ }
968
+ else if (go.isPrimitiveType(param.type) && (param.type.typeName === 'float32' || param.type.typeName === 'float64' || param.type.typeName === 'int32' || param.type.typeName === 'int64')) {
969
+ let parser;
970
+ if (!go.isRequiredParameter(param)) {
971
+ requiredHelpers.parseOptional = true;
972
+ parser = 'parseOptional';
973
+ }
974
+ else {
975
+ requiredHelpers.parseWithCast = true;
976
+ parser = 'parseWithCast';
977
+ }
978
+ if ((param.type.typeName === 'float32' || param.type.typeName === 'int32') || !go.isRequiredParameter(param)) {
979
+ content += `\t${createLocalVariableName(param, 'Param')}, err := ${parser}(${paramValue}, func(v string) (${param.type.typeName}, error) {\n`;
980
+ content += `\t\tp, parseErr := ${emitNumericConversion('v', param.type.typeName)}\n`;
981
+ content += '\t\tif parseErr != nil {\n\t\t\treturn 0, parseErr\n\t\t}\n';
982
+ let result = 'p';
983
+ if (param.type.typeName === 'float32' || param.type.typeName === 'int32') {
984
+ result = `${param.type.typeName}(${result})`;
985
+ }
986
+ content += `\t\treturn ${result}, nil\n\t})\n`;
987
+ }
988
+ else {
989
+ content += `\t${createLocalVariableName(param, 'Param')}, err := ${emitNumericConversion(paramValue, param.type.typeName)}\n`;
990
+ }
991
+ content += '\tif err != nil {\n\t\treturn nil, err\n\t}\n';
992
+ }
993
+ else if (go.isHeaderMapParameter(param)) {
994
+ imports.add('strings');
995
+ imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/to');
996
+ const localVar = createLocalVariableName(param, 'Param');
997
+ content += `\tvar ${localVar} map[string]*string\n`;
998
+ content += `\tfor hh := range ${paramValue} {\n`;
999
+ const headerPrefix = param.collectionPrefix;
1000
+ requiredHelpers.getHeaderValue = true;
1001
+ content += `\t\tif len(hh) > len("${headerPrefix}") && strings.EqualFold(hh[:len("x-ms-meta-")], "${headerPrefix}") {\n`;
1002
+ content += `\t\t\tif ${localVar} == nil {\n\t\t\t\t${localVar} = map[string]*string{}\n\t\t\t}\n`;
1003
+ content += `\t\t\t${localVar}[hh[len("${headerPrefix}"):]] = to.Ptr(getHeaderValue(req.Header, hh))\n`;
1004
+ content += '\t\t}\n\t}\n';
1005
+ }
1006
+ else if (go.isConstantType(param.type) && param.type.type !== 'string') {
1007
+ let parseHelper;
1008
+ if (!go.isRequiredParameter(param)) {
1009
+ requiredHelpers.parseOptional = true;
1010
+ parseHelper = 'parseOptional';
1011
+ }
1012
+ else {
1013
+ requiredHelpers.parseWithCast = true;
1014
+ parseHelper = 'parseWithCast';
1015
+ }
1016
+ let parse;
1017
+ let zeroValue;
1018
+ if (param.type.type === 'bool') {
1019
+ imports.add('strconv');
1020
+ parse = 'strconv.ParseBool(v)';
1021
+ zeroValue = 'false';
1022
+ }
1023
+ else {
1024
+ // emitNumericConversion adds the necessary import of strconv
1025
+ parse = emitNumericConversion('v', param.type.type);
1026
+ zeroValue = '0';
1027
+ }
1028
+ const toConstType = go.getTypeDeclaration(param.type, clientPkg);
1029
+ content += `\t${createLocalVariableName(param, 'Param')}, err := ${parseHelper}(${paramValue}, func(v string) (${toConstType}, error) {\n`;
1030
+ content += `\t\tp, parseErr := ${parse}\n`;
1031
+ content += `\t\tif parseErr != nil {\n\t\t\treturn ${zeroValue}, parseErr\n\t\t}\n`;
1032
+ content += `\t\treturn ${toConstType}(p), nil\n\t})\n`;
1033
+ content += '\tif err != nil {\n\t\treturn nil, err\n\t}\n';
1034
+ }
1035
+ else if (!go.isRequiredParameter(param)) {
1036
+ // we check this last as it's a superset of the previous conditions
1037
+ requiredHelpers.getOptional = true;
1038
+ if (go.isConstantType(param.type)) {
1039
+ paramValue = `${go.getTypeDeclaration(param.type, clientPkg)}(${paramValue})`;
1040
+ }
1041
+ content += `\t${createLocalVariableName(param, 'Param')} := getOptional(${paramValue})\n`;
1042
+ }
1043
+ }
1044
+ // create the param groups and populate their values
1045
+ for (const paramGroup of values(paramGroups.keys())) {
1046
+ if (paramGroup.required) {
1047
+ content += `\t${uncapitalize(paramGroup.name)} := ${clientPkg}.${paramGroup.groupName}{\n`;
1048
+ for (const param of values(paramGroups.get(paramGroup))) {
1049
+ content += `\t\t${capitalize(param.name)}: ${getFinalParamValue(clientPkg, param, paramValues)},\n`;
1050
+ }
1051
+ content += '\t}\n';
1052
+ }
1053
+ else {
1054
+ content += `\tvar ${uncapitalize(paramGroup.name)} *${clientPkg}.${paramGroup.groupName}\n`;
1055
+ const params = paramGroups.get(paramGroup);
1056
+ const paramNilCheck = new Array();
1057
+ for (const param of values(params)) {
1058
+ // check array before body in case the body is just an array
1059
+ if (go.isSliceType(param.type)) {
1060
+ paramNilCheck.push(`len(${getFinalParamValue(clientPkg, param, paramValues)}) > 0`);
1061
+ }
1062
+ else if (go.isBodyParameter(param)) {
1063
+ if (param.bodyFormat === 'binary') {
1064
+ imports.add('io');
1065
+ paramNilCheck.push('req.Body != nil');
1066
+ }
1067
+ else {
1068
+ imports.add('reflect');
1069
+ paramNilCheck.push('!reflect.ValueOf(body).IsZero()');
1070
+ }
1071
+ }
1072
+ else if (go.isFormBodyParameter(param) || go.isMultipartFormBodyParameter(param)) {
1073
+ imports.add('reflect');
1074
+ paramNilCheck.push(`!reflect.ValueOf(${param.name}).IsZero()`);
1075
+ }
1076
+ else {
1077
+ paramNilCheck.push(`${getFinalParamValue(clientPkg, param, paramValues)} != nil`);
1078
+ }
1079
+ }
1080
+ content += `\tif ${paramNilCheck.join(' || ')} {\n`;
1081
+ content += `\t\t${uncapitalize(paramGroup.name)} = &${clientPkg}.${paramGroup.groupName}{\n`;
1082
+ for (const param of values(params)) {
1083
+ let byRef = '&';
1084
+ if (param.byValue || (!go.isRequiredParameter(param) && !go.isBodyParameter(param) && !go.isFormBodyParameter(param) && !go.isMultipartFormBodyParameter(param))) {
1085
+ byRef = '';
1086
+ }
1087
+ content += `\t\t\t${capitalize(param.name)}: ${byRef}${getFinalParamValue(clientPkg, param, paramValues)},\n`;
1088
+ }
1089
+ content += '\t\t}\n';
1090
+ content += '\t}\n';
1091
+ }
1092
+ }
1093
+ return {
1094
+ content: content,
1095
+ params: paramValues
1096
+ };
1097
+ }
1098
+ // works in conjunction with parseHeaderPathQueryParams
1099
+ function populateApiParams(clientPkg, method, paramValues, imports) {
1100
+ // FooOperation(req.Context(), matches[regex.SubexpIndex("resourceGroupName")], qp.Get("api-version"), nil)
1101
+ // this assumes that our caller has created matches and qp as required
1102
+ const params = new Array();
1103
+ // for non-paged APIs, first param is always the context. use the one
1104
+ // from the HTTP request. be careful to properly handle paged LROs
1105
+ if (go.isLROMethod(method) || !go.isPageableMethod(method)) {
1106
+ params.push('req.Context()');
1107
+ }
1108
+ // now create the API call sig
1109
+ for (const param of values(helpers.getMethodParameters(method, consolidateHostParams))) {
1110
+ if (helpers.isParameterGroup(param)) {
1111
+ if (param.groupName === method.optionalParamsGroup.groupName) {
1112
+ // this is the optional params type. in some cases we just pass nil
1113
+ const countParams = values(param.params).where((each) => { return !go.isResumeTokenParameter(each); }).count();
1114
+ if (countParams === 0) {
1115
+ // if the options param is empty or only contains the resume token param just pass nil
1116
+ params.push('nil');
1117
+ continue;
1118
+ }
1119
+ }
1120
+ // by convention, for param groups, the param parsing code
1121
+ // creates a local var with the name of the param
1122
+ params.push(uncapitalize(param.name));
1123
+ continue;
1124
+ }
1125
+ imports.addImportForType(param.type);
1126
+ params.push(getFinalParamValue(clientPkg, param, paramValues));
1127
+ }
1128
+ return params.join(', ');
1129
+ }
1130
+ // getRawParamValue returns the "raw" value for the specified parameter.
1131
+ // depending on the type, the value might require parsing before it can be passed to the fake.
1132
+ function getRawParamValue(param) {
1133
+ if (go.isFormBodyParameter(param) || go.isMultipartFormBodyParameter(param) || go.isPartialBodyParameter(param)) {
1134
+ // multipart form data values have been read and assigned
1135
+ // to local params with the same name. must check this first
1136
+ // as it's a superset of other cases that follow.
1137
+ return param.name;
1138
+ }
1139
+ else if (go.isPathParameter(param)) {
1140
+ // path params are in the matches slice
1141
+ return `matches[regex.SubexpIndex("${sanitizeRegexpCaptureGroupName(param.pathSegment)}")]`;
1142
+ }
1143
+ else if (go.isQueryParameter(param)) {
1144
+ // use qp
1145
+ if (go.isQueryCollectionParameter(param) && param.collectionFormat === 'multi') {
1146
+ return `qp["${param.queryParameter}"]`;
1147
+ }
1148
+ return `qp.Get("${param.queryParameter}")`;
1149
+ }
1150
+ else if (go.isHeaderParameter(param)) {
1151
+ if (go.isHeaderMapParameter(param)) {
1152
+ return 'req.Header';
1153
+ }
1154
+ // use req
1155
+ requiredHelpers.getHeaderValue = true;
1156
+ return `getHeaderValue(req.Header, "${param.headerName}")`;
1157
+ }
1158
+ else if (go.isBodyParameter(param)) {
1159
+ if (param.bodyFormat === 'binary') {
1160
+ return 'req.Body.(io.ReadSeekCloser)';
1161
+ }
1162
+ // JSON/XML/text bodies have been deserialized into a local named body
1163
+ return 'body';
1164
+ }
1165
+ else if (go.isURIParameter(param)) {
1166
+ return 'req.URL.Host';
1167
+ }
1168
+ else {
1169
+ throw new Error(`unhandled parameter ${param.name}`);
1170
+ }
1171
+ }
1172
+ // getFinalParamValue returns the "final" value of param to be passed to the fake.
1173
+ function getFinalParamValue(clientPkg, param, paramValues) {
1174
+ let paramValue = paramValues.get(param.name);
1175
+ if (!paramValue) {
1176
+ // the param didn't require parsing so the "raw" value can be used
1177
+ paramValue = getRawParamValue(param);
1178
+ }
1179
+ // there are a few corner-cases that require some fix-ups
1180
+ if ((go.isBodyParameter(param) || go.isFormBodyParameter(param) || go.isFormBodyCollectionParameter(param) || go.isMultipartFormBodyParameter(param)) && go.isTimeType(param.type)) {
1181
+ // time types in the body have been unmarshalled into our time helpers thus require a cast to time.Time
1182
+ return `time.Time(${paramValue})`;
1183
+ }
1184
+ else if (go.isRequiredParameter(param)) {
1185
+ // optional params are always in their "final" form
1186
+ if (go.isHeaderCollectionParameter(param) || go.isPathCollectionParameter(param) || go.isQueryCollectionParameter(param)) {
1187
+ // for required params that are collections of strings, we split them inline.
1188
+ // not necessary for optional params as they're already in slice format.
1189
+ if (param.collectionFormat !== 'multi' && go.isPrimitiveType(param.type.elementType) && param.type.elementType.typeName === 'string') {
1190
+ requiredHelpers.splitHelper = true;
1191
+ return `splitHelper(${paramValue}, "${helpers.getDelimiterForCollectionFormat(param.collectionFormat)}")`;
1192
+ }
1193
+ }
1194
+ else if (go.isHeaderParameter(param) && go.isConstantType(param.type) && param.type.type === 'string') {
1195
+ // since headers aren't escaped, we cast required, string-based enums inline
1196
+ return `${go.getTypeDeclaration(param.type, clientPkg)}(${paramValue})`;
1197
+ }
1198
+ }
1199
+ return paramValue;
1200
+ }
1201
+ // takes multiple host parameters and consolidates them into a single "host" parameter.
1202
+ // this is necessary as there's no way to rehydrate multiple host parameters.
1203
+ // e.g. host := "{vault}{secret}{dnsSuffix}" becomes http://contososecret.com
1204
+ // there's no way to reliably split the host back up into its constituent parameters.
1205
+ // so we just pass the full value as a single host parameter.
1206
+ function consolidateHostParams(params) {
1207
+ if (!values(params).where((each) => { return go.isURIParameter(each); }).any()) {
1208
+ // no host params
1209
+ return params;
1210
+ }
1211
+ // consolidate multiple host params into a single "host" param
1212
+ const consolidatedParams = new Array();
1213
+ let hostParamAdded = false;
1214
+ for (const param of values(params)) {
1215
+ if (!go.isURIParameter(param)) {
1216
+ consolidatedParams.push(param);
1217
+ }
1218
+ else if (!hostParamAdded) {
1219
+ consolidatedParams.push(param);
1220
+ hostParamAdded = true;
1221
+ }
1222
+ }
1223
+ return consolidatedParams;
1224
+ }
1225
+ // copied from generator/operations.ts but with a slight tweak to consolidate host parameters
1226
+ function getAPIParametersSig(method, imports, pkgName) {
1227
+ const methodParams = helpers.getMethodParameters(method, consolidateHostParams);
1228
+ const params = new Array();
1229
+ if (!go.isPageableMethod(method) || go.isLROMethod(method)) {
1230
+ imports.add('context');
1231
+ params.push('ctx context.Context');
1232
+ }
1233
+ for (const methodParam of values(methodParams)) {
1234
+ let paramName = uncapitalize(methodParam.name);
1235
+ if (helpers.isParameter(methodParam) && go.isURIParameter(methodParam)) {
1236
+ paramName = 'host';
1237
+ }
1238
+ params.push(`${paramName} ${helpers.formatParameterTypeName(methodParam, pkgName)}`);
1239
+ }
1240
+ return params.join(', ');
1241
+ }
1242
+ // copied from generator/helpers.ts but without the XML-specific stuff
1243
+ function getResultFieldName(result) {
1244
+ if (go.isAnyResult(result)) {
1245
+ return result.fieldName;
1246
+ }
1247
+ else if (go.isModelResult(result)) {
1248
+ return result.modelType.name;
1249
+ }
1250
+ else if (go.isPolymorphicResult(result)) {
1251
+ return result.interfaceType.name;
1252
+ }
1253
+ return result.fieldName;
1254
+ }
1255
+ //# sourceMappingURL=servers.js.map