From 7db1bd73991b309cba1e1e3f233ed6012fa9c60f Mon Sep 17 00:00:00 2001 From: Kenneth Aasan Date: Thu, 14 Sep 2023 14:06:20 +0200 Subject: [PATCH] feat!: refactors generators to use the same arg types (#1505) --- src/generators/AbstractGenerator.ts | 43 +++++++---- .../cplusplus/CplusplusGenerator.ts | 55 ++++++++------ src/generators/csharp/CSharpGenerator.ts | 49 +++++++----- src/generators/dart/DartGenerator.ts | 42 ++++++----- src/generators/go/GoGenerator.ts | 45 ++++++----- src/generators/java/JavaGenerator.ts | 74 +++++++++++-------- .../javascript/JavaScriptGenerator.ts | 37 ++++++---- src/generators/kotlin/KotlinGenerator.ts | 44 +++++++---- src/generators/php/PhpGenerator.ts | 39 +++++----- src/generators/python/PythonGenerator.ts | 52 ++++++++----- src/generators/rust/RustGenerator.ts | 55 +++++++++----- src/generators/template/TemplateGenerator.ts | 44 +++++++---- .../typescript/TypeScriptGenerator.ts | 61 +++++++++------ test/TestUtils/TestGenerator.ts | 16 ++-- test/generators/AbstractGenerator.spec.ts | 16 ++-- 15 files changed, 418 insertions(+), 254 deletions(-) diff --git a/src/generators/AbstractGenerator.ts b/src/generators/AbstractGenerator.ts index 3f6da294e5..97de6f3826 100644 --- a/src/generators/AbstractGenerator.ts +++ b/src/generators/AbstractGenerator.ts @@ -43,6 +43,25 @@ export const defaultGeneratorOptions: CommonGeneratorOptions = { } }; +export interface AbstractGeneratorRenderArgs< + Options extends CommonGeneratorOptions, + ConstrainedModel = ConstrainedMetaModel +> { + constrainedModel: ConstrainedModel; + inputModel: InputMetaModel; + options?: DeepPartial; +} + +export interface AbstractGeneratorRenderCompleteModelArgs< + Options extends CommonGeneratorOptions, + RenderCompleteModelOptions +> { + constrainedModel: ConstrainedMetaModel; + inputModel: InputMetaModel; + completeOptions: Partial; + options?: DeepPartial; +} + /** * Abstract generator which must be implemented by each language */ @@ -56,15 +75,13 @@ export abstract class AbstractGenerator< ) {} public abstract render( - model: MetaModel, - inputModel: InputMetaModel, - options?: DeepPartial + args: AbstractGeneratorRenderArgs ): Promise; public abstract renderCompleteModel( - model: MetaModel, - inputModel: InputMetaModel, - completeOptions: Partial, - options?: DeepPartial + args: AbstractGeneratorRenderCompleteModelArgs< + Options, + RenderCompleteModelOptions + > ): Promise; public abstract constrainToMetaModel( model: MetaModel, @@ -186,12 +203,12 @@ export abstract class AbstractGenerator< return Promise.all( this.getConstrainedModels(inputModel).map( async ({ constrainedModel, dependencyManager }) => { - const renderedOutput = await this.renderCompleteModel( + const renderedOutput = await this.renderCompleteModel({ constrainedModel, inputModel, completeOptions, - { dependencyManager } as DeepPartial - ); + options: { dependencyManager } as DeepPartial + }); return OutputModel.toOutputModel({ result: renderedOutput.result, modelName: renderedOutput.renderedName, @@ -213,13 +230,13 @@ export abstract class AbstractGenerator< return Promise.all( this.getConstrainedModels(inputModel).map( async ({ constrainedModel, dependencyManager }) => { - const renderedOutput = await this.render( + const renderedOutput = await this.render({ constrainedModel, inputModel, - { + options: { dependencyManager } as DeepPartial - ); + }); return OutputModel.toOutputModel({ result: renderedOutput.result, modelName: renderedOutput.renderedName, diff --git a/src/generators/cplusplus/CplusplusGenerator.ts b/src/generators/cplusplus/CplusplusGenerator.ts index d3d2e57604..77654d8e24 100644 --- a/src/generators/cplusplus/CplusplusGenerator.ts +++ b/src/generators/cplusplus/CplusplusGenerator.ts @@ -1,5 +1,7 @@ import { AbstractGenerator, + AbstractGeneratorRenderArgs, + AbstractGeneratorRenderCompleteModelArgs, CommonGeneratorOptions, defaultGeneratorOptions } from '../AbstractGenerator'; @@ -121,26 +123,32 @@ export class CplusplusGenerator extends AbstractGenerator< * @param inputModel */ render( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - options?: DeepPartial + args: AbstractGeneratorRenderArgs ): Promise { const optionsToUse = CplusplusGenerator.getOptions({ ...this.options, - ...options + ...args.options }); if (isReservedCplusplusKeyword(optionsToUse.namespace)) { throw new Error( `You cannot use reserved C++ keyword (${optionsToUse.namespace}) as namespace, please use another.` ); } - if (model instanceof ConstrainedObjectModel) { - return this.renderClass(model, inputModel, optionsToUse); - } else if (model instanceof ConstrainedEnumModel) { - return this.renderEnum(model, inputModel, optionsToUse); + if (args.constrainedModel instanceof ConstrainedObjectModel) { + return this.renderClass( + args.constrainedModel, + args.inputModel, + optionsToUse + ); + } else if (args.constrainedModel instanceof ConstrainedEnumModel) { + return this.renderEnum( + args.constrainedModel, + args.inputModel, + optionsToUse + ); } Logger.warn( - `C++ generator, cannot generate this type of model, ${model.name}` + `C++ generator, cannot generate this type of model, ${args.constrainedModel.name}` ); return Promise.resolve( RenderOutput.toRenderOutput({ @@ -161,30 +169,35 @@ export class CplusplusGenerator extends AbstractGenerator< * @param options used to render the full output */ async renderCompleteModel( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - completeModelOptions: Partial, - options: DeepPartial + args: AbstractGeneratorRenderCompleteModelArgs< + CplusplusOptions, + CplusplusRenderCompleteModelOptions + > ): Promise { // eslint-disable-next-line @typescript-eslint/no-unused-vars const completeModelOptionsToUse = mergePartialAndDefault( CplusplusGenerator.defaultCompleteModelOptions, - completeModelOptions + args.completeOptions ) as CplusplusRenderCompleteModelOptions; const optionsToUse = CplusplusGenerator.getOptions({ ...this.options, - ...options + ...args.options }); const dependencyManagerToUse = this.getDependencyManager(optionsToUse); - const outputModel = await this.render(model, inputModel, { - ...optionsToUse, - dependencyManager: dependencyManagerToUse + const outputModel = await this.render({ + ...args, + options: { + ...optionsToUse, + dependencyManager: dependencyManagerToUse + } }); - const imports = model.getNearestDependencies().map((model) => { - return `#include "${model.name}.hpp"`; - }); + const imports = args.constrainedModel + .getNearestDependencies() + .map((model) => { + return `#include "${model.name}.hpp"`; + }); const formattedOutputResult = FormatHelpers.indent( outputModel.result, 2, diff --git a/src/generators/csharp/CSharpGenerator.ts b/src/generators/csharp/CSharpGenerator.ts index b9018b88eb..39d14f7c2e 100644 --- a/src/generators/csharp/CSharpGenerator.ts +++ b/src/generators/csharp/CSharpGenerator.ts @@ -1,5 +1,7 @@ import { AbstractGenerator, + AbstractGeneratorRenderArgs, + AbstractGeneratorRenderCompleteModelArgs, CommonGeneratorOptions, defaultGeneratorOptions } from '../AbstractGenerator'; @@ -146,18 +148,18 @@ export class CSharpGenerator extends AbstractGenerator< * @param options used to render the full output */ async renderCompleteModel( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - completeModelOptions: DeepPartial, - options: DeepPartial + args: AbstractGeneratorRenderCompleteModelArgs< + CSharpOptions, + CSharpRenderCompleteModelOptions + > ): Promise { const completeModelOptionsToUse = mergePartialAndDefault( CSharpGenerator.defaultCompleteModelOptions, - completeModelOptions + args.completeOptions ) as CSharpRenderCompleteModelOptions; const optionsToUse = CSharpGenerator.getCSharpOptions({ ...this.options, - ...options + ...args.options }); if (isReservedCSharpKeyword(completeModelOptionsToUse.namespace)) { throw new Error( @@ -165,7 +167,10 @@ export class CSharpGenerator extends AbstractGenerator< ); } - const outputModel = await this.render(model, inputModel); + const outputModel = await this.render({ + ...args, + options: optionsToUse + }); const outputDependencies = outputModel.dependencies.length === 0 @@ -189,24 +194,34 @@ ${FormatHelpers.indent( } render( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - options?: DeepPartial + args: AbstractGeneratorRenderArgs ): Promise { const optionsToUse = CSharpGenerator.getCSharpOptions({ ...this.options, - ...options + ...args.options }); - if (model instanceof ConstrainedObjectModel) { + if (args.constrainedModel instanceof ConstrainedObjectModel) { if (this.options.modelType === 'record') { - return this.renderRecord(model, inputModel, optionsToUse); + return this.renderRecord( + args.constrainedModel, + args.inputModel, + optionsToUse + ); } - return this.renderClass(model, inputModel, optionsToUse); - } else if (model instanceof ConstrainedEnumModel) { - return this.renderEnum(model, inputModel, optionsToUse); + return this.renderClass( + args.constrainedModel, + args.inputModel, + optionsToUse + ); + } else if (args.constrainedModel instanceof ConstrainedEnumModel) { + return this.renderEnum( + args.constrainedModel, + args.inputModel, + optionsToUse + ); } Logger.warn( - `C# generator, cannot generate this type of model, ${model.name}` + `C# generator, cannot generate this type of model, ${args.constrainedModel.name}` ); return Promise.resolve( RenderOutput.toRenderOutput({ diff --git a/src/generators/dart/DartGenerator.ts b/src/generators/dart/DartGenerator.ts index 5fdf6280c9..c924f851ca 100644 --- a/src/generators/dart/DartGenerator.ts +++ b/src/generators/dart/DartGenerator.ts @@ -1,5 +1,7 @@ import { AbstractGenerator, + AbstractGeneratorRenderArgs, + AbstractGeneratorRenderCompleteModelArgs, CommonGeneratorOptions, defaultGeneratorOptions } from '../AbstractGenerator'; @@ -121,21 +123,27 @@ export class DartGenerator extends AbstractGenerator< * @param inputModel */ render( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - options?: DeepPartial + args: AbstractGeneratorRenderArgs ): Promise { const optionsToUse = DartGenerator.getDartOptions({ ...this.options, - ...options + ...args.options }); - if (model instanceof ConstrainedObjectModel) { - return this.renderClass(model, inputModel, optionsToUse); - } else if (model instanceof ConstrainedEnumModel) { - return this.renderEnum(model, inputModel, optionsToUse); + if (args.constrainedModel instanceof ConstrainedObjectModel) { + return this.renderClass( + args.constrainedModel, + args.inputModel, + optionsToUse + ); + } else if (args.constrainedModel instanceof ConstrainedEnumModel) { + return this.renderEnum( + args.constrainedModel, + args.inputModel, + optionsToUse + ); } Logger.warn( - `Dart generator, cannot generate this type of model, ${model.name}` + `Dart generator, cannot generate this type of model, ${args.constrainedModel.name}` ); return Promise.resolve( RenderOutput.toRenderOutput({ @@ -156,18 +164,18 @@ export class DartGenerator extends AbstractGenerator< * @param options used to render the full output */ async renderCompleteModel( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - completeModelOptions: Partial, - options: DeepPartial + args: AbstractGeneratorRenderCompleteModelArgs< + DartOptions, + DartRenderCompleteModelOptions + > ): Promise { const completeModelOptionsToUse = mergePartialAndDefault( DartGenerator.defaultCompleteModelOptions, - completeModelOptions + args.completeOptions ) as DartRenderCompleteModelOptions; const optionsToUse = DartGenerator.getDartOptions({ ...this.options, - ...options + ...args.options }); const dependencyManagerToUse = this.getDependencyManager(optionsToUse); if (isReservedDartKeyword(completeModelOptionsToUse.packageName)) { @@ -176,9 +184,9 @@ export class DartGenerator extends AbstractGenerator< ); } - const outputModel = await this.render(model, inputModel, optionsToUse); + const outputModel = await this.render({ ...args, options: optionsToUse }); const modelDependencies = dependencyManagerToUse.renderAllModelDependencies( - model, + args.constrainedModel, completeModelOptionsToUse.packageName ); const outputContent = `${modelDependencies} diff --git a/src/generators/go/GoGenerator.ts b/src/generators/go/GoGenerator.ts index c4c494ae2e..8fc5f5b3d3 100644 --- a/src/generators/go/GoGenerator.ts +++ b/src/generators/go/GoGenerator.ts @@ -1,5 +1,7 @@ import { AbstractGenerator, + AbstractGeneratorRenderArgs, + AbstractGeneratorRenderCompleteModelArgs, CommonGeneratorOptions, defaultGeneratorOptions } from '../AbstractGenerator'; @@ -113,22 +115,26 @@ export class GoGenerator extends AbstractGenerator< ); } - render( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - options?: DeepPartial - ): Promise { + render(args: AbstractGeneratorRenderArgs): Promise { const optionsToUse = GoGenerator.getGoOptions({ ...this.options, - ...options + ...args.options }); - if (model instanceof ConstrainedObjectModel) { - return this.renderStruct(model, inputModel, optionsToUse); - } else if (model instanceof ConstrainedEnumModel) { - return this.renderEnum(model, inputModel, optionsToUse); + if (args.constrainedModel instanceof ConstrainedObjectModel) { + return this.renderStruct( + args.constrainedModel, + args.inputModel, + optionsToUse + ); + } else if (args.constrainedModel instanceof ConstrainedEnumModel) { + return this.renderEnum( + args.constrainedModel, + args.inputModel, + optionsToUse + ); } Logger.warn( - `Go generator, cannot generate this type of model, ${model.name}` + `Go generator, cannot generate this type of model, ${args.constrainedModel.name}` ); return Promise.resolve( RenderOutput.toRenderOutput({ @@ -147,20 +153,23 @@ export class GoGenerator extends AbstractGenerator< * @param options */ async renderCompleteModel( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - completeModelOptions: Partial, - options: DeepPartial + args: AbstractGeneratorRenderCompleteModelArgs< + GoOptions, + GoRenderCompleteModelOptions + > ): Promise { const completeModelOptionsToUse = mergePartialAndDefault( GoGenerator.defaultCompleteModelOptions, - completeModelOptions + args.completeOptions ) as GoRenderCompleteModelOptions; const optionsToUse = GoGenerator.getGoOptions({ ...this.options, - ...options + ...args.options + }); + const outputModel = await this.render({ + ...args, + options: optionsToUse }); - const outputModel = await this.render(model, inputModel, optionsToUse); let importCode = ''; if (outputModel.dependencies.length > 0) { const dependencies = outputModel.dependencies diff --git a/src/generators/java/JavaGenerator.ts b/src/generators/java/JavaGenerator.ts index e6e5517482..00407aed48 100644 --- a/src/generators/java/JavaGenerator.ts +++ b/src/generators/java/JavaGenerator.ts @@ -1,5 +1,7 @@ import { AbstractGenerator, + AbstractGeneratorRenderArgs, + AbstractGeneratorRenderCompleteModelArgs, CommonGeneratorOptions, defaultGeneratorOptions } from '../AbstractGenerator'; @@ -125,26 +127,36 @@ export class JavaGenerator extends AbstractGenerator< * @param inputModel */ render( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - options?: DeepPartial + args: AbstractGeneratorRenderArgs ): Promise { const optionsToUse = JavaGenerator.getJavaOptions({ ...this.options, - ...options + ...args.options }); - if (model instanceof ConstrainedObjectModel) { - return this.renderClass(model, inputModel, optionsToUse); - } else if (model instanceof ConstrainedEnumModel) { - return this.renderEnum(model, inputModel, optionsToUse); + if (args.constrainedModel instanceof ConstrainedObjectModel) { + return this.renderClass({ + ...args, + constrainedModel: args.constrainedModel, + options: optionsToUse + }); + } else if (args.constrainedModel instanceof ConstrainedEnumModel) { + return this.renderEnum( + args.constrainedModel, + args.inputModel, + optionsToUse + ); } else if ( - model instanceof ConstrainedUnionModel && - !unionIncludesBuiltInTypes(model) + args.constrainedModel instanceof ConstrainedUnionModel && + !unionIncludesBuiltInTypes(args.constrainedModel) ) { - return this.renderUnion(model, inputModel, optionsToUse); + return this.renderUnion( + args.constrainedModel, + args.inputModel, + optionsToUse + ); } Logger.warn( - `Java generator, cannot generate this type of model, ${model.name}` + `Java generator, cannot generate this type of model, ${args.constrainedModel.name}` ); return Promise.resolve( RenderOutput.toRenderOutput({ @@ -165,26 +177,30 @@ export class JavaGenerator extends AbstractGenerator< * @param options used to render the full output */ async renderCompleteModel( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - completeModelOptions: Partial, - options: DeepPartial + args: AbstractGeneratorRenderCompleteModelArgs< + JavaOptions, + JavaRenderCompleteModelOptions + > ): Promise { - const completeModelOptionsToUse = mergePartialAndDefault( - JavaGenerator.defaultCompleteModelOptions, - completeModelOptions - ) as JavaRenderCompleteModelOptions; + const completeModelOptionsToUse = + mergePartialAndDefault( + JavaGenerator.defaultCompleteModelOptions, + args.completeOptions + ); const optionsToUse = JavaGenerator.getJavaOptions({ ...this.options, - ...options + ...args.options }); const dependencyManagerToUse = this.getDependencyManager(optionsToUse); this.assertPackageIsValid(completeModelOptionsToUse); - const outputModel = await this.render(model, inputModel, optionsToUse); + const outputModel = await this.render({ + ...args, + options: optionsToUse + }); const modelDependencies = dependencyManagerToUse.renderAllModelDependencies( - model, + args.constrainedModel, completeModelOptionsToUse.packageName ); const outputContent = `package ${completeModelOptionsToUse.packageName}; @@ -215,13 +231,11 @@ ${outputModel.result}`; } async renderClass( - model: ConstrainedObjectModel, - inputModel: InputMetaModel, - options?: DeepPartial + args: AbstractGeneratorRenderArgs ): Promise { const optionsToUse = JavaGenerator.getJavaOptions({ ...this.options, - ...options + ...args.options }); const dependencyManagerToUse = this.getDependencyManager(optionsToUse); const presets = this.getPresets('class'); @@ -229,14 +243,14 @@ ${outputModel.result}`; optionsToUse, this, presets, - model, - inputModel, + args.constrainedModel, + args.inputModel, dependencyManagerToUse ); const result = await renderer.runSelfPreset(); return RenderOutput.toRenderOutput({ result, - renderedName: model.name, + renderedName: args.constrainedModel.name, dependencies: dependencyManagerToUse.dependencies }); } diff --git a/src/generators/javascript/JavaScriptGenerator.ts b/src/generators/javascript/JavaScriptGenerator.ts index d164696a14..84b8d9cd32 100644 --- a/src/generators/javascript/JavaScriptGenerator.ts +++ b/src/generators/javascript/JavaScriptGenerator.ts @@ -1,5 +1,7 @@ import { AbstractGenerator, + AbstractGeneratorRenderArgs, + AbstractGeneratorRenderCompleteModelArgs, CommonGeneratorOptions, defaultGeneratorOptions } from '../AbstractGenerator'; @@ -100,19 +102,22 @@ export class JavaScriptGenerator extends AbstractGenerator< */ // eslint-disable-next-line @typescript-eslint/no-unused-vars async renderCompleteModel( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - completeModelOptions: Partial, - options: DeepPartial + args: AbstractGeneratorRenderCompleteModelArgs< + JavaScriptOptions, + JavaScriptRenderCompleteModelOptions + > ): Promise { //const completeModelOptionsToUse = mergePartialAndDefault(JavaScriptGenerator.defaultCompleteModelOptions, completeModelOptions) as JavaScriptRenderCompleteModelOptions; const optionsToUse = JavaScriptGenerator.getJavaScriptOptions({ ...this.options, - ...options + ...args.options }); const dependencyManagerToUse = this.getDependencyManager(optionsToUse); - const outputModel = await this.render(model, inputModel); - const modelDependencies = model.getNearestDependencies(); + const outputModel = await this.render({ + ...args, + options: optionsToUse + }); + const modelDependencies = args.constrainedModel.getNearestDependencies(); //Ensure model dependencies have their rendered name const modelDependencyImports = modelDependencies.map((dependencyModel) => { return dependencyManagerToUse.renderDependency( @@ -141,18 +146,22 @@ ${modelCode}`; } render( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - options?: DeepPartial + args: AbstractGeneratorRenderArgs ): Promise { const optionsToUse = JavaScriptGenerator.getJavaScriptOptions({ ...this.options, - ...options + ...args.options }); - if (model instanceof ConstrainedObjectModel) { - return this.renderClass(model, inputModel, optionsToUse); + if (args.constrainedModel instanceof ConstrainedObjectModel) { + return this.renderClass( + args.constrainedModel, + args.inputModel, + optionsToUse + ); } - Logger.warn(`JS generator, cannot generate model for '${model.name}'`); + Logger.warn( + `JS generator, cannot generate model for '${args.constrainedModel.name}'` + ); return Promise.resolve( RenderOutput.toRenderOutput({ result: '', diff --git a/src/generators/kotlin/KotlinGenerator.ts b/src/generators/kotlin/KotlinGenerator.ts index 1f647bffd9..c9b5ca1523 100644 --- a/src/generators/kotlin/KotlinGenerator.ts +++ b/src/generators/kotlin/KotlinGenerator.ts @@ -1,5 +1,7 @@ import { AbstractGenerator, + AbstractGeneratorRenderArgs, + AbstractGeneratorRenderCompleteModelArgs, CommonGeneratorOptions, defaultGeneratorOptions } from '../AbstractGenerator'; @@ -126,21 +128,27 @@ export class KotlinGenerator extends AbstractGenerator< * @param inputModel */ render( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - options?: DeepPartial + args: AbstractGeneratorRenderArgs ): Promise { const optionsToUse = KotlinGenerator.getKotlinOptions({ ...this.options, - ...options + ...args.options }); - if (model instanceof ConstrainedObjectModel) { - return this.renderClass(model, inputModel, optionsToUse); - } else if (model instanceof ConstrainedEnumModel) { - return this.renderEnum(model, inputModel, optionsToUse); + if (args.constrainedModel instanceof ConstrainedObjectModel) { + return this.renderClass( + args.constrainedModel, + args.inputModel, + optionsToUse + ); + } else if (args.constrainedModel instanceof ConstrainedEnumModel) { + return this.renderEnum( + args.constrainedModel, + args.inputModel, + optionsToUse + ); } Logger.warn( - `Kotlin generator, cannot generate this type of model, ${model.name}` + `Kotlin generator, cannot generate this type of model, ${args.constrainedModel.name}` ); return Promise.resolve( RenderOutput.toRenderOutput({ @@ -161,16 +169,22 @@ export class KotlinGenerator extends AbstractGenerator< * @param options used to render the full output */ async renderCompleteModel( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - options: KotlinRenderCompleteModelOptions + args: AbstractGeneratorRenderCompleteModelArgs< + KotlinOptions, + KotlinRenderCompleteModelOptions + > ): Promise { const optionsToUse = KotlinGenerator.getKotlinOptions({ ...this.options, - ...options + ...args.options + }); + const outputModel = await this.render({ + ...args, + options: optionsToUse }); - const outputModel = await this.render(model, inputModel, optionsToUse); - const packageName = this.sanitizePackageName(options.packageName); + const packageName = this.sanitizePackageName( + args.completeOptions.packageName ?? 'Asyncapi.Models' + ); const outputContent = `package ${packageName} ${outputModel.dependencies.join('\n')} diff --git a/src/generators/php/PhpGenerator.ts b/src/generators/php/PhpGenerator.ts index 91f72588c5..833b9ebfdc 100644 --- a/src/generators/php/PhpGenerator.ts +++ b/src/generators/php/PhpGenerator.ts @@ -1,5 +1,7 @@ import { AbstractGenerator, + AbstractGeneratorRenderArgs, + AbstractGeneratorRenderCompleteModelArgs, CommonGeneratorOptions, defaultGeneratorOptions } from '../AbstractGenerator'; @@ -117,17 +119,14 @@ export class PhpGenerator extends AbstractGenerator< * @param model * @param inputModel */ - render( - model: ConstrainedMetaModel, - inputModel: InputMetaModel - ): Promise { - if (model instanceof ConstrainedObjectModel) { - return this.renderClass(model, inputModel); - } else if (model instanceof ConstrainedEnumModel) { - return this.renderEnum(model, inputModel); + render(args: AbstractGeneratorRenderArgs): Promise { + if (args.constrainedModel instanceof ConstrainedObjectModel) { + return this.renderClass(args.constrainedModel, args.inputModel); + } else if (args.constrainedModel instanceof ConstrainedEnumModel) { + return this.renderEnum(args.constrainedModel, args.inputModel); } Logger.warn( - `PHP generator, cannot generate this type of model, ${model.name}` + `PHP generator, cannot generate this type of model, ${args.constrainedModel.name}` ); return Promise.resolve( RenderOutput.toRenderOutput({ @@ -146,26 +145,28 @@ export class PhpGenerator extends AbstractGenerator< * @param options used to render the full output */ async renderCompleteModel( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - options: PhpRenderCompleteModelOptions + args: AbstractGeneratorRenderCompleteModelArgs< + PhpOptions, + PhpRenderCompleteModelOptions + > ): Promise { - const completeModelOptionsToUse = mergePartialAndDefault( - PhpGenerator.defaultCompleteModelOptions, - options - ); + const completeModelOptionsToUse = + mergePartialAndDefault( + PhpGenerator.defaultCompleteModelOptions, + args.completeOptions + ); if (isReservedPhpKeyword(completeModelOptionsToUse.namespace)) { throw new Error( - `You cannot use reserved PHP keyword (${options.namespace}) as package name, please use another.` + `You cannot use reserved PHP keyword (${completeModelOptionsToUse.namespace}) as package name, please use another.` ); } const declares: string = completeModelOptionsToUse.declareStrictTypes ? 'declare(strict_types=1);' : ''; - const outputModel: RenderOutput = await this.render(model, inputModel); - const modelDependencies: string[] = model + const outputModel: RenderOutput = await this.render(args); + const modelDependencies: string[] = args.constrainedModel .getNearestDependencies() .map((dependencyModel) => { return `use ${completeModelOptionsToUse.namespace}\\${dependencyModel.name};`; diff --git a/src/generators/python/PythonGenerator.ts b/src/generators/python/PythonGenerator.ts index a4d1401d01..2d20bd0e5f 100644 --- a/src/generators/python/PythonGenerator.ts +++ b/src/generators/python/PythonGenerator.ts @@ -1,6 +1,8 @@ /* eslint-disable no-console */ import { AbstractGenerator, + AbstractGeneratorRenderArgs, + AbstractGeneratorRenderCompleteModelArgs, CommonGeneratorOptions, defaultGeneratorOptions } from '../AbstractGenerator'; @@ -129,21 +131,27 @@ export class PythonGenerator extends AbstractGenerator< * @param inputModel */ render( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - options?: DeepPartial + args: AbstractGeneratorRenderArgs ): Promise { const optionsToUse = PythonGenerator.getPythonOptions({ ...this.options, - ...options + ...args.options }); - if (model instanceof ConstrainedObjectModel) { - return this.renderClass(model, inputModel, optionsToUse); - } else if (model instanceof ConstrainedEnumModel) { - return this.renderEnum(model, inputModel, optionsToUse); + if (args.constrainedModel instanceof ConstrainedObjectModel) { + return this.renderClass( + args.constrainedModel, + args.inputModel, + optionsToUse + ); + } else if (args.constrainedModel instanceof ConstrainedEnumModel) { + return this.renderEnum( + args.constrainedModel, + args.inputModel, + optionsToUse + ); } Logger.warn( - `Python generator, cannot generate this type of model, ${model.name}` + `Python generator, cannot generate this type of model, ${args.constrainedModel.name}` ); return Promise.resolve( RenderOutput.toRenderOutput({ @@ -164,23 +172,29 @@ export class PythonGenerator extends AbstractGenerator< * @param options used to render the full output */ async renderCompleteModel( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - completeModelOptions: Partial, - options: DeepPartial + args: AbstractGeneratorRenderCompleteModelArgs< + PythonOptions, + PythonRenderCompleteModelOptions + > ): Promise { //const completeModelOptionsToUse = mergePartialAndDefault(PythonGenerator.defaultCompleteModelOptions, completeModelOptions) as PythonRenderCompleteModelOptions; const optionsToUse = PythonGenerator.getPythonOptions({ ...this.options, - ...options + ...args.options }); const dependencyManagerToUse = this.getDependencyManager(optionsToUse); - const outputModel = await this.render(model, inputModel, { - dependencyManager: dependencyManagerToUse - }); - const modelDependencies = model.getNearestDependencies().map((model) => { - return dependencyManagerToUse.renderDependency(model); + const outputModel = await this.render({ + ...args, + options: { + ...optionsToUse, + dependencyManager: dependencyManagerToUse + } }); + const modelDependencies = args.constrainedModel + .getNearestDependencies() + .map((model) => { + return dependencyManagerToUse.renderDependency(model); + }); const outputContent = `${modelDependencies.join('\n')} ${outputModel.dependencies.join('\n')} ${outputModel.result}`; diff --git a/src/generators/rust/RustGenerator.ts b/src/generators/rust/RustGenerator.ts index 6bd8778e22..758f5e2d60 100644 --- a/src/generators/rust/RustGenerator.ts +++ b/src/generators/rust/RustGenerator.ts @@ -1,5 +1,7 @@ import { AbstractGenerator, + AbstractGeneratorRenderArgs, + AbstractGeneratorRenderCompleteModelArgs, CommonGeneratorOptions, defaultGeneratorOptions } from '../AbstractGenerator'; @@ -35,6 +37,7 @@ import { UnionRenderer } from './renderers/UnionRenderer'; import { PackageRenderer } from './renderers/PackageRenderer'; import { DeepPartial, mergePartialAndDefault } from '../../utils/Partials'; import { RustDependencyManager } from './RustDependencyManager'; + export interface RustOptions extends CommonGeneratorOptions { typeMapping: TypeMapping; constraints: Constraints; @@ -177,25 +180,39 @@ export class RustGenerator extends AbstractGenerator< } render( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - options?: DeepPartial + args: AbstractGeneratorRenderArgs ): Promise { const optionsToUse = RustGenerator.getRustOptions({ ...this.options, - ...options + ...args.options }); - if (model instanceof ConstrainedObjectModel) { - return this.renderStruct(model, inputModel, optionsToUse); - } else if (model instanceof ConstrainedEnumModel) { - return this.renderEnum(model, inputModel, optionsToUse); - } else if (model instanceof ConstrainedTupleModel) { - return this.renderTuple(model, inputModel, optionsToUse); - } else if (model instanceof ConstrainedUnionModel) { - return this.renderUnion(model, inputModel, optionsToUse); + if (args.constrainedModel instanceof ConstrainedObjectModel) { + return this.renderStruct( + args.constrainedModel, + args.inputModel, + optionsToUse + ); + } else if (args.constrainedModel instanceof ConstrainedEnumModel) { + return this.renderEnum( + args.constrainedModel, + args.inputModel, + optionsToUse + ); + } else if (args.constrainedModel instanceof ConstrainedTupleModel) { + return this.renderTuple( + args.constrainedModel, + args.inputModel, + optionsToUse + ); + } else if (args.constrainedModel instanceof ConstrainedUnionModel) { + return this.renderUnion( + args.constrainedModel, + args.inputModel, + optionsToUse + ); } Logger.warn( - `Rust generator, cannot generate this type of model, ${model.name}` + `Rust generator, cannot generate this type of model, ${args.constrainedModel.name}` ); return Promise.resolve( RenderOutput.toRenderOutput({ @@ -214,17 +231,17 @@ export class RustGenerator extends AbstractGenerator< * @param options */ async renderCompleteModel( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - _completeModelOptions: Partial, - options: DeepPartial + args: AbstractGeneratorRenderCompleteModelArgs< + RustOptions, + RustRenderCompleteModelOptions + > ): Promise { const optionsToUse = RustGenerator.getRustOptions({ ...this.options, - ...options + ...args.options }); Logger.debug('Generating complete models with options: ', optionsToUse); - const outputModel = await this.render(model, inputModel); + const outputModel = await this.render({ ...args, options: optionsToUse }); const outputContent = outputModel.result; return RenderOutput.toRenderOutput({ result: outputContent, diff --git a/src/generators/template/TemplateGenerator.ts b/src/generators/template/TemplateGenerator.ts index 3cfeba8343..afa1f7db91 100644 --- a/src/generators/template/TemplateGenerator.ts +++ b/src/generators/template/TemplateGenerator.ts @@ -1,5 +1,7 @@ import { AbstractGenerator, + AbstractGeneratorRenderArgs, + AbstractGeneratorRenderCompleteModelArgs, CommonGeneratorOptions, defaultGeneratorOptions } from '../AbstractGenerator'; @@ -47,6 +49,10 @@ export class TemplateGenerator extends AbstractGenerator< constraints: TemplateDefaultConstraints }; + static defaultCompleteModelOptions: TemplateRenderCompleteModelOptions = { + packageName: 'Asyncapi.Models' + }; + constructor(options?: DeepPartial) { const realizedOptions = TemplateGenerator.getTemplateOptions(options); super('Template', realizedOptions); @@ -120,16 +126,15 @@ export class TemplateGenerator extends AbstractGenerator< * @param inputModel */ render( - model: ConstrainedMetaModel, - inputModel: InputMetaModel + args: AbstractGeneratorRenderArgs ): Promise { - if (model instanceof ConstrainedObjectModel) { - return this.renderClass(model, inputModel); - } else if (model instanceof ConstrainedEnumModel) { - return this.renderEnum(model, inputModel); + if (args.constrainedModel instanceof ConstrainedObjectModel) { + return this.renderClass(args.constrainedModel, args.inputModel); + } else if (args.constrainedModel instanceof ConstrainedEnumModel) { + return this.renderEnum(args.constrainedModel, args.inputModel); } Logger.warn( - `Template generator, cannot generate this type of model, ${model.name}` + `Template generator, cannot generate this type of model, ${args.constrainedModel.name}` ); return Promise.resolve( RenderOutput.toRenderOutput({ @@ -150,23 +155,30 @@ export class TemplateGenerator extends AbstractGenerator< * @param options used to render the full output */ async renderCompleteModel( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - options: TemplateRenderCompleteModelOptions + args: AbstractGeneratorRenderCompleteModelArgs< + TemplateOptions, + TemplateRenderCompleteModelOptions + > ): Promise { - if (isReservedTemplateKeyword(options.packageName)) { + const completeModelOptionsToUse = + mergePartialAndDefault( + TemplateGenerator.defaultCompleteModelOptions, + args.completeOptions + ); + + if (isReservedTemplateKeyword(completeModelOptionsToUse.packageName)) { throw new Error( - `You cannot use reserved Template keyword (${options.packageName}) as package name, please use another.` + `You cannot use reserved Template keyword (${args.completeOptions.packageName}) as package name, please use another.` ); } - const outputModel = await this.render(model, inputModel); - const modelDependencies = model + const outputModel = await this.render(args); + const modelDependencies = args.constrainedModel .getNearestDependencies() .map((dependencyModel) => { - return `import ${options.packageName}.${dependencyModel.name};`; + return `import ${completeModelOptionsToUse.packageName}.${dependencyModel.name};`; }); - const outputContent = `package ${options.packageName}; + const outputContent = `package ${completeModelOptionsToUse.packageName}; ${modelDependencies.join('\n')} ${outputModel.dependencies.join('\n')} ${outputModel.result}`; diff --git a/src/generators/typescript/TypeScriptGenerator.ts b/src/generators/typescript/TypeScriptGenerator.ts index 251d6ee9e4..e9058f4be8 100644 --- a/src/generators/typescript/TypeScriptGenerator.ts +++ b/src/generators/typescript/TypeScriptGenerator.ts @@ -1,5 +1,7 @@ import { AbstractGenerator, + AbstractGeneratorRenderArgs, + AbstractGeneratorRenderCompleteModelArgs, CommonGeneratorOptions, defaultGeneratorOptions } from '../AbstractGenerator'; @@ -156,25 +158,28 @@ export class TypeScriptGenerator extends AbstractGenerator< * @param options */ async renderCompleteModel( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - completeModelOptions: Partial, - options: DeepPartial + args: AbstractGeneratorRenderCompleteModelArgs< + TypeScriptOptions, + TypeScriptRenderCompleteModelOptions + > ): Promise { const completeModelOptionsToUse = mergePartialAndDefault( TypeScriptGenerator.defaultCompleteModelOptions, - completeModelOptions + args.completeOptions ) as TypeScriptRenderCompleteModelOptions; const optionsToUse = TypeScriptGenerator.getOptions({ ...this.options, - ...options + ...args.options }); const dependencyManagerToUse = this.getDependencyManager(optionsToUse); - const outputModel = await this.render(model, inputModel, { - ...optionsToUse, - dependencyManager: dependencyManagerToUse + const outputModel = await this.render({ + ...args, + options: { + ...optionsToUse, + dependencyManager: dependencyManagerToUse + } }); - const modelDependencies = model.getNearestDependencies(); + const modelDependencies = args.constrainedModel.getNearestDependencies(); //Create the correct model dependency imports const modelDependencyImports = modelDependencies.map((model) => { @@ -184,7 +189,7 @@ export class TypeScriptGenerator extends AbstractGenerator< ); }); const modelExport = dependencyManagerToUse.renderExport( - model, + args.constrainedModel, completeModelOptionsToUse.exportType ); @@ -207,23 +212,37 @@ ${modelCode}`; * Render any ConstrainedMetaModel to code based on the type */ render( - model: ConstrainedMetaModel, - inputModel: InputMetaModel, - options?: DeepPartial + args: AbstractGeneratorRenderArgs ): Promise { const optionsToUse = TypeScriptGenerator.getOptions({ ...this.options, - ...options + ...args.options }); - if (model instanceof ConstrainedObjectModel) { + if (args.constrainedModel instanceof ConstrainedObjectModel) { if (this.options.modelType === 'interface') { - return this.renderInterface(model, inputModel, optionsToUse); + return this.renderInterface( + args.constrainedModel, + args.inputModel, + optionsToUse + ); } - return this.renderClass(model, inputModel, optionsToUse); - } else if (model instanceof ConstrainedEnumModel) { - return this.renderEnum(model, inputModel, optionsToUse); + return this.renderClass( + args.constrainedModel, + args.inputModel, + optionsToUse + ); + } else if (args.constrainedModel instanceof ConstrainedEnumModel) { + return this.renderEnum( + args.constrainedModel, + args.inputModel, + optionsToUse + ); } - return this.renderType(model, inputModel, optionsToUse); + return this.renderType( + args.constrainedModel, + args.inputModel, + optionsToUse + ); } async renderClass( diff --git a/test/TestUtils/TestGenerator.ts b/test/TestUtils/TestGenerator.ts index 1b23ecf10f..8c3bd6f508 100644 --- a/test/TestUtils/TestGenerator.ts +++ b/test/TestUtils/TestGenerator.ts @@ -7,7 +7,8 @@ import { MetaModel, ConstrainedAnyModel, Preset, - InputMetaModel + AbstractGeneratorRenderCompleteModelArgs, + AbstractGeneratorRenderArgs } from '../../src'; import { AbstractDependencyManager } from '../../src/generators/AbstractDependencyManager'; @@ -30,26 +31,21 @@ export class TestGenerator extends AbstractGenerator { return [model]; } - public render( - model: MetaModel, - inputModel: InputMetaModel - ): Promise { + public render(args: AbstractGeneratorRenderArgs): Promise { return Promise.resolve( RenderOutput.toRenderOutput({ - result: model.name || 'rendered content', + result: args.constrainedModel.name || 'rendered content', renderedName: 'TestName' }) ); } public renderCompleteModel( - model: MetaModel, - inputModel: InputMetaModel, - options: any + args: AbstractGeneratorRenderCompleteModelArgs ): Promise { return Promise.resolve( RenderOutput.toRenderOutput({ - result: model.name || 'rendered complete content', + result: args.constrainedModel.name || 'rendered complete content', renderedName: 'TestName' }) ); diff --git a/test/generators/AbstractGenerator.spec.ts b/test/generators/AbstractGenerator.spec.ts index dc6636501e..5748cf2c18 100644 --- a/test/generators/AbstractGenerator.spec.ts +++ b/test/generators/AbstractGenerator.spec.ts @@ -1,4 +1,8 @@ -import { InputMetaModel, AnyModel } from '../../src/models'; +import { + InputMetaModel, + AnyModel, + ConstrainedMetaModel +} from '../../src/models'; import { TestGenerator } from '../TestUtils/TestGenerator'; describe('AbstractGenerator', () => { @@ -65,10 +69,12 @@ describe('AbstractGenerator', () => { const doc: any = { type: 'string', $id: 'SomeModel' }; const commonInputModel = await generator.process(doc); const keys = Object.keys(commonInputModel.models); - const renderedContent = await generator.render( - commonInputModel.models[keys[0]], - commonInputModel - ); + const renderedContent = await generator.render({ + constrainedModel: commonInputModel.models[ + keys[0] + ] as ConstrainedMetaModel, + inputModel: commonInputModel + }); expect(renderedContent.result).toEqual('SomeModel'); expect(renderedContent.renderedName).toEqual('TestName');