I want to parse a build.gradle.kts (Gradle build script in Kotlin), so I can find out what values are currently set and I also want to modify or add new entries in some categories.
Example (build.gradle.kts):
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "2.2.6.RELEASE"
kotlin("jvm") version "1.3.71"
etc...
}
group = "net.myProject"
version = "1.0"
java.sourceCompatibility = JavaVersion.VERSION_11
val developmentOnly by configurations.creating
configurations {
runtimeClasspath {
extendsFrom(developmentOnly)
}
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-actuator")
testImplementation("org.springframework.boot:spring-boot-starter-test") {
exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
}
etc...
}
tasks.withType<Test> {
useJUnitPlatform()
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "1.8"
}
}
It´s basically a classical Spring Boot application. What I would want to be able to do is:
Get some kind of structured representation of the file
So I can append a fixed version to a dependency (e.g. implementation("org.springframework.boot:spring-boot-starter-actuator :2.2.6.RELEASE")
And so I could append new dependencies into the dependencies list
I know that this is a special DSL for Gradle Build Scripts here, but where can I find this and how can I parse/use it?
Thanks!
Unfortunately kotlin doesn't seem to provide it's own parser, which means there won't be a simple answer and you'll have to deal with language updates down the line. You'll probably also want to make sure that the parsed structure allows you to preserve white-spaces to keep your formatting intact.
ktlint might be an interesting starting point. It uses the PSI-Elements from IntelliJ and also reuses IntelliJ's parser.
val normalizedText = text.replace("\r\n", "\n").replace("\r", "\n")
val positionByOffset = calculateLineColByOffset(normalizedText)
val fileName = if (script) "file.kts" else "file.kt"
val psiFile = psiFileFactory.createFileFromText(fileName, KotlinLanguage.INSTANCE, normalizedText) as KtFile
val errorElement = psiFile.findErrorElement()
if (errorElement != null) {
val (line, col) = positionByOffset(errorElement.textOffset)
throw ParseException(line, col, errorElement.errorDescription)
}
val rootNode = psiFile.node
// use visitor pattern on rootNode
Frankly, unless this brings a lot of value to your project, I'd try to find a different solution. Maybe you can read the values in your build.gradle.kts from an easily parsable source like a json file?
Hope that helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With