Skip to content

Commit 8ef4e32

Browse files
committed
[feature]add new option that could disable kotlin data class, then all data clas will translate to kotlin normal class
1 parent 1af23dc commit 8ef4e32

File tree

4 files changed

+203
-14
lines changed

4 files changed

+203
-14
lines changed
Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
package extensions
22

33
import extensions.chen.biao.KeepAnnotationSupport
4-
import extensions.wu.seal.KeepAnnotationSupportForAndroidX
54
import extensions.jose.han.ParcelableAnnotationSupport
65
import extensions.ted.zeng.PropertyAnnotationLineSupport
7-
import extensions.wu.seal.ClassNameSuffixSupport
8-
import extensions.wu.seal.ForceInitDefaultValueWithOriginJsonValueSupport
9-
import extensions.wu.seal.PropertyPrefixSupport
10-
import extensions.wu.seal.PropertySuffixSupport
6+
import extensions.wu.seal.*
117
import extensions.xu.rui.PrimitiveTypeNonNullableSupport
128

139
/**
@@ -18,14 +14,15 @@ object ExtensionsCollector {
1814
* all extensions
1915
*/
2016
val extensions = listOf(
21-
KeepAnnotationSupport,
22-
KeepAnnotationSupportForAndroidX,
23-
PropertyAnnotationLineSupport,
24-
ParcelableAnnotationSupport,
25-
PropertyPrefixSupport,
26-
PropertySuffixSupport,
27-
ClassNameSuffixSupport,
28-
PrimitiveTypeNonNullableSupport,
29-
ForceInitDefaultValueWithOriginJsonValueSupport
17+
KeepAnnotationSupport,
18+
KeepAnnotationSupportForAndroidX,
19+
PropertyAnnotationLineSupport,
20+
ParcelableAnnotationSupport,
21+
PropertyPrefixSupport,
22+
PropertySuffixSupport,
23+
ClassNameSuffixSupport,
24+
PrimitiveTypeNonNullableSupport,
25+
ForceInitDefaultValueWithOriginJsonValueSupport,
26+
DisableDataClassSupport
3027
)
3128
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package extensions.wu.seal
2+
3+
import extensions.Extension
4+
import wu.seal.jsontokotlin.model.classscodestruct.DataClass
5+
import wu.seal.jsontokotlin.model.classscodestruct.KotlinClass
6+
import wu.seal.jsontokotlin.model.classscodestruct.NormalClass
7+
import wu.seal.jsontokotlin.ui.checkBox
8+
import wu.seal.jsontokotlin.ui.horizontalLinearLayout
9+
import javax.swing.JPanel
10+
11+
/**
12+
* Extension support disable kotlin data class, after enable this, all kotlin data classes will be changed to [NormalClass]
13+
*/
14+
object DisableDataClassSupport : Extension() {
15+
16+
const val configKey = "wu.seal.disable_data_class_support"
17+
18+
override fun createUI(): JPanel {
19+
20+
return horizontalLinearLayout {
21+
checkBox(
22+
"Disable Kotlin Data Class",
23+
getConfig(configKey).toBoolean()
24+
) { isSelectedAfterClick ->
25+
setConfig(configKey, isSelectedAfterClick.toString())
26+
}()
27+
fillSpace()
28+
}
29+
}
30+
31+
override fun intercept(kotlinClass: KotlinClass): KotlinClass {
32+
33+
if (kotlinClass is DataClass && getConfig(configKey).toBoolean()) {
34+
with(kotlinClass) {
35+
return NormalClass(annotations, name, properties, parentClassTemplate, modifiable)
36+
}
37+
} else {
38+
return kotlinClass
39+
}
40+
}
41+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package wu.seal.jsontokotlin.model.classscodestruct
2+
3+
import wu.seal.jsontokotlin.interceptor.IKotlinClassInterceptor
4+
import wu.seal.jsontokotlin.utils.LogUtil
5+
import wu.seal.jsontokotlin.utils.getCommentCode
6+
import wu.seal.jsontokotlin.utils.getIndent
7+
import java.lang.IllegalStateException
8+
9+
/**
10+
* Created by Seal.Wu on 2020-03-05
11+
* Normal general class code struct
12+
* diff with data class is that there no 'data' modifier
13+
*/
14+
data class NormalClass(
15+
val annotations: List<Annotation> = listOf(),
16+
override val name: String,
17+
val properties: List<Property> = listOf(),
18+
val parentClassTemplate: String = "",
19+
override val modifiable: Boolean = true
20+
) : ModifiableKotlinClass, NoGenericKotlinClass {
21+
22+
override val hasGeneric: Boolean = false
23+
24+
override val referencedClasses: List<KotlinClass>
25+
get() {
26+
return properties.flatMap { property ->
27+
mutableListOf(property.typeObject).apply {
28+
addAll(property.typeObject.getAllGenericsRecursively())
29+
}
30+
}
31+
}
32+
33+
override fun rename(newName: String): KotlinClass = copy(name = newName)
34+
35+
override fun replaceReferencedClasses(replaceRule: Map<KotlinClass, KotlinClass>): KotlinClass {
36+
val propertiesReferencedModifiableKotlinClass = properties.flatMap {
37+
if (it.typeObject is GenericKotlinClass) {
38+
it.typeObject.getAllGenericsRecursively().toMutableList().also { list -> list.add(it.typeObject) }
39+
} else {
40+
listOf(it.typeObject)
41+
}
42+
}.filter { it.modifiable }
43+
if (propertiesReferencedModifiableKotlinClass.size != replaceRule.size) {
44+
throw IllegalStateException("properties used kotlin classes size should be equal referenced classes size!")
45+
}
46+
if (!replaceRule.all { it.key.modifiable }) {
47+
throw IllegalStateException("to be replaced referenced class should be modifiable!")
48+
}
49+
val newProperties = properties.map { property ->
50+
property.typeObject.let {
51+
val newTypObj = when (it) {
52+
is GenericKotlinClass -> property.typeObject.replaceReferencedClasses(replaceRule)
53+
is ModifiableKotlinClass -> replaceRule[property.typeObject] ?: error("Modifiable Kotlin Class Must have a replacement")
54+
else -> it
55+
}
56+
LogUtil.i("replace type: ${property.type} to ${newTypObj.name}")
57+
return@let property.copy(type = newTypObj.name, typeObject = newTypObj)
58+
}
59+
}
60+
61+
return copy(properties = newProperties)
62+
}
63+
64+
override fun getCode(): String {
65+
val indent = getIndent()
66+
val code = buildString {
67+
if (annotations.isNotEmpty()) {
68+
val annotationsCode = annotations.joinToString("\n") { it.getAnnotationString() }
69+
if (annotationsCode.isNotBlank()) {
70+
append(annotationsCode).append("\n")
71+
}
72+
}
73+
if (properties.isEmpty()) {
74+
append("class ").append(name).append("(").append("\n")
75+
} else {
76+
append("class ").append(name).append("(").append("\n")
77+
}
78+
properties.forEachIndexed { index, property ->
79+
val code = property.getCode()
80+
val addIndentCode = code.split("\n").joinToString("\n") { indent + it }
81+
append(addIndentCode)
82+
if (index != properties.size - 1) append(",")
83+
if (property.comment.isNotBlank()) append(" // ").append(getCommentCode(property.comment))
84+
append("\n")
85+
}
86+
append(")")
87+
if (parentClassTemplate.isNotBlank()) {
88+
append(" : ")
89+
append(parentClassTemplate)
90+
}
91+
val nestedClasses = referencedClasses.filter { it.modifiable }
92+
if (nestedClasses.isNotEmpty()) {
93+
append(" {")
94+
append("\n")
95+
val nestedClassesCode = nestedClasses.joinToString("\n\n") { it.getCode() }
96+
append(nestedClassesCode.lines().joinToString("\n") { if (it.isNotBlank()) "$indent$it" else it })
97+
append("\n")
98+
append("}")
99+
}
100+
}
101+
return code
102+
}
103+
104+
105+
override fun <T : KotlinClass> applyInterceptors(enabledKotlinClassInterceptors: List<IKotlinClassInterceptor<T>>): KotlinClass {
106+
val newProperties = mutableListOf<Property>()
107+
properties.forEach {
108+
newProperties.add(it.copy(typeObject = it.typeObject.applyInterceptors(enabledKotlinClassInterceptors)))
109+
}
110+
var newKotlinDataClass: KotlinClass = copy(properties = newProperties)
111+
enabledKotlinClassInterceptors.forEach {
112+
newKotlinDataClass = it.intercept(newKotlinDataClass)
113+
}
114+
return newKotlinDataClass
115+
}
116+
117+
override fun getOnlyCurrentCode(): String {
118+
val newProperties = properties.map { it.copy(typeObject = KotlinClass.ANY) }
119+
return copy(properties = newProperties).getCode()
120+
}
121+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package extensions.wu.seal
2+
3+
import com.winterbe.expekt.should
4+
import org.junit.Test
5+
6+
import org.junit.Assert.*
7+
import org.junit.Before
8+
import wu.seal.jsontokotlin.generateKotlinClassCode
9+
import wu.seal.jsontokotlin.test.TestConfig
10+
11+
class DisableDataClassSupportTest {
12+
private val json = """{"a":1}"""
13+
private val expectCode: String = """
14+
class Output(
15+
@SerializedName("a")
16+
val a: Int = 0 // 1
17+
)
18+
""".trimIndent()
19+
20+
@Before
21+
fun setUp() {
22+
TestConfig.setToTestInitState()
23+
}
24+
25+
@Test
26+
fun intercept() {
27+
DisableDataClassSupport.getTestHelper().setConfig(DisableDataClassSupport.configKey, true.toString())
28+
json.generateKotlinClassCode("Output").should.be.equal(expectCode)
29+
}
30+
}

0 commit comments

Comments
 (0)