Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: enum generation should handle union types #349

Merged
merged 12 commits into from
Sep 3, 2021
5 changes: 4 additions & 1 deletion src/generators/csharp/renderers/EnumRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,12 @@ export const CSHARP_DEFAULT_ENUM_PRESET: EnumPreset<EnumRenderer> = {
},
item({ item }) {
let itemName = String(item);
if (typeof item === 'number') {
if (typeof item === 'number' || typeof item === 'bigint') {
itemName = `Number_${itemName}`;
} else if (typeof item === 'object') {
itemName = `${JSON.stringify(item)}`;
}

return pascalCase(itemName);
},
};
6 changes: 6 additions & 0 deletions src/generators/java/renderers/EnumRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ ${this.indent(this.renderBlock(content, 2))}
case 'boolean': {
return FormatHelpers.toConstantCase(`boolean ${value}`);
}
case 'object': {
return FormatHelpers.toConstantCase(JSON.stringify(value));
}
default: return FormatHelpers.toConstantCase(String(value));
}
}
Expand All @@ -49,6 +52,9 @@ ${this.indent(this.renderBlock(content, 2))}
if (typeof value === 'string') {
return `"${value}"`;
}
if (typeof value === 'object') {
return `"${JSON.stringify(value).replace(/"/g, '\\"')}"`;
magicmatatjahu marked this conversation as resolved.
Show resolved Hide resolved
}
return String(value);
}

Expand Down
48 changes: 46 additions & 2 deletions src/generators/typescript/renderers/EnumRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,57 @@ ${this.indent(this.renderBlock(content, 2))}
runItemPreset(item: any): Promise<string> {
return this.runPreset('item', { item });
}

normalizeKey(value: any): any {
let key;
switch (typeof value) {
case 'bigint':
case 'number': {
key = `number ${value}`;
break;
}
case 'object': {
key = JSON.stringify(value);
break;
}
default: {
key = String(value);
}
}
return FormatHelpers.toConstantCase(key);
}

normalizeValue(value: any): any {
let normalizedValue;
switch (typeof value) {
case 'string':
case 'boolean':
normalizedValue = `"${value}"`;
magicmatatjahu marked this conversation as resolved.
Show resolved Hide resolved
break;
case 'bigint':
case 'number': {
normalizedValue = value;
break;
}
case 'object': {
normalizedValue = `'${JSON.stringify(value)}'`;
magicmatatjahu marked this conversation as resolved.
Show resolved Hide resolved
break;
}
default: {
normalizedValue = String(value);
}
}
return normalizedValue;
}
}

export const TS_DEFAULT_ENUM_PRESET: EnumPreset<EnumRenderer> = {
async self({ renderer }) {
return `export ${await renderer.defaultSelf()}`;
},
item({ item }): string {
return `${FormatHelpers.toConstantCase(`${item}`)} = "${item}",`;
item({ item, renderer }): string {
const key = renderer.normalizeKey(item);
const value = renderer.normalizeValue(item);
return `${key} = ${value},`;
}
};
2 changes: 1 addition & 1 deletion test/generators/csharp/CSharpGenerator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ describe('CSharpGenerator', () => {
name: 'with enums of mixed types',
doc: {
$id: 'Things',
enum: ['Texas', 1, false],
enum: ['Texas', 1, false, {test: 'test'}],
}
},
])('should render `enum` type $name', ({doc}) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,13 +202,13 @@ exports[`CSharpGenerator should render \`enum\` type $name should not be empty 2

exports[`CSharpGenerator should render \`enum\` type $name should not be empty 3`] = `
"public enum Things {
Texas, Number_1, False
Texas, Number_1, False, TestTest
}"
`;

exports[`CSharpGenerator should render \`enum\` type $name should not be empty 4`] = `
"public enum Things {
Texas, Number_1, False
Texas, Number_1, False, TestTest
}"
`;

Expand Down
2 changes: 1 addition & 1 deletion test/generators/go/GoGenerator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ type States string`,
name: 'with enums of mixed types',
doc: {
$id: 'Things',
enum: ['Texas', 1, false],
enum: ['Texas', 1, false, {test: 'test'}],
},
expected: `// Things represents an enum of mixed types.
type Things interface{}`,
Expand Down
4 changes: 2 additions & 2 deletions test/generators/java/JavaGenerator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,10 +267,10 @@ describe('JavaGenerator', () => {
const doc = {
$id: 'Union',
type: ['string', 'integer', 'boolean'],
enum: ['Texas', 'Alabama', 0, 1, true],
enum: ['Texas', 'Alabama', 0, 1, true, {test: 'test'}],
};
const expected = `public enum Union {
TEXAS("Texas"), ALABAMA("Alabama"), NUMBER_0(0), NUMBER_1(1), BOOLEAN_TRUE(true);
TEXAS("Texas"), ALABAMA("Alabama"), NUMBER_0(0), NUMBER_1(1), BOOLEAN_TRUE(true), TEST_TEST("{\\"test\\":\\"test\\"}");

private Object value;

Expand Down
24 changes: 24 additions & 0 deletions test/generators/typescript/TypeScriptGenerator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,30 @@ ${content}`;
expect(enumModel.dependencies).toEqual([]);
});

test('should render union `enum` values', async () => {
const doc = {
$id: 'States',
enum: [2, 'test', true, {test: 'test'}]
};
const expected = `export enum States {
NUMBER_2 = 2,
TEST = "test",
TRUE = "true",
TEST_TEST = '{"test":"test"}',
}`;

const inputModel = await generator.process(doc);
const model = inputModel.models['States'];

let enumModel = await generator.render(model, inputModel);
expect(enumModel.result).toEqual(expected);
expect(enumModel.dependencies).toEqual([]);

enumModel = await generator.renderEnum(model, inputModel);
expect(enumModel.result).toEqual(expected);
expect(enumModel.dependencies).toEqual([]);
});

test('should work custom preset for `enum` type', async () => {
const doc = {
$id: 'CustomEnum',
Expand Down
6 changes: 4 additions & 2 deletions test/generators/typescript/preset/MarshallingPreset.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const doc = {
required: ['string prop'],
properties: {
'string prop': { type: 'string' },
enumProp: { $id: 'EnumTest', enum: ['Some enum String', "some other enum string"]},
enumProp: { $id: 'EnumTest', enum: ['Some enum String', true, {test: 'test'}, 2]},
numberProp: { type: 'number' },
objectProp: { $ref: '#/definitions/NestedTest' }
},
Expand Down Expand Up @@ -50,7 +50,9 @@ describe('Marshalling preset', () => {
test('should provide a two way conversion', async () => {
enum EnumTest {
SOME_ENUM_STRING = "Some enum String",
SOME_OTHER_ENUM_STRING = "some other enum string"
NUMBER_2 = 2,
TRUE = "true",
TEST_TEST = '{"test": "test"}',
}
class NestedTest {
private _stringProp?: string;
Expand Down