Hey all :wave: I have an issue when migrating proj...
# dokka
n
Hey all 👋 I have an issue when migrating project from pure Android to KMP So in short we have a multimodule android project and are migrating it to KMP module by module. Recently it was noticed that modules which were converted to KMP have broken documentation:
val fieldName: <Error class: unknown class>
instead of a real resolved class. This happens when a class in KMP module references a class that is located in any other module in the project or 3rd party libs, e.g. it can't resolve Android context. However it resolves all the primitive types/classes in the same module and some kotlin stdlib classes (not sure if all of them, or for some specific packages, since i didn't dive too much into that). The configuration is pretty much the same for both android/kmp setups:
Copy code
tasks.withType<DokkaTaskPartial>().configureEach {
    moduleName.set("$groupId:$artifactId")
    pluginsMapConfiguration.set(
        mutableMapOf(customCssPluginConfiguration)
    )
    dokkaSourceSets {
        configureEach {
            jdkVersion.set(8)
            skipDeprecated.set(true)
            skipEmptyPackages.set(true)
            includeNonPublic.set(false)
            reportUndocumented.set(true)
            externalDocUrls.forEach {
                externalDocumentationLink {
                    url.set(URL(it))
                }
            }
        }
    }
}
The
dokkaHtmlMultiModule
task passes without any issues Dokka version - 1.8.10 Please let me know if any additional info is required. I'd really appreciate any kind of help 🙏
i
Hey! Were you able to resolve the problem? Do the problematic KMP modules only have the common source set configured, or is there a common+platform combination, like common+jvm? If the modules are common only, you might be hitting https://github.com/Kotlin/dokka/issues/2679 In other cases,
Error class
appears when Dokka doesn't have access to the referenced classes, so it's most likely a configuration problem in which certain classes are not available on Dokka's classpath during analysis Can't say much more without looking at the project as a whole.. is there anything else that's unusual about it?
n
Hey, the problem indeed seems to be similiar with the issue you mentioned.
Do the problematic KMP modules only have the common source set configured, or is there a common+platform combination, like common+jvm?
Not sure if i understand you correctly. The configuration is targeting both
android()
and
jvm()
. The initial project has 3 source sets: android, jvm and common + tests for them. However i setup a clean project with android and common source sets in one modules and the issue is reproducable for common but not for the android source set. I will try to provide the sample project later today.
@Ignat Beresnev I've created the least needed configuration to reproduce this issue: https://github.com/NukeLar/dokka-test There is a corelibs/corelib module which is used as a dependency with 2 simple classes And also there is the libs/commonlib3 module (sorry for the namings, it had quite some experimentation 🙂) The commonlib3 contains 2 source sets:
commonMain
- the one that has a bug
androidMain
- added for the comparison build.gradle.kts with the dokka configuration The bugged class is the
CommonLib3Class
, it contains reference to corelibs/corelib classes and a 3rd party
java.awt.Rectangle
With just this setup the output documentation looks like in the following image, android is generated fine, common has issues with referencing other modules
The ultimate goal is to have a combined source set, which contains code from both android and common sources and hide other 'default' sources. For that you can find some commented code in build.gradle.kts. If you uncomment it the docs will look like in the image For the android class everything is broken, but the common class now starts seeing a
java.awt.Rectangle
One more thing that i discovered is the following workaround:
Copy code
tasks.withType<DokkaTaskPartial>().configureEach {
    dokkaSourceSets {
        register("combined") {
            displayName.set("androidJvm")
            platform.set(Platform.jvm)
            sourceRoots.from(kotlin.sourceSets.getByName("androidMain").kotlin.srcDirs)
            sourceRoots.from(kotlin.sourceSets.getByName("commonMain").kotlin.srcDirs)
            // add these 2 lines to get the proper linking
            dependsOn("androidMain")
            dependsOn("commonMain")
        }
        configureEach {
            println("sourceSetName = $name")
            if (name.contains("jvm") || name.contains("android") || name.contains("common")) {
                // instead of suppressing we just add empty visibility for the default source sets, this is required to be able to depend on these source sets and hide them in doccs
                documentedVisibilities.set(setOf())
            }
            jdkVersion.set(8)
            skipDeprecated.set(true)
            skipEmptyPackages.set(true)
            includeNonPublic.set(false)
            reportUndocumented.set(true)
        }
    }
}
It results into a perfect resolution of all the dependencies, however this feels wrong and it seems to me that the
dependsOn
is misused here. And finally this solution has a problem which is not visible here but reproduces in my target project which has way more modules and more complex dependencies. Even though it fixes the
Error class
issue for all the cases - some of such classes don't have a hyperlink, and are just plain text. There is even a worse situation when there is a reference to a class with proper link, but it points to a dead link with [androidMain] prefix, the link path is generated, but not a class there, since we removed
documentedVisibilities
for other sources. Hope this info helps, this is the closest solution i've managed to found to what i want to achive, but it just feels that i'm going wrong way.