UNPKG

@autorest/go

Version:
166 lines 8.2 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { comment } from '@azure-tools/codegen'; import { values } from '@azure-tools/linq'; import * as go from '../../codemodel.go/src/index.js'; import * as helpers from './helpers.js'; import { ImportManager } from './imports.js'; import { getStar } from './models.js'; import { CodegenError } from './errors.js'; // Creates the content in responses.go export function generateResponses(codeModel) { return __awaiter(this, void 0, void 0, function* () { if (codeModel.responseEnvelopes.length === 0) { return { responses: '', serDe: '' }; } const imports = new ImportManager(); const serdeImports = new ImportManager(); let responses = helpers.contentPreamble(codeModel); let serDe = ''; let respContent = ''; let serdeContent = ''; for (const respEnv of codeModel.responseEnvelopes) { respContent += emit(respEnv, imports); if (codeModel.options.generateFakes) { serdeContent += generateMarshaller(respEnv, serdeImports); } serdeContent += generateUnmarshaller(respEnv, serdeImports); } responses += imports.text(); responses += respContent; if (serdeContent.length > 0) { serDe = helpers.contentPreamble(codeModel); serDe += serdeImports.text(); serDe += serdeContent; } return { responses: responses, serDe: serDe }; }); } function generateMarshaller(respEnv, imports) { let text = ''; if (go.isLROMethod(respEnv.method) && respEnv.result && go.isPolymorphicResult(respEnv.result)) { // fakes require a custom marshaller for polymorphics results so that the data is in the correct shape. // without it, the response envelope type name is the outer type which is incorrect. imports.add('encoding/json'); const receiver = respEnv.name[0].toLowerCase(); text += `${comment(`MarshalJSON implements the json.Marshaller interface for type ${respEnv.name}.`, '// ', undefined, helpers.commentLength)}\n`; text += `func (${receiver} ${respEnv.name}) MarshalJSON() ([]byte, error) {\n`; // TODO: this doesn't include any headers. however, LROs with header responses are currently broken :( text += `\treturn json.Marshal(${receiver}.${go.getTypeDeclaration(respEnv.result.interfaceType)})\n}\n\n`; } return text; } // check if the response envelope requires an unmarshaller function generateUnmarshaller(respEnv, imports) { // if the response envelope contains a discriminated type we need an unmarshaller let polymorphicRes; // in addition, if it's an LRO operation that returns a scalar, we will also need one let monomorphicRes; if (respEnv.result && go.isPolymorphicResult(respEnv.result)) { polymorphicRes = respEnv.result; } else if (go.isLROMethod(respEnv.method) && respEnv.result && go.isMonomorphicResult(respEnv.result)) { monomorphicRes = respEnv.result; } if (!polymorphicRes && !monomorphicRes) { // no unmarshaller required return ''; } const receiver = respEnv.name[0].toLowerCase(); let unmarshaller = `${comment(`UnmarshalJSON implements the json.Unmarshaller interface for type ${respEnv.name}.`, '// ', undefined, helpers.commentLength)}\n`; unmarshaller += `func (${receiver} *${respEnv.name}) UnmarshalJSON(data []byte) error {\n`; // add a custom unmarshaller to the response envelope if (polymorphicRes) { const type = polymorphicRes.interfaceType.name; unmarshaller += `\tres, err := unmarshal${type}(data)\n`; unmarshaller += '\tif err != nil {\n'; unmarshaller += '\t\treturn err\n'; unmarshaller += '\t}\n'; unmarshaller += `\t${receiver}.${type} = res\n`; unmarshaller += '\treturn nil\n'; } else if (monomorphicRes) { imports.add('encoding/json'); unmarshaller += `\treturn json.Unmarshal(data, &${receiver}.${monomorphicRes.fieldName})\n`; } else { throw new CodegenError('InternalError', `unhandled case for response envelope ${respEnv.name}`); } unmarshaller += '}\n\n'; return unmarshaller; } function emit(respEnv, imports) { var _a, _b; let text = helpers.formatDocComment(respEnv.docs); text += `type ${respEnv.name} struct {\n`; if (!respEnv.result && respEnv.headers.length === 0) { // this is an empty response envelope text += '\t// placeholder for future response values\n'; } else { // fields will contain the merged headers and response field so they can be sorted together const fields = new Array(); // used to track when to add an extra \n between fields that have comments let first = true; if (respEnv.result) { if (go.isModelResult(respEnv.result) || go.isPolymorphicResult(respEnv.result)) { // anonymously embedded type always goes first text += helpers.formatDocComment(respEnv.result.docs); text += `\t${go.getTypeDeclaration(go.getResultPossibleType(respEnv.result))}\n`; first = false; } else { const type = go.getResultPossibleType(respEnv.result); imports.addImportForType(type); let tag = ''; if (go.isMonomorphicResult(respEnv.result) && respEnv.result.format === 'XML') { // only emit tags for XML; JSON uses custom marshallers/unmarshallers if ((_a = respEnv.result.xml) === null || _a === void 0 ? void 0 : _a.wraps) { tag = ` \`xml:"${respEnv.result.xml.wraps}"\``; } else if ((_b = respEnv.result.xml) === null || _b === void 0 ? void 0 : _b.name) { tag = ` \`xml:"${respEnv.result.xml.name}"\``; } } fields.push({ docs: respEnv.result.docs, field: `\t${respEnv.result.fieldName} ${getStar(respEnv.result.byValue)}${go.getTypeDeclaration(type)}${tag}\n` }); } } for (const header of values(respEnv.headers)) { imports.addImportForType(header.type); fields.push({ docs: header.docs, field: `\t${header.fieldName} ${getStar(header.byValue)}${go.getTypeDeclaration(header.type)}\n` }); } fields.sort((a, b) => { return helpers.sortAscending(a.field, b.field); }); for (const field of fields) { if (field.docs.summary || field.docs.description) { if (!first) { // add an extra new-line between fields IFF the field // has a comment and it's not the very first one. text += '\n'; } text += helpers.formatDocComment(field.docs); } text += field.field; first = false; } } text += '}\n\n'; return text; } //# sourceMappingURL=responses.js.map