Skip to content

Commit

Permalink
Merge branch 'master' into 3.0
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/main/kotlin/wu/seal/jsontokotlin/codeelements/KName.kt
#	src/main/kotlin/wu/seal/jsontokotlin/codeelements/KPropertyName.kt
  • Loading branch information
sealkingking committed Jan 18, 2019
2 parents 462263b + 07e3748 commit f67c2e3
Show file tree
Hide file tree
Showing 15 changed files with 613 additions and 51 deletions.
44 changes: 34 additions & 10 deletions src/main/kotlin/wu/seal/jsontokotlin/KotlinCodeMaker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,13 @@ class KotlinCodeMaker {
if (originElement.asJsonArray.onlyHasOneElementRecursive()) {
val unSupportJsonException = UnSupportJsonException("Unsupported Json String")
val adviceType = getArrayType("Any", originElement.asJsonArray).replace(Regex("Int|Float|String|Boolean"), "Any")
unSupportJsonException.adviceType = adviceType
unSupportJsonException.advice = """No need converting, just use $adviceType is enough for your json string"""
throw unSupportJsonException
} else {
//when [1,"a"]
val unSupportJsonException = UnSupportJsonException("Unsupported Json String")
unSupportJsonException.adviceType = "List<Any>"
unSupportJsonException.advice = """No need converting, List<Any> may be a good class type for your json string"""
throw unSupportJsonException
}
Expand Down Expand Up @@ -113,7 +115,11 @@ class KotlinCodeMaker {
val classAnnotation = KClassAnnotation.getClassAnnotation(className.toString())
stringBuilder.append(classAnnotation)
if (classAnnotation.isNotBlank()) stringBuilder.append("\n")
stringBuilder.append("data class ").append(className).append("(\n")
if (inputElement?.isJsonNull == true || (inputElement as? JsonObject)?.entrySet()?.isEmpty() == true) {
stringBuilder.append("class ").append(className).append("(\n")
} else {
stringBuilder.append("data class ").append(className).append("(\n")
}
}


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

if (jsonElementValue.isJsonArray) {
val type = getArrayType(property, jsonElementValue.asJsonArray)
var type = getArrayType(property, jsonElementValue.asJsonArray)

if (isExpectedJsonObjArrayType(jsonElementValue.asJsonArray) || jsonElementValue.asJsonArray.onlyHasOneObjectElementRecursive()
|| jsonElementValue.asJsonArray.onlyOneSubArrayContainsElementAndAllObjectRecursive()) {

toBeAppend.add(KotlinCodeMaker(getChildType(getRawType(type)), jsonElementValue).makeKotlinData())
val subCode = try {
KotlinCodeMaker(getChildType(getRawType(type)), jsonElementValue).makeKotlinData()
} catch (e: UnSupportJsonException) {
type = e.adviceType
""
}
toBeAppend.add(subCode)
}
addProperty(stringBuilder, property, type, "", isLast)

Expand All @@ -144,21 +156,33 @@ class KotlinCodeMaker {
} else if (jsonElementValue.isJsonObject) {
if (ConfigManager.enableMapType && maybeJsonObjectBeMapType(jsonElementValue.asJsonObject)) {
val mapKeyType = getMapKeyTypeConvertFromJsonObject(jsonElementValue.asJsonObject)
val mapValueType = getMapValueTypeConvertFromJsonObject(jsonElementValue.asJsonObject)
var mapValueType = getMapValueTypeConvertFromJsonObject(jsonElementValue.asJsonObject)
if (mapValueIsObjectType(mapValueType)) {
val subCode = try {
KotlinCodeMaker(
getChildType(mapValueType),
jsonElementValue.asJsonObject.entrySet().first().value
).makeKotlinData()
} catch (e: UnSupportJsonException) {
mapValueType = e.adviceType
""
}
toBeAppend.add(
KotlinCodeMaker(
getChildType(mapValueType),
jsonElementValue.asJsonObject.entrySet().first().value
).makeKotlinData()
subCode
)
}
val mapType = "Map<$mapKeyType,$mapValueType>"
addProperty(stringBuilder, property, mapType, "", isLast)

} else {
val type = getJsonObjectType(property)
toBeAppend.add(KotlinCodeMaker(getRawType(type), jsonElementValue).makeKotlinData())
var type = getJsonObjectType(property)
val subCode = try {
KotlinCodeMaker(getRawType(type), jsonElementValue).makeKotlinData()
} catch (e: UnSupportJsonException) {
type = e.adviceType
""
}
toBeAppend.add(subCode)
addProperty(stringBuilder, property, type, "", isLast)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ package wu.seal.jsontokotlin
*/
class UnSupportJsonException(message: String = "") : Exception(message) {
var advice: String = ""

var adviceType: String = ""
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ data class KotlinDataClass(
append(annotationsCode).append("\n")
}
}
append("data class ").append(name).append("(").append("\n")
if (properties.isEmpty()) {
append("class ").append(name).append("(").append("\n")
} else {
append("data class ").append(name).append("(").append("\n")
}
properties.forEach {
val code = it.getCode()
val addIndentCode = code.split("\n").joinToString("\n") { indent + it }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ object KClassName : KName(), IKClassName {
/**
* keep " " character
*/
val pattern = "$illegalCharacter".replace(Regex(nameSeparator.toString()), "")
val pattern = illegalCharacter.toMutableList().apply { removeAll(nameSeparator) }.toRegex()

val temp = rawClassName.replace(Regex(pattern), "").let {
val temp = rawClassName.replace(pattern, "").let {

return@let removeStartNumberAndIllegalCharacter(it)

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

val stringBuilder = StringBuilder()

temp.split(Regex(nameSeparator.toString())).forEach {
temp.split(nameSeparator.toRegex()).forEach {
if (it.isNotBlank()) {
stringBuilder.append(it.substring(0, 1).toUpperCase().plus(it.substring(1)))
}
Expand Down
28 changes: 15 additions & 13 deletions src/main/kotlin/wu/seal/jsontokotlin/codeelements/KName.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,34 +22,30 @@ abstract class KName : IKName {
)


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


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


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

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

val numberAndIllegalCharacters = listOf(*illegalCharacter.toTypedArray(), "\\d")
val firstNumberAndIllegalCharactersRegex = "^(${numberAndIllegalCharacters.toRegex()})+".toRegex()

return it.trim().replaceFirst(firstNumberAndIllegalCharactersRegex, "")

it.trim().replaceFirst(Regex("${numberAndIllegalCharacters.toString().trim()}+"), "")
} else {
it
}
}

protected fun toBeLegalName(name: String): String {
val tempName = name.replace(illegalCharacter.toString(), "")
val tempName = name.replace(illegalCharacter.toRegex(), "")

return if (tempName in illegalNameList) {
tempName + suffix
Expand All @@ -58,4 +54,10 @@ abstract class KName : IKName {
}
}

/**
* array string into regex match patten that could match any element of the array
*/
protected fun Iterable<String>.toRegex() = joinToString(separator = "|").toRegex()


}
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ object KPropertyName : KName(), IPropertyNameMaker {
/**
* keep nameSeparator character
*/
val pattern = "$illegalCharacter".replace(Regex(nameSeparator.toString()), "")
val pattern = illegalCharacter.toMutableList().apply { removeAll(nameSeparator) }.toRegex()

val temp = rawString.replace(Regex(pattern), "").let {
val temp = rawString.replace(pattern, "").let {

return@let removeStartNumberAndIllegalCharacter(it)

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

val stringBuilder = StringBuilder()

temp.split(Regex(nameSeparator.toString())).forEach {
temp.split(nameSeparator.toRegex()).forEach {
if (it.isNotBlank()) {
stringBuilder.append(it.substring(0, 1).toUpperCase().plus(it.substring(1)))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.project.Project
import wu.seal.jsontokotlin.ConfigManager
import java.lang.IllegalStateException
import java.util.regex.Pattern

/**
* File contains functions which simply other functions's invoke
Expand Down Expand Up @@ -50,7 +52,12 @@ fun getClassesStringList(classesString: String): List<String> {
* export the class name from class block string
*/
fun getClassNameFromClassBlockString(classBlockString: String): String {
return classBlockString.substringAfter("data class").substringBefore("(").trim()
val pattern = Pattern.compile("(data )?class (?<className>[^(]+).*")
val matcher = pattern.matcher(classBlockString)
if (matcher.find()) {
return matcher.group("className").trim()
}
throw IllegalStateException("cannot find class name in classBlockString: $classBlockString")
}

fun replaceClassNameToClassBlockString(classBlockString: String, newClassName: String): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,45 +93,45 @@ class ClassCodeParser(private val classBlockString: String) {
}

private fun getPropertyKeyword(propertyLine: String): String {
val stringBeforeColon = propertyLine.substringBefore(":").trim()
val stringBeforeLastColonWithoutComment = propertyLine.substringBefore("//").substringBeforeLast(":").trim()
return when {
stringBeforeColon.contains(")") -> {
val noAnnotationString = stringBeforeColon.substringAfterLast(")").trim()
stringBeforeLastColonWithoutComment.contains(")") -> {
val noAnnotationString = stringBeforeLastColonWithoutComment.substringAfterLast(")").trim()
val keyword = noAnnotationString.split(" ").first()
keyword
}
stringBeforeColon.contains("@") -> {
val keyword = stringBeforeColon.split(" ")[1]
stringBeforeLastColonWithoutComment.contains("@") -> {
val keyword = stringBeforeLastColonWithoutComment.split(" ")[1]
keyword
}
else -> {
val keyword = stringBeforeColon.split(" ").first()
val keyword = stringBeforeLastColonWithoutComment.split(" ").first()
keyword
}
}.trim()
}

private fun getPropertyName(propertyLine: String): String {

val stringBeforeColon = propertyLine.substringBefore(":").trim()
val stringBeforeLastColonWithoutComment = propertyLine.substringBefore("//").substringBeforeLast(":").trim()
return when {
stringBeforeColon.contains(")") -> {
val noAnnotationString = stringBeforeColon.substringAfterLast(")").trim()
stringBeforeLastColonWithoutComment.contains(")") -> {
val noAnnotationString = stringBeforeLastColonWithoutComment.substringAfterLast(")").trim()
val splits = noAnnotationString.split(" ")
val propertyName =
splits.filterIndexed { index, s -> listOf(0).contains(index).not() }
.joinToString(" ")
propertyName
}
stringBeforeColon.contains("@") -> {
val splits = stringBeforeColon.split(" ")
stringBeforeLastColonWithoutComment.contains("@") -> {
val splits = stringBeforeLastColonWithoutComment.split(" ")
val propertyName =
splits.filterIndexed { index, s -> listOf(0, 1).contains(index).not() }
.joinToString(" ")
propertyName
}
else -> {
val splits = stringBeforeColon.split(" ")
val splits = stringBeforeLastColonWithoutComment.split(" ")
val propertyName =
splits.filterIndexed { index, s -> listOf(0).contains(index).not() }
.joinToString(" ")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class NestedClassModelClassesCodeParser(private val nestedClassCode: String) {
var backParenthesesCount = 0
var backBigParenthesesCount = 0
lines.forEach {
if (it.startsWith("data class")) {
if (it.matches("^(data )?class.+".toRegex())) {
classStringBuilder.append("\n")
classStringBuilder.append(it)
dataclassStringCount++
Expand All @@ -58,4 +58,4 @@ class NestedClassModelClassesCodeParser(private val nestedClassCode: String) {
}
return classStrings
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package wu.seal.jsontokotlin.codeelements

import com.winterbe.expekt.should
import org.junit.Assert.assertTrue
import org.junit.Test

Expand Down Expand Up @@ -28,6 +29,9 @@ class KClassNameTest {

}

/**
* test get name logic works well when name contains illegal character
*/
@Test
fun getName() {
val rawClassName = """
Expand All @@ -36,13 +40,15 @@ class KClassNameTest {

val legalClassName = KClassName.getName(rawClassName)

assertTrue(legalClassName.startsWith("N"))
assertTrue(legalClassName == "NAM12335E431")
legalClassName.should.startWith("N")

legalClassName.should.be.equal("NAM12335E431")

val rawClassName1 = "341@!$#43214%$#@%34"

val legalClassName1 = KClassName.getName(rawClassName1)
assertTrue(legalClassName1.isNotEmpty())
assertTrue(legalClassName1 == "X3414321434")
legalClassName1.should.be.equal("X3414321434")

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,12 @@ class KPropertyNameTest {
resultCamelCaseNameUnderScore.should.be.equal("abcAbc")
resultCamelCaseNameWithMiddleScore.should.be.equal("abcAbc")
}

/**
* Test Property name camle case format if OK when there two colon inside string
*/
@Test
fun testPropertyNameCameCaseFormatWithTwoColon() {
KPropertyName.getName("hello:baby:come").should.be.equal("helloBabyCome")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ class MakeKeywordNamedPropertyValidInterceptorTest {

@Test
fun intercept() {
val toBeParsedCode = """data class (val in: String,
val toBeParsedCode = """data class A(val in: String,
val as: Int,
val dupa: Double
)"""
val kotlinDataClass = KotlinDataClass.fromParsedKotlinDataClass(ClassCodeParser(toBeParsedCode).getKotlinDataClass())
val intercepted = MakeKeywordNamedPropertyValidInterceptor().intercept(kotlinDataClass)
intercepted.getCode().should.be.equal("""data class (
intercepted.getCode().should.be.equal("""data class A(
val `in`: String,
val `as`: Int,
val dupa: Double
Expand Down
Loading

0 comments on commit f67c2e3

Please sign in to comment.