Skip to content

Commit

Permalink
Refactor some docs handling (#1439)
Browse files Browse the repository at this point in the history
Centralize some doc generation code. This will help with an upcoming
change that refactors the doc code.
Clean up some helpers imports.
  • Loading branch information
jhendrixMSFT authored Oct 14, 2024
1 parent c80d117 commit ee52f12
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 63 deletions.
17 changes: 8 additions & 9 deletions packages/codegen.go/src/clientFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@

import * as go from '../../codemodel.go/src/index.js';
import { values } from '@azure-tools/linq';
import { contentPreamble, formatCommentAsBulletItem, formatParameterTypeName, getAllClientParameters } from './helpers.js';
import * as helpers from './helpers.js';
import { ImportManager } from './imports.js';


// Creates the content for client_factory.go (ARM only)
export async function generateClientFactory(codeModel: go.CodeModel): Promise<string> {
// generate client factory only for ARM
Expand All @@ -20,15 +19,15 @@ export async function generateClientFactory(codeModel: go.CodeModel): Promise<st
// the list of packages to import
const imports = new ImportManager();

const allClientParams = getAllClientParameters(codeModel);
const allClientParams = helpers.getAllClientParameters(codeModel);

// add factory type
imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore');
result += '// ClientFactory is a client factory used to create any client in this module.\n';
result += '// Don\'t use this type directly, use NewClientFactory instead.\n';
result += 'type ClientFactory struct {\n';
for (const clientParam of values(allClientParams)) {
result += `\t${clientParam.name} ${formatParameterTypeName(clientParam)}\n`;
result += `\t${clientParam.name} ${helpers.formatParameterTypeName(clientParam)}\n`;
}
result += '\tinternal *arm.Client\n';
result += '}\n\n';
Expand All @@ -38,12 +37,12 @@ export async function generateClientFactory(codeModel: go.CodeModel): Promise<st
result += '// NewClientFactory creates a new instance of ClientFactory with the specified values.\n';
result += '// The parameter values will be propagated to any client created from this factory.\n';
for (const clientParam of values(allClientParams)) {
result += `${formatCommentAsBulletItem(`${clientParam.name} - ${clientParam.description}`)}\n`;
result += `${helpers.formatCommentAsBulletItem(`${clientParam.name} - ${clientParam.description}`)}\n`;
}
result += `${formatCommentAsBulletItem('credential - used to authorize requests. Usually a credential from azidentity.')}\n`;
result += `${formatCommentAsBulletItem('options - pass nil to accept the default values.')}\n`;
result += `${helpers.formatCommentAsBulletItem('credential - used to authorize requests. Usually a credential from azidentity.')}\n`;
result += `${helpers.formatCommentAsBulletItem('options - pass nil to accept the default values.')}\n`;

result += `func NewClientFactory(${allClientParams.map(param => { return `${param.name} ${formatParameterTypeName(param)}`; }).join(', ')}${allClientParams.length>0 ? ',' : ''} credential azcore.TokenCredential, options *arm.ClientOptions) (*ClientFactory, error) {\n`;
result += `func NewClientFactory(${allClientParams.map(param => { return `${param.name} ${helpers.formatParameterTypeName(param)}`; }).join(', ')}${allClientParams.length>0 ? ',' : ''} credential azcore.TokenCredential, options *arm.ClientOptions) (*ClientFactory, error) {\n`;
result += '\tinternal, err := arm.NewClient(moduleName, moduleVersion, credential, options)\n';
result += '\tif err != nil {\n';
result += '\t\treturn nil, err\n';
Expand Down Expand Up @@ -75,6 +74,6 @@ export async function generateClientFactory(codeModel: go.CodeModel): Promise<st
result += '}\n\n';
}

result = contentPreamble(codeModel) + imports.text() + result;
result = helpers.contentPreamble(codeModel) + imports.text() + result;
return result;
}
13 changes: 4 additions & 9 deletions packages/codegen.go/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { comment } from '@azure-tools/codegen';
import { values } from '@azure-tools/linq';
import { commentLength, contentPreamble } from './helpers.js';
import * as helpers from './helpers.js';
import * as go from '../../codemodel.go/src/index.js';

// Creates the content in constants.go
Expand All @@ -14,7 +13,7 @@ export async function generateConstants(codeModel: go.CodeModel): Promise<string
if (!codeModel.clients || (codeModel.constants.length === 0 && !codeModel.host && codeModel.type !== 'azure-arm')) {
return '';
}
let text = contentPreamble(codeModel);
let text = helpers.contentPreamble(codeModel);
if (codeModel.host) {
text += `const host = "${codeModel.host}"\n\n`;
}
Expand All @@ -30,16 +29,12 @@ export async function generateConstants(codeModel: go.CodeModel): Promise<string
text += ')\n\n';
}
for (const enm of values(codeModel.constants)) {
if (enm.description) {
text += `${comment(`${enm.name} - ${enm.description}`, '// ', undefined, commentLength)}\n`;
}
text += helpers.formatDocCommentWithPrefix(enm.name, enm.description);
text += `type ${enm.name} ${enm.type}\n\n`;
const vals = new Array<string>();
text += 'const (\n';
for (const val of values(enm.values)) {
if (val.description) {
text += `\t${comment(`${val.name} - ${val.description}`, '//', undefined, commentLength)}\n`;
}
text += helpers.formatDocCommentWithPrefix(val.name, val.description);
let formatValue = `"${val.value}"`;
if (enm.type !== 'string') {
formatValue = `${val.value}`;
Expand Down
17 changes: 17 additions & 0 deletions packages/codegen.go/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,23 @@ export function formatCommentAsBulletItem(description: string): string {
return chunks.join('\n');
}

// conditionally returns a doc comment on an entity that requires a prefix.
// e.g.: // {Prefix} - {docs}
export function formatDocCommentWithPrefix(prefix: string, docs?: string): string {
if (!docs) {
return '';
}
return `${comment(`${prefix} - ${docs}`, '// ', undefined, commentLength)}\n`;
}

// conditionally returns a doc comment
export function formatDocComment(docs?: string): string {
if (!docs) {
return '';
}
return `${comment(docs, '// ', undefined, commentLength)}\n`;
}

export function getParentImport(codeModel: go.CodeModel): string {
const clientPkg = codeModel.packageName;
if (codeModel.options.module) {
Expand Down
34 changes: 17 additions & 17 deletions packages/codegen.go/src/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import * as go from '../../codemodel.go/src/index.js';
import { capitalize, comment } from '@azure-tools/codegen';
import { values } from '@azure-tools/linq';
import { commentLength, contentPreamble, formatLiteralValue, getSerDeFormat, recursiveUnwrapMapSlice, SerDeFormat, sortAscending } from './helpers.js';
import * as helpers from './helpers.js';
import { ImportManager } from './imports.js';

export interface ModelsSerDe {
Expand All @@ -26,7 +26,7 @@ export async function generateModels(codeModel: go.CodeModel): Promise<ModelsSer
// this list of packages to import
const modelImports = new ImportManager();
const serdeImports = new ImportManager();
let modelText = contentPreamble(codeModel);
let modelText = helpers.contentPreamble(codeModel);

// we do model generation first as it can add imports to the imports list
const modelDefs = generateModelDefs(modelImports, serdeImports, codeModel);
Expand All @@ -43,18 +43,18 @@ export async function generateModels(codeModel: go.CodeModel): Promise<ModelsSer
for (const modelDef of values(modelDefs)) {
modelText += modelDef.text();

modelDef.Methods.sort((a: ModelMethod, b: ModelMethod) => { return sortAscending(a.name, b.name); });
modelDef.Methods.sort((a: ModelMethod, b: ModelMethod) => { return helpers.sortAscending(a.name, b.name); });
for (const method of values(modelDef.Methods)) {
if (method.desc.length > 0) {
modelText += `${comment(method.desc, '// ', undefined, commentLength)}\n`;
modelText += `${comment(method.desc, '// ', undefined, helpers.commentLength)}\n`;
}
modelText += method.text;
}

modelDef.SerDe.methods.sort((a: ModelMethod, b: ModelMethod) => { return sortAscending(a.name, b.name); });
modelDef.SerDe.methods.sort((a: ModelMethod, b: ModelMethod) => { return helpers.sortAscending(a.name, b.name); });
for (const method of values(modelDef.SerDe.methods)) {
if (method.desc.length > 0) {
serdeTextBody += `${comment(method.desc, '// ', undefined, commentLength)}\n`;
serdeTextBody += `${comment(method.desc, '// ', undefined, helpers.commentLength)}\n`;
}
serdeTextBody += method.text;
}
Expand Down Expand Up @@ -134,7 +134,7 @@ export async function generateModels(codeModel: go.CodeModel): Promise<ModelsSer
}
let serdeText = '';
if (serdeTextBody.length > 0) {
serdeText = contentPreamble(codeModel);
serdeText = helpers.contentPreamble(codeModel);
serdeText += serdeImports.text();
serdeText += serdeTextBody;
}
Expand Down Expand Up @@ -165,7 +165,7 @@ function generateModelDefs(modelImports: ImportManager, serdeImports: ImportMana
if (field.description) {
field.description += '\n';
}
field.description += `Field has constant value ${formatLiteralValue(field.type, false)}, any specified value is ignored.`;
field.description += `Field has constant value ${helpers.formatLiteralValue(field.type, false)}, any specified value is ignored.`;
}
if (field.description) {
descriptionMods.push(field.description);
Expand All @@ -176,7 +176,7 @@ function generateModelDefs(modelImports: ImportManager, serdeImports: ImportMana
field.description = descriptionMods.join('; ');
}

const serDeFormat = getSerDeFormat(model, codeModel);
const serDeFormat = helpers.getSerDeFormat(model, codeModel);
const modelDef = new ModelDef(model.name, serDeFormat, model.fields, model.description);
for (const field of values(modelDef.Fields)) {
modelImports.addImportForType(field.type);
Expand Down Expand Up @@ -269,7 +269,7 @@ function generateToMultipartForm(modelDef: ModelDef) {
let method = `func (${receiver} ${modelDef.Name}) toMultipartFormData() (map[string]any, error) {\n`;
method += '\tobjectMap := make(map[string]any)\n';
for (const field of modelDef.Fields) {
const fieldType = recursiveUnwrapMapSlice(field.type);
const fieldType = helpers.recursiveUnwrapMapSlice(field.type);
let setField: string;
let star = '';
if (!field.byValue) {
Expand Down Expand Up @@ -316,7 +316,7 @@ function generateJSONMarshallerBody(modelType: go.ModelType | go.PolymorphicType
}
if (field.annotations.isDiscriminator) {
if (field.defaultValue) {
marshaller += `\tobjectMap["${field.serializedName}"] = ${formatLiteralValue(field.defaultValue, true)}\n`;
marshaller += `\tobjectMap["${field.serializedName}"] = ${helpers.formatLiteralValue(field.defaultValue, true)}\n`;
} else {
// if there's no discriminator value (e.g. Fish in test server), use the field's value.
// this will enable support for custom types that aren't (yet) described in the swagger.
Expand Down Expand Up @@ -348,7 +348,7 @@ function generateJSONMarshallerBody(modelType: go.ModelType | go.PolymorphicType
marshaller += `\tpopulate(objectMap, "${field.serializedName}", aux)\n`;
modelDef.SerDe.needsJSONPopulate = true;
} else if (go.isLiteralValue(field.type)) {
const setter = `objectMap["${field.serializedName}"] = ${formatLiteralValue(field.type, true)}`;
const setter = `objectMap["${field.serializedName}"] = ${helpers.formatLiteralValue(field.type, true)}`;
if (!field.annotations.required) {
marshaller += `\tif ${receiver}.${field.name} != nil {\n\t\t${setter}\n\t}\n`;
} else {
Expand All @@ -360,7 +360,7 @@ function generateJSONMarshallerBody(modelType: go.ModelType | go.PolymorphicType
} else {
if (field.defaultValue) {
imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/to');
marshaller += `\tif ${receiver}.${field.name} == nil {\n\t\t${receiver}.${field.name} = to.Ptr(${formatLiteralValue(field.defaultValue, true)})\n\t}\n`;
marshaller += `\tif ${receiver}.${field.name} == nil {\n\t\t${receiver}.${field.name} = to.Ptr(${helpers.formatLiteralValue(field.defaultValue, true)})\n\t}\n`;
}
let populate = 'populate';
if (go.isTimeType(field.type)) {
Expand Down Expand Up @@ -771,13 +771,13 @@ class SerDeInfo {
// represents model definition as a Go struct
class ModelDef {
readonly Name: string;
readonly Format: SerDeFormat;
readonly Format: helpers.SerDeFormat;
readonly Description?: string;
readonly Fields: Array<go.ModelField>;
readonly SerDe: SerDeInfo;
readonly Methods: Array<ModelMethod>;

constructor(name: string, format: SerDeFormat, fields: Array<go.ModelField>, description?: string) {
constructor(name: string, format: helpers.SerDeFormat, fields: Array<go.ModelField>, description?: string) {
this.Name = name;
this.Format = format;
this.Description = description;
Expand All @@ -789,7 +789,7 @@ class ModelDef {
text(): string {
let text = '';
if (this.Description) {
text += `${comment(this.Description, '// ', undefined, commentLength)}\n`;
text += `${comment(this.Description, '// ', undefined, helpers.commentLength)}\n`;
}
text += `type ${this.Name} struct {\n`;

Expand All @@ -814,7 +814,7 @@ class ModelDef {
// has a comment and it's not the very first one.
text += '\n';
}
text += `\t${comment(field.description, '// ', undefined, commentLength)}\n`;
text += `\t${comment(field.description, '// ', undefined, helpers.commentLength)}\n`;
}
let typeName = go.getTypeDeclaration(field.type);
if (go.isLiteralValue(field.type)) {
Expand Down
11 changes: 4 additions & 7 deletions packages/codegen.go/src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { capitalize, comment } from '@azure-tools/codegen';
import { values } from '@azure-tools/linq';
import * as go from '../../codemodel.go/src/index.js';
import { commentLength, contentPreamble } from './helpers.js';
import * as helpers from './helpers.js';
import { ImportManager } from './imports.js';

// Creates the content in options.go
Expand All @@ -16,7 +16,7 @@ export async function generateOptions(codeModel: go.CodeModel): Promise<string>
}

const imports = new ImportManager();
let optionsText = contentPreamble(codeModel);
let optionsText = helpers.contentPreamble(codeModel);
let content = '';

for (const paramGroup of values(codeModel.paramGroups)) {
Expand All @@ -29,10 +29,7 @@ export async function generateOptions(codeModel: go.CodeModel): Promise<string>
}

function emit(struct: go.StructType, imports: ImportManager): string {
let text = '';
if (struct.description) {
text += `${comment(struct.description, '// ', undefined, commentLength)}\n`;
}
let text = helpers.formatDocComment(struct.description);
text += `type ${struct.name} struct {\n`;

if (struct.fields.length === 0) {
Expand All @@ -50,7 +47,7 @@ function emit(struct: go.StructType, imports: ImportManager): string {
// has a comment and it's not the very first one.
text += '\n';
}
text += `\t${comment(field.description, '// ', undefined, commentLength)}\n`;
text += `\t${comment(field.description, '// ', undefined, helpers.commentLength)}\n`;
}

let typeName = go.getTypeDeclaration(field.type);
Expand Down
12 changes: 6 additions & 6 deletions packages/codegen.go/src/polymorphics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import * as go from '../../codemodel.go/src/index.js';
import { values } from '@azure-tools/linq';
import { contentPreamble, formatLiteralValue, getParentImport, recursiveUnwrapMapSlice } from './helpers.js';
import * as helpers from './helpers.js';
import { ImportManager } from './imports.js';

// Creates the content in polymorphic_helpers.go
Expand All @@ -15,12 +15,12 @@ export async function generatePolymorphicHelpers(codeModel: go.CodeModel, fakeSe
return '';
}

let text = contentPreamble(codeModel, fakeServerPkg);
let text = helpers.contentPreamble(codeModel, fakeServerPkg);
const imports = new ImportManager();
imports.add('encoding/json');
if (fakeServerPkg) {
// content is being generated into a separate package, add the necessary import
imports.add(getParentImport(codeModel));
imports.add(helpers.getParentImport(codeModel));
}

text += imports.text();
Expand All @@ -36,13 +36,13 @@ export async function generatePolymorphicHelpers(codeModel: go.CodeModel, fakeSe
if (go.isInterfaceType(type)) {
scalars.add(type.name);
} else if (go.isSliceType(type)) {
const leafType = recursiveUnwrapMapSlice(type);
const leafType = helpers.recursiveUnwrapMapSlice(type);
if (go.isInterfaceType(leafType)) {
scalars.add(leafType.name);
arrays.add(leafType.name);
}
} else if (go.isMapType(type)) {
const leafType = recursiveUnwrapMapSlice(type);
const leafType = helpers.recursiveUnwrapMapSlice(type);
if (go.isInterfaceType(leafType)) {
scalars.add(leafType.name);
maps.add(leafType.name);
Expand Down Expand Up @@ -115,7 +115,7 @@ export async function generatePolymorphicHelpers(codeModel: go.CodeModel, fakeSe
text += `\tvar b ${prefix}${interfaceType.name}\n`;
text += `\tswitch m["${interfaceType.discriminatorField}"] {\n`;
for (const possibleType of interfaceType.possibleTypes) {
let disc = formatLiteralValue(possibleType.discriminatorValue!, true);
let disc = helpers.formatLiteralValue(possibleType.discriminatorValue!, true);
// when the discriminator value is an enum, cast the const as a string
if (go.isConstantType(possibleType.discriminatorValue!.type)) {
disc = `string(${prefix}${disc})`;
Expand Down
Loading

0 comments on commit ee52f12

Please sign in to comment.