@autorest/go
Version:
AutoRest Go Generator
194 lines • 9.65 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* 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 * as m4 from '@autorest/codemodel';
import { serialize } from '@azure-tools/codegen';
import { values } from '@azure-tools/linq';
import { startSession } from '@autorest/extension-base';
import * as go from '../../../codemodel.go/src/index.js';
import { adaptClients } from './clients.js';
import { adaptConstantType, adaptInterfaceType, adaptModel, adaptModelField } from './types.js';
import { aggregateProperties } from '../transform/helpers.js';
import { fileURLToPath } from 'url';
// converts an M4 code model into a GoCodeModel
export function m4ToGoCodeModel(host) {
return __awaiter(this, void 0, void 0, function* () {
const debug = (yield host.getValue('debug')) || false;
try {
const session = yield startSession(host, m4.codeModelSchema);
const info = new go.Info(session.model.info.title);
const options = new go.Options(yield session.getValue('header-text', 'MISSING LICENSE HEADER'), yield session.getValue('generate-fakes', session.model.language.go.azureARM), yield session.getValue('inject-spans', session.model.language.go.azureARM), yield session.getValue('disallow-unknown-fields', false), yield session.getValue('generate-sdk-example', false));
const azcoreVersion = yield session.getValue('azcore-version', '');
if (azcoreVersion !== '') {
options.azcoreVersion = azcoreVersion;
}
let type = 'data-plane';
if (session.model.language.go.azureARM) {
type = 'azure-arm';
}
const codeModel = new go.CodeModel(info, type, session.model.language.go.packageName, options);
if (session.model.language.go.host) {
codeModel.host = session.model.language.go.host;
}
if (session.model.language.go.module && session.model.language.go.moduleVersion) {
codeModel.options.module = new go.Module(session.model.language.go.module, session.model.language.go.moduleVersion);
}
else if (session.model.language.go.module || session.model.language.go.moduleVersion) {
throw new Error('--module and --module-version must both or neither be set');
}
else if (session.model.language.go.containingModule !== '') {
codeModel.options.containingModule = session.model.language.go.containingModule;
}
adaptConstantTypes(session.model, codeModel);
adaptInterfaceTypes(session.model, codeModel);
adaptModels(session.model, codeModel);
adaptClients(session.model, codeModel);
const paramGroups = new Map();
for (const client of values(codeModel.clients)) {
for (const method of client.methods) {
codeModel.responseEnvelopes.push(method.responseEnvelope);
for (const param of values(method.parameters)) {
if (param.group) {
if (!paramGroups.has(param.group.groupName)) {
paramGroups.set(param.group.groupName, param.group);
}
}
}
if (!paramGroups.has(method.optionalParamsGroup.groupName)) {
// the optional params group wasn't present, that means that it's empty.
paramGroups.set(method.optionalParamsGroup.groupName, method.optionalParamsGroup);
}
}
}
if (paramGroups.size > 0) {
// adapt all of the parameter groups
for (const groupName of paramGroups.keys()) {
const paramGroup = paramGroups.get(groupName);
codeModel.paramGroups.push(adaptParameterGroup(paramGroup));
}
}
codeModel.sortContent();
// output the model to the pipeline
host.writeFile({
filename: 'go-code-model.yaml',
content: serialize(codeModel),
artifactType: 'go-code-model'
});
}
catch (E) {
if (debug) {
console.error(`${fileURLToPath(import.meta.url)} - FAILURE ${JSON.stringify(E)} ${E.stack}`);
}
throw E;
}
});
}
function adaptConstantTypes(m4CodeModel, goCodeModel) {
// group all enum categories into a single array so they can be sorted
for (const choice of values(m4CodeModel.schemas.choices)) {
if (choice.language.go.omitType) {
continue;
}
const constType = adaptConstantType(choice);
goCodeModel.constants.push(constType);
}
for (const choice of values(m4CodeModel.schemas.sealedChoices)) {
if (choice.language.go.omitType || choice.choices.length === 1) {
continue;
}
const constType = adaptConstantType(choice);
goCodeModel.constants.push(constType);
}
}
function adaptParameterGroup(paramGroup) {
const structType = new go.StructType(paramGroup.groupName);
structType.docs = paramGroup.docs;
if (paramGroup.params.length > 0) {
for (const param of values(paramGroup.params)) {
if (param.kind === 'literal') {
continue;
}
let byValue = param.kind === 'required' || (param.location === 'client' && go.isClientSideDefault(param.kind));
// if the param isn't required, check if it should be passed by value or not.
// optional params that are implicitly nil-able shouldn't be pointer-to-type.
if (!byValue) {
byValue = param.byValue;
}
const field = new go.StructField(param.name, param.type, byValue);
field.docs = param.docs;
structType.fields.push(field);
}
}
return structType;
}
function adaptInterfaceTypes(m4CodeModel, goCodeModel) {
var _a;
if (!m4CodeModel.language.go.discriminators) {
return;
}
const ifaceObjs = new Array();
const discriminators = m4CodeModel.language.go.discriminators;
// discriminators contains all of the root discriminated types but *not* any sub-roots (e.g. Salmon).
for (const discriminator of values(discriminators)) {
if (discriminator.language.go.omitType || ((_a = discriminator.extensions) === null || _a === void 0 ? void 0 : _a['x-ms-external'])) {
continue;
}
// we must adapt all InterfaceTypes first. this is because ModelTypes/PolymorphicTypes can
// contain references to InterfaceTypes and/or cyclic references
recursiveAdaptInterfaceType(discriminator, goCodeModel.interfaceTypes, ifaceObjs);
}
// now that the InterfaceTypes have been created, we can populate the rootType and possibleTypes
for (const ifaceObj of values(ifaceObjs)) {
ifaceObj.iface.rootType = adaptModel(ifaceObj.obj);
ifaceObj.iface.possibleTypes = new Array();
for (const disc of values(ifaceObj.obj.discriminator.all)) {
const possibleType = adaptModel(disc);
ifaceObj.iface.possibleTypes.push(possibleType);
}
}
}
function recursiveAdaptInterfaceType(obj, ifaces, ifaceObjs, parent) {
const iface = adaptInterfaceType(obj, parent);
if (ifaces.includes(iface)) {
return;
}
ifaces.push(iface);
ifaceObjs.push({ iface, obj });
for (const val of values(obj.discriminator.immediate)) {
const asObj = val;
if (asObj.discriminator) {
recursiveAdaptInterfaceType(asObj, ifaces, ifaceObjs, iface);
}
}
}
function adaptModels(m4CodeModel, goCodeModel) {
var _a;
const modelObjs = new Array();
for (const obj of values(m4CodeModel.schemas.objects)) {
if (obj.language.go.omitType || ((_a = obj.extensions) === null || _a === void 0 ? void 0 : _a['x-ms-external'])) {
continue;
}
// we must adapt all model types first. this is because models can contain cyclic references
const modelType = adaptModel(obj);
goCodeModel.models.push(modelType);
modelObjs.push({ type: modelType, obj: obj });
}
for (const modelObj of values(modelObjs)) {
const props = aggregateProperties(modelObj.obj);
for (const prop of values(props)) {
const field = adaptModelField(prop, modelObj.obj);
modelObj.type.fields.push(field);
}
}
}
//# sourceMappingURL=adapter.js.map