diff --git a/src/language/generator/cpp/gap-pattern-generator.ts b/src/language/generator/cpp/gap-pattern-generator.ts index 05a5fdd..e81e125 100644 --- a/src/language/generator/cpp/gap-pattern-generator.ts +++ b/src/language/generator/cpp/gap-pattern-generator.ts @@ -25,6 +25,12 @@ export abstract class GapPatternCppGenerator extends CppGenerator { fs.rmSync(UriUtils.joinPath(projectUri, this.sourceGenFolder).fsPath, { recursive: true, force: true }); } } + name(element: ast.NamedElement | string, gen: boolean): string { + const genSuffix = 'Gen'; + if (typeof (element) === 'string') + return gen ? element + genSuffix : element; + return gen ? element.name + genSuffix : element.name; + } protected useGenerationGapPattern(type: ast.Type): boolean { return ast.isReferenceType(type); } @@ -64,7 +70,7 @@ export abstract class GapPatternCppGenerator extends CppGenerator { acceptTask(() => this.generateSource(sourcePath, type, notice)); } - const qualifiedNameGen = useGenerationGapPattern ? qualifiedName + 'Gen' : qualifiedName; + const qualifiedNameGen = this.name(qualifiedName, useGenerationGapPattern); const includeGenPath = UriUtils.joinPath(projectUri, this.includeGenFolder, qualifiedNameGen + '.h').fsPath; acceptTask(() => this.generateHeaderGen(includeGenPath, type, useGenerationGapPattern, notice)); @@ -226,14 +232,14 @@ export abstract class GapPatternCppGenerator extends CppGenerator { break; } if (body?.length) { - const guard = `${fqn(type, '_').toUpperCase()}${gen ? 'GEN' : ''}_H_`; + const guard = this.name(fqn(type, '_'), gen).toUpperCase() + '_H_'; await this.generateFile(path, s` ${notice} // ----------------------------------------------------------------------------- // File Name : ${Path.basename(path)} // Generated by : ${this.generatedBy()} // ----------------------------------------------------------------------------- - /// @file ${fqn(type, '/')}${gen ? 'Gen' : ''}.h + /// @file ${this.name(fqn(type, '/'), gen)}.h // This file is auto-generated, Do not edit otherwise your changes will be lost #ifndef ${guard} @@ -293,7 +299,7 @@ export abstract class GapPatternCppGenerator extends CppGenerator { // File Name : ${Path.basename(path)} // Generated by : ${this.generatedBy()} // ----------------------------------------------------------------------------- - /// @file ${fqn(type, '/')}${gen ? 'Gen' : ''}.cpp + /// @file ${this.name(fqn(type, '/'), gen)}.cpp // This file is auto-generated, Do not edit otherwise your changes will be lost ${this.includes([...this.sourceIncludes(type), type])} @@ -315,7 +321,7 @@ export abstract class GapPatternCppGenerator extends CppGenerator { } async generateNativeTypeHeaderGen(type: ast.NativeType, gen: boolean): Promise { const namespace = getNativeNamespace(type); - return `using ${type.name}${gen ? 'Gen' : ''} = ${namespace ? namespace + '::' : ''}${getNativeType(type)};`; + return `using ${this.name(type, gen)} = ${namespace ? namespace + '::' : ''}${getNativeType(type)};`; } async generateNativeTypeSourceGen(_type: ast.NativeType, _gen: boolean): Promise { return undefined; @@ -341,15 +347,15 @@ export abstract class GapPatternCppGenerator extends CppGenerator { const base = this.fqn(type.base?.ref, ast.isException(type) ? '::Smp::Exception' : undefined); return s` ${gen ? `class ${type.name};` : ''} - ${this.comment(type)}class ${type.name}${gen ? 'Gen' : ''}${base ? `: public ${base}` : ''} + ${this.comment(type)}class ${this.name(type, gen)}${base ? `: public ${base}` : ''} { ${gen ? `friend class ${this.fqn(type)};` : ''} public: static void _Register(::Smp::Publication::ITypeRegistry* registry); - //«IF constructor»${type.name}${gen ? 'Gen' : ''} () = default;«ENDIF» - //«IF destructor»~${type.name}${gen ? 'Gen' : ''} () noexcept = default;«ENDIF» - //${type.name}${gen ? 'Gen' : ''} (const ${type.name}${gen ? 'Gen' : ''} &) = default; + //«IF constructor»${this.name(type, gen)} () = default;«ENDIF» + //«IF destructor»~${this.name(type, gen)} () noexcept = default;«ENDIF» + //${this.name(type, gen)} (const ${this.name(type, gen)} &) = default; ${this.declareMembersGen(type, VisibilityKind.public, gen)} }; @@ -362,7 +368,7 @@ export abstract class GapPatternCppGenerator extends CppGenerator { const fields = type.elements.filter(ast.isField).filter(field => !isStatic(field) && !isString8(field.type.ref)); return s` ${this.defineMembersGen(type, gen)} - void ${type.name}${gen ? 'Gen' : ''}::_Register(::Smp::Publication::ITypeRegistry* registry) + void ${this.name(type, gen)}::_Register(::Smp::Publication::ITypeRegistry* registry) { ${fields.length > 0 ? 'auto *type = ' : ''}registry->AddClassType( "${type.name}", // Name @@ -419,7 +425,7 @@ export abstract class GapPatternCppGenerator extends CppGenerator { async generateStructureHeaderGen(type: ast.Structure, gen: boolean): Promise { return s` - ${this.comment(type)}struct ${type.name}${gen ? 'Gen' : ''} + ${this.comment(type)}struct ${this.name(type, gen)} { ${this.declareMembersGen(type, VisibilityKind.public, gen)} @@ -434,7 +440,7 @@ export abstract class GapPatternCppGenerator extends CppGenerator { const fields = type.elements.filter(ast.isField).filter(field => !isStatic(field) && !isString8(field.type.ref)); return s` ${this.defineMembersGen(type, gen)} - void ${type.name}${gen ? 'Gen' : ''}::_Register(::Smp::Publication::ITypeRegistry* registry) + void ${this.name(type, gen)}::_Register(::Smp::Publication::ITypeRegistry* registry) { ${fields.length > 0 ? 'auto *type = ' : ''}registry->AddStructureType( "${type.name}", // Name @@ -470,7 +476,7 @@ export abstract class GapPatternCppGenerator extends CppGenerator { async generateIntegerHeaderGen(type: ast.Integer, gen: boolean): Promise { return s` ${this.uuidDeclaration(type)} - ${this.comment(type)}using ${type.name}${gen ? 'Gen' : ''} = ${this.fqn(type.primitiveType?.ref, '::Smp::Int32')}; + ${this.comment(type)}using ${this.name(type, gen)} = ${this.fqn(type.primitiveType?.ref, '::Smp::Int32')}; void _Register_${type.name}(::Smp::Publication::ITypeRegistry* registry); `; } @@ -501,7 +507,7 @@ export abstract class GapPatternCppGenerator extends CppGenerator { async generateFloatHeaderGen(type: ast.Float, gen: boolean): Promise { return s` ${this.uuidDeclaration(type)} - ${this.comment(type)}using ${type.name}${gen ? 'Gen' : ''} = ${this.fqn(type.primitiveType?.ref, '::Smp::Float64')}; + ${this.comment(type)}using ${this.name(type, gen)} = ${this.fqn(type.primitiveType?.ref, '::Smp::Float64')}; void _Register_${type.name}(::Smp::Publication::ITypeRegistry* registry); `; } @@ -575,9 +581,9 @@ export abstract class GapPatternCppGenerator extends CppGenerator { } async generateInterfaceHeaderGen(type: ast.Interface, gen: boolean): Promise { return s` - ${this.comment(type)}class ${type.name}${gen ? 'Gen' : ''}${type.base.length > 0 ? ': ' : ''}${type.base.map(b => `public virtual ${this.fqn(b.ref)}`).join(', ')} { + ${this.comment(type)}class ${this.name(type, gen)}${type.base.length > 0 ? ': ' : ''}${type.base.map(b => `public virtual ${this.fqn(b.ref)}`).join(', ')} { public: - virtual ~${type.name}${gen ? 'Gen' : ''} () = default; + virtual ~${this.name(type, gen)} () = default; ${this.declareMembersGen(type, VisibilityKind.public, gen)} }; @@ -595,7 +601,7 @@ export abstract class GapPatternCppGenerator extends CppGenerator { } async generateArrayHeaderGen(type: ast.ArrayType, gen: boolean): Promise { return s` - ${this.comment(type)}struct ${type.name}${gen ? 'Gen' : ''} + ${this.comment(type)}struct ${this.name(type, gen)} { ${this.fqn(type.itemType.ref)} internalArray[${this.expression(type.size)}]; }; @@ -632,7 +638,7 @@ export abstract class GapPatternCppGenerator extends CppGenerator { } async generateEnumerationHeaderGen(type: ast.Enumeration, gen: boolean): Promise { return s` - ${this.comment(type)}enum class ${type.name}${gen ? 'Gen' : ''}: ::Smp::Int32 { + ${this.comment(type)}enum class ${this.name(type, gen)}: ::Smp::Int32 { ${type.literal.map(literal => `${this.comment(literal)}${literal.name} = ${this.expression(literal.value)}`).join(',\n')} }; @@ -640,12 +646,12 @@ export abstract class GapPatternCppGenerator extends CppGenerator { void _Register_${type.name}(::Smp::Publication::ITypeRegistry* registry); - const std::map<${type.name}${gen ? 'Gen' : ''}, std::string> ${type.name}_name_map = { - ${type.literal.map(literal => `{ ${type.name}${gen ? 'Gen' : ''}::${literal.name}, "${literal.name}" }`).join(', ')} + const std::map<${this.name(type, gen)}, std::string> ${type.name}_name_map = { + ${type.literal.map(literal => `{ ${this.name(type, gen)}::${literal.name}, "${literal.name}" }`).join(', ')} }; - const std::map<${type.name}${gen ? 'Gen' : ''}, std::string> ${type.name}_descr_map = { - ${type.literal.map(literal => `{ ${type.name}${gen ? 'Gen' : ''}::${literal.name}, ${this.description(literal)} }`).join(', ')} + const std::map<${this.name(type, gen)}, std::string> ${type.name}_descr_map = { + ${type.literal.map(literal => `{ ${this.name(type, gen)}::${literal.name}, ${this.description(literal)} }`).join(', ')} }; `; } @@ -673,7 +679,7 @@ export abstract class GapPatternCppGenerator extends CppGenerator { } async generateStringHeaderGen(type: ast.StringType, gen: boolean): Promise { return s` - ${this.comment(type)}struct ${type.name}${gen ? 'Gen' : ''} + ${this.comment(type)}struct ${this.name(type, gen)} { ::Smp::Char8 internalString[(${this.expression(type.length)}) + 1]; }; @@ -825,13 +831,13 @@ export abstract class GapPatternCppGenerator extends CppGenerator { protected defineConstantGen(element: ast.Constant, gen: boolean): string | undefined { if (!this.stringTypeIsConstexpr() && ast.isStringType(element.type.ref)) { return s` - ${this.comment(element)}const ${this.fqn(element.type.ref)} ${element.$container.name}${gen ? 'Gen' : ''}::${element.name}${this.directListInitializer(element.value)}; + ${this.comment(element)}const ${this.fqn(element.type.ref)} ${this.name(element.$container, gen)}::${element.name}${this.directListInitializer(element.value)}; `; } if (this.cxxStandard < CxxStandard.CXX_STD_17) { return s` - ${this.comment(element)}static constexpr ${this.fqn(element.type.ref)} ${element.$container.name}${gen ? 'Gen' : ''}::${element.name}; + ${this.comment(element)}static constexpr ${this.fqn(element.type.ref)} ${this.name(element.$container, gen)}::${element.name}; `; } return undefined; @@ -928,7 +934,7 @@ export abstract class GapPatternCppGenerator extends CppGenerator { if (isStatic(element)) return ` // Field ${element.name} - ${this.fqn(element.type.ref)} ${element.$container.name}${gen ? 'Gen' : ''}::${element.name}${this.directListInitializer(element.default)}; + ${this.fqn(element.type.ref)} ${this.name(element.$container, gen)}::${element.name}${this.directListInitializer(element.default)}; `; return undefined; } @@ -944,7 +950,7 @@ export abstract class GapPatternCppGenerator extends CppGenerator { protected declareOperationGen(op: ast.Operation, gen: boolean): string | undefined { if (isConstructor(op)) // a constructor - return `${this.comment(op)}${op.$container.name}${gen ? 'Gen' : ''}(${op.parameter.map(param => this.declareParameter(param)).join(', ')});`; + return `${this.comment(op)}${this.name(op.$container, gen)}(${op.parameter.map(param => this.declareParameter(param)).join(', ')});`; else if (isStatic(op)) // a static method return `${this.comment(op)}static ${this.type(op.returnParameter)} ${this.operationName(op)}(${op.parameter.map(param => this.declareParameter(param)).join(', ')});`; else if (isVirtual(op)) // a virtual method @@ -1041,15 +1047,15 @@ export abstract class GapPatternCppGenerator extends CppGenerator { } protected definePropertySetterGen(element: ast.Property, gen: boolean): string | undefined { return s` - void ${element.$container.name}${gen ? 'Gen' : ''}::set_${element.name}(${this.type(element)} value) { - ${isStatic(element) ? `${element.$container.name}${gen ? 'Gen' : ''}::` : 'this->'}${element.attachedField?.ref?.name} = value; + void ${this.name(element.$container, gen)}::set_${element.name}(${this.type(element)} value) { + ${isStatic(element) ? `${this.name(element.$container, gen)}::` : 'this->'}${element.attachedField?.ref?.name} = value; } `; } protected definePropertyGetterGen(element: ast.Property, gen: boolean): string | undefined { return s` - ${this.type(element)} ${element.$container.name}${gen ? 'Gen' : ''}::get_${element.name}()${isConstGetter(element) ? ' const' : ''}{ - return ${isStatic(element) ? `${element.$container.name}${gen ? 'Gen' : ''}::` : 'this->'}${element.attachedField?.ref?.name}; + ${this.type(element)} ${this.name(element.$container, gen)}::get_${element.name}()${isConstGetter(element) ? ' const' : ''}{ + return ${isStatic(element) ? `${this.name(element.$container, gen)}::` : 'this->'}${element.attachedField?.ref?.name}; } `; } diff --git a/src/language/profiles/xsmp-sdk/generator.ts b/src/language/profiles/xsmp-sdk/generator.ts index e753b4d..d9ba206 100644 --- a/src/language/profiles/xsmp-sdk/generator.ts +++ b/src/language/profiles/xsmp-sdk/generator.ts @@ -33,7 +33,7 @@ export class XsmpSdkGenerator extends GapPatternCppGenerator { override async generateArrayHeaderGen(type: ast.ArrayType, gen: boolean): Promise { return s` - ${this.comment(type)}using ${type.name}${gen ? 'Gen' : ''} = ::Xsmp::Array<${this.fqn(type.itemType.ref)}, ${this.expression(type.size)}>${isSimpleArray(type) ? '::simple' : ''}; + ${this.comment(type)}using ${this.name(type, gen)} = ::Xsmp::Array<${this.fqn(type.itemType.ref)}, ${this.expression(type.size)}>${isSimpleArray(type) ? '::simple' : ''}; ${this.uuidDeclaration(type)} @@ -46,7 +46,7 @@ export class XsmpSdkGenerator extends GapPatternCppGenerator { override async generateStringHeaderGen(type: ast.StringType, gen: boolean): Promise { return s` - ${this.comment(type)}using ${type.name}${gen ? 'Gen' : ''} = ::Xsmp::String<${this.expression(type.length)}>; + ${this.comment(type)}using ${this.name(type, gen)} = ::Xsmp::String<${this.expression(type.length)}>; ${this.uuidDeclaration(type)} @@ -199,9 +199,9 @@ export class XsmpSdkGenerator extends GapPatternCppGenerator { } override async generateStructureHeaderGen(type: ast.Structure, gen: boolean): Promise { const fields = type.elements.filter(ast.isField).filter(field => !isStatic(field)); - const rawFqn = `${this.fqn(type)}${gen ? 'Gen' : ''}`; + const rawFqn = this.name(this.fqn(type), gen); return s` - ${this.comment(type)}struct ${type.name}${gen ? 'Gen' : ''} { + ${this.comment(type)}struct ${this.name(type, gen)} { ${this.declareMembersGen(type, VisibilityKind.public, gen)} static void _Register(::Smp::Publication::ITypeRegistry* registry); @@ -331,7 +331,7 @@ export class XsmpSdkGenerator extends GapPatternCppGenerator { `; } override async generateComponentHeaderGen(type: ast.Component, gen: boolean): Promise { - const name = `${type.name}${gen ? 'Gen' : ''}`; + const name = this.name(type, gen); const bases = this.componentBases(type); return s` ${gen ? `// forward declaration of user class\nclass ${type.name};` : ''} @@ -432,7 +432,7 @@ export class XsmpSdkGenerator extends GapPatternCppGenerator { } override async generateComponentSourceGen(type: ast.Component, gen: boolean): Promise { - const name = `${type.name}${gen ? 'Gen' : ''}`; + const name = this.name(type, gen); const base = this.componentBase(type); const fqn = this.fqn(type); const initializer = this.initializeMembers(type, gen); @@ -515,7 +515,7 @@ export class XsmpSdkGenerator extends GapPatternCppGenerator { return ` // Handler for Operation ${op.name} {"${op.name}", - [](${op.$container.name}${gen ? 'Gen' : ''}* component, ::Smp::IRequest *${r || op.parameter.length > 0 ? 'request' : ''}) { + [](${this.name(op.$container, gen)}* component, ::Smp::IRequest *${r || op.parameter.length > 0 ? 'request' : ''}) { ${op.parameter.map(this.initParameter, this).join('\n')} ${r ? `const auto p_${r.name ?? 'return'} = ` : ''}component->${op.name}(${op.parameter.map(param => `${isByPointer(param) ? '&' : ''}p_${param.name}`).join(', ')}); @@ -567,7 +567,7 @@ export class XsmpSdkGenerator extends GapPatternCppGenerator { protected generateRqHandlerProperty(property: ast.Property, gen: boolean): string { const accessKind = getAccessKind(property); - const cmp = `${property.$container.name}${gen ? 'Gen' : ''}`; + const cmp = this.name(property.$container, gen); return s` ${accessKind !== 'writeOnly' ? ` // Getter handler for Property ${property.name} diff --git a/src/language/utils/xsmp-utils.ts b/src/language/utils/xsmp-utils.ts index de4f509..245b725 100644 --- a/src/language/utils/xsmp-utils.ts +++ b/src/language/utils/xsmp-utils.ts @@ -263,12 +263,12 @@ export function getDescription(element: ast.NamedElement | ast.ReturnParameter): } return result.length > 0 ? result.join('\n').trim() : undefined; } -export function isConstructor(element: ast.NamedElement): boolean | undefined { +export function isConstructor(element: ast.NamedElement | ast.ReturnParameter): boolean | undefined { return attributeBoolValue(element, 'Attributes.Constructor'); } export function operatorKind(op: ast.Operation): OperatorKind { const attr = attribute(op, 'Attributes.Operator'); - if (!attr || !attr.value) { + if (!attr?.value) { return OperatorKind.NONE; } const value = Solver.getValueAs(attr.value, (attr.type.ref as ast.AttributeType).type.ref!)?.enumerationLiteral()?.getValue(); @@ -305,10 +305,10 @@ export function isForcible(element: ast.Field): boolean | undefined { return attributeBoolValue(element, 'Attributes.Forcible'); } export function isStatic(element: ast.Operation | ast.Property | ast.Field | ast.Association): boolean | undefined { - return attributeBoolValue(element, 'Attributes.Static'); + return !isConstructor(element) && attributeBoolValue(element, 'Attributes.Static'); } export function isAbstract(element: ast.Operation | ast.Property): boolean { - return !isConstructor(element) && !isStatic(element) + return !isStatic(element) && (ast.isInterface(element.$container) || (attributeBoolValue(element, 'Attributes.Abstract') ?? false)); } export function isVirtual(element: ast.Operation | ast.Property): boolean { @@ -319,7 +319,10 @@ export function isMutable(element: ast.Field | ast.Association): boolean | undef return attributeBoolValue(element, 'Attributes.Mutable'); } export function isConst(element: ast.Parameter | ast.ReturnParameter | ast.Association | ast.Operation | ast.Property): boolean | undefined { - return attributeBoolValue(element, 'Attributes.Const'); + if (isConstructor(element)) { + return false; + } + return attributeBoolValue(element, 'Attributes.Const') ?? (ast.isParameter(element) && (!element.direction || element.direction === 'in') && !ast.isValueType(element.type.ref)); } export function isConstGetter(element: ast.Property): boolean | undefined { return attributeBoolValue(element, 'Attributes.ConstGetter');