fwcd / kotlin-debug-adapter

Kotlin/JVM debugging for any editor/IDE using the Debug Adapter Protocol
MIT License
120 stars 24 forks source link

Resolving dependencies not working -> Gradle fails with "configuration linuxCompileClasspath not found" #83

Open tobwes opened 1 year ago

tobwes commented 1 year ago

As the title says, debugging is not possible, because classes can't be resolved. Apparently, kotlin-debug-adapter fails to find dependencies. In emacs, dap reports:

{
  "type": "event",
  "seq": 8,
  "event": "output",
  "body": {
    "category": "console",
    "output": "[WARN] async1    Gradle task failed: \nFAILURE: Build failed with an exception.\n\n* Where:\nInitialization script '/tmp/classpath15573429753944166066.gradle' line: 70\n\n* What went wrong:\nExecution failed for task ':kotlinLSPProjectDeps'.\n> Configuration with name 'linuxCompileClasspath' not found.\n\n* Try:\n> Run with --stacktrace option to get the stack trace.\n> Run with --info or --debug option to get more log output.\n> Run with --scan to get full insights.\n> Get more help at https://help.gradle.org.\n\nBUILD FAILED in 3s\n"
  }
}

Pretty printed gradle error:

[WARN] async1    Gradle task failed: 
FAILURE: Build failed with an exception.

* Where:
Initialization script '/tmp/classpath15573429753944166066.gradle' line: 70

* What went wrong:
Execution failed for task ':kotlinLSPProjectDeps'.
> Configuration with name 'linuxCompileClasspath' not found.

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.

BUILD FAILED in 3s

I'm not sure whether I have correctly set up my project in gradle, because I'm new to Kotlin and gradle, but everything else seems to work until now. Here is my projects build.gradle.kts. I want to debug the jvmTest compilation (although, because resolving the classpath didn't work, I've created a fat jar testJar, I'm currently extracting this to build/classes/kotlin/jvm/main and then i run debug. This doesn't work either, because it doesn't stop at breakpoints...):

plugins {
    java
    id("java-library")
    kotlin("multiplatform") version "1.9.20"
}

repositories {
    mavenCentral()
}  

dependencies {
    implementation(kotlin("stdlib"))
}

kotlin {

    jvm("jvm") {
        compilations.all {
            kotlinOptions {
                jvmTarget = "17"
            }
        }
    }

    linuxX64("linux")
    mingwX64("windows")

    targets.withType<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget> {
        binaries {
            sharedLib {
                baseName = if(name == "windows") "libnative" else "native"
            }
        }
    }

    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation(kotlin("stdlib"))
                implementation("org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.6")
            }
        }
        val commonTest by getting {
            dependencies {
                implementation(kotlin("test-common"))
                implementation(kotlin("test-annotations-common"))
            }
        }
        val windowsMain by getting {
            dependsOn(sourceSets["commonMain"])
        }
        val windowsTest by getting {
            dependsOn(sourceSets["commonTest"])
        }
        val linuxMain by getting {
            dependsOn(sourceSets["commonMain"])
        }
        val linuxTest by getting {
            dependsOn(sourceSets["commonTest"])
            dependencies {
                implementation(kotlin("test"))
            }
        }
        val jvmMain by getting {
            dependsOn(sourceSets["commonMain"])
        }
        val jvmTest by getting {
            dependsOn(sourceSets["commonTest"])
            dependencies {
                implementation("org.junit.platform:junit-platform-console-standalone:1.10.1")
                implementation(kotlin("test-junit5"))

                // needed by IDEA?                                                                                                                             
                implementation("org.junit.jupiter:junit-jupiter-engine:5.10.1")
                implementation("org.junit.jupiter:junit-jupiter-params:5.10.1")
                implementation("org.junit.jupiter:junit-jupiter-api:5.10.1")
            }
        }
    }

}

    tasks.register<Jar>("testJar") {
        archiveClassifier = "test"

        manifest {
            attributes["Main-Class"]="acteo.test.TestRunnerKt"
        }

        duplicatesStrategy = DuplicatesStrategy.INCLUDE
        val contents = (
            kotlin.jvm().compilations.get("test").runtimeDependencyFiles // get the test runtime classpath                                                     
                .filter { it.exists() }
                .map { if (it.isDirectory) it else zipTree(it) }
            + kotlin.jvm().compilations.get("test").output
        )
        from(contents)
    }

    tasks.register("runJvmTest", JavaExec::class) {
        dependsOn("testJar")

        val build_dir: File = project.getLayout().getBuildDirectory().getAsFile().get()
        classpath = files("$build_dir/libs/acteo-kotlin-test.jar")
        mainClass = "acteo.test.TestRunnerKt"

        // You can configure additional JavaExec options if needed                                                                                             
        // For example, setting system properties or passing arguments                                                                                         
        // systemProperty("key", "value")                                                                                                                      
        // args("arg1", "arg2")                                                                                                                                
    }

tasks.withType<Wrapper> {
    gradleVersion = "8.4"
    distributionType = Wrapper.DistributionType.ALL
}

tasks.named<Test>("jvmTest") {
    useJUnitPlatform()

    filter {
        isFailOnNoMatchingTests = false
    }
    testLogging {
        showExceptions = true
        showStandardStreams = true
        events = setOf(
            org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED,
            //org.gradle.api.tasks.testing.logging.TestLogEvent.PASSED,                                                                                        
            org.gradle.api.tasks.testing.logging.TestLogEvent.SKIPPED
        )
        exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
        afterSuite(
            KotlinClosure2({
                desc: TestDescriptor, result: TestResult ->
                    if (desc.parent == null) {
                        // Only execute on the outermost suite                                                                                                 
                        val color = if(result.resultType == TestResult.ResultType.SUCCESS) AnsiEscapeCodes.Colors.green else AnsiEscapeCodes.Colors.red
                        val reset = AnsiEscapeCodes.reset

                        println("")
                        println(" **** Result: $color ${result.resultType} $reset ****")
                        println("  >    Tests: ${result.testCount}")
                        println("  >   Passed: ${result.successfulTestCount}")
                        println("  >   Failed: ${result.failedTestCount}")
                        println("  >  Skipped: ${result.skippedTestCount}")
                    }
            })
        )
    }
}
themkat commented 1 year ago

Both the debug adapter and the language server are a bit janky when it comes to multi platform projects. None of the contributors work with multiplatform, so support for it is at a bare minimum. Some issues: https://github.com/fwcd/kotlin-language-server/issues/447, https://github.com/fwcd/kotlin-language-server/issues/376 .

There is also the added issue with projects with multiple modules in the debug adapter: #77 . So far the max depth it checks is 2 or 3 or something if I remember correctly.