Skip to content

Commit f67c2e3

Browse files
committed
Merge branch 'master' into 3.0
# Conflicts: # src/main/kotlin/wu/seal/jsontokotlin/codeelements/KName.kt # src/main/kotlin/wu/seal/jsontokotlin/codeelements/KPropertyName.kt
2 parents 462263b + 07e3748 commit f67c2e3

File tree

15 files changed

+613
-51
lines changed

15 files changed

+613
-51
lines changed

src/main/kotlin/wu/seal/jsontokotlin/KotlinCodeMaker.kt

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,13 @@ class KotlinCodeMaker {
6161
if (originElement.asJsonArray.onlyHasOneElementRecursive()) {
6262
val unSupportJsonException = UnSupportJsonException("Unsupported Json String")
6363
val adviceType = getArrayType("Any", originElement.asJsonArray).replace(Regex("Int|Float|String|Boolean"), "Any")
64+
unSupportJsonException.adviceType = adviceType
6465
unSupportJsonException.advice = """No need converting, just use $adviceType is enough for your json string"""
6566
throw unSupportJsonException
6667
} else {
6768
//when [1,"a"]
6869
val unSupportJsonException = UnSupportJsonException("Unsupported Json String")
70+
unSupportJsonException.adviceType = "List<Any>"
6971
unSupportJsonException.advice = """No need converting, List<Any> may be a good class type for your json string"""
7072
throw unSupportJsonException
7173
}
@@ -113,7 +115,11 @@ class KotlinCodeMaker {
113115
val classAnnotation = KClassAnnotation.getClassAnnotation(className.toString())
114116
stringBuilder.append(classAnnotation)
115117
if (classAnnotation.isNotBlank()) stringBuilder.append("\n")
116-
stringBuilder.append("data class ").append(className).append("(\n")
118+
if (inputElement?.isJsonNull == true || (inputElement as? JsonObject)?.entrySet()?.isEmpty() == true) {
119+
stringBuilder.append("class ").append(className).append("(\n")
120+
} else {
121+
stringBuilder.append("data class ").append(className).append("(\n")
122+
}
117123
}
118124

119125

@@ -128,12 +134,18 @@ class KotlinCodeMaker {
128134
val isLast = (index == size - 1)
129135

130136
if (jsonElementValue.isJsonArray) {
131-
val type = getArrayType(property, jsonElementValue.asJsonArray)
137+
var type = getArrayType(property, jsonElementValue.asJsonArray)
132138

133139
if (isExpectedJsonObjArrayType(jsonElementValue.asJsonArray) || jsonElementValue.asJsonArray.onlyHasOneObjectElementRecursive()
134140
|| jsonElementValue.asJsonArray.onlyOneSubArrayContainsElementAndAllObjectRecursive()) {
135141

136-
toBeAppend.add(KotlinCodeMaker(getChildType(getRawType(type)), jsonElementValue).makeKotlinData())
142+
val subCode = try {
143+
KotlinCodeMaker(getChildType(getRawType(type)), jsonElementValue).makeKotlinData()
144+
} catch (e: UnSupportJsonException) {
145+
type = e.adviceType
146+
""
147+
}
148+
toBeAppend.add(subCode)
137149
}
138150
addProperty(stringBuilder, property, type, "", isLast)
139151

@@ -144,21 +156,33 @@ class KotlinCodeMaker {
144156
} else if (jsonElementValue.isJsonObject) {
145157
if (ConfigManager.enableMapType && maybeJsonObjectBeMapType(jsonElementValue.asJsonObject)) {
146158
val mapKeyType = getMapKeyTypeConvertFromJsonObject(jsonElementValue.asJsonObject)
147-
val mapValueType = getMapValueTypeConvertFromJsonObject(jsonElementValue.asJsonObject)
159+
var mapValueType = getMapValueTypeConvertFromJsonObject(jsonElementValue.asJsonObject)
148160
if (mapValueIsObjectType(mapValueType)) {
161+
val subCode = try {
162+
KotlinCodeMaker(
163+
getChildType(mapValueType),
164+
jsonElementValue.asJsonObject.entrySet().first().value
165+
).makeKotlinData()
166+
} catch (e: UnSupportJsonException) {
167+
mapValueType = e.adviceType
168+
""
169+
}
149170
toBeAppend.add(
150-
KotlinCodeMaker(
151-
getChildType(mapValueType),
152-
jsonElementValue.asJsonObject.entrySet().first().value
153-
).makeKotlinData()
171+
subCode
154172
)
155173
}
156174
val mapType = "Map<$mapKeyType,$mapValueType>"
157175
addProperty(stringBuilder, property, mapType, "", isLast)
158176

159177
} else {
160-
val type = getJsonObjectType(property)
161-
toBeAppend.add(KotlinCodeMaker(getRawType(type), jsonElementValue).makeKotlinData())
178+
var type = getJsonObjectType(property)
179+
val subCode = try {
180+
KotlinCodeMaker(getRawType(type), jsonElementValue).makeKotlinData()
181+
} catch (e: UnSupportJsonException) {
182+
type = e.adviceType
183+
""
184+
}
185+
toBeAppend.add(subCode)
162186
addProperty(stringBuilder, property, type, "", isLast)
163187
}
164188

src/main/kotlin/wu/seal/jsontokotlin/UnsupportJsonException.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ package wu.seal.jsontokotlin
66
*/
77
class UnSupportJsonException(message: String = "") : Exception(message) {
88
var advice: String = ""
9-
9+
var adviceType: String = ""
1010
}

src/main/kotlin/wu/seal/jsontokotlin/classscodestruct/KotlinDataClass.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ data class KotlinDataClass(
2323
append(annotationsCode).append("\n")
2424
}
2525
}
26-
append("data class ").append(name).append("(").append("\n")
26+
if (properties.isEmpty()) {
27+
append("class ").append(name).append("(").append("\n")
28+
} else {
29+
append("data class ").append(name).append("(").append("\n")
30+
}
2731
properties.forEach {
2832
val code = it.getCode()
2933
val addIndentCode = code.split("\n").joinToString("\n") { indent + it }

src/main/kotlin/wu/seal/jsontokotlin/codeelements/KClassName.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ object KClassName : KName(), IKClassName {
2626
/**
2727
* keep " " character
2828
*/
29-
val pattern = "$illegalCharacter".replace(Regex(nameSeparator.toString()), "")
29+
val pattern = illegalCharacter.toMutableList().apply { removeAll(nameSeparator) }.toRegex()
3030

31-
val temp = rawClassName.replace(Regex(pattern), "").let {
31+
val temp = rawClassName.replace(pattern, "").let {
3232

3333
return@let removeStartNumberAndIllegalCharacter(it)
3434

@@ -53,7 +53,7 @@ object KClassName : KName(), IKClassName {
5353

5454
val stringBuilder = StringBuilder()
5555

56-
temp.split(Regex(nameSeparator.toString())).forEach {
56+
temp.split(nameSeparator.toRegex()).forEach {
5757
if (it.isNotBlank()) {
5858
stringBuilder.append(it.substring(0, 1).toUpperCase().plus(it.substring(1)))
5959
}

src/main/kotlin/wu/seal/jsontokotlin/codeelements/KName.kt

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,34 +22,30 @@ abstract class KName : IKName {
2222
)
2323

2424

25-
protected val illegalCharacter = listOf(
26-
"\\+", "\\-", "\\*", "/", "%", "=", "&", "|", "!", "\\[", "\\]", "\\{", "\\}", "\\(", "\\)", "\\\\", "\"", "_"
27-
, ",", ".", ":", "\\?", "\\>", "\\<", "@", ";", "'", "\\`", "\\~", "\\$", "^", "#", "\\", "/", " ", "\t", "\n"
25+
protected val illegalCharacter = listOf<String>(
26+
"\\+", "\\-", "\\*", "/", "%", "=", "&", "\\|", "!", "\\[", "\\]", "\\{", "\\}", "\\(", "\\)", "\\\\", "\"", "_"
27+
, ",", "\\.", ":", "\\?", "\\>", "\\<", "@", ";", "'", "\\`", "\\~", "\\$", "\\^", "#", "\\", "/", " ", "\t", "\n"
2828
)
2929

3030

31-
protected val nameSeparator = listOf(" ", "_", "-")
31+
protected val nameSeparator = listOf<String>(" ", "_", "\\-", ":")
3232

3333

3434
/**
3535
* remove the start number or whiteSpace characters in this string
3636
*/
3737
protected fun removeStartNumberAndIllegalCharacter(it: String): String {
3838

39-
return if (it.replace(Regex(illegalCharacter.toString()), "").indexOfFirst {
40-
return@indexOfFirst it in '0'..'9'
41-
} == 0) {
39+
val numberAndIllegalCharacters = listOf<String>(*illegalCharacter.toTypedArray(), "\\d")
4240

43-
val numberAndIllegalCharacters = listOf(*illegalCharacter.toTypedArray(), "\\d")
41+
val firstNumberAndIllegalCharactersRegex = "^(${numberAndIllegalCharacters.toRegex()})+".toRegex()
42+
43+
return it.trim().replaceFirst(firstNumberAndIllegalCharactersRegex, "")
4444

45-
it.trim().replaceFirst(Regex("${numberAndIllegalCharacters.toString().trim()}+"), "")
46-
} else {
47-
it
48-
}
4945
}
5046

5147
protected fun toBeLegalName(name: String): String {
52-
val tempName = name.replace(illegalCharacter.toString(), "")
48+
val tempName = name.replace(illegalCharacter.toRegex(), "")
5349

5450
return if (tempName in illegalNameList) {
5551
tempName + suffix
@@ -58,4 +54,10 @@ abstract class KName : IKName {
5854
}
5955
}
6056

57+
/**
58+
* array string into regex match patten that could match any element of the array
59+
*/
60+
protected fun Iterable<String>.toRegex() = joinToString(separator = "|").toRegex()
61+
62+
6163
}

src/main/kotlin/wu/seal/jsontokotlin/codeelements/KPropertyName.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ object KPropertyName : KName(), IPropertyNameMaker {
4747
/**
4848
* keep nameSeparator character
4949
*/
50-
val pattern = "$illegalCharacter".replace(Regex(nameSeparator.toString()), "")
50+
val pattern = illegalCharacter.toMutableList().apply { removeAll(nameSeparator) }.toRegex()
5151

52-
val temp = rawString.replace(Regex(pattern), "").let {
52+
val temp = rawString.replace(pattern, "").let {
5353

5454
return@let removeStartNumberAndIllegalCharacter(it)
5555

@@ -68,7 +68,7 @@ object KPropertyName : KName(), IPropertyNameMaker {
6868

6969
val stringBuilder = StringBuilder()
7070

71-
temp.split(Regex(nameSeparator.toString())).forEach {
71+
temp.split(nameSeparator.toRegex()).forEach {
7272
if (it.isNotBlank()) {
7373
stringBuilder.append(it.substring(0, 1).toUpperCase().plus(it.substring(1)))
7474
}

src/main/kotlin/wu/seal/jsontokotlin/utils/SimplifiedMethods.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import com.intellij.openapi.application.ApplicationManager
88
import com.intellij.openapi.command.CommandProcessor
99
import com.intellij.openapi.project.Project
1010
import wu.seal.jsontokotlin.ConfigManager
11+
import java.lang.IllegalStateException
12+
import java.util.regex.Pattern
1113

1214
/**
1315
* File contains functions which simply other functions's invoke
@@ -50,7 +52,12 @@ fun getClassesStringList(classesString: String): List<String> {
5052
* export the class name from class block string
5153
*/
5254
fun getClassNameFromClassBlockString(classBlockString: String): String {
53-
return classBlockString.substringAfter("data class").substringBefore("(").trim()
55+
val pattern = Pattern.compile("(data )?class (?<className>[^(]+).*")
56+
val matcher = pattern.matcher(classBlockString)
57+
if (matcher.find()) {
58+
return matcher.group("className").trim()
59+
}
60+
throw IllegalStateException("cannot find class name in classBlockString: $classBlockString")
5461
}
5562

5663
fun replaceClassNameToClassBlockString(classBlockString: String, newClassName: String): String {

src/main/kotlin/wu/seal/jsontokotlin/utils/classblockparse/ClassCodeParser.kt

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -93,45 +93,45 @@ class ClassCodeParser(private val classBlockString: String) {
9393
}
9494

9595
private fun getPropertyKeyword(propertyLine: String): String {
96-
val stringBeforeColon = propertyLine.substringBefore(":").trim()
96+
val stringBeforeLastColonWithoutComment = propertyLine.substringBefore("//").substringBeforeLast(":").trim()
9797
return when {
98-
stringBeforeColon.contains(")") -> {
99-
val noAnnotationString = stringBeforeColon.substringAfterLast(")").trim()
98+
stringBeforeLastColonWithoutComment.contains(")") -> {
99+
val noAnnotationString = stringBeforeLastColonWithoutComment.substringAfterLast(")").trim()
100100
val keyword = noAnnotationString.split(" ").first()
101101
keyword
102102
}
103-
stringBeforeColon.contains("@") -> {
104-
val keyword = stringBeforeColon.split(" ")[1]
103+
stringBeforeLastColonWithoutComment.contains("@") -> {
104+
val keyword = stringBeforeLastColonWithoutComment.split(" ")[1]
105105
keyword
106106
}
107107
else -> {
108-
val keyword = stringBeforeColon.split(" ").first()
108+
val keyword = stringBeforeLastColonWithoutComment.split(" ").first()
109109
keyword
110110
}
111111
}.trim()
112112
}
113113

114114
private fun getPropertyName(propertyLine: String): String {
115115

116-
val stringBeforeColon = propertyLine.substringBefore(":").trim()
116+
val stringBeforeLastColonWithoutComment = propertyLine.substringBefore("//").substringBeforeLast(":").trim()
117117
return when {
118-
stringBeforeColon.contains(")") -> {
119-
val noAnnotationString = stringBeforeColon.substringAfterLast(")").trim()
118+
stringBeforeLastColonWithoutComment.contains(")") -> {
119+
val noAnnotationString = stringBeforeLastColonWithoutComment.substringAfterLast(")").trim()
120120
val splits = noAnnotationString.split(" ")
121121
val propertyName =
122122
splits.filterIndexed { index, s -> listOf(0).contains(index).not() }
123123
.joinToString(" ")
124124
propertyName
125125
}
126-
stringBeforeColon.contains("@") -> {
127-
val splits = stringBeforeColon.split(" ")
126+
stringBeforeLastColonWithoutComment.contains("@") -> {
127+
val splits = stringBeforeLastColonWithoutComment.split(" ")
128128
val propertyName =
129129
splits.filterIndexed { index, s -> listOf(0, 1).contains(index).not() }
130130
.joinToString(" ")
131131
propertyName
132132
}
133133
else -> {
134-
val splits = stringBeforeColon.split(" ")
134+
val splits = stringBeforeLastColonWithoutComment.split(" ")
135135
val propertyName =
136136
splits.filterIndexed { index, s -> listOf(0).contains(index).not() }
137137
.joinToString(" ")

src/main/kotlin/wu/seal/jsontokotlin/utils/classblockparse/NestedClassModelClassesCodeParser.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class NestedClassModelClassesCodeParser(private val nestedClassCode: String) {
3131
var backParenthesesCount = 0
3232
var backBigParenthesesCount = 0
3333
lines.forEach {
34-
if (it.startsWith("data class")) {
34+
if (it.matches("^(data )?class.+".toRegex())) {
3535
classStringBuilder.append("\n")
3636
classStringBuilder.append(it)
3737
dataclassStringCount++
@@ -58,4 +58,4 @@ class NestedClassModelClassesCodeParser(private val nestedClassCode: String) {
5858
}
5959
return classStrings
6060
}
61-
}
61+
}

src/test/kotlin/wu/seal/jsontokotlin/codeelements/KClassNameTest.kt

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package wu.seal.jsontokotlin.codeelements
22

3+
import com.winterbe.expekt.should
34
import org.junit.Assert.assertTrue
45
import org.junit.Test
56

@@ -28,6 +29,9 @@ class KClassNameTest {
2829

2930
}
3031

32+
/**
33+
* test get name logic works well when name contains illegal character
34+
*/
3135
@Test
3236
fun getName() {
3337
val rawClassName = """
@@ -36,13 +40,15 @@ class KClassNameTest {
3640

3741
val legalClassName = KClassName.getName(rawClassName)
3842

39-
assertTrue(legalClassName.startsWith("N"))
40-
assertTrue(legalClassName == "NAM12335E431")
43+
legalClassName.should.startWith("N")
44+
45+
legalClassName.should.be.equal("NAM12335E431")
4146

4247
val rawClassName1 = "341@!$#43214%$#@%34"
48+
4349
val legalClassName1 = KClassName.getName(rawClassName1)
4450
assertTrue(legalClassName1.isNotEmpty())
45-
assertTrue(legalClassName1 == "X3414321434")
51+
legalClassName1.should.be.equal("X3414321434")
4652

4753
}
4854

0 commit comments

Comments
 (0)