From e9ca783adbd09663ce66a76ae36fe06c5e36cd91 Mon Sep 17 00:00:00 2001 From: Jonas Lagoni Date: Wed, 28 Jul 2021 14:09:16 +0200 Subject: [PATCH] fix: ensure reserved keywords can never be rendered for TS output (#311) --- docs/generators.md | 6 +-- .../typescript/TypeScriptRenderer.ts | 9 +++-- test/generators/java/JavaRenderer.spec.ts | 8 ++++ .../typescript/TypeScriptGenerator.spec.ts | 40 +++++++++++++++++++ .../typescript/TypeScriptRenderer.spec.ts | 8 ++++ 5 files changed, 65 insertions(+), 6 deletions(-) diff --git a/docs/generators.md b/docs/generators.md index c48facb71d..1d67c448d3 100644 --- a/docs/generators.md +++ b/docs/generators.md @@ -38,8 +38,8 @@ Below is a list of additional options available for a given generator. | `renderTypes` | Boolean | Render signature for types. | `true` | | `modelType` | String | It indicates which model type should be rendered for the `object` type. Its value can be either `interface` or `class`. | `class` | | `namingConvention` | Object | Options for naming conventions. | - | -| `namingConvention.type` | Function | A function that returns the format of the type. | _Returns pascal cased name_ | -| `namingConvention.property` | Function | A function that returns the format of the property. | _Returns camel cased name_ | +| `namingConvention.type` | Function | A function that returns the format of the type. | _Returns pascal cased name, and ensures that reserved keywords are never rendered__ | +| `namingConvention.property` | Function | A function that returns the format of the property. | _Returns camel cased name, and ensures that names of properties does not clash against reserved keywords_ | ### [Java](../src/generators/java/JavaGenerator.ts) @@ -47,7 +47,7 @@ Below is a list of additional options available for a given generator. |---|---|---|---| | `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` | | `namingConvention` | Object | Options for naming conventions. | - | -| `namingConvention.type` | Function | A function that returns the format of the type. | _Returns pascal cased name_ | +| `namingConvention.type` | Function | A function that returns the format of the type. | _Returns pascal cased name, and ensures that reserved keywords are never rendered__ | | `namingConvention.property` | Function | A function that returns the format of the property. | _Returns camel cased name, and ensures that names of properties does not clash against reserved keywords_ | ### [JavaScript](../src/generators/javascript/JavaScriptGenerator.ts) diff --git a/src/generators/typescript/TypeScriptRenderer.ts b/src/generators/typescript/TypeScriptRenderer.ts index 468b3aea7a..2fbf520904 100644 --- a/src/generators/typescript/TypeScriptRenderer.ts +++ b/src/generators/typescript/TypeScriptRenderer.ts @@ -68,7 +68,6 @@ export const ReservedTypeScriptKeywords = [ 'static', 'yield' ]; - /** * Common renderer for TypeScript types * @@ -85,6 +84,10 @@ export abstract class TypeScriptRenderer extends AbstractRenderer { const name = renderer.nameType('type__someType'); expect(name).toEqual('TypeSomeType'); }); + test('should render reserved type keyword correctly', () => { + const name = renderer.nameType('enum'); + expect(name).toEqual('ReservedEnum'); + }); }); describe('nameProperty()', () => { @@ -22,6 +26,10 @@ describe('JavaRenderer', () => { const name = renderer.nameProperty('property__someProperty'); expect(name).toEqual('propertySomeProperty'); }); + test('should render reserved property keyword correctly', () => { + const name = renderer.nameProperty('enum'); + expect(name).toEqual('reservedEnum'); + }); }); describe('renderType()', () => { test('Should render refs with pascal case', () => { diff --git a/test/generators/typescript/TypeScriptGenerator.spec.ts b/test/generators/typescript/TypeScriptGenerator.spec.ts index 5626970244..442a5bf025 100644 --- a/test/generators/typescript/TypeScriptGenerator.spec.ts +++ b/test/generators/typescript/TypeScriptGenerator.spec.ts @@ -5,6 +5,46 @@ describe('TypeScriptGenerator', () => { beforeEach(() => { generator = new TypeScriptGenerator(); }); + + test('should not render `class` with reserved keyword', async () => { + const doc = { + $id: 'Address', + type: 'object', + properties: { + enum: { type: 'string' }, + reservedEnum: { type: 'string' } + }, + additionalProperties: false + }; + const expected = `export class Address { + private _reservedReservedEnum?: string; + private _reservedEnum?: string; + + constructor(input: { + reservedReservedEnum?: string, + reservedEnum?: string, + }) { + this._reservedReservedEnum = input.reservedReservedEnum; + this._reservedEnum = input.reservedEnum; + } + + get reservedReservedEnum(): string | undefined { return this._reservedReservedEnum; } + set reservedReservedEnum(reservedReservedEnum: string | undefined) { this._reservedReservedEnum = reservedReservedEnum; } + + get reservedEnum(): string | undefined { return this._reservedEnum; } + set reservedEnum(reservedEnum: string | undefined) { this._reservedEnum = reservedEnum; } +}`; + + const inputModel = await generator.process(doc); + const model = inputModel.models['Address']; + + let classModel = await generator.renderClass(model, inputModel); + expect(classModel.result).toEqual(expected); + + classModel = await generator.render(model, inputModel); + expect(classModel.result).toEqual(expected); + }); + test('should render `class` type', async () => { const doc = { $id: '_address', diff --git a/test/generators/typescript/TypeScriptRenderer.spec.ts b/test/generators/typescript/TypeScriptRenderer.spec.ts index 4479c0f2b5..441dd1fd6b 100644 --- a/test/generators/typescript/TypeScriptRenderer.spec.ts +++ b/test/generators/typescript/TypeScriptRenderer.spec.ts @@ -15,6 +15,10 @@ describe('TypeScriptRenderer', () => { const name = renderer.nameType('type__someType'); expect(name).toEqual('TypeSomeType'); }); + test('should render reserved type keyword correctly', () => { + const name = renderer.nameType('enum'); + expect(name).toEqual('ReservedEnum'); + }); }); describe('nameProperty()', () => { @@ -22,6 +26,10 @@ describe('TypeScriptRenderer', () => { const name = renderer.nameProperty('property__someProperty'); expect(name).toEqual('propertySomeProperty'); }); + test('should render reserved property keyword correctly', () => { + const name = renderer.nameProperty('enum'); + expect(name).toEqual('reservedEnum'); + }); }); describe('renderComments()', () => {