KSP on Kotlin Multiplatform fails on the kspJs with "Collection has more than one element."

1.3k views Asked by At

I'm experimenting with KSP (Kotlin Symbol Processing) to see what it's capable of and I'm trying to get it working on a Kotlin Multiplatform project. When I only enable kspJvm, it works perfectly, as soon as I enable kspJs as well, it fails with "Collection has more than one element."

I've recreated the issue in this demo github project: https://github.com/janvladimirmostert/observable-demo

In my processor, I have the following config:

build.gradle.kts:

val kspVersion: String by project

group = "io.jvaas"

plugins {
    kotlin("multiplatform")
}

kotlin {
    jvm {
        compilations.all {
            kotlinOptions.jvmTarget = "11"
        }
    }
    sourceSets {
        val commonMain by getting
        val jvmMain by getting {
            dependencies {
                implementation("com.google.devtools.ksp:symbol-processing-api:$kspVersion")
            }
        }
    }
}

gradle.properties:

kotlinVersion=1.6.0
kspVersion=1.6.0-1.0.1

src/commonMain/kotlin/io/jvaas/observe/Observable.kt

package io.jvaas.observe

annotation class Observable

src/jvmMain/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider

io.jvaas.observe.ObservableProcessorProvider

src/jvmMain/kotlin/io/jvaas/observe/ObservableProcessor.kt

class ObservableProcessor(
    val codeGenerator: CodeGenerator,
    val logger: KSPLogger,
) : SymbolProcessor {

    ...

}

class ObservableProcessorProvider : SymbolProcessorProvider {
    override fun create(
        environment: SymbolProcessorEnvironment
    ): SymbolProcessor {
        return ObservableProcessor(environment.codeGenerator, environment.logger)
    }
}

In my consumer I have the following:

import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackOutput.Target.UMD

group = "com.od"

plugins {
    application
    id("com.google.devtools.ksp") version "1.6.0-1.0.1"
    kotlin("plugin.serialization")
    kotlin("multiplatform")
    id("com.github.johnrengelman.shadow")
}


kotlin {

    jvm {
        compilations.all {
            kotlinOptions.jvmTarget = "11"
        }
    }
    js(IR) {
        browser {
            binaries.executable()
            webpackTask {
                output.libraryTarget = UMD
            }
        }
    }
    sourceSets {
        val commonMain by getting {
            dependencies {

                val serializationVersion = "1.3.1"
                implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$serializationVersion")
                implementation("io.jvaas:jvaas-observe")

            }
        }
        val commonTest by getting

        val jvmMain by getting {
            dependencies {

                
            }
        }
        val jvmTest by getting {
            dependencies {
                implementation(kotlin("test-junit"))
            }
        }
        val jsMain by getting


        val jsTest by getting {
            dependencies {
                implementation(kotlin("test-js"))
            }
        }
    }
}

dependencies {
    add("kspJvm", "io.jvaas:jvaas-observe")
    // add("kspJs", "io.jvaas:jvaas-observe") // <--- fails if enabled
    //ksp("io.jvaas:jvaas-observe")
}

application {
    mainClassName = "com.od.demo.Main"
}

applications/od-server/src/commonMain/kotlin/com/od/demo/Blah.kt

package com.od.demo

import io.jvaas.observe.Observable

@Observable
class Blah {

    var test1: String = ""
    var test2: Int = 0
    var test3: Array<String> = arrayOf()

}

This correctly gets processed when the kspJvm option is enabled and correctly outpus a file at

applications/od-server/build/generated/ksp/jvmMain/kotlin/com/od/demo/BlahO.kt

If I enable it for kspJs, it fails

add("kspJs", "io.jvaas:jvaas-observe")


Execution failed for task ':applications:od-server:compileProductionExecutableKotlinJs'.
> Failed to calculate the value of task ':applications:od-server:compileProductionExecutableKotlinJs' property 'entryModule$kotlin_gradle_plugin'.
   > Collection has more than one element.

I've tried the usual gradle build --info / --debug / --scan but it's not clear where I can start looking to resolve this issue.

As mentioned above, I made a demo project to demonstrate the error: https://github.com/janvladimirmostert/observable-demo

Any ideas on how to resolve that error?

1

There are 1 answers

0
Jan Vladimir Mostert On BEST ANSWER

Issue has been fixed in https://github.com/google/ksp/issues/744 but I'm not sure if it has been released yet.