From de0d0ae359b077dfc00f72f840d40efd53245505 Mon Sep 17 00:00:00 2001 From: "V.Shkriabets" Date: Thu, 2 Oct 2025 20:01:11 +0300 Subject: [PATCH 1/7] Add C++ GetArrayDataTypeUseCase --- .../generators/cpp/GetArrayDataTypeUseCase.kt | 23 +++ .../generators/cpp/GetTypeNameUseCase.kt | 43 ++++++ .../cpp/PrepareRightValueUseCase.kt | 1 - .../generators/cpp/CppEnumGeneratorTest.kt | 78 +++++++++-- .../cpp/GetArrayDataTypeUseCaseTest.kt | 75 ++++++++++ .../cpp/PrepareRightValueUseCaseTest.kt | 131 ++++++++++++++++++ 6 files changed, 341 insertions(+), 10 deletions(-) create mode 100644 cgen-lib/src/main/kotlin/generators/cpp/GetArrayDataTypeUseCase.kt create mode 100644 cgen-lib/src/main/kotlin/generators/cpp/GetTypeNameUseCase.kt create mode 100644 cgen-lib/src/test/java/generators/cpp/GetArrayDataTypeUseCaseTest.kt create mode 100644 cgen-lib/src/test/java/generators/cpp/PrepareRightValueUseCaseTest.kt diff --git a/cgen-lib/src/main/kotlin/generators/cpp/GetArrayDataTypeUseCase.kt b/cgen-lib/src/main/kotlin/generators/cpp/GetArrayDataTypeUseCase.kt new file mode 100644 index 0000000..5d31188 --- /dev/null +++ b/cgen-lib/src/main/kotlin/generators/cpp/GetArrayDataTypeUseCase.kt @@ -0,0 +1,23 @@ +package generators.cpp + +import ce.defs.DataType + +class GetArrayDataTypeUseCase { + fun getArrayType(type: DataType): String = + when (type) { + DataType.int8 -> "std::vector" + DataType.uint8 -> "std::vector" + DataType.int16 -> "std::vector" + DataType.int32 -> "std::vector" + DataType.int64 -> "std::vector" + DataType.uint16 -> "std::vector" + DataType.uint32 -> "std::vector" + DataType.uint64 -> "std::vector" + DataType.float32 -> "std::vector" + DataType.float64 -> "std::vector" + is DataType.string -> "std::vector" + is DataType.userClass -> "std::vector<${type.path}>" + is DataType.custom -> "std::vector<${type.block.name}>" + else -> "ktQQTP_array_$type" + } +} \ No newline at end of file diff --git a/cgen-lib/src/main/kotlin/generators/cpp/GetTypeNameUseCase.kt b/cgen-lib/src/main/kotlin/generators/cpp/GetTypeNameUseCase.kt new file mode 100644 index 0000000..5af73fd --- /dev/null +++ b/cgen-lib/src/main/kotlin/generators/cpp/GetTypeNameUseCase.kt @@ -0,0 +1,43 @@ +package generators.cpp + +import ce.defs.DataType +import generators.obj.abstractSyntaxTree.findOrCreateSub +import generators.obj.abstractSyntaxTree.getParentPath +import generators.obj.abstractSyntaxTree.getPath +import generators.obj.syntaxParseTree.FileData +import generators.obj.syntaxParseTree.ImportsBlock + +class GetTypeNameUseCase( + private val arrayDataType: GetArrayDataTypeUseCase +) { + fun typeTo(file: FileData, + type: DataType + ) : String { + when (type) { + is DataType.custom -> + file.findOrCreateSub(ImportsBlock::class.java) + .addInclude("${type.block.getParentPath()}.${type.block.name}"); + else -> {} + } + return when (type) { + DataType.VOID -> "void" + DataType.int8, DataType.int8Nullable -> "Byte" + DataType.int16, DataType.int16Nullable -> "Short" + DataType.int32, DataType.int32Nullable -> "Int" + DataType.int64, DataType.int64Nullable -> "Long" + DataType.uint8, DataType.uint8Nullable -> "UByte" + DataType.uint16, DataType.uint16Nullable -> "UShort" + DataType.uint32, DataType.uint32Nullable -> "UInt" + DataType.uint64, DataType.uint64Nullable -> "ULong" + DataType.float32, DataType.float32Nullable -> "Float" + DataType.float64, DataType.float64Nullable -> "Double" + DataType.bool, DataType.boolNullable -> "Boolean" + is DataType.string -> "String" + is DataType.array -> arrayDataType.getArrayType(type.elementDataType) + is DataType.userClass -> type.path + is DataType.custom -> type.block.name + is DataType.userClassTest2 -> type.node.getPath() + else -> "ktQQTP_$type" + } + (if (type.canBeNull) "?" else "") + } +} \ No newline at end of file diff --git a/cgen-lib/src/main/kotlin/generators/cpp/PrepareRightValueUseCase.kt b/cgen-lib/src/main/kotlin/generators/cpp/PrepareRightValueUseCase.kt index 2e151f2..7bf2d2a 100644 --- a/cgen-lib/src/main/kotlin/generators/cpp/PrepareRightValueUseCase.kt +++ b/cgen-lib/src/main/kotlin/generators/cpp/PrepareRightValueUseCase.kt @@ -3,7 +3,6 @@ package generators.cpp import ce.defs.DataType import ce.defs.DataValue import ce.defs.RValue -import generators.kotlin.GetTypeNameUseCase import generators.obj.abstractSyntaxTree.DataField import generators.obj.abstractSyntaxTree.NewInstance import generators.obj.abstractSyntaxTree.addSub diff --git a/cgen-lib/src/test/java/generators/cpp/CppEnumGeneratorTest.kt b/cgen-lib/src/test/java/generators/cpp/CppEnumGeneratorTest.kt index 830c8af..d80eea7 100644 --- a/cgen-lib/src/test/java/generators/cpp/CppEnumGeneratorTest.kt +++ b/cgen-lib/src/test/java/generators/cpp/CppEnumGeneratorTest.kt @@ -5,26 +5,34 @@ import ce.defs.Target import ce.domain.usecase.add.AddRegionDefaultsUseCaseImpl import ce.formatters.CLikeCodestyleRepo import ce.settings.CodeStyle +import ce.treeio.XmlTreeReader import generators.obj.abstractSyntaxTree.* import generators.obj.syntaxParseTree.* import org.gradle.internal.impldep.org.junit.Assert import org.junit.jupiter.api.Test class CppEnumGeneratorTest { + private val reader = XmlTreeReader() + private val arrayDataType = GetArrayDataTypeUseCase() + private val dataTypeToString = GetTypeNameUseCase(arrayDataType) + private val codeStyle = CodeStyle( + newLinesBeforeClass = 1, + tabSize = 2, + preventEmptyBlocks = true, + ) + val repo = CLikeCodestyleRepo(codeStyle) + val fileGenerator = CppFileGenerator() + val prepareRightValueUseCase = PrepareRightValueUseCase(dataTypeToString) + val item = CppEnumGenerator( + addBlockDefaultsUseCase = AddRegionDefaultsUseCaseImpl(repo) + ) @Test fun testWithIntValues() { - val codeStyle = CodeStyle( - newLinesBeforeClass = 1, - tabSize = 2, - preventEmptyBlocks = true, - ) - val repo = CLikeCodestyleRepo(codeStyle) + val project = OutputTree(Target.Cpp) - val item = CppEnumGenerator( - addBlockDefaultsUseCase = AddRegionDefaultsUseCaseImpl(repo) - ) + val headerFile = CppHeaderFile("a").apply { setParent2(project) } val cxxFile = CppFileData("b").apply { setParent2(project) } val files = listOf(headerFile, cxxFile) @@ -72,4 +80,56 @@ class CppEnumGeneratorTest { Assert.assertEquals(Separator::class.java, region.subs[2]::class.java) } + + + @Test + fun testSimpleEnumClass() { + val tree = reader.loadFromString(""" + + + + + + + + + + + """.trimIndent()) as Namespace + val block = tree.subs.first() as ConstantsEnum + + val projectOutput = OutputTree(Target.Kotlin) + val files = fileGenerator.createFile(projectOutput, + workingDirectory = "./", + packageDirectory = "", + "a", block) + val mainFile = files.first() + item(files, block) + + // expected result + // + // ./ + // + // + // + // ... + // + // + // + // + // + // + // + + Assert.assertTrue("Dirty flag should be true", mainFile.isDirty) + Assert.assertEquals(4, mainFile.subs.size) + Assert.assertTrue(mainFile.subs[3] is RegionImpl) + val region = mainFile.subs[3] as Region + Assert.assertEquals(2, region.subs.size) + Assert.assertTrue(region.subs[0] is CommentsBlock) + Assert.assertTrue(region.subs[1] is OutBlock) + Assert.assertEquals("Enum test", (region.subs[0] as CommentsBlock).subs[0].name) + val outBlock = region.findOrNull(OutBlock::class.java)!! + Assert.assertEquals(3, outBlock.subs.size) + } } \ No newline at end of file diff --git a/cgen-lib/src/test/java/generators/cpp/GetArrayDataTypeUseCaseTest.kt b/cgen-lib/src/test/java/generators/cpp/GetArrayDataTypeUseCaseTest.kt new file mode 100644 index 0000000..1cc0aa7 --- /dev/null +++ b/cgen-lib/src/test/java/generators/cpp/GetArrayDataTypeUseCaseTest.kt @@ -0,0 +1,75 @@ +package generators.cpp + +import ce.defs.DataType +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + +class GetArrayDataTypeUseCaseTest { + private val useCase = GetArrayDataTypeUseCase() + @Test + fun getArrayTypeReturnsByteArrayForInt8() { + val result = useCase.getArrayType(DataType.int8) + assertEquals("std::vector", result) + } + + @Test + fun getArrayTypeReturnsByteArrayForUint8() { + val result = useCase.getArrayType(DataType.uint8) + assertEquals("std::vector", result) + } + + @Test + fun getArrayTypeReturnsShortArrayForInt16() { + val result = useCase.getArrayType(DataType.int16) + assertEquals("std::vector", result) + } + + @Test + fun getArrayTypeReturnsIntArrayForInt32() { + val result = useCase.getArrayType(DataType.int32) + assertEquals("std::vector", result) + } + + @Test + fun getArrayTypeReturnsLongArrayForInt64() { + val result = useCase.getArrayType(DataType.int64) + assertEquals("std::vector", result) + } + + @Test + fun getArrayTypeReturnsShortArrayForUint16() { + val result = useCase.getArrayType(DataType.uint16) + assertEquals("std::vector", result) + } + + @Test + fun getArrayTypeReturnsIntArrayForUint32() { + val result = useCase.getArrayType(DataType.uint32) + assertEquals("std::vector", result) + } + + @Test + fun getArrayTypeReturnsFloatArrayForFloat32() { + val result = useCase.getArrayType(DataType.float32) + assertEquals("std::vector", result) + } + + @Test + fun getArrayTypeReturnsDoubleArrayForFloat64() { + val result = useCase.getArrayType(DataType.float64) + assertEquals("std::vector", result) + } + + @Test + fun getArrayTypeReturnsStringArrayForStringType() { + val result = useCase.getArrayType(DataType.string) + assertEquals("std::vector", result) + } + + @Test + fun getArrayTypeReturnsUserClassPathForUserClassType() { + val userClassType = DataType.userClass("MyClass") + val result = useCase.getArrayType(userClassType) + assertEquals("std::vector", result) + } +} \ No newline at end of file diff --git a/cgen-lib/src/test/java/generators/cpp/PrepareRightValueUseCaseTest.kt b/cgen-lib/src/test/java/generators/cpp/PrepareRightValueUseCaseTest.kt new file mode 100644 index 0000000..01ce5d1 --- /dev/null +++ b/cgen-lib/src/test/java/generators/cpp/PrepareRightValueUseCaseTest.kt @@ -0,0 +1,131 @@ +package generators.cpp + +import ce.defs.DataType +import ce.defs.DataValueImpl +import ce.defs.NotDefined +import ce.defs.RValue +import generators.obj.abstractSyntaxTree.DataClass +import generators.obj.abstractSyntaxTree.DataField +import generators.obj.abstractSyntaxTree.NewInstance +import generators.obj.syntaxParseTree.ArgumentNode +import generators.obj.syntaxParseTree.Arguments +import generators.obj.syntaxParseTree.Constructor +import generators.obj.syntaxParseTree.FileDataImpl +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Test + +class PrepareRightValueUseCaseTest { + private val arrayDataType = GetArrayDataTypeUseCase() + private val dataTypeToString = GetTypeNameUseCase(arrayDataType) + private val fileData = FileDataImpl(name = "testFile") + private val prepareRightValueUseCase = PrepareRightValueUseCase(dataTypeToString) + + @Test + fun toRightValueReturnsVoidForVoidType() { + val result = prepareRightValueUseCase.toRightValue(DataType.VOID, + DataValueImpl("ignored"), fileData) + assertEquals("void", result.name) + } + + @Test + fun toRightValueReturnsSimpleValueForIntegerTypes() { + val result = prepareRightValueUseCase.toRightValue(DataType.int32, + DataValueImpl(simple = 42), fileData) + assertEquals("42", result.name) + } + + @Test + fun toRightValueAppendsFForFloat32Type() { + val result = prepareRightValueUseCase.toRightValue(DataType.float32, + DataValueImpl(simple = 3.14), fileData) + assertEquals("3.14f", result.name) + } + + @Test + fun toRightValueReturnsSimpleValueForFloat64Type() { + val result = prepareRightValueUseCase.toRightValue(DataType.float64, + DataValueImpl(simple = 3.14), fileData) + assertEquals("3.14", result.name) + } + + @Test + fun toRightValueReturnsSimpleValueForBooleanType() { + val result = prepareRightValueUseCase.toRightValue(DataType.bool, + DataValueImpl(simple = true), fileData) + assertEquals("true", result.name) + } + + @Test + fun toRightValueReturnsSimpleValueForStringType() { + val result = prepareRightValueUseCase.toRightValue(DataType.string, + DataValueImpl(simple = "hello"), fileData) + assertEquals("\"hello\"", result.name) + } + + @Test + fun toRightValueCustomClass() { + val dataClassDescriptor = DataClass("c").apply { + field("A", DataType.int32, 1) + } + val dataType = DataType.custom(dataClassDescriptor) + val instance = NewInstance("newInstance") + instance.setType(type = dataType) + instance.argument("a", DataType.int32, NotDefined) + instance.argument("b", DataType.int32, 1) + val field = DataField("name").apply { + setValue(instance) + setType(dataType) + } + + val result = prepareRightValueUseCase.toRightValue(dataField = field, fileData = fileData) + assertTrue(result is RValue) + } + + @Test + fun testConstructorToAst() { + val className = "className" + val dataClassDescriptor = DataClass(className).apply { + field("a", DataType.string, "") + field("b", DataType.int32, 0) + } + val dataType = DataType.custom(dataClassDescriptor) + val instance = dataClassDescriptor.instance( + mapOf("a" to "defined", "b" to 123) + ) + + val result = prepareRightValueUseCase.prepareConstructor(instance, fileData) + // expected result + // + // + // + // + // <=> + // + // + // <=> + // + // + // + // + assertTrue(result is RValue) + assertEquals(1, result.subs.size) + assertTrue(result.subs[0] is Constructor) + val constructor = result.subs[0] as Constructor + Assertions.assertEquals(1, constructor.subs.size) + assertTrue(constructor.subs[0] is Arguments) + val arguments = constructor.subs[0] as Arguments + assertEquals(2, arguments.subs.size) + val arg1 = arguments.subs[0] as ArgumentNode + val arg2 = arguments.subs[1] as ArgumentNode + assertEquals(3, arg1.subs.size) + assertEquals(3, arg2.subs.size) + assertEquals("a", arg1.subs[0].name) + assertEquals(RValue::class.java, arg1.subs[2].javaClass) + val rvalue1 = arg1.subs[2] as RValue + assertEquals("\"defined\"", rvalue1.name) + assertEquals("b", arg2.subs[0].name) + assertEquals("123", arg2.subs[2].name) + } +} \ No newline at end of file From 2cf3a7c35ad6c44387c0440e2c439e41390c7cdc Mon Sep 17 00:00:00 2001 From: "V.Shkriabets" Date: Thu, 2 Oct 2025 20:11:01 +0300 Subject: [PATCH 2/7] Fix tests --- .../generators/cpp/GetTypeNameUseCase.kt | 24 +++++++++---------- .../cpp/PrepareRightValueUseCase.kt | 23 +++++++++++++++++- .../generators/cpp/CppEnumGeneratorTest.kt | 17 +++++++------ .../cpp/PrepareRightValueUseCaseTest.kt | 15 +++++------- 4 files changed, 48 insertions(+), 31 deletions(-) diff --git a/cgen-lib/src/main/kotlin/generators/cpp/GetTypeNameUseCase.kt b/cgen-lib/src/main/kotlin/generators/cpp/GetTypeNameUseCase.kt index 5af73fd..94cc699 100644 --- a/cgen-lib/src/main/kotlin/generators/cpp/GetTypeNameUseCase.kt +++ b/cgen-lib/src/main/kotlin/generators/cpp/GetTypeNameUseCase.kt @@ -21,18 +21,18 @@ class GetTypeNameUseCase( } return when (type) { DataType.VOID -> "void" - DataType.int8, DataType.int8Nullable -> "Byte" - DataType.int16, DataType.int16Nullable -> "Short" - DataType.int32, DataType.int32Nullable -> "Int" - DataType.int64, DataType.int64Nullable -> "Long" - DataType.uint8, DataType.uint8Nullable -> "UByte" - DataType.uint16, DataType.uint16Nullable -> "UShort" - DataType.uint32, DataType.uint32Nullable -> "UInt" - DataType.uint64, DataType.uint64Nullable -> "ULong" - DataType.float32, DataType.float32Nullable -> "Float" - DataType.float64, DataType.float64Nullable -> "Double" - DataType.bool, DataType.boolNullable -> "Boolean" - is DataType.string -> "String" + DataType.int8, DataType.int8Nullable -> "int8_t" + DataType.int16, DataType.int16Nullable -> "int16_t" + DataType.int32, DataType.int32Nullable -> "int32_t" + DataType.int64, DataType.int64Nullable -> "int64_t" + DataType.uint8, DataType.uint8Nullable -> "uint8_t" + DataType.uint16, DataType.uint16Nullable -> "uint16_t" + DataType.uint32, DataType.uint32Nullable -> "uint32_t" + DataType.uint64, DataType.uint64Nullable -> "uint64_t" + DataType.float32, DataType.float32Nullable -> "float" + DataType.float64, DataType.float64Nullable -> "double" + DataType.bool, DataType.boolNullable -> "bool" + is DataType.string -> "std::string" is DataType.array -> arrayDataType.getArrayType(type.elementDataType) is DataType.userClass -> type.path is DataType.custom -> type.block.name diff --git a/cgen-lib/src/main/kotlin/generators/cpp/PrepareRightValueUseCase.kt b/cgen-lib/src/main/kotlin/generators/cpp/PrepareRightValueUseCase.kt index 7bf2d2a..cb3e1e6 100644 --- a/cgen-lib/src/main/kotlin/generators/cpp/PrepareRightValueUseCase.kt +++ b/cgen-lib/src/main/kotlin/generators/cpp/PrepareRightValueUseCase.kt @@ -4,11 +4,15 @@ import ce.defs.DataType import ce.defs.DataValue import ce.defs.RValue import generators.obj.abstractSyntaxTree.DataField +import generators.obj.abstractSyntaxTree.Input import generators.obj.abstractSyntaxTree.NewInstance import generators.obj.abstractSyntaxTree.addSub +import generators.obj.syntaxParseTree.ArgumentNode import generators.obj.syntaxParseTree.Arguments import generators.obj.syntaxParseTree.Constructor import generators.obj.syntaxParseTree.FileData +import generators.obj.syntaxParseTree.Keyword +import generators.obj.syntaxParseTree.VariableName class PrepareRightValueUseCase( private val getTypeNameUseCase: GetTypeNameUseCase @@ -66,7 +70,24 @@ class PrepareRightValueUseCase( type = item.getType() ) ).apply { - addSub(Arguments()) + val arguments = Arguments() + addSub(arguments) + item.subs + .filter { it is Input } + .forEach { + val input = it as Input + val argumentNode = ArgumentNode() + arguments.addSub( + argumentNode + ) + argumentNode.addSub( + toRightValue( + type = input.getType(), + value = input.getValue(), + fileData = fileData + ) + ) + } } ) return result diff --git a/cgen-lib/src/test/java/generators/cpp/CppEnumGeneratorTest.kt b/cgen-lib/src/test/java/generators/cpp/CppEnumGeneratorTest.kt index d80eea7..c862de9 100644 --- a/cgen-lib/src/test/java/generators/cpp/CppEnumGeneratorTest.kt +++ b/cgen-lib/src/test/java/generators/cpp/CppEnumGeneratorTest.kt @@ -81,7 +81,6 @@ class CppEnumGeneratorTest { } - @Test fun testSimpleEnumClass() { val tree = reader.loadFromString(""" @@ -111,14 +110,14 @@ class CppEnumGeneratorTest { // ./ // // - // - // ... - // - // - // - // - // - // + // + // ... + // + // + // + // + // + // // Assert.assertTrue("Dirty flag should be true", mainFile.isDirty) diff --git a/cgen-lib/src/test/java/generators/cpp/PrepareRightValueUseCaseTest.kt b/cgen-lib/src/test/java/generators/cpp/PrepareRightValueUseCaseTest.kt index 01ce5d1..95f1028 100644 --- a/cgen-lib/src/test/java/generators/cpp/PrepareRightValueUseCaseTest.kt +++ b/cgen-lib/src/test/java/generators/cpp/PrepareRightValueUseCaseTest.kt @@ -101,10 +101,10 @@ class PrepareRightValueUseCaseTest { // // // - // <=> + // // // - // <=> + // // // // @@ -119,13 +119,10 @@ class PrepareRightValueUseCaseTest { assertEquals(2, arguments.subs.size) val arg1 = arguments.subs[0] as ArgumentNode val arg2 = arguments.subs[1] as ArgumentNode - assertEquals(3, arg1.subs.size) - assertEquals(3, arg2.subs.size) - assertEquals("a", arg1.subs[0].name) - assertEquals(RValue::class.java, arg1.subs[2].javaClass) - val rvalue1 = arg1.subs[2] as RValue + assertEquals(1, arg1.subs.size) + assertEquals(RValue::class.java, arg1.subs[0].javaClass) + val rvalue1 = arg1.subs[0] as RValue assertEquals("\"defined\"", rvalue1.name) - assertEquals("b", arg2.subs[0].name) - assertEquals("123", arg2.subs[2].name) + assertEquals("123", arg2.subs[0].name) } } \ No newline at end of file From db74c5194bf5539f539a8c8df6b2faef80db4dcf Mon Sep 17 00:00:00 2001 From: "V.Shkriabets" Date: Thu, 2 Oct 2025 21:49:02 +0300 Subject: [PATCH 3/7] Fix C++ AST build logic --- .../kotlin/ce/repository/GeneratorsRepo.kt | 11 ++-- .../cpp/CppConstantsBlockGenerator.kt | 1 - .../kotlin/generators/cpp/CppEnumGenerator.kt | 50 +++------------- .../generators/kotlin/KotlinEnumGenerator.kt | 4 -- .../java/ce/formatters/cxx/FormatInclude.kt | 8 +-- .../cpp/CppConstantsBlockGeneratorTest.kt | 3 - .../generators/cpp/CppEnumGeneratorTest.kt | 59 +++++++++++-------- 7 files changed, 52 insertions(+), 84 deletions(-) diff --git a/cgen-lib/src/main/kotlin/ce/repository/GeneratorsRepo.kt b/cgen-lib/src/main/kotlin/ce/repository/GeneratorsRepo.kt index dcb9a83..e14f8e1 100644 --- a/cgen-lib/src/main/kotlin/ce/repository/GeneratorsRepo.kt +++ b/cgen-lib/src/main/kotlin/ce/repository/GeneratorsRepo.kt @@ -132,15 +132,18 @@ class GeneratorsRepo( } Target.Cpp -> { - val arrayDataType = GetArrayDataTypeUseCase() - val dataTypeToString = GetTypeNameUseCase( + val arrayDataType = generators.cpp.GetArrayDataTypeUseCase() + val dataTypeToString = generators.cpp.GetTypeNameUseCase( arrayDataType = arrayDataType ) - val prepareRightValueUseCase = PrepareRightValueUseCase( + val prepareRightValueUseCase = generators.cpp.PrepareRightValueUseCase( getTypeNameUseCase = dataTypeToString ) mapOf( - ConstantsEnum::class.java to CppEnumGenerator(addBlockUseCase), + ConstantsEnum::class.java to CppEnumGenerator( + addBlockDefaultsUseCase = addBlockUseCase, + prepareRightValueUseCase = prepareRightValueUseCase + ), ConstantsBlock::class.java to CppConstantsBlockGenerator( addBlockDefaultsUseCase = addBlockUseCase, prepareRightValueUseCase = prepareRightValueUseCase), diff --git a/cgen-lib/src/main/kotlin/generators/cpp/CppConstantsBlockGenerator.kt b/cgen-lib/src/main/kotlin/generators/cpp/CppConstantsBlockGenerator.kt index ba2ef68..c42e2f9 100644 --- a/cgen-lib/src/main/kotlin/generators/cpp/CppConstantsBlockGenerator.kt +++ b/cgen-lib/src/main/kotlin/generators/cpp/CppConstantsBlockGenerator.kt @@ -1,7 +1,6 @@ package generators.cpp import ce.domain.usecase.add.AddRegionDefaultsUseCase -import generators.kotlin.PrepareRightValueUseCase import generators.obj.AutoincrementField import generators.obj.TransformBlockUseCase import generators.obj.abstractSyntaxTree.ConstantDesc diff --git a/cgen-lib/src/main/kotlin/generators/cpp/CppEnumGenerator.kt b/cgen-lib/src/main/kotlin/generators/cpp/CppEnumGenerator.kt index ce390b8..a06d4dc 100644 --- a/cgen-lib/src/main/kotlin/generators/cpp/CppEnumGenerator.kt +++ b/cgen-lib/src/main/kotlin/generators/cpp/CppEnumGenerator.kt @@ -10,7 +10,6 @@ import generators.obj.abstractSyntaxTree.addCommentLine import generators.obj.abstractSyntaxTree.addEnumLeaf import generators.obj.abstractSyntaxTree.addKeyword import generators.obj.abstractSyntaxTree.addOutBlock -import generators.obj.abstractSyntaxTree.addSeparator import generators.obj.abstractSyntaxTree.addSub import generators.obj.abstractSyntaxTree.addVarName import generators.obj.abstractSyntaxTree.findOrNull @@ -22,6 +21,7 @@ import generators.obj.syntaxParseTree.RegionImpl class CppEnumGenerator( private val addBlockDefaultsUseCase: AddRegionDefaultsUseCase, + private val prepareRightValueUseCase: PrepareRightValueUseCase, ) : TransformBlockUseCase { override fun invoke(files: List, desc: ConstantsEnum) { @@ -45,13 +45,16 @@ class CppEnumGenerator( desc.subs.forEach { leaf -> if (leaf is DataField) { val it = leaf - if (withRawValues) { + autoIncrement(it) + val rValue = prepareRightValueUseCase.toRightValue( + dataField = it, + fileData = headerFile + ) addEnumLeaf(it.name).apply { - autoIncrement(it) addVarName(it.name) addKeyword("=") - addSub(Types.toValue(it.getType(), it.getValue())) + addSub(rValue) } } else { addEnumLeaf(it.name) @@ -59,44 +62,5 @@ class CppEnumGenerator( } } } - region.addSeparator(";") - - -// -// desc.subs.forEach { -// if (it is ConstantDesc) { -// autoIncrement.invoke(it) -// region.addSub( -// ConstantLeaf().apply { -// addKeyword("const") -// addDatatype(Types.typeTo(headerFile, it.type)) -// addVarName(it.name) -// addKeyword("=") -// addRValue(Types.toValue(it.type, it.value)) -// addKeyword(";") -// } -// ) -// } -// } - - -// classDefinition.append("enum ${desc.name} {").append(fileGenerator.newLine()) -// val autoIncrement = AutoincrementField() -// desc.subs.forEach { leaf -> -// val it = leaf as DataField -// putTabs(classDefinition, 1) -// -// if (withRawValues) { -// autoIncrement.invoke(it) -// classDefinition.append(it.name); -// classDefinition.append(" = ${Types.toValue(this, it.type, it.value)},") -// classDefinition.append(fileGenerator.newLine()) -// } else { -// classDefinition.append("${it.name},${fileGenerator.newLine()}"); -// } -// } -// appendClassDefinition(this, "};"); - } - } \ No newline at end of file diff --git a/cgen-lib/src/main/kotlin/generators/kotlin/KotlinEnumGenerator.kt b/cgen-lib/src/main/kotlin/generators/kotlin/KotlinEnumGenerator.kt index 924c2bc..af77a9d 100644 --- a/cgen-lib/src/main/kotlin/generators/kotlin/KotlinEnumGenerator.kt +++ b/cgen-lib/src/main/kotlin/generators/kotlin/KotlinEnumGenerator.kt @@ -40,16 +40,12 @@ class KotlinEnumGenerator( addVarName("rawValue") addKeyword(":") addDatatype(dataTypeToString.typeTo(file, desc.defaultDataType)) -// addKeyword("=") -// addRValue(Types.toValue(desc.type, desc.value)) }) -// addDataField("val rawValue : ${Types.typeTo(file, desc.defaultDataType)}", desc.defaultDataType) } } desc.subs.forEach { leaf -> if (leaf is DataField) { val it = leaf - if (withRawValues) { autoIncrement(it) val rValue = prepareRightValueUseCase.toRightValue( diff --git a/cgen-lib/src/test/java/ce/formatters/cxx/FormatInclude.kt b/cgen-lib/src/test/java/ce/formatters/cxx/FormatInclude.kt index 1c264a3..f2123c2 100644 --- a/cgen-lib/src/test/java/ce/formatters/cxx/FormatInclude.kt +++ b/cgen-lib/src/test/java/ce/formatters/cxx/FormatInclude.kt @@ -10,19 +10,19 @@ import generators.cpp.CompilerDirective import generators.cpp.CppConstantsBlockGenerator import generators.cpp.CppFileGenerator import generators.cpp.CppHeaderFile -import generators.kotlin.GetArrayDataTypeUseCase -import generators.kotlin.GetTypeNameUseCase -import generators.kotlin.PrepareRightValueUseCase +import generators.cpp.GetArrayDataTypeUseCase +import generators.cpp.GetTypeNameUseCase +import generators.cpp.PrepareRightValueUseCase import generators.obj.abstractSyntaxTree.ConstantsBlock import generators.obj.abstractSyntaxTree.NamespaceImpl import generators.obj.abstractSyntaxTree.TreeRoot import generators.obj.abstractSyntaxTree.addSub import generators.obj.syntaxParseTree.FileDataImpl +import generators.obj.syntaxParseTree.FileMetaInformation import generators.obj.syntaxParseTree.ImportsBlock import generators.obj.syntaxParseTree.NamespaceBlock import generators.obj.syntaxParseTree.NlSeparator import generators.obj.syntaxParseTree.OutputTree -import generators.obj.syntaxParseTree.FileMetaInformation import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test diff --git a/cgen-lib/src/test/java/generators/cpp/CppConstantsBlockGeneratorTest.kt b/cgen-lib/src/test/java/generators/cpp/CppConstantsBlockGeneratorTest.kt index 9a53b34..8685602 100644 --- a/cgen-lib/src/test/java/generators/cpp/CppConstantsBlockGeneratorTest.kt +++ b/cgen-lib/src/test/java/generators/cpp/CppConstantsBlockGeneratorTest.kt @@ -6,9 +6,6 @@ import ce.defs.Target import ce.domain.usecase.add.AddRegionDefaultsUseCaseImpl import ce.formatters.CLikeCodestyleRepo import ce.settings.CodeStyle -import generators.kotlin.GetArrayDataTypeUseCase -import generators.kotlin.GetTypeNameUseCase -import generators.kotlin.PrepareRightValueUseCase import generators.obj.abstractSyntaxTree.ConstantsBlock import generators.obj.abstractSyntaxTree.NamespaceImpl import generators.obj.abstractSyntaxTree.TreeRoot diff --git a/cgen-lib/src/test/java/generators/cpp/CppEnumGeneratorTest.kt b/cgen-lib/src/test/java/generators/cpp/CppEnumGeneratorTest.kt index c862de9..8dacd86 100644 --- a/cgen-lib/src/test/java/generators/cpp/CppEnumGeneratorTest.kt +++ b/cgen-lib/src/test/java/generators/cpp/CppEnumGeneratorTest.kt @@ -6,8 +6,18 @@ import ce.domain.usecase.add.AddRegionDefaultsUseCaseImpl import ce.formatters.CLikeCodestyleRepo import ce.settings.CodeStyle import ce.treeio.XmlTreeReader -import generators.obj.abstractSyntaxTree.* -import generators.obj.syntaxParseTree.* +import generators.obj.abstractSyntaxTree.ConstantsEnum +import generators.obj.abstractSyntaxTree.Namespace +import generators.obj.abstractSyntaxTree.NamespaceImpl +import generators.obj.abstractSyntaxTree.TreeRoot +import generators.obj.abstractSyntaxTree.addSub +import generators.obj.abstractSyntaxTree.findOrNull +import generators.obj.syntaxParseTree.CommentsBlock +import generators.obj.syntaxParseTree.NamespaceBlock +import generators.obj.syntaxParseTree.OutBlock +import generators.obj.syntaxParseTree.OutputTree +import generators.obj.syntaxParseTree.Region +import generators.obj.syntaxParseTree.RegionImpl import org.gradle.internal.impldep.org.junit.Assert import org.junit.jupiter.api.Test @@ -24,15 +34,13 @@ class CppEnumGeneratorTest { val fileGenerator = CppFileGenerator() val prepareRightValueUseCase = PrepareRightValueUseCase(dataTypeToString) val item = CppEnumGenerator( - addBlockDefaultsUseCase = AddRegionDefaultsUseCaseImpl(repo) + addBlockDefaultsUseCase = AddRegionDefaultsUseCaseImpl(repo), + prepareRightValueUseCase = prepareRightValueUseCase ) @Test fun testWithIntValues() { - - val project = OutputTree(Target.Cpp) - val headerFile = CppHeaderFile("a").apply { setParent2(project) } val cxxFile = CppFileData("b").apply { setParent2(project) } val files = listOf(headerFile, cxxFile) @@ -59,7 +67,6 @@ class CppEnumGeneratorTest { // <=><2> // <=><33> // - // <;> // // // @@ -70,15 +77,12 @@ class CppEnumGeneratorTest { val outNamespace = headerFile.findOrNull(NamespaceBlock::class.java)!! Assert.assertEquals(1, outNamespace.subs.size) val region = outNamespace.findOrNull(RegionImpl::class.java)!! - Assert.assertEquals(3, region.subs.size) + Assert.assertEquals(2, region.subs.size) Assert.assertEquals(CommentsBlock::class.java, region.subs[0]::class.java) Assert.assertEquals("182TEST_COMMENT", (region.subs[0] as CommentsBlock).subs[0].name) Assert.assertEquals(OutBlock::class.java, region.subs[1]::class.java) val outBlock = region.findOrNull(OutBlock::class.java)!! Assert.assertEquals(3, outBlock.subs.size) - - Assert.assertEquals(Separator::class.java, region.subs[2]::class.java) - } @Test @@ -102,28 +106,33 @@ class CppEnumGeneratorTest { workingDirectory = "./", packageDirectory = "", "a", block) - val mainFile = files.first() + val headerFile = files.first { it is CppHeaderFile } item(files, block) // expected result - // - // ./ - // + // + // + // // - // - // ... - // + // + // + // ... + // // // // - // - // - // + // + // + // + // - Assert.assertTrue("Dirty flag should be true", mainFile.isDirty) - Assert.assertEquals(4, mainFile.subs.size) - Assert.assertTrue(mainFile.subs[3] is RegionImpl) - val region = mainFile.subs[3] as Region + Assert.assertTrue("Dirty flag should be true", headerFile.isDirty) + Assert.assertEquals(4, headerFile.subs.size) + Assert.assertTrue(headerFile.subs[3] is NamespaceBlock) + val nsBlock = headerFile.subs[3] as NamespaceBlock + Assert.assertEquals(1, nsBlock.subs.size) + Assert.assertTrue(nsBlock.subs[0] is RegionImpl) + val region = nsBlock.subs[0] as Region Assert.assertEquals(2, region.subs.size) Assert.assertTrue(region.subs[0] is CommentsBlock) Assert.assertTrue(region.subs[1] is OutBlock) From 3fcd9b6e4be4dc2c35e874f10776856ee508028a Mon Sep 17 00:00:00 2001 From: "V.Shkriabets" Date: Thu, 2 Oct 2025 21:56:55 +0300 Subject: [PATCH 4/7] Add C++ Enum format test --- .../kotlin/generators/cpp/CppEnumGenerator.kt | 2 +- .../formatters/cxx/CxxEnumFormattingTests.kt | 125 ++++++++++++++++++ 2 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 cgen-lib/src/test/java/ce/formatters/cxx/CxxEnumFormattingTests.kt diff --git a/cgen-lib/src/main/kotlin/generators/cpp/CppEnumGenerator.kt b/cgen-lib/src/main/kotlin/generators/cpp/CppEnumGenerator.kt index a06d4dc..0d8065b 100644 --- a/cgen-lib/src/main/kotlin/generators/cpp/CppEnumGenerator.kt +++ b/cgen-lib/src/main/kotlin/generators/cpp/CppEnumGenerator.kt @@ -51,7 +51,7 @@ class CppEnumGenerator( dataField = it, fileData = headerFile ) - addEnumLeaf(it.name).apply { + addEnumLeaf("").apply { addVarName(it.name) addKeyword("=") addSub(rValue) diff --git a/cgen-lib/src/test/java/ce/formatters/cxx/CxxEnumFormattingTests.kt b/cgen-lib/src/test/java/ce/formatters/cxx/CxxEnumFormattingTests.kt new file mode 100644 index 0000000..46d9a50 --- /dev/null +++ b/cgen-lib/src/test/java/ce/formatters/cxx/CxxEnumFormattingTests.kt @@ -0,0 +1,125 @@ +package ce.formatters.cxx + +import ce.defs.RValue +import ce.formatters.CLikeCodestyleRepo +import ce.formatters.CodeFormatterUseCaseImpl +import ce.settings.CodeStyle +import generators.obj.abstractSyntaxTree.addEnumLeaf +import generators.obj.abstractSyntaxTree.addOutBlock +import generators.obj.abstractSyntaxTree.addSub +import generators.obj.syntaxParseTree.ArgumentNode +import generators.obj.syntaxParseTree.Arguments +import generators.obj.syntaxParseTree.EnumNode +import generators.obj.syntaxParseTree.Keyword +import generators.obj.syntaxParseTree.NlSeparator +import generators.obj.syntaxParseTree.OutBlock +import generators.obj.syntaxParseTree.OutBlockArguments +import generators.obj.syntaxParseTree.RegionImpl +import org.gradle.internal.impldep.org.junit.Assert +import org.junit.jupiter.api.Test + +class CxxEnumFormattingTests { + val codeStyle1NlBeforeRegion = CodeStyle( + newLinesBeforeClass = 1, + tabSize = 4, + preventEmptyBlocks = true, + ) + + val codeStyleNoSpace = CodeStyle( + newLinesBeforeClass = 0, + tabSize = 2, + preventEmptyBlocks = true, + ) + val repoNoSpace = CLikeCodestyleRepo(codeStyleNoSpace) + val formatter = CodeFormatterUseCaseImpl(repoNoSpace) + + @Test + fun testSimpleEnumCxx() { + val input = RegionImpl().apply { + addOutBlock("enum ENUM") { + addEnumLeaf("A") + addEnumLeaf("B") + addEnumLeaf("C") + addEnumLeaf("D") + } + } + val output = formatter(input) + // expected result + // + // + // <{> + // <,> + // <,> + // <,> + // + // <}> + // + // + // + Assert.assertEquals(2, output.subs.size) + val outBlock = output.subs[0] as OutBlock + Assert.assertEquals(19, outBlock.subs.size) + } + + @Test + fun testEnumRawValueCxx() { + val input = RegionImpl().apply { + addOutBlock("enum ENUM") { + addSub(OutBlockArguments()) + listOf("A","B","C","D").forEachIndexed { idx,name -> + addEnumLeaf(name).apply { + addSub(Arguments()) + .addSub(RValue(idx.toString())) + } + } + } + } + val output = formatter(input) + // expected result + // + // + // <{> + // + // + // + // + // <=> + // + // + // <,> + // + // ... <,> + // + // ... <,> + // + // ... + // <}> + // + // + // + Assert.assertEquals(2, output.subs.size) + val outBlock = output.subs[0] as OutBlock + Assert.assertTrue(outBlock.subs[0] is Keyword) + Assert.assertTrue(outBlock.subs[1] is Keyword) + Assert.assertTrue(outBlock.subs[2] is NlSeparator) + Assert.assertEquals(19, outBlock.subs.size) + + val outBlockArguments = outBlock.subs[1] as OutBlockArguments + Assert.assertEquals(1, outBlockArguments.subs.size) + + Assert.assertTrue(outBlockArguments.subs[0] is ArgumentNode) + val argumentNode = outBlockArguments.subs[0] as ArgumentNode + Assert.assertTrue(argumentNode.subs[0] is Keyword) + Assert.assertEquals(6, argumentNode.subs.size) + + Assert.assertTrue(outBlock.subs[7] is EnumNode) + val firstEnumNode = outBlock.subs[7] as EnumNode + Assert.assertEquals(3 , firstEnumNode.subs.size) + Assert.assertTrue(firstEnumNode.subs[0] is Keyword) + Assert.assertTrue(firstEnumNode.subs[1] is Arguments) + Assert.assertTrue(firstEnumNode.subs[2] is Keyword) + val firstNodeArguments = firstEnumNode.subs[1] as Arguments + Assert.assertEquals(1 , firstNodeArguments.subs.size) + Assert.assertTrue(firstNodeArguments.subs[0] is RValue) + } +} \ No newline at end of file From e03bff8b3f419f7c86062e2917f13ab06b417357 Mon Sep 17 00:00:00 2001 From: "V.Shkriabets" Date: Fri, 3 Oct 2025 08:43:59 +0300 Subject: [PATCH 5/7] Fix tests --- .../formatters/CodeFormatterCxxUseCaseImpl.kt | 21 ++++ .../kotlin/ce/repository/GeneratorsRepo.kt | 23 ++-- .../generators/cpp/CppDataClassGenerator.kt | 29 ++--- .../generators/cpp/GetTypeNameUseCase.kt | 9 +- .../src/main/kotlin/generators/cpp/Types.kt | 1 + .../generators/obj/abstractSyntaxTree/Node.kt | 7 ++ .../cxx/CodeFormatterCxxUseCaseImplTest.kt | 103 +----------------- .../formatters/cxx/CxxEnumFormattingTests.kt | 59 +++++----- .../cpp/CppDataClassGeneratorTest.kt | 20 ++-- 9 files changed, 93 insertions(+), 179 deletions(-) diff --git a/cgen-lib/src/main/kotlin/ce/formatters/CodeFormatterCxxUseCaseImpl.kt b/cgen-lib/src/main/kotlin/ce/formatters/CodeFormatterCxxUseCaseImpl.kt index f54a52d..c08a67e 100644 --- a/cgen-lib/src/main/kotlin/ce/formatters/CodeFormatterCxxUseCaseImpl.kt +++ b/cgen-lib/src/main/kotlin/ce/formatters/CodeFormatterCxxUseCaseImpl.kt @@ -1,11 +1,16 @@ package ce.formatters +import ce.defs.RValue import generators.obj.abstractSyntaxTree.Leaf import generators.obj.abstractSyntaxTree.Node import generators.obj.abstractSyntaxTree.addSeparator import generators.obj.abstractSyntaxTree.addSub +import generators.obj.abstractSyntaxTree.insertSub import generators.obj.syntaxParseTree.EnumNode +import generators.obj.syntaxParseTree.Keyword import generators.obj.syntaxParseTree.Separator +import generators.obj.syntaxParseTree.Space +import generators.obj.syntaxParseTree.VariableName import javax.inject.Inject class CodeFormatterCxxUseCaseImpl @Inject constructor(codeStyleRepo: CodeStyleRepo) : @@ -38,4 +43,20 @@ class CodeFormatterCxxUseCaseImpl @Inject constructor(codeStyleRepo: CodeStyleRe outputParent.addSeparator(";") } } + + override fun processEnumNode(input: EnumNode, parent: Node?, indent: Int, next: Leaf?, prev: Leaf?): EnumNode { + val result = super.processEnumNode(input, parent, indent, next, prev) + // make sure that we have spaces between name, = and rvalue + if (result.subs.size >= 3) { + val varName = result.subs[0] + val eq = result.subs[1] + val rValue = result.subs[2] + if (varName is VariableName && eq is Keyword && rValue is RValue) { + // add spaces + result.insertSub(2, Space()) + result.insertSub(1, Space()) + } + } + return result + } } \ No newline at end of file diff --git a/cgen-lib/src/main/kotlin/ce/repository/GeneratorsRepo.kt b/cgen-lib/src/main/kotlin/ce/repository/GeneratorsRepo.kt index e14f8e1..489ed1e 100644 --- a/cgen-lib/src/main/kotlin/ce/repository/GeneratorsRepo.kt +++ b/cgen-lib/src/main/kotlin/ce/repository/GeneratorsRepo.kt @@ -7,23 +7,11 @@ import ce.formatters.CodeFormatterJavaUseCaseImpl import ce.formatters.CodeFormatterKotlinUseCaseImpl import ce.formatters.CodeFormatterUseCase import ce.settings.Project -import generators.cpp.CppConstantsBlockGenerator -import generators.cpp.CppDataClassGenerator -import generators.cpp.CppEnumGenerator -import generators.cpp.CppFileGenerator -import generators.cpp.CppInterfaceGenerator -import generators.java.JavaConstantsGenerator -import generators.java.JavaDataClassGenerator -import generators.java.JavaEnumGenerator -import generators.java.JavaFileGenerator -import generators.java.JavaInterfaceGenerator +import generators.cpp.* +import generators.java.* +import generators.kotlin.* import generators.kotlin.GetArrayDataTypeUseCase import generators.kotlin.GetTypeNameUseCase -import generators.kotlin.KotlinEnumGenerator -import generators.kotlin.KotlinFileGenerator -import generators.kotlin.KotlinInterfaceGenerator -import generators.kotlin.KtConstantsGenerator -import generators.kotlin.KtDataClassGenerator import generators.kotlin.PrepareRightValueUseCase import generators.obj.MetaGenerator import generators.obj.PrepareFilesListUseCaseImpl @@ -147,7 +135,10 @@ class GeneratorsRepo( ConstantsBlock::class.java to CppConstantsBlockGenerator( addBlockDefaultsUseCase = addBlockUseCase, prepareRightValueUseCase = prepareRightValueUseCase), - DataClass::class.java to CppDataClassGenerator(addBlockUseCase), + DataClass::class.java to CppDataClassGenerator( + addBlockDefaultsUseCase = addBlockUseCase, + prepareRightValueUseCase = prepareRightValueUseCase, + dataTypeToString = dataTypeToString), InterfaceDescription::class.java to CppInterfaceGenerator(addBlockUseCase) ) } diff --git a/cgen-lib/src/main/kotlin/generators/cpp/CppDataClassGenerator.kt b/cgen-lib/src/main/kotlin/generators/cpp/CppDataClassGenerator.kt index 6c377ca..4a07e47 100644 --- a/cgen-lib/src/main/kotlin/generators/cpp/CppDataClassGenerator.kt +++ b/cgen-lib/src/main/kotlin/generators/cpp/CppDataClassGenerator.kt @@ -2,26 +2,13 @@ package generators.cpp import ce.domain.usecase.add.AddRegionDefaultsUseCase import generators.obj.TransformBlockUseCase -import generators.obj.abstractSyntaxTree.DataClass -import generators.obj.abstractSyntaxTree.DataField -import generators.obj.abstractSyntaxTree.addCommentLine -import generators.obj.abstractSyntaxTree.addDatatype -import generators.obj.abstractSyntaxTree.addKeyword -import generators.obj.abstractSyntaxTree.addOutBlock -import generators.obj.abstractSyntaxTree.addSub -import generators.obj.abstractSyntaxTree.addVarName -import generators.obj.abstractSyntaxTree.findOrCreateSub -import generators.obj.abstractSyntaxTree.findOrNull -import generators.obj.abstractSyntaxTree.getParentPath -import generators.obj.syntaxParseTree.CommentsBlock -import generators.obj.syntaxParseTree.FieldNode -import generators.obj.syntaxParseTree.FileData -import generators.obj.syntaxParseTree.ImportsBlock -import generators.obj.syntaxParseTree.NamespaceBlock -import generators.obj.syntaxParseTree.RegionImpl +import generators.obj.abstractSyntaxTree.* +import generators.obj.syntaxParseTree.* class CppDataClassGenerator( private val addBlockDefaultsUseCase: AddRegionDefaultsUseCase, + private val prepareRightValueUseCase: PrepareRightValueUseCase, + private val dataTypeToString: GetTypeNameUseCase, ) : TransformBlockUseCase { override fun invoke(blockFiles: List, desc: DataClass) { @@ -43,11 +30,15 @@ class CppDataClassGenerator( desc.subs.forEach { leaf -> if (leaf is DataField) { addSub(FieldNode().apply { - addDatatype(Types.typeTo(header, leaf.getType())) + addDatatype(dataTypeToString.typeTo(header, leaf.getType())) addVarName(leaf.name) if (leaf.getValue().isDefined()) { addKeyword("=") - addSub(Types.toValue(leaf.getType(), leaf.getValue())) + val rValue = prepareRightValueUseCase.toRightValue( + dataField = leaf, + fileData = header + ) + addSub(rValue) } }) } diff --git a/cgen-lib/src/main/kotlin/generators/cpp/GetTypeNameUseCase.kt b/cgen-lib/src/main/kotlin/generators/cpp/GetTypeNameUseCase.kt index 94cc699..f4731e1 100644 --- a/cgen-lib/src/main/kotlin/generators/cpp/GetTypeNameUseCase.kt +++ b/cgen-lib/src/main/kotlin/generators/cpp/GetTypeNameUseCase.kt @@ -19,7 +19,7 @@ class GetTypeNameUseCase( .addInclude("${type.block.getParentPath()}.${type.block.name}"); else -> {} } - return when (type) { + val baseType = when (type) { DataType.VOID -> "void" DataType.int8, DataType.int8Nullable -> "int8_t" DataType.int16, DataType.int16Nullable -> "int16_t" @@ -32,12 +32,15 @@ class GetTypeNameUseCase( DataType.float32, DataType.float32Nullable -> "float" DataType.float64, DataType.float64Nullable -> "double" DataType.bool, DataType.boolNullable -> "bool" - is DataType.string -> "std::string" + + DataType.string, DataType.stringNullable -> "std::string" is DataType.array -> arrayDataType.getArrayType(type.elementDataType) is DataType.userClass -> type.path is DataType.custom -> type.block.name is DataType.userClassTest2 -> type.node.getPath() else -> "ktQQTP_$type" - } + (if (type.canBeNull) "?" else "") + } + val result = if (type.canBeNull) "std::optional<$baseType>" else baseType + return result } } \ No newline at end of file diff --git a/cgen-lib/src/main/kotlin/generators/cpp/Types.kt b/cgen-lib/src/main/kotlin/generators/cpp/Types.kt index 6820fc6..69f9ac4 100644 --- a/cgen-lib/src/main/kotlin/generators/cpp/Types.kt +++ b/cgen-lib/src/main/kotlin/generators/cpp/Types.kt @@ -7,6 +7,7 @@ import generators.obj.abstractSyntaxTree.findOrCreateSub import generators.obj.syntaxParseTree.FileData import generators.obj.syntaxParseTree.ImportsBlock +@Deprecated("Use GetTypeNameUseCase") object Types { fun typeTo(file: FileData, type: DataType diff --git a/cgen-lib/src/main/kotlin/generators/obj/abstractSyntaxTree/Node.kt b/cgen-lib/src/main/kotlin/generators/obj/abstractSyntaxTree/Node.kt index 0ad08d6..3020bc4 100644 --- a/cgen-lib/src/main/kotlin/generators/obj/abstractSyntaxTree/Node.kt +++ b/cgen-lib/src/main/kotlin/generators/obj/abstractSyntaxTree/Node.kt @@ -67,6 +67,13 @@ fun T.addSub(leaf: R): R { return leaf } +fun T.insertSub(idx: Int, leaf: R): R { + subs.add(idx, leaf) + leaf.setParent2(this) + (findParent(FileData::class) as FileData?)?.isDirty = true + return leaf +} + fun T.addSubs(vararg leafs: R) { leafs.forEach { subs.add(it) diff --git a/cgen-lib/src/test/java/ce/formatters/cxx/CodeFormatterCxxUseCaseImplTest.kt b/cgen-lib/src/test/java/ce/formatters/cxx/CodeFormatterCxxUseCaseImplTest.kt index dcf810c..6ab2fab 100644 --- a/cgen-lib/src/test/java/ce/formatters/cxx/CodeFormatterCxxUseCaseImplTest.kt +++ b/cgen-lib/src/test/java/ce/formatters/cxx/CodeFormatterCxxUseCaseImplTest.kt @@ -1,26 +1,12 @@ package ce.formatters.cxx -import ce.defs.DataType import ce.formatters.CLikeCodestyleRepo import ce.formatters.CodeFormatterCxxUseCaseImpl import ce.settings.CodeStyle -import generators.obj.abstractSyntaxTree.DataField import generators.obj.abstractSyntaxTree.addEnumLeaf -import generators.obj.abstractSyntaxTree.addKeyword import generators.obj.abstractSyntaxTree.addOutBlock -import generators.obj.abstractSyntaxTree.addRValue -import generators.obj.abstractSyntaxTree.addSeparator import generators.obj.abstractSyntaxTree.addSub -import generators.obj.abstractSyntaxTree.addVarName -import generators.obj.syntaxParseTree.Indent -import generators.obj.syntaxParseTree.Keyword -import generators.obj.syntaxParseTree.NamespaceBlock -import generators.obj.syntaxParseTree.NlSeparator -import generators.obj.syntaxParseTree.OutBlock -import generators.obj.syntaxParseTree.OutBlockArguments -import generators.obj.syntaxParseTree.Region -import generators.obj.syntaxParseTree.RegionImpl -import generators.obj.syntaxParseTree.Separator +import generators.obj.syntaxParseTree.* import org.gradle.internal.impldep.org.junit.Assert import org.junit.jupiter.api.Test @@ -33,93 +19,6 @@ class CodeFormatterCxxUseCaseImplTest { val repoNoSpace = CLikeCodestyleRepo(codeStyleNoSpace) val formatter = CodeFormatterCxxUseCaseImpl(repoNoSpace) - @Test - fun testSimpleEnum() { - val input = RegionImpl().apply { - addOutBlock("enum ENUM") { - addEnumLeaf("A") - addEnumLeaf("B") - addEnumLeaf("C") - addEnumLeaf("D") - } - addSeparator(";") - } - val output = formatter(input) - // expected result - // - // - // <{> - // <,> - // <,> - // <,> - // - // <}> - // - // <;> - // - // - Assert.assertEquals(3, output.subs.size) - val outBlock = output.subs[0] as OutBlock - Assert.assertEquals(19, outBlock.subs.size) - Assert.assertEquals(Separator::class.java, output.subs[1]::class.java) - } - - @Test - fun testEnumWithValue() { - val input = RegionImpl().apply { - addOutBlock("enum class ENUM") { - addSub(OutBlockArguments()).apply { - addSub(DataField("name").apply { - setType(DataType.int16) - }) - } - addEnumLeaf("A").apply { - addVarName("A") - addKeyword("=") - addRValue("0") - } - addEnumLeaf("B").apply { - addVarName("B") - addKeyword("=") - addRValue("1") - } - addEnumLeaf("C").apply { - addVarName("C") - addKeyword("=") - addRValue("2") - } - addEnumLeaf("D").apply { - addVarName("D") - addKeyword("=") - addRValue("3") - } - } - addSeparator(";") - } - val output = formatter(input) - // expected result - // - // - // <(> <)> - // <{> - // <,> - // <,> - // <,> - // - // <}> - // - // <;> - // - // - Assert.assertEquals(3, output.subs.size) - val outBlock = output.subs[0] as OutBlock - Assert.assertTrue(outBlock.subs[0] is Keyword) - Assert.assertTrue(outBlock.subs[1] is OutBlockArguments) - Assert.assertTrue(outBlock.subs[2] is Keyword) - Assert.assertEquals(22, outBlock.subs.size) - Assert.assertEquals(Separator::class.java, output.subs[1]::class.java) - } - @Test fun testNamespaceIndents() { val input = NamespaceBlock("b").apply { diff --git a/cgen-lib/src/test/java/ce/formatters/cxx/CxxEnumFormattingTests.kt b/cgen-lib/src/test/java/ce/formatters/cxx/CxxEnumFormattingTests.kt index 46d9a50..bc7f8d9 100644 --- a/cgen-lib/src/test/java/ce/formatters/cxx/CxxEnumFormattingTests.kt +++ b/cgen-lib/src/test/java/ce/formatters/cxx/CxxEnumFormattingTests.kt @@ -2,11 +2,14 @@ package ce.formatters.cxx import ce.defs.RValue import ce.formatters.CLikeCodestyleRepo +import ce.formatters.CodeFormatterCxxUseCaseImpl import ce.formatters.CodeFormatterUseCaseImpl import ce.settings.CodeStyle import generators.obj.abstractSyntaxTree.addEnumLeaf +import generators.obj.abstractSyntaxTree.addKeyword import generators.obj.abstractSyntaxTree.addOutBlock import generators.obj.abstractSyntaxTree.addSub +import generators.obj.abstractSyntaxTree.addVarName import generators.obj.syntaxParseTree.ArgumentNode import generators.obj.syntaxParseTree.Arguments import generators.obj.syntaxParseTree.EnumNode @@ -15,6 +18,8 @@ import generators.obj.syntaxParseTree.NlSeparator import generators.obj.syntaxParseTree.OutBlock import generators.obj.syntaxParseTree.OutBlockArguments import generators.obj.syntaxParseTree.RegionImpl +import generators.obj.syntaxParseTree.Space +import generators.obj.syntaxParseTree.VariableName import org.gradle.internal.impldep.org.junit.Assert import org.junit.jupiter.api.Test @@ -31,16 +36,17 @@ class CxxEnumFormattingTests { preventEmptyBlocks = true, ) val repoNoSpace = CLikeCodestyleRepo(codeStyleNoSpace) - val formatter = CodeFormatterUseCaseImpl(repoNoSpace) + val formatter = CodeFormatterCxxUseCaseImpl(repoNoSpace) @Test fun testSimpleEnumCxx() { val input = RegionImpl().apply { addOutBlock("enum ENUM") { - addEnumLeaf("A") - addEnumLeaf("B") - addEnumLeaf("C") - addEnumLeaf("D") + listOf("A","B","C","D").forEachIndexed { idx,name -> + addEnumLeaf("").apply { + addVarName(name) + } + } } } val output = formatter(input) @@ -48,7 +54,11 @@ class CxxEnumFormattingTests { // // // <{> - // <,> + // + // + // + // + // <,> // <,> // <,> // @@ -59,17 +69,21 @@ class CxxEnumFormattingTests { Assert.assertEquals(2, output.subs.size) val outBlock = output.subs[0] as OutBlock Assert.assertEquals(19, outBlock.subs.size) + Assert.assertTrue(outBlock.subs[4] is EnumNode) + val firstEnumNode = outBlock.subs[4] as EnumNode + Assert.assertEquals(1 , firstEnumNode.subs.size) + Assert.assertTrue(firstEnumNode.subs[0] is VariableName) } @Test fun testEnumRawValueCxx() { val input = RegionImpl().apply { addOutBlock("enum ENUM") { - addSub(OutBlockArguments()) listOf("A","B","C","D").forEachIndexed { idx,name -> - addEnumLeaf(name).apply { - addSub(Arguments()) - .addSub(RValue(idx.toString())) + addEnumLeaf("").apply { + addVarName(name) + addKeyword("=") + addSub(RValue(idx.toString())) } } } @@ -99,27 +113,18 @@ class CxxEnumFormattingTests { // Assert.assertEquals(2, output.subs.size) val outBlock = output.subs[0] as OutBlock - Assert.assertTrue(outBlock.subs[0] is Keyword) + Assert.assertTrue(outBlock.subs[0] is Space) Assert.assertTrue(outBlock.subs[1] is Keyword) Assert.assertTrue(outBlock.subs[2] is NlSeparator) Assert.assertEquals(19, outBlock.subs.size) - val outBlockArguments = outBlock.subs[1] as OutBlockArguments - Assert.assertEquals(1, outBlockArguments.subs.size) - - Assert.assertTrue(outBlockArguments.subs[0] is ArgumentNode) - val argumentNode = outBlockArguments.subs[0] as ArgumentNode - Assert.assertTrue(argumentNode.subs[0] is Keyword) - Assert.assertEquals(6, argumentNode.subs.size) - - Assert.assertTrue(outBlock.subs[7] is EnumNode) - val firstEnumNode = outBlock.subs[7] as EnumNode - Assert.assertEquals(3 , firstEnumNode.subs.size) - Assert.assertTrue(firstEnumNode.subs[0] is Keyword) - Assert.assertTrue(firstEnumNode.subs[1] is Arguments) + Assert.assertTrue(outBlock.subs[4] is EnumNode) + val firstEnumNode = outBlock.subs[4] as EnumNode + Assert.assertEquals(5 , firstEnumNode.subs.size) + Assert.assertTrue(firstEnumNode.subs[0] is VariableName) + Assert.assertTrue(firstEnumNode.subs[1] is Space) Assert.assertTrue(firstEnumNode.subs[2] is Keyword) - val firstNodeArguments = firstEnumNode.subs[1] as Arguments - Assert.assertEquals(1 , firstNodeArguments.subs.size) - Assert.assertTrue(firstNodeArguments.subs[0] is RValue) + Assert.assertTrue(firstEnumNode.subs[3] is Space) + Assert.assertTrue(firstEnumNode.subs[4] is RValue) } } \ No newline at end of file diff --git a/cgen-lib/src/test/java/generators/cpp/CppDataClassGeneratorTest.kt b/cgen-lib/src/test/java/generators/cpp/CppDataClassGeneratorTest.kt index 53f5b27..f0122e4 100644 --- a/cgen-lib/src/test/java/generators/cpp/CppDataClassGeneratorTest.kt +++ b/cgen-lib/src/test/java/generators/cpp/CppDataClassGeneratorTest.kt @@ -5,21 +5,15 @@ import ce.defs.Target import ce.domain.usecase.add.AddRegionDefaultsUseCaseImpl import ce.formatters.CLikeCodestyleRepo import ce.settings.CodeStyle -import generators.obj.abstractSyntaxTree.DataClass -import generators.obj.abstractSyntaxTree.NamespaceImpl -import generators.obj.abstractSyntaxTree.TreeRoot -import generators.obj.abstractSyntaxTree.addSub -import generators.obj.abstractSyntaxTree.findOrNull -import generators.obj.syntaxParseTree.CommentsBlock -import generators.obj.syntaxParseTree.FieldNode -import generators.obj.syntaxParseTree.NamespaceBlock -import generators.obj.syntaxParseTree.OutBlock -import generators.obj.syntaxParseTree.OutputTree -import generators.obj.syntaxParseTree.Region +import generators.obj.abstractSyntaxTree.* +import generators.obj.syntaxParseTree.* import org.gradle.internal.impldep.org.junit.Assert import org.junit.jupiter.api.Test class CppDataClassGeneratorTest { + private val arrayDataType = GetArrayDataTypeUseCase() + private val dataTypeToString = GetTypeNameUseCase(arrayDataType) + private val prepareRightValueUseCase = PrepareRightValueUseCase(dataTypeToString) @Test fun testSimpleStructure() { @@ -32,7 +26,9 @@ class CppDataClassGeneratorTest { val project = OutputTree(Target.Cpp) val item = CppDataClassGenerator( - addBlockDefaultsUseCase = AddRegionDefaultsUseCaseImpl(repo) + addBlockDefaultsUseCase = AddRegionDefaultsUseCaseImpl(repo), + prepareRightValueUseCase = prepareRightValueUseCase, + dataTypeToString = dataTypeToString ) val headerFile = CppHeaderFile("a").apply { setParent2(project) } val cxxFile = CppFileData("b").apply { setParent2(project) } From 7dc4c355e7bfac8759ceff1b926b5bf06d51c6b7 Mon Sep 17 00:00:00 2001 From: "V.Shkriabets" Date: Fri, 3 Oct 2025 08:44:49 +0300 Subject: [PATCH 6/7] Fix tests --- .../java/generators/cpp/CppEnumGeneratorTest.kt | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/cgen-lib/src/test/java/generators/cpp/CppEnumGeneratorTest.kt b/cgen-lib/src/test/java/generators/cpp/CppEnumGeneratorTest.kt index 8dacd86..1933a7c 100644 --- a/cgen-lib/src/test/java/generators/cpp/CppEnumGeneratorTest.kt +++ b/cgen-lib/src/test/java/generators/cpp/CppEnumGeneratorTest.kt @@ -6,18 +6,8 @@ import ce.domain.usecase.add.AddRegionDefaultsUseCaseImpl import ce.formatters.CLikeCodestyleRepo import ce.settings.CodeStyle import ce.treeio.XmlTreeReader -import generators.obj.abstractSyntaxTree.ConstantsEnum -import generators.obj.abstractSyntaxTree.Namespace -import generators.obj.abstractSyntaxTree.NamespaceImpl -import generators.obj.abstractSyntaxTree.TreeRoot -import generators.obj.abstractSyntaxTree.addSub -import generators.obj.abstractSyntaxTree.findOrNull -import generators.obj.syntaxParseTree.CommentsBlock -import generators.obj.syntaxParseTree.NamespaceBlock -import generators.obj.syntaxParseTree.OutBlock -import generators.obj.syntaxParseTree.OutputTree -import generators.obj.syntaxParseTree.Region -import generators.obj.syntaxParseTree.RegionImpl +import generators.obj.abstractSyntaxTree.* +import generators.obj.syntaxParseTree.* import org.gradle.internal.impldep.org.junit.Assert import org.junit.jupiter.api.Test @@ -101,7 +91,7 @@ class CppEnumGeneratorTest { """.trimIndent()) as Namespace val block = tree.subs.first() as ConstantsEnum - val projectOutput = OutputTree(Target.Kotlin) + val projectOutput = OutputTree(Target.Cpp) val files = fileGenerator.createFile(projectOutput, workingDirectory = "./", packageDirectory = "", From b7312fe674f06375b2b3c65d9014ee56afbd94d0 Mon Sep 17 00:00:00 2001 From: "V.Shkriabets" Date: Fri, 3 Oct 2025 08:48:07 +0300 Subject: [PATCH 7/7] Fix comments --- .../src/main/kotlin/generators/cpp/GetArrayDataTypeUseCase.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgen-lib/src/main/kotlin/generators/cpp/GetArrayDataTypeUseCase.kt b/cgen-lib/src/main/kotlin/generators/cpp/GetArrayDataTypeUseCase.kt index 5d31188..ecb9316 100644 --- a/cgen-lib/src/main/kotlin/generators/cpp/GetArrayDataTypeUseCase.kt +++ b/cgen-lib/src/main/kotlin/generators/cpp/GetArrayDataTypeUseCase.kt @@ -15,7 +15,7 @@ class GetArrayDataTypeUseCase { DataType.uint64 -> "std::vector" DataType.float32 -> "std::vector" DataType.float64 -> "std::vector" - is DataType.string -> "std::vector" + DataType.string -> "std::vector" is DataType.userClass -> "std::vector<${type.path}>" is DataType.custom -> "std::vector<${type.block.name}>" else -> "ktQQTP_array_$type"