From 2fe01aef6accc213a086a45bf92ef7b6b53b07b8 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Wed, 8 Aug 2018 23:57:43 -0700 Subject: [PATCH] Less repetition in C++ --- src/quicktype-core/Renderer.ts | 22 +++-- src/quicktype-core/language/CPlusPlus.ts | 120 +++++++++++------------ 2 files changed, 71 insertions(+), 71 deletions(-) diff --git a/src/quicktype-core/Renderer.ts b/src/quicktype-core/Renderer.ts index b49bf6c6..b3c40e5e 100644 --- a/src/quicktype-core/Renderer.ts +++ b/src/quicktype-core/Renderer.ts @@ -208,25 +208,31 @@ export abstract class Renderer { this._emitContext.changeIndent(offset); } + iterableForEach(iterable: Iterable, emitter: (v: T, position: ForEachPosition) => void): void { + const items = Array.from(iterable); + let onFirst = true; + for (const [i, v] of iterableEnumerate(items)) { + const position = + items.length === 1 ? "only" : onFirst ? "first" : i === items.length - 1 ? "last" : "middle"; + emitter(v, position); + onFirst = false; + } + } + forEach( iterable: Iterable<[K, V]>, interposedBlankLines: number, leadingBlankLines: number, emitter: (v: V, k: K, position: ForEachPosition) => void ): void { - const items = Array.from(iterable); - let onFirst = true; - for (const [i, [k, v]] of iterableEnumerate(items)) { - if (onFirst) { + this.iterableForEach(iterable, ([k, v], position) => { + if (position === "only" || position === "first") { this.ensureBlankLine(leadingBlankLines); } else { this.ensureBlankLine(interposedBlankLines); } - const position = - items.length === 1 ? "only" : onFirst ? "first" : i === items.length - 1 ? "last" : "middle"; emitter(v, k, position); - onFirst = false; - } + }); } forEachWithBlankLines( diff --git a/src/quicktype-core/language/CPlusPlus.ts b/src/quicktype-core/language/CPlusPlus.ts index fea091be..4d89af61 100644 --- a/src/quicktype-core/language/CPlusPlus.ts +++ b/src/quicktype-core/language/CPlusPlus.ts @@ -4,7 +4,8 @@ import { toReadonlyArray, iterableFirst, iterableFind, - iterableSome + iterableSome, + withDefault } from "collection-utils"; import { TargetLanguage } from "../TargetLanguage"; @@ -287,6 +288,28 @@ export enum MemberNames { SetPattern } +type ConstraintMember = { + name: MemberNames; + getter: MemberNames; + setter: MemberNames; + cppType: string; + cppConstType?: string; +}; + +const constraintMembers: ConstraintMember[] = [ + { name: MemberNames.MinValue, getter: MemberNames.GetMinValue, setter: MemberNames.SetMinValue, cppType: "int" }, + { name: MemberNames.MaxValue, getter: MemberNames.GetMaxValue, setter: MemberNames.SetMaxValue, cppType: "int" }, + { name: MemberNames.MinLength, getter: MemberNames.GetMinLength, setter: MemberNames.SetMinLength, cppType: "int" }, + { name: MemberNames.MaxLength, getter: MemberNames.GetMaxLength, setter: MemberNames.SetMaxLength, cppType: "int" }, + { + name: MemberNames.Pattern, + getter: MemberNames.GetPattern, + setter: MemberNames.SetPattern, + cppType: "std::string", + cppConstType: "const std::string &" + } +]; + export type IncludeRecord = { kind: IncludeKind | undefined /** How to include that */; typeKind: TypeKind | undefined /** What exactly to include */; @@ -728,25 +751,27 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { return this._memberNameStyle(jsonName + "Constraint"); } + protected emitMember(cppType: Sourcelike, name: Sourcelike): void { + this.emitLine(cppType, " ", name, ";"); + } + protected emitClassMembers(c: ClassType, constraints: Map | undefined): void { if (this._options.codeFormat) { this.emitLine("private:"); this.forEachClassProperty(c, "none", (name, jsonName, property) => { - this.emitLine( + this.emitMember( this.cppType( property.type, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: false }, true ), - " ", - name, - ";" + name ); if (constraints !== undefined && constraints.has(jsonName)) { /** FIXME!!! NameStyle will/can collide with other Names */ const cnst = this.lookupGlobalName(GlobalNames.ClassMemberConstraints); - this.emitLine(cnst, " ", this.constraintMember(jsonName), ";"); + this.emitMember(cnst, this.constraintMember(jsonName)); } }); @@ -757,15 +782,13 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.forEachClassProperty(c, "none", (name, jsonName, property) => { this.emitDescription(this.descriptionForClassProperty(c, jsonName)); if (!this._options.codeFormat) { - this.emitLine( + this.emitMember( this.cppType( property.type, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: false }, true ), - " ", - name, - ";" + name ); } else { const [getterName, mutableGetterName, setterName] = defined( @@ -846,6 +869,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { const constraints = constraintsForType(property.type); if (constraints === undefined) return; const { minMax, minMaxLength, pattern } = constraints; + // FIXME: Use an array for this let constrArg: string = "("; constrArg += minMax !== undefined && minMax[0] !== undefined ? minMax[0] : "boost::none"; constrArg += ", "; @@ -1201,75 +1225,45 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } protected emitConstraintClasses(): void { - const memberMinValue = this.lookupMemberName(MemberNames.MinValue); const getterMinValue = this.lookupMemberName(MemberNames.GetMinValue); - const setterMinValue = this.lookupMemberName(MemberNames.SetMinValue); - const memberMaxValue = this.lookupMemberName(MemberNames.MaxValue); const getterMaxValue = this.lookupMemberName(MemberNames.GetMaxValue); - const setterMaxValue = this.lookupMemberName(MemberNames.SetMaxValue); - const memberMinLength = this.lookupMemberName(MemberNames.MinLength); const getterMinLength = this.lookupMemberName(MemberNames.GetMinLength); - const setterMinLength = this.lookupMemberName(MemberNames.SetMinLength); - const memberMaxLength = this.lookupMemberName(MemberNames.MaxLength); const getterMaxLength = this.lookupMemberName(MemberNames.GetMaxLength); - const setterMaxLength = this.lookupMemberName(MemberNames.SetMaxLength); - const memberPattern = this.lookupMemberName(MemberNames.Pattern); const getterPattern = this.lookupMemberName(MemberNames.GetPattern); - const setterPattern = this.lookupMemberName(MemberNames.SetPattern); const classConstraint = this.lookupGlobalName(GlobalNames.ClassMemberConstraints); this.emitBlock(["class ", classConstraint], true, () => { this.emitLine("private:"); - this.emitLine("boost::optional ", memberMinValue, ";"); - this.emitLine("boost::optional ", memberMaxValue, ";"); - this.emitLine("boost::optional ", memberMinLength, ";"); - this.emitLine("boost::optional ", memberMaxLength, ";"); - this.emitLine("boost::optional ", memberPattern, ";"); + for (const member of constraintMembers) { + this.emitMember(["boost::optional<", member.cppType, ">"], this.lookupMemberName(member.name)); + } this.ensureBlankLine(); this.emitLine("public:"); this.emitLine(classConstraint, "("); this.indent(() => { - this.emitLine("boost::optional ", memberMinValue, ","); - this.emitLine("boost::optional ", memberMaxValue, ","); - this.emitLine("boost::optional ", memberMinLength, ","); - this.emitLine("boost::optional ", memberMaxLength, ","); - this.emitLine("boost::optional ", memberPattern); + this.iterableForEach(constraintMembers, ({ name, cppType }, pos) => { + const comma = pos === "first" || pos === "middle" ? "," : []; + this.emitLine("boost::optional<", cppType, "> ", this.lookupMemberName(name), comma); + }); }); - this.emitLine( - ") : ", - memberMinValue, - "(", - memberMinValue, - "), ", - memberMaxValue, - "(", - memberMaxValue, - "), ", - memberMinLength, - "(", - memberMinLength, - "), ", - memberMaxLength, - "(", - memberMaxLength, - "), ", - memberPattern, - "(", - memberPattern, - ") {}" - ); + + const args = constraintMembers.map(({ name }) => { + const member = this.lookupMemberName(name); + return [member, "(", member, ")"]; + }); + this.emitLine(") : ", arrayIntercalate([", "], args), " {}"); + this.emitLine(classConstraint, "() = default;"); this.emitLine("virtual ~", classConstraint, "() = default;"); - this.ensureBlankLine(); - this.emitGetterSetter("int", getterMinValue, setterMinValue, memberMinValue); - this.ensureBlankLine(); - this.emitGetterSetter("int", getterMaxValue, setterMaxValue, memberMaxValue); - this.ensureBlankLine(); - this.emitGetterSetter("int", getterMinLength, setterMinLength, memberMinLength); - this.ensureBlankLine(); - this.emitGetterSetter("int", getterMaxLength, setterMaxLength, memberMaxLength); - this.ensureBlankLine(); - this.emitGetterSetter("const std::string &", getterPattern, setterPattern, memberPattern); + for (const member of constraintMembers) { + this.ensureBlankLine(); + this.emitGetterSetter( + withDefault(member.cppConstType, member.cppType), + this.lookupMemberName(member.getter), + this.lookupMemberName(member.setter), + this.lookupMemberName(member.name) + ); + } }); this.ensureBlankLine();