Skip to content

Commit 926a299

Browse files
feat: add namingConvention option and pass generator to renderers (#266)
Co-authored-by: Maciej Urbańczyk <urbanczyk.maciej.95@gmail.com>
1 parent e9d544f commit 926a299

31 files changed

+454
-130
lines changed

docs/generators.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,34 @@ Below is a list of additional options available for a given generator.
3737
|---|---|---|---|
3838
| `renderTypes` | Boolean | Render signature for types. | `true` |
3939
| `modelType` | String | It indicates which model type should be rendered for the `object` type. Its value can be either `interface` or `class`. | `class` |
40+
| `namingConvention` | Object | Options for naming conventions. | - |
41+
| `namingConvention.type` | Function | A function that returns the format of the type. | _Returns pascal cased name_ |
42+
| `namingConvention.property` | Function | A function that returns the format of the property. | _Returns camel cased name_ |
43+
44+
### [Java](../src/generators/java/JavaGenerator.ts)
45+
46+
| Option | Type | Description | Default value |
47+
|---|---|---|---|
48+
| `collectionType` | String | It indicates with which signature should be rendered the `array` type. Its value can be either `List` (`List<{type}>`) or `Array` (`{type}[]`). | `List` |
49+
| `namingConvention` | Object | Options for naming conventions. | - |
50+
| `namingConvention.type` | Function | A function that returns the format of the type. | _Returns pascal cased name_ |
51+
| `namingConvention.property` | Function | A function that returns the format of the property. | _Returns camel cased name_ |
52+
53+
### [JavaScript](../src/generators/javascript/JavaScriptGenerator.ts)
54+
55+
| Option | Type | Description | Default value |
56+
|---|---|---|---|
57+
| `namingConvention` | Object | Options for naming conventions. | - |
58+
| `namingConvention.type` | Function | A function that returns the format of the type. | _Returns pascal cased name_ |
59+
| `namingConvention.property` | Function | A function that returns the format of the property. | _Returns camel cased name_ |
60+
61+
### [Go](../src/generators/javascript/GoGenerator.ts)
62+
63+
| Option | Type | Description | Default value |
64+
|---|---|---|---|
65+
| `namingConvention` | Object | Options for naming conventions. | - |
66+
| `namingConvention.type` | Function | A function that returns the format of the type. | _Returns pascal cased name_ |
67+
| `namingConvention.field` | Function | A function that returns the format of the field. | _Returns pascal cased name_ |
4068

4169
## Custom generator
4270

src/generators/AbstractGenerator.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ export interface CommonGeneratorOptions<P extends Preset = Preset> {
1313
presets?: Presets<P>;
1414
}
1515

16-
export const defaultGeneratorOptions = {
16+
export const defaultGeneratorOptions: CommonGeneratorOptions = {
1717
indentation: {
1818
type: IndentationTypes.SPACES,
1919
size: 2,
20-
},
20+
}
2121
};
2222

2323
/**
@@ -87,7 +87,7 @@ export abstract class AbstractGenerator<Options extends CommonGeneratorOptions =
8787
return {
8888
...defaultGeneratorOptions,
8989
...defaultOptions,
90-
...passedOptions,
90+
...passedOptions
9191
};
9292
}
9393
}

src/generators/AbstractRenderer.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1-
import { CommonGeneratorOptions } from './AbstractGenerator';
1+
import { AbstractGenerator, CommonGeneratorOptions } from './AbstractGenerator';
22
import { CommonModel, CommonInputModel, Preset } from '../models';
33
import { FormatHelpers, IndentationTypes } from '../helpers';
44

55
/**
66
* Abstract renderer with common helper methods
77
*/
8-
export abstract class AbstractRenderer<O extends CommonGeneratorOptions = CommonGeneratorOptions> {
8+
export abstract class AbstractRenderer<
9+
O extends CommonGeneratorOptions = CommonGeneratorOptions,
10+
G extends AbstractGenerator = AbstractGenerator
11+
> {
912
constructor(
1013
protected readonly options: O,
14+
readonly generator: G,
1115
protected readonly presets: Array<[Preset, unknown]>,
1216
protected readonly model: CommonModel,
1317
protected readonly inputModel: CommonInputModel,
@@ -51,6 +55,7 @@ export abstract class AbstractRenderer<O extends CommonGeneratorOptions = Common
5155
runAdditionalContentPreset(): Promise<string> {
5256
return this.runPreset('additionalContent');
5357
}
58+
5459
async runPreset<RT = string>(
5560
functionName: string,
5661
params: Record<string, unknown> = {},

src/generators/go/GoGenerator.ts

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,37 @@ import {
44
defaultGeneratorOptions,
55
} from '../AbstractGenerator';
66
import { CommonModel, CommonInputModel, RenderOutput } from '../../models';
7-
import { TypeHelpers, ModelKind } from '../../helpers';
7+
import { TypeHelpers, ModelKind, FormatHelpers } from '../../helpers';
88
import { GoPreset, GO_DEFAULT_PRESET } from './GoPreset';
99
import { StructRenderer } from './renderers/StructRenderer';
1010
import { EnumRenderer } from './renderers/EnumRenderer';
11+
import { pascalCaseTransformMerge } from 'pascal-case';
1112

12-
export type GoOptions = CommonGeneratorOptions<GoPreset>
13+
/**
14+
* The Go naming convention type
15+
*/
16+
export type GoNamingConvention = {
17+
type?: (name: string | undefined, ctx: { model: CommonModel, inputModel: CommonInputModel }) => string;
18+
field?: (name: string | undefined, ctx: { model: CommonModel, inputModel: CommonInputModel, field?: CommonModel }) => string;
19+
};
20+
21+
/**
22+
* A GoNamingConvention implementation for Go
23+
*/
24+
export const GoNamingConventionImplementation: GoNamingConvention = {
25+
type: (name: string | undefined) => {
26+
if (!name) {return '';}
27+
return FormatHelpers.toPascalCase(name, { transform: pascalCaseTransformMerge });
28+
},
29+
field: (fieldName: string | undefined) => {
30+
if (!fieldName) {return '';}
31+
return FormatHelpers.toPascalCase(fieldName, { transform: pascalCaseTransformMerge });
32+
}
33+
};
34+
35+
export interface GoOptions extends CommonGeneratorOptions<GoPreset> {
36+
namingConvention?: GoNamingConvention;
37+
}
1338

1439
/**
1540
* Generator for Go
@@ -18,6 +43,7 @@ export class GoGenerator extends AbstractGenerator<GoOptions> {
1843
static defaultOptions: GoOptions = {
1944
...defaultGeneratorOptions,
2045
defaultPreset: GO_DEFAULT_PRESET,
46+
namingConvention: GoNamingConventionImplementation
2147
};
2248

2349
constructor(
@@ -29,27 +55,25 @@ export class GoGenerator extends AbstractGenerator<GoOptions> {
2955
render(model: CommonModel, inputModel: CommonInputModel): Promise<RenderOutput> {
3056
const kind = TypeHelpers.extractKind(model);
3157
switch (kind) {
32-
case ModelKind.OBJECT: {
58+
case ModelKind.OBJECT:
3359
return this.renderStruct(model, inputModel);
34-
}
35-
case ModelKind.ENUM: {
60+
case ModelKind.ENUM:
3661
return this.renderEnum(model, inputModel);
3762
}
38-
}
3963

4064
return Promise.resolve(RenderOutput.toRenderOutput({ result: '', dependencies: [] }));
4165
}
4266

4367
async renderEnum(model: CommonModel, inputModel: CommonInputModel): Promise<RenderOutput> {
4468
const presets = this.getPresets('enum');
45-
const renderer = new EnumRenderer(this.options, presets, model, inputModel);
69+
const renderer = new EnumRenderer(this.options, this, presets, model, inputModel);
4670
const result = await renderer.runSelfPreset();
4771
return RenderOutput.toRenderOutput({ result, dependencies: renderer.dependencies });
4872
}
4973

5074
async renderStruct(model: CommonModel, inputModel: CommonInputModel): Promise<RenderOutput> {
5175
const presets = this.getPresets('struct');
52-
const renderer = new StructRenderer(this.options, presets, model, inputModel);
76+
const renderer = new StructRenderer(this.options, this, presets, model, inputModel);
5377
const result = await renderer.runSelfPreset();
5478
return RenderOutput.toRenderOutput({ result, dependencies: renderer.dependencies });
5579
}

src/generators/go/GoRenderer.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { AbstractRenderer } from '../AbstractRenderer';
2-
import { GoOptions } from './GoGenerator';
2+
import { GoGenerator, GoOptions } from './GoGenerator';
33
import { CommonModel, CommonInputModel, Preset } from '../../models';
44
import { FormatHelpers } from '../../helpers/FormatHelpers';
5-
import { pascalCaseTransformMerge } from 'pascal-case';
65

76
/**
87
* Common renderer for Go types
@@ -12,11 +11,12 @@ import { pascalCaseTransformMerge } from 'pascal-case';
1211
export abstract class GoRenderer extends AbstractRenderer<GoOptions> {
1312
constructor(
1413
options: GoOptions,
14+
generator: GoGenerator,
1515
presets: Array<[Preset, unknown]>,
1616
model: CommonModel,
1717
inputModel: CommonInputModel,
1818
) {
19-
super(options, presets, model, inputModel);
19+
super(options, generator, presets, model, inputModel);
2020
}
2121

2222
async renderFields(): Promise<string> {
@@ -31,13 +31,40 @@ export abstract class GoRenderer extends AbstractRenderer<GoOptions> {
3131
return this.renderBlock(content);
3232
}
3333

34+
/**
35+
* Renders the name of a type based on provided generator option naming convention type function.
36+
*
37+
* This is used to render names of models and then later used if that class is referenced from other models.
38+
*
39+
* @param name
40+
* @param model
41+
*/
42+
nameType(name: string | undefined, model?: CommonModel): string {
43+
return this.options?.namingConvention?.type
44+
? this.options.namingConvention.type(name, { model: model || this.model, inputModel: this.inputModel })
45+
: name || '';
46+
}
47+
48+
/**
49+
* Renders the name of a field based on provided generator option naming convention field function.
50+
*
51+
* @param fieldName
52+
* @param property
53+
*/
54+
nameField(fieldName: string | undefined, field?: CommonModel): string {
55+
return this.options?.namingConvention?.field
56+
? this.options.namingConvention.field(fieldName, { model: this.model, inputModel: this.inputModel, field })
57+
: fieldName || '';
58+
}
59+
3460
runFieldPreset(fieldName: string, field: CommonModel): Promise<string> {
3561
return this.runPreset('field', { fieldName, field });
3662
}
3763

3864
renderType(model: CommonModel): string {
3965
if (model.$ref !== undefined) {
40-
return `*${FormatHelpers.toPascalCase(model.$ref, { transform: pascalCaseTransformMerge })}`;
66+
const formattedRef = this.nameType(model.$ref);
67+
return `*${formattedRef}`;
4168
}
4269

4370
if (Array.isArray(model.type)) {

src/generators/go/renderers/EnumRenderer.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { GoRenderer } from '../GoRenderer';
22
import { EnumPreset, CommonModel } from '../../../models';
3-
import { FormatHelpers } from '../../../helpers';
43

54
/**
65
* Renderer for Go's `enum` type
@@ -9,7 +8,7 @@ import { FormatHelpers } from '../../../helpers';
98
*/
109
export class EnumRenderer extends GoRenderer {
1110
public defaultSelf(): string {
12-
const formattedName = this.model.$id && FormatHelpers.toPascalCase(this.model.$id);
11+
const formattedName = this.nameType(this.model.$id);
1312
const type = this.enumType(this.model);
1413
const doc = formattedName && this.renderCommentForEnumType(formattedName, type);
1514

src/generators/go/renderers/StructRenderer.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import { GoRenderer } from '../GoRenderer';
22
import { StructPreset } from '../GoPreset';
3-
import { FormatHelpers } from '../../../helpers/FormatHelpers';
4-
import { pascalCaseTransformMerge } from 'pascal-case';
53

64
/**
75
* Renderer for Go's `struct` type
@@ -14,8 +12,8 @@ export class StructRenderer extends GoRenderer {
1412
await this.renderFields(),
1513
await this.runAdditionalContentPreset()
1614
];
17-
18-
const formattedName = this.model.$id && FormatHelpers.toPascalCase(this.model.$id, { transform: pascalCaseTransformMerge });
15+
16+
const formattedName = this.nameType(this.model.$id);
1917
const doc = this.renderComments(`${formattedName} represents a ${formattedName} model.`);
2018

2119
return `${doc}
@@ -30,6 +28,7 @@ export const GO_DEFAULT_STRUCT_PRESET: StructPreset<StructRenderer> = {
3028
return renderer.defaultSelf();
3129
},
3230
field({ fieldName, field, renderer }) {
33-
return `${FormatHelpers.toPascalCase(fieldName, { transform: pascalCaseTransformMerge }) } ${ renderer.renderType(field)}`;
31+
fieldName = renderer.nameField(fieldName, field);
32+
return `${ fieldName } ${ renderer.renderType(field)}`;
3433
},
3534
};

src/generators/java/JavaGenerator.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,20 @@ import {
44
defaultGeneratorOptions,
55
} from '../AbstractGenerator';
66
import { CommonModel, CommonInputModel, RenderOutput } from '../../models';
7-
import { ModelKind, TypeHelpers } from '../../helpers';
7+
import { CommonNamingConvention, CommonNamingConventionImplementation, ModelKind, TypeHelpers } from '../../helpers';
88
import { JavaPreset, JAVA_DEFAULT_PRESET } from './JavaPreset';
99
import { ClassRenderer } from './renderers/ClassRenderer';
1010
import { EnumRenderer } from './renderers/EnumRenderer';
11-
12-
export type JavaOptions = CommonGeneratorOptions<JavaPreset>
13-
11+
export interface JavaOptions extends CommonGeneratorOptions<JavaPreset> {
12+
collectionType?: 'List' | 'Array';
13+
namingConvention?: CommonNamingConvention;
14+
}
1415
export class JavaGenerator extends AbstractGenerator<JavaOptions> {
1516
static defaultOptions: JavaOptions = {
1617
...defaultGeneratorOptions,
17-
defaultPreset: JAVA_DEFAULT_PRESET,
18+
defaultPreset: JAVA_DEFAULT_PRESET,
19+
collectionType: 'Array',
20+
namingConvention: CommonNamingConventionImplementation
1821
};
1922

2023
constructor(
@@ -33,14 +36,14 @@ export class JavaGenerator extends AbstractGenerator<JavaOptions> {
3336

3437
async renderClass(model: CommonModel, inputModel: CommonInputModel): Promise<RenderOutput> {
3538
const presets = this.getPresets('class');
36-
const renderer = new ClassRenderer(this.options, presets, model, inputModel);
39+
const renderer = new ClassRenderer(this.options, this, presets, model, inputModel);
3740
const result = await renderer.runSelfPreset();
3841
return RenderOutput.toRenderOutput({result, dependencies: renderer.dependencies});
3942
}
4043

4144
async renderEnum(model: CommonModel, inputModel: CommonInputModel): Promise<RenderOutput> {
4245
const presets = this.getPresets('enum');
43-
const renderer = new EnumRenderer(this.options, presets, model, inputModel);
46+
const renderer = new EnumRenderer(this.options, this, presets, model, inputModel);
4447
const result = await renderer.runSelfPreset();
4548
return RenderOutput.toRenderOutput({result, dependencies: renderer.dependencies});
4649
}

0 commit comments

Comments
 (0)