gradle: make ast generation faster using kaml and coroutines

This commit is contained in:
Alex Zenla 2023-09-20 15:13:33 -07:00
parent ad5fc9bf0f
commit 21ff33f776
Signed by: alex
GPG Key ID: C0780728420EBFE5
9 changed files with 52 additions and 27 deletions

View File

@ -1,5 +1,7 @@
@file:Suppress("UnstableApiUsage")
plugins { plugins {
`kotlin-dsl` `kotlin-dsl`
embeddedKotlin("plugin.serialization")
} }
repositories { repositories {
@ -10,10 +12,8 @@ repositories {
dependencies { dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.10") implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.10")
implementation("org.jetbrains.kotlin:kotlin-serialization:1.9.10") implementation("org.jetbrains.kotlin:kotlin-serialization:1.9.10")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
implementation("com.fasterxml.jackson.core:jackson-databind:2.15.2") implementation("com.charleskorn.kaml:kaml:0.55.0")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.15.2")
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.15.2")
} }
gradlePlugin { gradlePlugin {

View File

@ -1,6 +1,9 @@
package gay.pizza.pork.buildext.ast package gay.pizza.pork.buildext.ast
import gay.pizza.pork.buildext.codegen.KotlinWriter import gay.pizza.pork.buildext.codegen.KotlinWriter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets
import java.nio.file.Path import java.nio.file.Path
import kotlin.io.path.deleteExisting import kotlin.io.path.deleteExisting
@ -8,7 +11,9 @@ import kotlin.io.path.deleteIfExists
import kotlin.io.path.listDirectoryEntries import kotlin.io.path.listDirectoryEntries
import kotlin.io.path.writeText import kotlin.io.path.writeText
open class AstCodegenShared(val pkg: String, val outputDirectory: Path, val world: AstWorld) { abstract class AstCodegenShared(val pkg: String, val outputDirectory: Path, val world: AstWorld) {
abstract suspend fun generate()
protected fun deleteAllContents() { protected fun deleteAllContents() {
for (child in outputDirectory.listDirectoryEntries("*.kt")) { for (child in outputDirectory.listDirectoryEntries("*.kt")) {
child.deleteExisting() child.deleteExisting()
@ -21,4 +26,12 @@ open class AstCodegenShared(val pkg: String, val outputDirectory: Path, val worl
path.deleteIfExists() path.deleteIfExists()
path.writeText(content, StandardCharsets.UTF_8) path.writeText(content, StandardCharsets.UTF_8)
} }
fun runUntilCompletion() {
runBlocking {
withContext(Dispatchers.IO) {
generate()
}
}
}
} }

View File

@ -1,5 +1,8 @@
package gay.pizza.pork.buildext.ast package gay.pizza.pork.buildext.ast
import kotlinx.serialization.Serializable
@Serializable
data class AstDescription( data class AstDescription(
val root: String, val root: String,
val types: Map<String, AstTypeDescription> val types: Map<String, AstTypeDescription>

View File

@ -1,5 +1,8 @@
package gay.pizza.pork.buildext.ast package gay.pizza.pork.buildext.ast
import kotlinx.serialization.Serializable
@Serializable
class AstEnumDescription( class AstEnumDescription(
val name: String, val name: String,
val values: Map<String, String> val values: Map<String, String>

View File

@ -4,6 +4,8 @@ import gay.pizza.pork.buildext.codegen.KotlinClass
import gay.pizza.pork.buildext.codegen.KotlinFunction import gay.pizza.pork.buildext.codegen.KotlinFunction
import gay.pizza.pork.buildext.codegen.KotlinParameter import gay.pizza.pork.buildext.codegen.KotlinParameter
import gay.pizza.pork.buildext.codegen.KotlinWriter import gay.pizza.pork.buildext.codegen.KotlinWriter
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import java.nio.file.Path import java.nio.file.Path
import kotlin.io.path.createDirectories import kotlin.io.path.createDirectories
import kotlin.io.path.exists import kotlin.io.path.exists
@ -16,18 +18,18 @@ class AstPorkIdeaCodegen(pkg: String, outputDirectory: Path, world: AstWorld) :
outputDirectory.createDirectories() outputDirectory.createDirectories()
} }
val codegen = AstPorkIdeaCodegen(pkg, outputDirectory, world) val codegen = AstPorkIdeaCodegen(pkg, outputDirectory, world)
codegen.generate() codegen.runUntilCompletion()
} }
} }
fun generate() { override suspend fun generate(): Unit = coroutineScope {
deleteAllContents() deleteAllContents()
writePorkElement() launch { writePorkElement() }
writeNamedElement() launch { writeNamedElement() }
for (type in world.typeRegistry.types) { for (type in world.typeRegistry.types) {
writePsiElement(type) launch { writePsiElement(type) }
} }
writeElementFactory() launch { writeElementFactory() }
} }
fun writePorkElement() { fun writePorkElement() {

View File

@ -2,24 +2,26 @@
package gay.pizza.pork.buildext.ast package gay.pizza.pork.buildext.ast
import gay.pizza.pork.buildext.codegen.* import gay.pizza.pork.buildext.codegen.*
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import java.nio.file.Path import java.nio.file.Path
import kotlin.io.path.createDirectories import kotlin.io.path.createDirectories
import kotlin.io.path.exists import kotlin.io.path.exists
class AstStandardCodegen(pkg: String, outputDirectory: Path, world: AstWorld) : class AstStandardCodegen(pkg: String, outputDirectory: Path, world: AstWorld) :
AstCodegenShared(pkg, outputDirectory, world) { AstCodegenShared(pkg, outputDirectory, world) {
fun generate() { override suspend fun generate(): Unit = coroutineScope {
deleteAllContents() deleteAllContents()
for (type in world.typeRegistry.types) { for (type in world.typeRegistry.types) {
writeAstType(type) launch { writeAstType(type) }
} }
writeNodeExtensions() launch { writeNodeExtensions() }
writeNodeType() launch { writeNodeType() }
writeNodeVisitor() launch { writeNodeVisitor() }
writeNodeCoalescer() launch { writeNodeCoalescer() }
writeNodeVisitorExtensions() launch { writeNodeVisitorExtensions() }
writeNodeParser() launch { writeNodeParser() }
writeNodeParserExtensions() launch { writeNodeParserExtensions() }
} }
private fun writeNodeType() { private fun writeNodeType() {
@ -497,7 +499,7 @@ class AstStandardCodegen(pkg: String, outputDirectory: Path, world: AstWorld) :
outputDirectory.createDirectories() outputDirectory.createDirectories()
} }
val codegen = AstStandardCodegen(pkg, outputDirectory, world) val codegen = AstStandardCodegen(pkg, outputDirectory, world)
codegen.generate() codegen.runUntilCompletion()
} }
} }
} }

View File

@ -1,5 +1,8 @@
package gay.pizza.pork.buildext.ast package gay.pizza.pork.buildext.ast
import kotlinx.serialization.Serializable
@Serializable
data class AstTypeDescription( data class AstTypeDescription(
val parent: String? = null, val parent: String? = null,
val values: List<AstValueDescription>? = null, val values: List<AstValueDescription>? = null,

View File

@ -1,5 +1,8 @@
package gay.pizza.pork.buildext.ast package gay.pizza.pork.buildext.ast
import kotlinx.serialization.Serializable
@Serializable
data class AstValueDescription( data class AstValueDescription(
val name: String, val name: String,
val type: String, val type: String,

View File

@ -1,8 +1,6 @@
package gay.pizza.pork.buildext.ast package gay.pizza.pork.buildext.ast
import com.fasterxml.jackson.databind.ObjectMapper import com.charleskorn.kaml.Yaml
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
import com.fasterxml.jackson.module.kotlin.KotlinModule
import java.nio.file.Path import java.nio.file.Path
import kotlin.io.path.readText import kotlin.io.path.readText
@ -83,9 +81,7 @@ class AstWorld {
fun read(path: Path): AstWorld { fun read(path: Path): AstWorld {
val astYamlText = path.readText() val astYamlText = path.readText()
val mapper = ObjectMapper(YAMLFactory()) val astDescription =Yaml.default.decodeFromString(AstDescription.serializer(), astYamlText)
mapper.registerModules(KotlinModule.Builder().build())
val astDescription = mapper.readValue(astYamlText, AstDescription::class.java)
return build(astDescription) return build(astDescription)
} }
} }