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

Add example to demonstrate how to configure a custom Dokka plugin #3871

Open
wants to merge 20 commits into
base: master
Choose a base branch
from

Conversation

adam-enko
Copy link
Member

@adam-enko adam-enko commented Oct 17, 2024

Add an example to demonstrate how to configure a custom Dokka plugin using DGPv2.

DGPv2 has much more strict requirements for configuring a Dokka plugin, to ensure that inputs/outputs for a Gradle task are properly configured. However, this does make the configuration harder to write. This is something we could look at improving in the future, but for now, here is an example to demo how it can be done (albeit in a verbose and unintuitive/Gradle way).

#3869

To verify, check the expected docs. fun main() is not visible:

image

@adam-enko adam-enko added runner: Gradle plugin An issue/PR related to Dokka's Gradle plugin documentation An issue/PR related to Dokka's external or internal documentation labels Oct 17, 2024
adam-enko added a commit that referenced this pull request Oct 17, 2024
DokkaPluginParametersBuilder is bugged, undocumented, and untested.

It's difficult to use, and there's an alternative (see #3871).

#3869
@adam-enko adam-enko added this to the Dokka 2.0.0 milestone Oct 17, 2024
@adam-enko adam-enko self-assigned this Oct 31, 2024
@adam-enko adam-enko force-pushed the adam/feat/KT-70336/custom-plugin-config-example branch from 3430ec8 to f7d9d09 Compare October 31, 2024 15:02
adam-enko added a commit that referenced this pull request Nov 4, 2024
DokkaPluginParametersBuilder is bugged, undocumented, and untested.

It's difficult to use, and there's an alternative (see #3871).

#3869
@adam-enko adam-enko force-pushed the adam/feat/KT-70336/custom-plugin-config-example branch from 6142c00 to a93644c Compare November 12, 2024 18:52
@adam-enko adam-enko marked this pull request as ready for review November 12, 2024 21:15
Copy link
Collaborator

@whyoleg whyoleg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@adam-enko adam-enko requested review from abdulowork and removed request for Tapchicoma November 13, 2024 13:18
@@ -86,6 +97,9 @@ class ExampleProjectsTest {
) {
val exampleProjectName = ExampleProject.of(project.projectDir)

val isEnabled: Boolean =
project.projectDir.name == System.getProperty("exampleProjectFilter")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if you run these via :dokka-integration-tests:gradle:testExampleProjects they are now all going to be skipped. Do the CI builds now use per example project runs?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to use something like:

val isEnabled: Boolean = System.getProperty("exampleProjectFilter").let {
    if (it == null) return@let true
    return@let it == project.projectDir.name
}

?

Copy link
Member Author

@adam-enko adam-enko Nov 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I see your point, and I think it's correct, but I see the tests are run in CI 🤔

https://teamcity.jetbrains.com/buildConfiguration/KotlinTools_Dokka_IntegrationTests/4885102?buildTab=tests&name=ExampleProjects

image

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Judging by the log the per-project tasks get pulled in by the integrationTest task though I wonder why this happens and how easily this is broken

@@ -215,5 +219,28 @@ testing {
systemProperty("junit.jupiter.execution.parallel.mode.default", "CONCURRENT")
}
}

// Register specific Gradle test runs for each example so the examples can be tested individually.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we discussed this in the previous PR, but I still feel that it would be more conventional to have a generated testGen source directory (under git and with an idempotency check) than a per test project Gradle task

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of the benefits is that you could then run an arbitrary subset of such tests using the standard Test task's --tests filter

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, those would be good benefits. I'm just struggling to think about how to generate tests dynamically though, because I usually find code generation inconvenient and prone to mistakes.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you decide to look further into the direction of generating test cases, I think the setup is usually something like:

  • src/MyTestsInfrastructure.kt
abstract class TestsInfrastructure  {
  // hand craft some eloquent testing infrastructure with an API that easy to generate in 1 LOC
  fun runTest(testDataPath: String) { ... }
}
  • src/tests-gen/Tests.kt
// This class is generated
class Tests : TestsInfrastructure {
  @Test
  fun test_basicExample() = runTest("path/to/basicExample")
}


return """
{
"annotatedWith": $annotatedWithJson

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a bit surprised Dokka doesn't support the standard Java serialization for this configuration

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: wdyt about suggesting:

buildscript {
    dependencies {
        classpath("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3")
    }
}

and serializing using:

return Json.Default.encodeToString(
    JsonObject.serializer(),
    JsonObject(
        mapOf("annotatedWith" to JsonArray(annotatedWith.get().map { JsonPrimitive(it) }))
    )
)

?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I were doing this in my own project, I would use Kotlinx Serialization. But because this is a basic example, I want to show the most simple configuration possible, even if manually creating Json is ugly and invites mistakes.

In the future we want to improve the experience of configuring custom Dokka plugins (#3869, #3925), and provide a better wrapper.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. I wonder if it would be simpler to just provide a File as a transport between Gradle -> Dokka Plugin and then let the user choose an arbitrary serialization format


@get:Input
@get:Optional
abstract val annotatedWith: ListProperty<String>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: IIUC this sample primarily shows how you parametrize a dokkaPlugin, but I am not sure whether the ListProperty makes sense for the use case of suppressing some documentation; would you want to suppress documentation using multiple different annotations? I feel it might be clearer to use a Property<String> with a single FQN and then the JSON serialization can also be simplified

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, I'll implement this.

Copy link

@abdulowork abdulowork left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please go through my comments. I am primarily concerned whether we might be accidentally skipping the example IT in CI runs

@whyoleg whyoleg modified the milestones: Dokka 2.0.0, Dokka 2.0.20 Dec 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation An issue/PR related to Dokka's external or internal documentation runner: Gradle plugin An issue/PR related to Dokka's Gradle plugin
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants