3

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!

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.