Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to parse and modify build.gradle.kts Kotlin Gradle build script?

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:

  1. Get some kind of structured representation of the file

  2. So I can append a fixed version to a dependency (e.g. implementation("org.springframework.boot:spring-boot-starter-actuator :2.2.6.RELEASE")

  3. 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!

like image 763
stk Avatar asked Jan 20 '26 15:01

stk


1 Answers

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.

like image 142
Mene Avatar answered Jan 22 '26 07:01

Mene