Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AndroidX classes produce Error class: unknown class in generated HTML #71

Closed
EdricChan03 opened this issue May 11, 2023 · 7 comments
Closed
Labels
affects:android bug Something isn't working
Milestone

Comments

@EdricChan03
Copy link
Contributor

EdricChan03 commented May 11, 2023

For whatever reason, AndroidX classes (for e.g. androidx.browser.customtabs.CustomTabColorSchemeParams) produces Error class: unknown class in the resulting HTML output:

Built Dokka sources produces an "Error class: unknown class" error for CustomTabColorSchemeParams

CustomTabColorSchemeParams also isn't clickable in the generated KDoc.

Source code for reference

I'm currently using 1.3.0, but this issue also appears to be present in 1.2.0 from some quick testing.

Checking the dokka_parameters.json file does show that the androidx.browser artifact is included in the classpath though:

Expand to view dokka_parameters.json
{
  "moduleName": "browser-ktx",
  "moduleVersion": "0.0.1",
  "offlineMode": false,
  "failOnWarning": false,
  "sourceSets": [
    {
      "sourceSetId": {
        "scopeId": ":androidx:browser:browser-ktx",
        "sourceSetName": "main"
      },
      "displayName": "androidJvm",
      "classpath": [
        "[...]/.gradle/caches/modules-2/files-2.1/androidx.browser/browser/1.5.0/[...]/browser-1.5.0.aar",
        "[...]/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.8.21/[...]/kotlin-stdlib-jdk8-1.8.21.jar",
        "[...]/.gradle/caches/modules-2/files-2.1/androidx.core/core/1.1.0/[...]/core-1.1.0.aar",
        "[...]/.gradle/caches/modules-2/files-2.1/androidx.versionedparcelable/versionedparcelable/1.1.0/[...]/versionedparcelable-1.1.0.aar",
        "[...]/.gradle/caches/modules-2/files-2.1/androidx.collection/collection/1.1.0/[...]/collection-1.1.0.jar",
        "[...]/.gradle/caches/modules-2/files-2.1/androidx.annotation/annotation/1.2.0/[...]/annotation-1.2.0.jar",
        "[...]/.gradle/caches/modules-2/files-2.1/com.google.guava/listenablefuture/1.0/[...]/listenablefuture-1.0.jar",
        "[...]/.gradle/caches/modules-2/files-2.1/androidx.lifecycle/lifecycle-runtime/2.0.0/[...]/lifecycle-runtime-2.0.0.aar",
        "[...]/.gradle/caches/modules-2/files-2.1/androidx.lifecycle/lifecycle-common/2.0.0/[...]/lifecycle-common-2.0.0.jar",
        "[...]/.gradle/caches/modules-2/files-2.1/androidx.arch.core/core-common/2.0.0/[...]/core-common-2.0.0.jar",
        "[...]/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.8.21/[...]/kotlin-stdlib-jdk7-1.8.21.jar",
        "[...]/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.8.21/[...]/kotlin-stdlib-1.8.21.jar",
        "[...]/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.8.21/[...]/kotlin-stdlib-common-1.8.21.jar",
        "[...]/.gradle/caches/modules-2/files-2.1/org.jetbrains/annotations/13.0/[...]/annotations-13.0.jar",
        "[...]/.gradle/caches/modules-2/files-2.1/androidx.concurrent/concurrent-futures/1.0.0/[...]/concurrent-futures-1.0.0.jar",
        "[...]/.gradle/caches/modules-2/files-2.1/androidx.interpolator/interpolator/1.0.0/[...]/interpolator-1.0.0.aar",
        "[...]/Library/Android/sdk/platforms/android-33/android.jar"
      ],
      "sourceRoots": [
        "[...]/androidx-ktx-extras/androidx/browser/browser-ktx/src/main/kotlin"
      ],
      "dependentSourceSetIds": [
      ],
      "samples": [
      ],
      "includes": [
      ],
      "reportUndocumented": true,
      "skipEmptyPackages": true,
      "skipDeprecated": false,
      "jdkVersion": 8,
      "sourceLinks": [
        {
          "localDirectory": "[...]/androidx-ktx-extras/androidx/browser/browser-ktx/src/main/kotlin",
          "remoteUrl": "https://github.com/EdricChan03/androidx-ktx-extras/tree/main/androidx/browser/browser-ktx/src/main/kotlin",
          "remoteLineSuffix": "#L"
        }
      ],
      "perPackageOptions": [
      ],
      "externalDocumentationLinks": [
        {
          "url": "https://developer.android.com/reference/kotlin/",
          "packageListUrl": "https://developer.android.com/reference/kotlin/package-list"
        },
        {
          "url": "https://developer.android.com/reference/kotlin/",
          "packageListUrl": "https://developer.android.com/reference/kotlin/androidx/package-list"
        },
        {
          "url": "https://docs.oracle.com/javase/8/docs/api/",
          "packageListUrl": "https://docs.oracle.com/javase/8/docs/api/package-list"
        },
        {
          "url": "https://kotlinlang.org/api/latest/jvm/stdlib/",
          "packageListUrl": "https://kotlinlang.org/api/latest/jvm/stdlib/package-list"
        }
      ],
      "enableKotlinStdLibDocumentationLink": true,
      "enableJdkDocumentationLink": true,
      "suppressedFiles": [
      ],
      "analysisPlatform": "jvm",
      "documentedVisibilities": [
        "PUBLIC"
      ]
    }
  ],
  "pluginsClasspath": [
    "[...]/.gradle/caches/modules-2/files-2.1/org.jetbrains.dokka/dokka-analysis/1.8.10/[...]/dokka-analysis-1.8.10.jar",
    "[...]/.gradle/caches/modules-2/files-2.1/org.jetbrains.dokka/templating-plugin/1.8.10/[...]/templating-plugin-1.8.10.jar",
    "[...]/.gradle/caches/modules-2/files-2.1/org.jetbrains.dokka/dokka-base/1.8.10/[...]/dokka-base-1.8.10.jar",
    "[...]/.gradle/caches/modules-2/files-2.1/org.jetbrains.dokka/kotlin-analysis-intellij/1.8.10/[...]/kotlin-analysis-intellij-1.8.10.jar",
    "[...]/.gradle/caches/modules-2/files-2.1/org.jetbrains.dokka/kotlin-analysis-compiler/1.8.10/[...]/kotlin-analysis-compiler-1.8.10.jar",
    "[...]/.gradle/caches/modules-2/files-2.1/org.freemarker/freemarker/2.3.31/[...]/freemarker-2.3.31.jar",
    "[...]/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-html-jvm/0.8.0/[...]/kotlinx-html-jvm-0.8.0.jar"
  ],
  "pluginsConfiguration": [
    {
      "fqPluginName": "org.jetbrains.dokka.base.DokkaBase",
      "serializationFormat": "JSON",
      "values": "{\"customAssets\":[],\"customStyleSheets\":[],\"separateInheritedMembers\":false,\"mergeImplicitExpectActualDeclarations\":false}"
    },
    {
      "fqPluginName": "org.jetbrains.dokka.versioning.VersioningPlugin",
      "serializationFormat": "JSON",
      "values": "{\"versionsOrdering\":[],\"olderVersions\":[],\"renderVersionsNavigationOnAllPages\":true}"
    }
  ],
  "delayTemplateSubstitution": false,
  "suppressObviousFunctions": true,
  "includes": [
  ],
  "suppressInheritedMembers": false,
  "finalizeCoroutines": false,
  "modules": [
  ]
}

Sources

Additional info

Curiously enough, the annotations seem to work as expected though... 🤔

@aSemy aSemy added the bug Something isn't working label May 11, 2023
@aSemy
Copy link
Contributor

aSemy commented May 12, 2023

Thanks for the report, this is something that needs to be fixed.

I first encountered this problem in #57. I hoped it would be fixed by #59, but apparently not.

I suspect it's an issue with classpath ordering, but I'm not certain. It could also be caused by Dokka trying to merge multiple source sets.

I'm not very familiar with Android development, so help would be appreciated. Specifically,

@EdricChan03
Copy link
Contributor Author

EdricChan03 commented May 19, 2023

So I've just tested adding the Dokka plugin itself to the project (with dokkatooPublicationDirectory.set(layout.buildDirectory.dir("dokkatoo")) applied to Dokkatoo) and noticed that running the standard dokkaHtmlMultiModule task with the --info flag shows the following dependency graph:

Output with --info flag
Tasks to be executed: [task ':androidx:browser:browser-ktx:preBuild', task ':androidx:browser:browser-ktx:preDebugBuild', task ':androidx:browser:browser-ktx:generateDebugResValues', task ':androidx:browser:browser-ktx:generateDebugResources', task ':androidx:browser:browser-ktx:packageDebugResources', task ':androidx:browser:browser-ktx:parseDebugLocalResources', task ':androidx:browser:browser-ktx:processDebugManifest', task ':androidx:browser:browser-ktx:generateDebugRFile', task ':androidx:browser:browser-ktx:preReleaseBuild', task ':androidx:browser:browser-ktx:generateReleaseResValues', task ':androidx:browser:browser-ktx:generateReleaseResources', task ':androidx:browser:browser-ktx:packageReleaseResources', task ':androidx:browser:browser-ktx:parseReleaseLocalResources', task ':androidx:browser:browser-ktx:processReleaseManifest', task ':androidx:browser:browser-ktx:generateReleaseRFile', task ':androidx:browser:browser-ktx:dokkaHtmlPartial', <truncated>, task ':dokkaHtmlMultiModule']

(or with the --dry-run flag:)

Output with --dry-run flag
:androidx:browser:browser-ktx:preBuild SKIPPED
:androidx:browser:browser-ktx:preDebugBuild SKIPPED
:androidx:browser:browser-ktx:generateDebugResValues SKIPPED
:androidx:browser:browser-ktx:generateDebugResources SKIPPED
:androidx:browser:browser-ktx:packageDebugResources SKIPPED
:androidx:browser:browser-ktx:parseDebugLocalResources SKIPPED
:androidx:browser:browser-ktx:processDebugManifest SKIPPED
:androidx:browser:browser-ktx:generateDebugRFile SKIPPED
:androidx:browser:browser-ktx:preReleaseBuild SKIPPED
:androidx:browser:browser-ktx:generateReleaseResValues SKIPPED
:androidx:browser:browser-ktx:generateReleaseResources SKIPPED
:androidx:browser:browser-ktx:packageReleaseResources SKIPPED
:androidx:browser:browser-ktx:parseReleaseLocalResources SKIPPED
:androidx:browser:browser-ktx:processReleaseManifest SKIPPED
:androidx:browser:browser-ktx:generateReleaseRFile SKIPPED
:androidx:browser:browser-ktx:dokkaHtmlPartial SKIPPED
:androidx:work:work-runtime-ktx:preBuild SKIPPED
:androidx:work:work-runtime-ktx:preDebugBuild SKIPPED
:androidx:work:work-runtime-ktx:generateDebugResValues SKIPPED
:androidx:work:work-runtime-ktx:generateDebugResources SKIPPED
:androidx:work:work-runtime-ktx:packageDebugResources SKIPPED
:androidx:work:work-runtime-ktx:parseDebugLocalResources SKIPPED
:androidx:work:work-runtime-ktx:processDebugManifest SKIPPED
:androidx:work:work-runtime-ktx:generateDebugRFile SKIPPED
:androidx:work:work-runtime-ktx:preReleaseBuild SKIPPED
:androidx:work:work-runtime-ktx:generateReleaseResValues SKIPPED
:androidx:work:work-runtime-ktx:generateReleaseResources SKIPPED
:androidx:work:work-runtime-ktx:packageReleaseResources SKIPPED
:androidx:work:work-runtime-ktx:parseReleaseLocalResources SKIPPED
:androidx:work:work-runtime-ktx:processReleaseManifest SKIPPED
:androidx:work:work-runtime-ktx:generateReleaseRFile SKIPPED
:androidx:work:work-runtime-ktx:dokkaHtmlPartial SKIPPED
<truncated>
:dokkaHtmlMultiModule SKIPPED

While Dokkatoo (dokkatooGeneratePublicationHtml --info) has the following task dependency graph:

Output with --info flag
Tasks to be executed: [task ':androidx:browser:browser-ktx:prepareDokkatooParametersHtml', task ':androidx:browser:browser-ktx:dokkatooGenerateModuleHtml', task ':androidx:browser:browser-ktx:prepareDokkatooModuleDescriptorHtml', task ':androidx:work:work-runtime-ktx:prepareDokkatooParametersHtml', task ':androidx:work:work-runtime-ktx:dokkatooGenerateModuleHtml', task ':androidx:work:work-runtime-ktx:prepareDokkatooModuleDescriptorHtml', task ':prepareDokkatooParametersHtml', task ':dokkatooGeneratePublicationHtml', task ':androidx:browser:browser-ktx:dokkatooGeneratePublicationHtml', task ':androidx:work:work-runtime-ktx:dokkatooGeneratePublicationHtml', <truncated>]

(or with the --dry-run flag:)

Output with --dry-run flag
:androidx:browser:browser-ktx:prepareDokkatooParametersHtml SKIPPED
:androidx:browser:browser-ktx:dokkatooGenerateModuleHtml SKIPPED
:androidx:browser:browser-ktx:prepareDokkatooModuleDescriptorHtml SKIPPED
:androidx:work:work-runtime-ktx:prepareDokkatooParametersHtml SKIPPED
:androidx:work:work-runtime-ktx:dokkatooGenerateModuleHtml SKIPPED
:androidx:work:work-runtime-ktx:prepareDokkatooModuleDescriptorHtml SKIPPED
:prepareDokkatooParametersHtml SKIPPED
:dokkatooGeneratePublicationHtml SKIPPED
:androidx:browser:browser-ktx:dokkatooGeneratePublicationHtml SKIPPED
:androidx:work:work-runtime-ktx:dokkatooGeneratePublicationHtml SKIPPED

So I guess there's something going on in the partial task that Dokka uses for sub-projects? I presume it's delegating to KGP to compile the Android libraries via AGP, as I've also noticed that the partial task immediately shows what seems to be AGP output right after:

> Task :androidx:browser:browser-ktx:dokkaHtmlPartial UP-TO-DATE
Transforming browser-1.5.0.aar (androidx.browser:browser:1.5.0) with IdentityTransform
Transforming core-1.1.0.aar (androidx.core:core:1.1.0) with IdentityTransform
Transforming annotations-13.0.jar (org.jetbrains:annotations:13.0) with IdentityTransform
Transforming annotations-13.0.jar (org.jetbrains:annotations:13.0) with IdentityTransform
Transforming core-1.1.0.aar (androidx.core:core:1.1.0) with AarToClassTransform
Transforming collection-1.1.0.jar (androidx.collection:collection:1.1.0) with IdentityTransform
Transforming collection-1.1.0.jar (androidx.collection:collection:1.1.0) with IdentityTransform
Transforming versionedparcelable-1.1.0.aar (androidx.versionedparcelable:versionedparcelable:1.1.0) with IdentityTransform
Transforming versionedparcelable-1.1.0.aar (androidx.versionedparcelable:versionedparcelable:1.1.0) with AarToClassTransform
Transforming kotlin-stdlib-jdk8-1.8.21.jar (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.21) with IdentityTransform
Transforming browser-1.5.0.aar (androidx.browser:browser:1.5.0) with AarToClassTransform
Transforming kotlin-stdlib-jdk8-1.8.21.jar (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.21) with IdentityTransform
Transforming kotlin-stdlib-jdk7-1.8.21.jar (org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.21) with IdentityTransform
Transforming kotlin-stdlib-jdk7-1.8.21.jar (org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.21) with IdentityTransform
Transforming kotlin-stdlib-1.8.21.jar (org.jetbrains.kotlin:kotlin-stdlib:1.8.21) with IdentityTransform
Transforming listenablefuture-1.0.jar (com.google.guava:listenablefuture:1.0) with IdentityTransform
Transforming kotlin-stdlib-1.8.21.jar (org.jetbrains.kotlin:kotlin-stdlib:1.8.21) with IdentityTransform
Transforming listenablefuture-1.0.jar (com.google.guava:listenablefuture:1.0) with IdentityTransform
Transforming kotlin-stdlib-common-1.8.21.jar (org.jetbrains.kotlin:kotlin-stdlib-common:1.8.21) with IdentityTransform
Transforming annotation-jvm-1.6.0.jar (androidx.annotation:annotation-jvm:1.6.0) with IdentityTransform
Transforming kotlin-stdlib-common-1.8.21.jar (org.jetbrains.kotlin:kotlin-stdlib-common:1.8.21) with IdentityTransform
Transforming annotation-jvm-1.6.0.jar (androidx.annotation:annotation-jvm:1.6.0) with IdentityTransform
Transforming lifecycle-runtime-2.0.0.aar (androidx.lifecycle:lifecycle-runtime:2.0.0) with IdentityTransform
Transforming lifecycle-common-2.0.0.jar (androidx.lifecycle:lifecycle-common:2.0.0) with IdentityTransform
Transforming lifecycle-common-2.0.0.jar (androidx.lifecycle:lifecycle-common:2.0.0) with IdentityTransform
Transforming lifecycle-runtime-2.0.0.aar (androidx.lifecycle:lifecycle-runtime:2.0.0) with AarToClassTransform
Transforming core-common-2.0.0.jar (androidx.arch.core:core-common:2.0.0) with IdentityTransform
Transforming core-common-2.0.0.jar (androidx.arch.core:core-common:2.0.0) with IdentityTransform

@aSemy
Copy link
Contributor

aSemy commented May 19, 2023

Hmm yes, that sounds like a relevant find, good work

So Dokka Gradle Plugin fetches the classpath from the KotlinCompile compilation task

https://github.com/Kotlin/dokka/blob/d9c8c6c0035ad59dc0a5495f3247205bb8553295/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/kotlinClasspathUtils.kt#L52-L63

This is not ideal because task properties are not really supposed to be used to transfer files, even if it is convenient and produces correct output.

Dokkatoo achieves the same result by fetching the classpath via configurations

private fun determineClasspath(
details: KotlinSourceSetDetails
): Provider<FileCollection> {
return details.compilations.map { compilations: List<KotlinCompilationDetails> ->
val classpath = objects.fileCollection()
if (compilations.isNotEmpty()) {
compilations.fold(classpath) { acc, compilation ->
acc.from(compilation.compilationClasspath)
// can't use compileDependencyFiles, it causes weird dependency resolution errors in Android projects
//acc.from(providers.provider { compilation.compileDependencyFiles })
}
} else {
classpath
.from(details.sourceDirectories)
.from(details.sourceDirectoriesOfDependents)
}
}
}

However, maybe this misses some sort of dependency transformation that Android requires...

@EdricChan03
Copy link
Contributor Author

EdricChan03 commented May 19, 2023

I've just added a temporary commit to my Dokka fork (EdricChan03/dokka@f29d209) that adds temporary logging of the Dokka config to disk, and I can confirm that it is transformed 🙃

(prettified a bit, original was all in a single line)

"classpath" : [
  "<project>/androidx/browser/browser-ktx/build/intermediates/compile_r_class_jar/debug/R.jar",
  "<home>/.gradle/caches/transforms-3/<...>/transformed/browser-1.5.0-api.jar",
  "<home>/.gradle/caches/transforms-3/<...>/transformed/core-1.1.0-api.jar",
  "<home>/.gradle/caches/transforms-3/<...>/transformed/versionedparcelable-1.1.0-api.jar",
  "<home>/.gradle/caches/modules-2/files-2.1/androidx.collection/collection/1.1.0/<...>/collection-1.1.0.jar",
  "<home>/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.8.21/<...>/kotlin-stdlib-jdk8-1.8.21.jar",
  "<home>/.gradle/caches/modules-2/files-2.1/androidx.annotation/annotation-jvm/1.6.0/<...>/annotation-jvm-1.6.0.jar",
  "<home>/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.8.21/<...>/kotlin-stdlib-jdk7-1.8.21.jar",
  "<home>/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.8.21/kotlin-stdlib-1.8.21.jar",
  "<home>/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.8.21/<...>/kotlin-stdlib-common-1.8.21.jar",
  "<home>/.gradle/caches/modules-2/files-2.1/org.jetbrains/annotations/13.0/<...>/annotations-13.0.jar",
  "<home>/.gradle/caches/modules-2/files-2.1/com.google.guava/listenablefuture/1.0/<...>/listenablefuture-1.0.jar",
  "<home>/.gradle/caches/transforms-3/<...>/transformed/lifecycle-runtime-2.0.0-api.jar",
  "<home>/.gradle/caches/modules-2/files-2.1/androidx.lifecycle/lifecycle-common/2.0.0/<...>/lifecycle-common-2.0.0.jar",
  "<home>/.gradle/caches/modules-2/files-2.1/androidx.arch.core/core-common/2.0.0/<...>/core-common-2.0.0.jar",
  "<home>/Library/Android/sdk/platforms/android-33/android.jar",
  "<home>/Library/Android/sdk/build-tools/30.0.3/core-lambda-stubs.jar"
],

Let me know if you need additional information/a reproducer

@aSemy aSemy mentioned this issue May 21, 2023
5 tasks
EdricChan03 added a commit to EdricChan03/androidx-ktx-extras that referenced this issue May 25, 2023
Until adamko-dev/dokkatoo#71 is fixed, we'll
probably have to rollback to plain ol' Dokka
@aSemy
Copy link
Contributor

aSemy commented Jun 4, 2023

I believe this issue will be fixed by #76.

Leave a comment or create a new issue if there's anything to improve with Android projects.

@aSemy aSemy closed this as completed Jun 4, 2023
@aSemy aSemy added this to the v1.4.0 milestone Jun 4, 2023
@EdricChan03
Copy link
Contributor Author

Yep, I can confirm it was fixed: https://edricchan03.github.io/androidx-ktx-extras

@aSemy
Copy link
Contributor

aSemy commented Jun 4, 2023

@EdricChan03 Great to hear! Thanks for the update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
affects:android bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants