Skip to content

Commit

Permalink
feat: add some domain functions to core
Browse files Browse the repository at this point in the history
  • Loading branch information
phodal committed Jan 6, 2024
1 parent fa10d9a commit ea2555b
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 2 deletions.
24 changes: 22 additions & 2 deletions chapi-domain/src/main/kotlin/chapi/domain/core/CodeContainer.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package chapi.domain.core

import chapi.domain.core.CodeDataStruct.Companion.contentByPosition
import kotlinx.serialization.Serializable

@Serializable
Expand All @@ -16,5 +17,24 @@ data class CodeContainer(
* In toml, the fields are the key-value pairs.
*/
var Fields: List<CodeField> = listOf(),
var Containers: List<CodeContainer> = listOf()
)
var Containers: List<CodeContainer> = listOf(),
) {
fun buildSourceCode(codeLines: List<String>) {
this.DataStructures.map { ds ->
ds.Imports = this.Imports

ds.Content = contentByPosition(codeLines, ds.Position)
ds.Functions.map {
// in Chapi, the position of function is not correct, so we need to fix it
val position = it.Position
if (it.Annotations.isNotEmpty()) {
val annotationPos = it.Annotations.first().Position
position.StartLine = annotationPos.StartLine
position.StartLinePosition = annotationPos.StartLinePosition
}

it.Content = contentByPosition(codeLines, it.Position)
}
}
}
}
110 changes: 110 additions & 0 deletions chapi-domain/src/main/kotlin/chapi/domain/core/CodeDataStruct.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ enum class DataStructType(val structType: String) {
INNER_STRUCTURES("InnerStructures"),
CREATOR_CLASS("CreatorClass"),
ABSTRACT_CLASS("AbstractClass"),

// for scala, Rust
TRAIT("Trait"),
ENUM("Enum")
Expand Down Expand Up @@ -91,5 +92,114 @@ data class CodeDataStruct(
fun fileWithoutSuffix(): String {
return FilePath.substringBeforeLast('.', "")
}

fun toUml(): String {
val output = StringBuilder()

val superClass = Implements + if (Extend.isNotBlank()) {
listOf(Extend)
} else {
emptyList()
}
val superClasses = if (superClass.isNotEmpty()) {
": " + superClass.joinToString(", ") + " "
} else {
""
}

output.append("class $NodeName $superClasses{\n")
Fields.forEach {
output.append(" ${it.TypeKey}: ${it.TypeType}\n")
}

var getterSetter: List<String> = listOf()
val methodsWithoutGetterSetter = Functions.filter { it.Name != NodeName }
.filter { it.Name !in listOf("toString", "hashCode", "equals") }
.filter {
val isGetter = it.Name.startsWith("get") && it.Parameters.isEmpty()
val isSetter = it.Name.startsWith("set") && it.Parameters.size == 1
if (isGetter || isSetter) {
getterSetter = listOf(it.Name)
return@filter false
}
return@filter true
}

if (getterSetter.isNotEmpty()) {
output.append("\n 'getter/setter: ${getterSetter.joinToString(", ")}\n")
}

val methodCodes = methodsWithoutGetterSetter
.joinToString("\n") { method ->
val params =
method.Parameters.joinToString(", ") { parameter ->
"${parameter.TypeValue}: ${parameter.TypeType}"
}
val returnType = method.ReturnType.replace("kotlin.", "")
" + ${method.Name}($params)" + if (returnType.isNotBlank()) ": $returnType" else ""
}

if (methodCodes.isNotBlank()) {
output.append("\n")
output.append(methodCodes)
}

output.append("\n")
output.append(" }\n")

// TODO: split output and add comments line
return output.split("\n").joinToString("\n") {
"// $it"
}
}

companion object {
fun contentByPosition(lines: List<String>, position: CodePosition): String {
val startLine = if (position.StartLine == 0) {
0
} else {
position.StartLine - 1
}
val endLine = if (position.StopLine == 0) {
0
} else {
position.StopLine - 1
}

val startLineContent = lines[startLine]
val endLineContent = lines[endLine]

val startColumn = if (position.StartLinePosition > startLineContent.length) {
if (startLineContent.isBlank()) {
0
} else {
startLineContent.length
}
} else {
position.StartLinePosition
}

val endColumn = if (position.StopLinePosition > endLineContent.length) {
if (endLineContent.isBlank()) {
0
} else {
endLineContent.length
}
} else {
position.StopLinePosition
}

val start = startLineContent.substring(startColumn)
val end = endLineContent.substring(endColumn)

val code = if (startLine == endLine) {
start
} else {
start + "\n" + lines.subList(startLine + 1, endLine).joinToString("\n") + "\n" + end
}

return code
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,38 @@ internal class CodeDataStructTest {
internal fun shouldEquals() {
assertEquals(CodeDataStruct(NodeName = "FunctionMap"), CodeDataStruct(NodeName = "FunctionMap"))
}

@Test
fun `toUml should return UML class representation for CodeDataStruct`() {
// Given
val codeDataStruct = CodeDataStruct(
NodeName = "TestClass",
Fields = listOf(
CodeField("Int", "", "id"),
CodeField("String", "", "name")
),
Functions = listOf(
CodeFunction("getName", "", ""),
CodeFunction("setName", "", "")
)
)

// When
val uml = codeDataStruct.toUml()

// Then
val expectedUml = """
|// class TestClass {
|// id: Int
|// name: String
|//
|// 'getter/setter: getName
|//
|// + setName()
|// }
|//
""".trimMargin()

assertEquals(expectedUml, uml)
}
}

0 comments on commit ea2555b

Please sign in to comment.