Skip to content

Commit e3c2f62

Browse files
chore: improve generators and presets (#60)
1 parent 6906c8e commit e3c2f62

File tree

18 files changed

+189
-154
lines changed

18 files changed

+189
-154
lines changed

src/generators/AbstractGenerator.ts

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1-
import { AbstractRenderer } from './AbstractRenderer';
2-
import { CommonInputModel, CommonModel, OutputModel, Preset, Presets, isPresetWithOptions } from '../models';
1+
import { CommonInputModel, CommonModel, OutputModel, Preset, Presets } from '../models';
32
import { InputProcessor } from '../processors';
43
import { IndentationTypes } from '../helpers';
4+
import { isPresetWithOptions } from '../utils';
55

6-
export interface CommonGeneratorOptions<P extends Preset = Preset, R extends Record<string, AbstractRenderer> = any> {
6+
export interface CommonGeneratorOptions<P extends Preset = Preset> {
77
indentation?: {
88
type: IndentationTypes;
99
size: number;
1010
};
11-
renderers?: R;
1211
defaultPreset?: P;
1312
presets?: Presets<P>;
1413
}
@@ -24,7 +23,6 @@ export const defaultGeneratorOptions = {
2423
* Abstract generator which must be implemented by each language
2524
*/
2625
export abstract class AbstractGenerator<Options extends CommonGeneratorOptions = CommonGeneratorOptions> {
27-
private processor = new InputProcessor();
2826
protected options: Options;
2927

3028
constructor(
@@ -38,7 +36,7 @@ export abstract class AbstractGenerator<Options extends CommonGeneratorOptions =
3836
public abstract render(model: CommonModel, inputModel: CommonInputModel): Promise<string>;
3937

4038
public async process(input: any): Promise<CommonInputModel> {
41-
return await this.processor.process(input);
39+
return await InputProcessor.processor.process(input);
4240
}
4341

4442
public generate(input: CommonInputModel): Promise<OutputModel[]>;
@@ -63,33 +61,34 @@ export abstract class AbstractGenerator<Options extends CommonGeneratorOptions =
6361
protected getPresets(presetType: string): Array<[Preset, unknown]> {
6462
const filteredPresets: Array<[Preset, unknown]> = [];
6563

66-
const defaultPreset = this.options.defaultPreset!;
67-
filteredPresets.push([defaultPreset[presetType], undefined]);
64+
const defaultPreset = this.options.defaultPreset;
65+
if (defaultPreset !== undefined) {
66+
filteredPresets.push([defaultPreset[String(presetType)], undefined]);
67+
}
6868

6969
const presets = this.options.presets || [];
7070
presets.forEach(p => {
7171
if (isPresetWithOptions(p)) {
72-
const preset = p.preset[presetType];
73-
preset && filteredPresets.push([preset, p.options]);
72+
const preset = p.preset[String(presetType)];
73+
if (preset) {
74+
filteredPresets.push([preset, p.options]);
75+
}
7476
} else {
75-
const preset = p[presetType];
76-
preset && filteredPresets.push([preset, undefined]);
77+
const preset = p[String(presetType)];
78+
if (preset) {
79+
filteredPresets.push([preset, undefined]);
80+
}
7781
}
7882
});
7983

8084
return filteredPresets;
8185
}
8286

8387
protected mergeOptions(defaultOptions: Options = {} as any, passedOptions: Options = {} as any): Options {
84-
const renders = {
85-
...(defaultOptions.renderers || {}),
86-
...(passedOptions.renderers || {})
87-
};
8888
return {
8989
...defaultGeneratorOptions,
9090
...defaultOptions,
9191
...passedOptions,
92-
renders,
9392
};
9493
}
9594
}

src/generators/AbstractRenderer.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export abstract class AbstractRenderer<O extends CommonGeneratorOptions = Common
1919

2020
renderBlock(lines: string[], newLines = 1): string {
2121
const n = Array(newLines).fill('\n').join('');
22-
return lines.join(n);
22+
return lines.filter(Boolean).join(n);
2323
}
2424

2525
indent(
@@ -36,14 +36,18 @@ export abstract class AbstractRenderer<O extends CommonGeneratorOptions = Common
3636
return this.runPreset('self');
3737
}
3838

39+
async runAdditionalContentPreset(): Promise<string> {
40+
return this.runPreset('additionalContent');
41+
}
42+
3943
async runPreset(
4044
functionName: string,
4145
params: object = {},
4246
): Promise<string> {
4347
let content = '';
4448
for (const [preset, options] of this.presets) {
45-
if (typeof preset[functionName] === 'function') {
46-
content = await preset[functionName]({
49+
if (typeof preset[String(functionName)] === 'function') {
50+
content = await preset[String(functionName)]({
4751
...params,
4852
renderer: this,
4953
content,

src/generators/java/renderers/ClassRenderer.ts

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,15 @@ import { FormatHelpers } from '../../../helpers';
1010
*/
1111
export class ClassRenderer extends JavaRenderer {
1212
async defaultSelf(): Promise<string> {
13-
return `public class ${this.model.$id} {
14-
${this.indent(await this.renderProperties())}
13+
const content = [
14+
await this.renderProperties(),
15+
await this.runCtorPreset(),
16+
await this.renderAccessors(),
17+
await this.runAdditionalContentPreset(),
18+
];
1519

16-
${this.indent(await this.renderAccessors())}
20+
return `public class ${this.model.$id} {
21+
${this.indent(this.renderBlock(content, 2))}
1722
}`;
1823
}
1924

@@ -26,36 +31,36 @@ ${this.indent(await this.renderAccessors())}
2631
const content: string[] = [];
2732

2833
for (const [propertyName, property] of Object.entries(properties)) {
29-
const rendererProperty = await this.runPropertyPreset(propertyName, property);
34+
const rendererProperty = await this.runPropertyPreset(propertyName, property, this.model);
3035
content.push(rendererProperty);
3136
}
3237

3338
return this.renderBlock(content);
3439
}
3540

36-
async runPropertyPreset(propertyName: string, property: CommonModel): Promise<string> {
37-
return this.runPreset('property', { propertyName, property });
41+
async runPropertyPreset(propertyName: string, property: CommonModel, parentModel: CommonModel): Promise<string> {
42+
return this.runPreset('property', { propertyName, property, parentModel });
3843
}
3944

4045
async renderAccessors(): Promise<string> {
4146
const properties = this.model.properties || {};
4247
const content: string[] = [];
4348

4449
for (const [propertyName, property] of Object.entries(properties)) {
45-
const getter = await this.runGetterPreset(propertyName, property);
46-
const setter = await this.runSetterPreset(propertyName, property);
50+
const getter = await this.runGetterPreset(propertyName, property, this.model);
51+
const setter = await this.runSetterPreset(propertyName, property, this.model);
4752
content.push(this.renderBlock([getter, setter]));
4853
}
4954

5055
return this.renderBlock(content, 2);
5156
}
5257

53-
async runGetterPreset(propertyName: string, property: CommonModel): Promise<string> {
54-
return this.runPreset('getter', { propertyName, property });
58+
async runGetterPreset(propertyName: string, property: CommonModel, parentModel: CommonModel): Promise<string> {
59+
return this.runPreset('getter', { propertyName, property, parentModel });
5560
}
5661

57-
async runSetterPreset(propertyName: string, property: CommonModel): Promise<string> {
58-
return this.runPreset('setter', { propertyName, property });
62+
async runSetterPreset(propertyName: string, property: CommonModel, parentModel: CommonModel): Promise<string> {
63+
return this.runPreset('setter', { propertyName, property, parentModel });
5964
}
6065
}
6166

src/generators/java/renderers/EnumRenderer.ts

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { JavaRenderer } from '../JavaRenderer';
22

3-
import { EnumPreset } from '../../../models';
3+
import { CommonModel, EnumPreset } from '../../../models';
44
import { FormatHelpers } from '../../../helpers';
55

66
/**
@@ -10,14 +10,13 @@ import { FormatHelpers } from '../../../helpers';
1010
*/
1111
export class EnumRenderer extends JavaRenderer {
1212
async defaultSelf(): Promise<string> {
13-
const enumName = this.model.$id;
14-
const type = Array.isArray(this.model.type) ? 'Object' : this.model.type!;
15-
const classType = this.toClassType(this.toJavaType(type, this.model));
13+
const content = [
14+
await this.renderItems(),
15+
await this.runAdditionalContentPreset(),
16+
];
1617

17-
return `public enum ${enumName} {
18-
${this.indent(await this.renderItems())};
19-
20-
${this.indent(this.renderHelpers(enumName!, classType))}
18+
return `public enum ${this.model.$id} {
19+
${this.indent(this.renderBlock(content, 2))}
2120
}`;
2221
}
2322

@@ -26,11 +25,12 @@ ${this.indent(this.renderHelpers(enumName!, classType))}
2625
const items: string[] = [];
2726

2827
for (const value of enums) {
29-
const renderedItem = await this.runItemPreset(value);
28+
const renderedItem = await this.runItemPreset(value, this.model);
3029
items.push(renderedItem);
3130
}
3231

33-
return items.join(', ');
32+
const content = items.join(', ');
33+
return `${content};`;
3434
}
3535

3636
normalizeKey(value: any): string {
@@ -55,9 +55,27 @@ ${this.indent(this.renderHelpers(enumName!, classType))}
5555
}
5656
}
5757

58-
renderHelpers(enumName: string, classType: string): string {
58+
async runItemPreset(item: any, parentModel: CommonModel): Promise<string> {
59+
return this.runPreset('item', { item, parentModel });
60+
}
61+
}
62+
63+
export const JAVA_DEFAULT_ENUM_PRESET: EnumPreset<EnumRenderer> = {
64+
self({ renderer }) {
65+
return renderer.defaultSelf();
66+
},
67+
item({ renderer, item }) {
68+
const key = renderer.normalizeKey(item);
69+
const value = renderer.normalizeValue(item);
70+
return `${key}(${value})`;
71+
},
72+
additionalContent({ renderer, model }) {
73+
const enumName = model.$id;
74+
const type = Array.isArray(model.type) ? 'Object' : model.type;
75+
const classType = renderer.toClassType(renderer.toJavaType(type, model));
76+
5977
return `private ${classType} value;
60-
78+
6179
${enumName}(${classType} value) {
6280
this.value = value;
6381
}
@@ -81,20 +99,5 @@ public static ${enumName} fromValue(${classType} value) {
8199
}
82100
throw new IllegalArgumentException("Unexpected value '" + value + "'");
83101
}`;
84-
}
85-
86-
async runItemPreset(item: any): Promise<string> {
87-
return this.runPreset('item', { item });
88-
}
89-
}
90-
91-
export const JAVA_DEFAULT_ENUM_PRESET: EnumPreset<EnumRenderer> = {
92-
self({ renderer }) {
93-
return renderer.defaultSelf();
94-
},
95-
item({ renderer, item }) {
96-
const key = renderer.normalizeKey(item);
97-
const value = renderer.normalizeValue(item);
98-
return `${key}(${value})`;
99102
},
100103
};

src/generators/javascript/renderers/ClassRenderer.ts

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@ import { FormatHelpers } from '../../../helpers';
1010
*/
1111
export class ClassRenderer extends JavaScriptRenderer {
1212
public async defaultSelf(): Promise<string> {
13+
const content = [
14+
await this.renderProperties(),
15+
await this.runCtorPreset(),
16+
await this.renderAccessors(),
17+
await this.runAdditionalContentPreset(),
18+
];
19+
1320
return `class ${this.model.$id} {
14-
${this.indent(await this.renderProperties())}
15-
16-
${this.indent(await this.runCtorPreset())}
17-
18-
${this.indent(await this.renderAccessors())}
21+
${this.indent(this.renderBlock(content, 2))}
1922
}`;
2023
}
2124

@@ -28,20 +31,20 @@ ${this.indent(await this.renderAccessors())}
2831
const content: string[] = [];
2932

3033
for (const [propertyName, property] of Object.entries(properties)) {
31-
const getter = await this.runGetterPreset(propertyName, property);
32-
const setter = await this.runSetterPreset(propertyName, property);
34+
const getter = await this.runGetterPreset(propertyName, property, this.model);
35+
const setter = await this.runSetterPreset(propertyName, property, this.model);
3336
content.push(this.renderBlock([getter, setter]));
3437
}
3538

3639
return this.renderBlock(content, 2);
3740
}
3841

39-
async runGetterPreset(propertyName: string, property: CommonModel): Promise<string> {
40-
return this.runPreset('getter', { propertyName, property });
42+
async runGetterPreset(propertyName: string, property: CommonModel, parentModel: CommonModel): Promise<string> {
43+
return this.runPreset('getter', { propertyName, property, parentModel });
4144
}
4245

43-
async runSetterPreset(propertyName: string, property: CommonModel): Promise<string> {
44-
return this.runPreset('setter', { propertyName, property });
46+
async runSetterPreset(propertyName: string, property: CommonModel, parentModel: CommonModel): Promise<string> {
47+
return this.runPreset('setter', { propertyName, property, parentModel });
4548
}
4649
}
4750

src/generators/typescript/TypeScriptGenerator.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { TypeRenderer } from './renderers/TypeRenderer';
1515

1616
export interface TypeScriptOptions extends CommonGeneratorOptions<TypeScriptPreset> {
1717
renderTypes?: boolean
18-
modelType?: 'class' | 'interface' | 'type';
18+
modelType?: 'class' | 'interface';
1919
}
2020

2121
/**
@@ -78,9 +78,6 @@ export class TypeScriptGenerator extends AbstractGenerator<TypeScriptOptions> {
7878
case 'interface': {
7979
return this.renderInterface(model, inputModel);
8080
}
81-
case 'type': {
82-
return this.renderType(model, inputModel);
83-
}
8481
default: return this.renderClass(model, inputModel);
8582
}
8683
}

src/generators/typescript/TypeScriptRenderer.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ export abstract class TypeScriptRenderer extends AbstractRenderer<TypeScriptOpti
5454
}
5555
}
5656

57-
renderTypeSignature(type: CommonModel | CommonModel[], isOptional = false): string {
57+
renderTypeSignature(type: CommonModel | CommonModel[], isRequired = true): string {
5858
if (this.options.renderTypes === false) {
5959
return '';
6060
}
61-
const annotation = isOptional ? '?:' : ':';
61+
const annotation = isRequired ? ':' : '?:';
6262
return `${annotation} ${this.renderType(type)}`;
6363
}
6464

@@ -74,20 +74,20 @@ ${lines.map(line => ` * ${line}`).join('\n')}
7474
const content: string[] = [];
7575

7676
for (const [propertyName, property] of Object.entries(properties)) {
77-
const rendererProperty = await this.runPropertyPreset(propertyName, property);
77+
const rendererProperty = await this.runPropertyPreset(propertyName, property, this.model);
7878
content.push(rendererProperty);
7979
}
8080

8181
return this.renderBlock(content);
8282
}
8383

84-
renderProperty(propertyName: string, property: CommonModel): string {
85-
propertyName = FormatHelpers.toCamelCase(propertyName);
86-
const signature = this.renderTypeSignature(property, true);
87-
return `${propertyName}${signature};`;
84+
renderProperty(propertyName: string, property: CommonModel, parentModel: CommonModel): string {
85+
const name = FormatHelpers.toCamelCase(propertyName);
86+
const signature = this.renderTypeSignature(property, parentModel.isRequired(propertyName));
87+
return `${name}${signature};`;
8888
}
8989

90-
async runPropertyPreset(propertyName: string, property: CommonModel): Promise<string> {
91-
return this.runPreset('property', { propertyName, property });
90+
async runPropertyPreset(propertyName: string, property: CommonModel, parentModel: CommonModel): Promise<string> {
91+
return this.runPreset('property', { propertyName, property, parentModel });
9292
}
9393
}

0 commit comments

Comments
 (0)