diff --git a/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/plugin/generator/PropertiesAccessorsGenerator.kt b/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/plugin/generator/PropertiesAccessorsGenerator.kt index 9868257..9b074b5 100644 --- a/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/plugin/generator/PropertiesAccessorsGenerator.kt +++ b/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/plugin/generator/PropertiesAccessorsGenerator.kt @@ -27,6 +27,7 @@ import com.highcapable.sweetproperty.plugin.config.proxy.ISweetPropertyConfigs import com.highcapable.sweetproperty.plugin.extension.accessors.proxy.IExtensionAccessors import com.highcapable.sweetproperty.plugin.generator.factory.PropertyMap import com.highcapable.sweetproperty.plugin.generator.factory.parseTypedValue +import com.highcapable.sweetproperty.plugin.generator.factory.toOptimize import com.highcapable.sweetproperty.utils.capitalize import com.highcapable.sweetproperty.utils.debug.SError import com.highcapable.sweetproperty.utils.firstNumberToLetter @@ -255,9 +256,10 @@ internal class PropertiesAccessorsGenerator { * * 解析完成后需要调用 [releaseParseTypeSpec] 完成解析 * @param successiveName 连续的名称 + * @param key 键值名称 (原始名称) * @param value 键值内容 */ - private fun parseTypeSpec(successiveName: String, value: Any) { + private fun parseTypeSpec(successiveName: String, key: String, value: Any) { /** * 获取生成的属性键值连续名称重复次数 * @return [Int] @@ -279,10 +281,7 @@ internal class PropertiesAccessorsGenerator { var grandAcccessorsName = "" var grandSuccessiveName = "" val successiveNames = mutableListOf>() - val splitNames = replace(".", "|").replace("-", "|") - .replace("_", "|").replace(" ", "_") - .split("|").dropWhile { it.isBlank() } - .ifEmpty { listOf(this) } + val splitNames = split("_").dropWhile { it.isBlank() }.ifEmpty { listOf(this) } splitNames.forEach { eachName -> val name = eachName.capitalize().toNonJavaName().firstNumberToLetter() grandAcccessorsName += if (grandAcccessorsName.isNotBlank()) ".$eachName" else eachName @@ -303,7 +302,7 @@ internal class PropertiesAccessorsGenerator { val lastClassName = lastItem?.second ?: "" val lastMethodName = lastItem?.third ?: "" val isPreLastIndex = index == successiveNames.lastIndex - 1 - if (successiveNames.size == 1) getOrCreateClassSpec(TOP_SUCCESSIVE_NAME).addFinalValueMethod(successiveName, methodName, className, value) + if (successiveNames.size == 1) getOrCreateClassSpec(TOP_SUCCESSIVE_NAME).addFinalValueMethod(key, methodName, className, value) if (index == successiveNames.lastIndex) return@forEachIndexed if (index == 0) noRepeated(TOP_SUCCESSIVE_NAME, methodName, className) { getOrCreateClassSpec(TOP_SUCCESSIVE_NAME, accessorsName) @@ -316,7 +315,7 @@ internal class PropertiesAccessorsGenerator { if (!isPreLastIndex) { addSuccessiveField(nextAccessorsName, nextClassName) addSuccessiveMethod(nextAccessorsName, nextMethodName, nextClassName) - } else addFinalValueMethod(successiveName, lastMethodName, lastClassName, value) + } else addFinalValueMethod(key, lastMethodName, lastClassName, value) } if (!isPreLastIndex) preAddConstructorSpecNames.add(className to nextClassName) } @@ -390,8 +389,8 @@ internal class PropertiesAccessorsGenerator { val keyValues = allKeyValues[index] clearGeneratedData() createTopClassSpec(configs) - keyValues.forEach { (key, value) -> - parseTypeSpec(key, value) + keyValues.toOptimize().forEach { (key, value) -> + parseTypeSpec(key, value.first, value.second) releaseParseTypeSpec() }; files.add(buildTypeSpec().createJavaFile(ACCESSORS_PACKAGE_NAME)) }; files diff --git a/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/plugin/generator/PropertiesSourcesGenerator.kt b/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/plugin/generator/PropertiesSourcesGenerator.kt index e10198a..137419a 100644 --- a/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/plugin/generator/PropertiesSourcesGenerator.kt +++ b/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/plugin/generator/PropertiesSourcesGenerator.kt @@ -25,9 +25,10 @@ import com.highcapable.sweetproperty.SweetProperty import com.highcapable.sweetproperty.plugin.config.proxy.ISweetPropertyConfigs import com.highcapable.sweetproperty.plugin.generator.factory.PropertyMap import com.highcapable.sweetproperty.plugin.generator.factory.parseTypedValue +import com.highcapable.sweetproperty.plugin.generator.factory.toOptimize +import com.highcapable.sweetproperty.plugin.generator.factory.toUnderscores import com.highcapable.sweetproperty.utils.debug.SError import com.highcapable.sweetproperty.utils.firstNumberToLetter -import com.highcapable.sweetproperty.utils.underscore import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.PropertySpec @@ -67,13 +68,13 @@ internal class PropertiesSourcesGenerator { """.trimIndent() ) if (configs.isEnableRestrictedAccess) addModifiers(KModifier.INTERNAL) - keyValues.forEach { (key, value) -> - val typedValue = value.parseTypedValue(configs.isEnableTypeAutoConversion) - addProperty(PropertySpec.builder(key.firstNumberToLetter().underscore(), typedValue.first).apply { - addKdoc("Resolve the \"$key\" value ${typedValue.second}") + keyValues.toOptimize().toUnderscores().forEach { (key, value) -> + val typedValue = value.second.parseTypedValue(configs.isEnableTypeAutoConversion) + addProperty(PropertySpec.builder(key.firstNumberToLetter(), typedValue.first).apply { + addKdoc("Resolve the \"${value.first.toKotlinPoetNoEscape()}\" value ${typedValue.second.toKotlinPoetNoEscape()}") if (configs.isEnableRestrictedAccess) addModifiers(KModifier.INTERNAL) addModifiers(KModifier.CONST) - initializer(typedValue.second.toKotlinPoetSpace()) + initializer(typedValue.second.toKotlinPoetNoEscape().toKotlinPoetSpace()) }.build()) } }.build()) @@ -85,4 +86,10 @@ internal class PropertiesSourcesGenerator { * @return [String] */ private fun String.toKotlinPoetSpace() = replace(" ", "·") + + /** + * 转换到 KotlinPoet 非转义字符内容 + * @return [String] + */ + private fun String.toKotlinPoetNoEscape() = replace("%", "%%") } \ No newline at end of file diff --git a/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/plugin/generator/factory/GeneratorFactory.kt b/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/plugin/generator/factory/GeneratorFactory.kt index 5313a35..f12ff52 100644 --- a/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/plugin/generator/factory/GeneratorFactory.kt +++ b/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/plugin/generator/factory/GeneratorFactory.kt @@ -21,11 +21,15 @@ */ package com.highcapable.sweetproperty.plugin.generator.factory +import com.highcapable.sweetproperty.utils.underscore import kotlin.reflect.KClass /** 属性键值数组类型定义 */ internal typealias PropertyMap = MutableMap +/** 属性键值优化数组类型定义 */ +internal typealias PropertyOptimizeMap = MutableMap> + /** 属性键值规则类型定义 */ internal typealias PropertyValueRule = (value: String) -> String @@ -64,4 +68,34 @@ internal fun Any.parseTypedValue(isAutoConversion: Boolean): Pair, Str }; return Pair(typeSpec, if (typeSpec == String::class) "\"$valueString\"" else valueString.let { if (typeSpec == Long::class && !it.endsWith("L")) "${it}L" else it }) +} + +/** + * [PropertyMap] 转换到 [PropertyOptimizeMap] + * + * 替换可能的键值名称特殊字符内容并保留原始键值名称 + * @return [PropertyOptimizeMap] + */ +internal fun PropertyMap.toOptimize(): PropertyOptimizeMap { + val newMap: PropertyOptimizeMap = mutableMapOf() + var uniqueNumber = 1 + forEach { (key, value) -> + var newKey = key.replace("\\W".toRegex(), "_") + while (newMap.containsKey(newKey)) newKey = "$newKey${++uniqueNumber}" + newMap[newKey] = key to value + }; return newMap +} + +/** + * [PropertyOptimizeMap] 转换为大写下划线命名 + * @return [PropertyOptimizeMap] + */ +internal fun PropertyOptimizeMap.toUnderscores(): PropertyOptimizeMap { + val newMap: PropertyOptimizeMap = mutableMapOf() + var uniqueNumber = 1 + forEach { (key, value) -> + var newKey = key.underscore() + while (newMap.containsKey(newKey)) newKey = "$newKey${++uniqueNumber}" + newMap[newKey] = value.first to value.second + }; return newMap } \ No newline at end of file