gradle: make ast generation faster using kaml and coroutines

This commit is contained in:
2023-09-20 15:13:33 -07:00
parent ad5fc9bf0f
commit 21ff33f776
9 changed files with 52 additions and 27 deletions

View File

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

View File

@ -1,6 +1,9 @@
package gay.pizza.pork.buildext.ast
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.file.Path
import kotlin.io.path.deleteExisting
@ -8,7 +11,9 @@ import kotlin.io.path.deleteIfExists
import kotlin.io.path.listDirectoryEntries
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() {
for (child in outputDirectory.listDirectoryEntries("*.kt")) {
child.deleteExisting()
@ -21,4 +26,12 @@ open class AstCodegenShared(val pkg: String, val outputDirectory: Path, val worl
path.deleteIfExists()
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
import kotlinx.serialization.Serializable
@Serializable
data class AstDescription(
val root: String,
val types: Map<String, AstTypeDescription>

View File

@ -1,5 +1,8 @@
package gay.pizza.pork.buildext.ast
import kotlinx.serialization.Serializable
@Serializable
class AstEnumDescription(
val name: 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.KotlinParameter
import gay.pizza.pork.buildext.codegen.KotlinWriter
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import java.nio.file.Path
import kotlin.io.path.createDirectories
import kotlin.io.path.exists
@ -16,18 +18,18 @@ class AstPorkIdeaCodegen(pkg: String, outputDirectory: Path, world: AstWorld) :
outputDirectory.createDirectories()
}
val codegen = AstPorkIdeaCodegen(pkg, outputDirectory, world)
codegen.generate()
codegen.runUntilCompletion()
}
}
fun generate() {
override suspend fun generate(): Unit = coroutineScope {
deleteAllContents()
writePorkElement()
writeNamedElement()
launch { writePorkElement() }
launch { writeNamedElement() }
for (type in world.typeRegistry.types) {
writePsiElement(type)
launch { writePsiElement(type) }
}
writeElementFactory()
launch { writeElementFactory() }
}
fun writePorkElement() {

View File

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

View File

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

View File

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

View File

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