Kotlin / dokka

API documentation engine for Kotlin
https://kotl.in/dokka
Apache License 2.0
3.4k stars 401 forks source link

[K2] KMP: Support intersecting source roots #3701

Open atyrin opened 1 month ago

atyrin commented 1 month ago

Sometimes projects may use the same folder as source root in different modules. Like the same dir for several targets in KMP. It can be done with such syntax:

kotlin {
  sourceSets {
    jsMain {
      kotlin.srcDir('src/browserMain/kotlin')
    }
    wasmJsMain {
      kotlin.srcDir('src/browserMain/kotlin')
    }
  }
}

Possible scenarios for that: Android and JVM source sets or Js and WasmJs. Sharing source sources for them using KMP hierarchies is just painful.

Projects that already use the pattern:

Kotlin with K2 works fine for them. IJ with Kotlin K2 Analysis also works: it just uses one of the platforms for analysis. And report warning:

Path [/Users/Andrei.Tyrin/IdeaProjects/_external/molecule/molecule-runtime/src/browserMain/kotlin] of module [molecule.molecule-runtime.jsMain] was removed from modules [molecule.molecule-runtime.wasmJsMain]

Dokka at the same time has the special treatment for that (#3239):

Pre-generation validity check failed: Source sets 'android' and 'jvm' have the common source roots: /Users/Andrei.Tyrin/IdeaProjects/_gates/firebase-kotlin-sdk_mpp/firebase-config/src/androidMain/kotlin. Every Kotlin source file should belong to only one source set (module).

There is a ticket to forbid such setup in KGP: https://youtrack.jetbrains.com/issue/KT-62829/Add-a-check-that-two-source-sets-cannot-have-the-same-file-system-directory. But the priority is low.

vmishenev commented 3 weeks ago

Related: #3373

vmishenev commented 3 weeks ago

There are 3 solutions here: 1) Support it on AA's side, e.g. https://youtrack.jetbrains.com/issue/IJPL-339/Multi-context-resolve-support-in-IJ-platform 2) Forbid such setup in KGP - https://youtrack.jetbrains.com/issue/KT-62829/Add-a-check-that-two-source-sets-cannot-have-the-same-file-system-directory 3) Add a workaround on Dokka's side

Workarounds: 1) Clone Documentable for common files For example,

    sourceSetA {  1.kt, 2.kt; platform: JVM; libsA}
    sourceSetB {  1.kt, 2.kt; platform: Android; libsB}
can be mapped to the following project structure of AA:
```
sourceSetA {  1.kt, 2.kt; platform: JVM; libsA}
sourceSetB {  1.kt; platform: Android; libsB}
```
`2.kt` should passed twice in the documentable translator.
**Pros:**
- Relative simplicity of implementation

**Cons:**
- Quite spread logic. It requires changes in the documentable translator and the session builder

2) Fake sourcesets The above-mentioned example can be mapped into:

    sourceSetA {  1.kt,  platform: JVM; libsA}
    sourceSetB {  1.kt; platform: Android; libsB}
    sourceSetAB {  2.kt; platform: JVM???; libsA}

    sourceSetA, sourceSetB depends on sourceSetAB (friend dependency)
**Disadvantages:**
- The target platform of a fake source set is under question: common can be insufficient. A different platform in a dependent source set can be unsupported(???) (or might be in the future).  

3) Independent AA sessions Create an AA session for each source set or only for intersecting source sets.

**Pros:**
- The same symbol can be resolved into different types depending on the platform (is there a real case?)

**Cons:**
- Works only for independent source sets that do not depend on each other
- Currently, an AA session is resource-consuming
whyoleg commented 2 weeks ago

Action point: