diff --git a/lyricist-processor-properties/.gitignore b/lyricist-processor-properties/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/lyricist-processor-properties/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/lyricist-processor-properties/build.gradle b/lyricist-processor-properties/build.gradle new file mode 100644 index 0000000..1431cfd --- /dev/null +++ b/lyricist-processor-properties/build.gradle @@ -0,0 +1,7 @@ +apply from: "../kotlin-module.gradle" +apply plugin: "com.vanniktech.maven.publish" + +dependencies { + implementation libs.ksp + implementation libs.caseFormat +} diff --git a/lyricist-processor-properties/gradle.properties b/lyricist-processor-properties/gradle.properties new file mode 100644 index 0000000..1255ade --- /dev/null +++ b/lyricist-processor-properties/gradle.properties @@ -0,0 +1,2 @@ +POM_NAME=Lyricist Properties Processor +POM_ARTIFACT_ID=lyricist-processor-properties \ No newline at end of file diff --git a/lyricist-processor-properties/src/main/java/cafe/adriel/lyricist/processor/properties/Template.kt b/lyricist-processor-properties/src/main/java/cafe/adriel/lyricist/processor/properties/Template.kt new file mode 100644 index 0000000..11be8ce --- /dev/null +++ b/lyricist-processor-properties/src/main/java/cafe/adriel/lyricist/processor/properties/Template.kt @@ -0,0 +1,8 @@ +package cafe.adriel.lyricist.processor.properties + +internal fun createTemplate(className: String, fields: String): String = + """ + |public data class $className( + | $fields + |) + """.trimMargin() diff --git a/lyricist-processor-properties/src/main/java/cafe/adriel/lyricist/processor/properties/TemplateResolver.kt b/lyricist-processor-properties/src/main/java/cafe/adriel/lyricist/processor/properties/TemplateResolver.kt new file mode 100644 index 0000000..832be3d --- /dev/null +++ b/lyricist-processor-properties/src/main/java/cafe/adriel/lyricist/processor/properties/TemplateResolver.kt @@ -0,0 +1,47 @@ +package cafe.adriel.lyricist.processor.properties + +import java.util.Properties + +public fun resolveProperties(properties: Properties): String = properties.map { (key, value) -> + val name = removeDots(key as String) + val (type, fieldValue) = resolveType(value as String) + + "val $name: $type = $fieldValue" +}.joinToString(separator = ",\n") + +private fun removeDots(input: String): String { + var replaced = input + while (true) { + val dot = replaced.indexOf(".") + if (dot == -1) break + + val first = replaced[dot + 1] + + replaced = replaced.replaceRange(dot..dot + 1, first.uppercase()) + } + return replaced +} + +private fun resolveType(value: String): Pair = when { + value.toBooleanStrictOrNull() != null -> "Boolean" to value + value.toIntOrNull() != null -> "Int" to value + else -> resolveComplexExpressionType(value) ?: ("String" to "\"$value\"") +} + +private val ValueWithArgumentsExpr = Regex("\\{(.*?)}") + +private fun resolveComplexExpressionType(value: String): Pair? { + val matches = ValueWithArgumentsExpr.findAll(value) + val textArgs = matches.map(MatchResult::value).toList() + if (textArgs.isEmpty()) + return null + + val names = textArgs.map { name -> name.substring(1 until name.lastIndex) } + val fnArgs = names.joinToString(separator = ", ") { name -> "$name: String" } + val returnArgs = names.joinToString(separator = ", ") + var replacedValue = value + for (match in matches) + replacedValue = replacedValue.replace(match.value, "$${match.value}") + + return "($fnArgs) -> String" to "{ $returnArgs -> \"$replacedValue\" }" +} diff --git a/sample-properties/build.gradle b/sample-properties/build.gradle new file mode 100644 index 0000000..150de64 --- /dev/null +++ b/sample-properties/build.gradle @@ -0,0 +1,6 @@ +apply plugin: "com.google.devtools.ksp" +apply from: "../kotlin-module.gradle" + +dependencies { + ksp(project(":lyricist-processor-properties")) +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index d4f7af9..fe7431d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -11,10 +11,12 @@ include( ":lyricist-core", ":lyricist-processor-compose", ":lyricist-processor-xml", + ":lyricist-processor-properties", ":sample", ":sample-xml", ":sample-multi-module", ":sample-multiplatform", + ":sample-properties", ) // There's an issue when a module has the same name of the project