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 dcb9a83..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 @@ -132,19 +120,25 @@ 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), - 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/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/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/CppEnumGenerator.kt b/cgen-lib/src/main/kotlin/generators/cpp/CppEnumGenerator.kt index ce390b8..0d8065b 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) { - addEnumLeaf(it.name).apply { - autoIncrement(it) + autoIncrement(it) + val rValue = prepareRightValueUseCase.toRightValue( + dataField = it, + fileData = headerFile + ) + addEnumLeaf("").apply { 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/cpp/GetArrayDataTypeUseCase.kt b/cgen-lib/src/main/kotlin/generators/cpp/GetArrayDataTypeUseCase.kt new file mode 100644 index 0000000..ecb9316 --- /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" + 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..f4731e1 --- /dev/null +++ b/cgen-lib/src/main/kotlin/generators/cpp/GetTypeNameUseCase.kt @@ -0,0 +1,46 @@ +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 -> {} + } + val baseType = when (type) { + DataType.VOID -> "void" + 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" + + 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" + } + 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/PrepareRightValueUseCase.kt b/cgen-lib/src/main/kotlin/generators/cpp/PrepareRightValueUseCase.kt index 2e151f2..cb3e1e6 100644 --- a/cgen-lib/src/main/kotlin/generators/cpp/PrepareRightValueUseCase.kt +++ b/cgen-lib/src/main/kotlin/generators/cpp/PrepareRightValueUseCase.kt @@ -3,13 +3,16 @@ 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.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 @@ -67,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/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/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/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 new file mode 100644 index 0000000..bc7f8d9 --- /dev/null +++ b/cgen-lib/src/test/java/ce/formatters/cxx/CxxEnumFormattingTests.kt @@ -0,0 +1,130 @@ +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 +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 generators.obj.syntaxParseTree.Space +import generators.obj.syntaxParseTree.VariableName +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 = CodeFormatterCxxUseCaseImpl(repoNoSpace) + + @Test + fun testSimpleEnumCxx() { + val input = RegionImpl().apply { + addOutBlock("enum ENUM") { + listOf("A","B","C","D").forEachIndexed { idx,name -> + addEnumLeaf("").apply { + addVarName(name) + } + } + } + } + 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) + 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") { + listOf("A","B","C","D").forEachIndexed { idx,name -> + addEnumLeaf("").apply { + addVarName(name) + addKeyword("=") + 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 Space) + Assert.assertTrue(outBlock.subs[1] is Keyword) + Assert.assertTrue(outBlock.subs[2] is NlSeparator) + Assert.assertEquals(19, outBlock.subs.size) + + 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) + 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/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/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) } diff --git a/cgen-lib/src/test/java/generators/cpp/CppEnumGeneratorTest.kt b/cgen-lib/src/test/java/generators/cpp/CppEnumGeneratorTest.kt index 830c8af..1933a7c 100644 --- a/cgen-lib/src/test/java/generators/cpp/CppEnumGeneratorTest.kt +++ b/cgen-lib/src/test/java/generators/cpp/CppEnumGeneratorTest.kt @@ -5,26 +5,32 @@ 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), + prepareRightValueUseCase = prepareRightValueUseCase + ) @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) @@ -51,7 +57,6 @@ class CppEnumGeneratorTest { // <=><2> // <=><33> // - // <;> // // // @@ -62,14 +67,67 @@ 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) + } + + @Test + fun testSimpleEnumClass() { + val tree = reader.loadFromString(""" + + + + + + + + + + + """.trimIndent()) as Namespace + val block = tree.subs.first() as ConstantsEnum - Assert.assertEquals(Separator::class.java, region.subs[2]::class.java) + val projectOutput = OutputTree(Target.Cpp) + val files = fileGenerator.createFile(projectOutput, + workingDirectory = "./", + packageDirectory = "", + "a", block) + val headerFile = files.first { it is CppHeaderFile } + item(files, block) + // expected result + // + // + // + // + // + // + // ... + // + // + // + // + // + // + // + // + + 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) + 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..95f1028 --- /dev/null +++ b/cgen-lib/src/test/java/generators/cpp/PrepareRightValueUseCaseTest.kt @@ -0,0 +1,128 @@ +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(1, arg1.subs.size) + assertEquals(RValue::class.java, arg1.subs[0].javaClass) + val rvalue1 = arg1.subs[0] as RValue + assertEquals("\"defined\"", rvalue1.name) + assertEquals("123", arg2.subs[0].name) + } +} \ No newline at end of file