Skip to content

Commit

Permalink
Compare DokkaSourceSetImpl by DokkaSourceSetID only (#3568)
Browse files Browse the repository at this point in the history
* Make SourceSet equals/hashCode use only it's ID
* Add checker that all sourceSet ids are unique during generation
* `verificationStage` should always run in tests
* `verificationStage` should run as a first step as in `SingleModuleGeneration::generate` in tests
* Add structural assertions over `DokkaSourceSet` and `DokkaConfiguration` for tests
* rename `dokka-test-api` Gradle project name for composite builds support
  • Loading branch information
whyoleg authored Apr 19, 2024
1 parent ff4c2d0 commit f524273
Show file tree
Hide file tree
Showing 36 changed files with 285 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -161,5 +161,13 @@ internal fun parseSourceSet(moduleName: String, args: Array<String>): DokkaConfi
override val suppressedFiles = suppressedFiles.toMutableSet()
override val documentedVisibilities: Set<DokkaConfiguration.Visibility> = documentedVisibilities.toSet()
.ifEmpty { DokkaDefaults.documentedVisibilities }

override fun equals(other: Any?): Boolean {
return sourceSetID == (other as? DokkaConfiguration.DokkaSourceSet)?.sourceSetID
}

override fun hashCode(): Int {
return sourceSetID.hashCode()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ dependencies {
testImplementation(libs.gradlePlugin.kotlin)
testImplementation(libs.gradlePlugin.kotlin.klibCommonizerApi)
testImplementation(libs.gradlePlugin.android)
testImplementation("org.jetbrains.dokka:dokka-test-api:$version")
}

@Suppress("UnstableApiUsage")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import org.jetbrains.dokka.PluginConfigurationImpl
import org.jetbrains.dokka.gradle.utils.create_
import org.jetbrains.dokka.gradle.utils.externalDocumentationLink_
import org.jetbrains.dokka.gradle.utils.withDependencies_
import org.jetbrains.dokka.testApi.assertDokkaConfigurationEquals
import org.jetbrains.dokka.toCompactJsonString
import java.io.File
import java.net.URI
Expand Down Expand Up @@ -66,7 +67,7 @@ class DokkaConfigurationJsonTest {
val configurationJson = sourceConfiguration.toCompactJsonString()
val parsedConfiguration = DokkaConfigurationImpl(configurationJson)

assertEquals(sourceConfiguration, parsedConfiguration)
assertDokkaConfigurationEquals(sourceConfiguration, parsedConfiguration)
println(parsedConfiguration)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import org.jetbrains.dokka.PluginConfigurationImpl
import org.jetbrains.dokka.gradle.utils.create_
import org.jetbrains.dokka.gradle.utils.externalDocumentationLink_
import org.jetbrains.dokka.gradle.utils.withDependencies_
import org.jetbrains.dokka.testApi.assertDokkaConfigurationEquals
import org.junit.jupiter.api.io.TempDir
import java.io.File
import java.io.ObjectInputStream
Expand Down Expand Up @@ -73,6 +74,6 @@ class DokkaConfigurationSerializableTest {
stream.readObject() as DokkaConfiguration
}

assertEquals(sourceConfiguration, parsedConfiguration)
assertDokkaConfigurationEquals(sourceConfiguration, parsedConfiguration)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import org.jetbrains.dokka.gradle.utils.all_
import org.jetbrains.dokka.gradle.utils.allprojects_
import org.jetbrains.dokka.gradle.utils.configureEach_
import org.jetbrains.dokka.gradle.utils.withDependencies_
import org.jetbrains.dokka.testApi.assertDokkaConfigurationEquals
import java.io.File
import kotlin.test.*

Expand Down Expand Up @@ -52,7 +53,7 @@ class DokkaCollectorTaskTest {

collectorTasks.forEach { task ->
val dokkaConfiguration = task.buildDokkaConfiguration()
assertEquals(
assertDokkaConfigurationEquals(
DokkaConfigurationImpl(
moduleName = "custom Module Name",
outputDir = rootProject.projectDir.resolve("customOutputDirectory"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,13 @@ private fun TestDokkaSourceSet.toDokkaSourceSet(relativeToDir: File): DokkaConfi
override val apiVersion: String?
get() = apiVersion

override fun equals(other: Any?): Boolean {
return sourceSetID == (other as? DokkaConfiguration.DokkaSourceSet)?.sourceSetID
}

override fun hashCode(): Int {
return sourceSetID.hashCode()
}

/*
* The properties below are not used by the analysis modules,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ dependencies {

testImplementation(kotlin("test"))
testImplementation(projects.dokkaSubprojects.coreContentMatcherTestUtils)
testImplementation(projects.dokkaSubprojects.coreTestApi)
testImplementation(projects.dokkaSubprojects.dokkaTestApi)
testImplementation(projects.dokkaSubprojects.analysisKotlinApi)

// TODO [beresnev] get rid of it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ plugins {
}

dependencies {
implementation(projects.dokkaSubprojects.coreTestApi)
implementation(projects.dokkaSubprojects.dokkaTestApi)

implementation(kotlin("reflect"))
implementation(kotlin("test"))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
public final class org/jetbrains/dokka/testApi/ConfigurationKt {
public static final fun assertDokkaConfigurationEquals (Lorg/jetbrains/dokka/DokkaConfiguration;Lorg/jetbrains/dokka/DokkaConfiguration;)V
public static final fun assertDokkaSourceSetEquals (Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;)V
}

public final class org/jetbrains/dokka/testApi/context/MockContext : org/jetbrains/dokka/plugability/DokkaContext {
public fun <init> ([Lkotlin/Pair;Lorg/jetbrains/dokka/DokkaConfiguration;Ljava/util/List;)V
public synthetic fun <init> ([Lkotlin/Pair;Lorg/jetbrains/dokka/DokkaConfiguration;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
Expand Down
3 changes: 3 additions & 0 deletions dokka-subprojects/core-test-api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ overridePublicationArtifactId("dokka-test-api")

dependencies {
api(projects.dokkaSubprojects.dokkaCore)
// for assertions over `DokkaConfiguration/DokkaSourceSet`
// it's compileOnly, so it should be able to handle both `junit` and `junit5`
compileOnly(kotlin("test"))

implementation(kotlin("reflect"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright 2014-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

package org.jetbrains.dokka.testApi

import org.jetbrains.dokka.DokkaConfiguration
import kotlin.test.assertEquals

public fun assertDokkaConfigurationEquals(
expected: DokkaConfiguration,
actual: DokkaConfiguration
) {
assertEquals(expected.moduleName, actual.moduleName, "DokkaConfiguration.moduleName")
assertEquals(expected.moduleVersion, actual.moduleVersion, "DokkaConfiguration.moduleVersion")
assertEquals(expected.outputDir, actual.outputDir, "DokkaConfiguration.outputDir")
assertEquals(expected.cacheRoot, actual.cacheRoot, "DokkaConfiguration.cacheRoot")
assertEquals(expected.offlineMode, actual.offlineMode, "DokkaConfiguration.offlineMode")
assertEquals(expected.pluginsClasspath, actual.pluginsClasspath, "DokkaConfiguration.pluginsClasspath")
assertEquals(expected.pluginsConfiguration, actual.pluginsConfiguration, "DokkaConfiguration.pluginsConfiguration")
assertEquals(expected.modules, actual.modules, "DokkaConfiguration.modules")
assertEquals(expected.failOnWarning, actual.failOnWarning, "DokkaConfiguration.failOnWarning")
assertEquals(
expected.delayTemplateSubstitution,
actual.delayTemplateSubstitution,
"DokkaConfiguration.delayTemplateSubstitution"
)
assertEquals(
expected.suppressObviousFunctions,
actual.suppressObviousFunctions,
"DokkaConfiguration.suppressObviousFunctions"
)
assertEquals(expected.includes, actual.includes, "DokkaConfiguration.includes")
assertEquals(
expected.suppressInheritedMembers,
actual.suppressInheritedMembers,
"DokkaConfiguration.suppressInheritedMembers"
)
assertEquals(expected.finalizeCoroutines, actual.finalizeCoroutines, "DokkaConfiguration.finalizeCoroutines")

assertEquals(expected.sourceSets.size, actual.sourceSets.size, "DokkaConfiguration.sourceSets.size")
expected.sourceSets.zip(actual.sourceSets) { expectedSourceSet, actualSourceSet ->
assertDokkaSourceSetEquals(expectedSourceSet, actualSourceSet)
}
}

public fun assertDokkaSourceSetEquals(
expected: DokkaConfiguration.DokkaSourceSet,
actual: DokkaConfiguration.DokkaSourceSet
) {
assertEquals(expected.sourceSetID, actual.sourceSetID, "DokkaSourceSet.sourceSetID")
assertEquals(expected.displayName, actual.displayName, "DokkaSourceSet.displayName")
assertEquals(expected.classpath, actual.classpath, "DokkaSourceSet.classpath")
assertEquals(expected.sourceRoots, actual.sourceRoots, "DokkaSourceSet.sourceRoots")
assertEquals(expected.dependentSourceSets, actual.dependentSourceSets, "DokkaSourceSet.dependentSourceSets")
assertEquals(expected.samples, actual.samples, "DokkaSourceSet.samples")
assertEquals(expected.includes, actual.includes, "DokkaSourceSet.includes")
@Suppress("DEPRECATION")
assertEquals(expected.includeNonPublic, actual.includeNonPublic, "DokkaSourceSet.includeNonPublic")
assertEquals(expected.reportUndocumented, actual.reportUndocumented, "DokkaSourceSet.reportUndocumented")
assertEquals(expected.skipEmptyPackages, actual.skipEmptyPackages, "DokkaSourceSet.skipEmptyPackages")
assertEquals(expected.skipDeprecated, actual.skipDeprecated, "DokkaSourceSet.skipDeprecated")
assertEquals(expected.jdkVersion, actual.jdkVersion, "DokkaSourceSet.jdkVersion")
assertEquals(expected.sourceLinks, actual.sourceLinks, "DokkaSourceSet.sourceLinks")
assertEquals(expected.perPackageOptions, actual.perPackageOptions, "DokkaSourceSet.perPackageOptions")
assertEquals(
expected.externalDocumentationLinks,
actual.externalDocumentationLinks,
"DokkaSourceSet.externalDocumentationLinks"
)
assertEquals(expected.languageVersion, actual.languageVersion, "DokkaSourceSet.languageVersion")
assertEquals(expected.apiVersion, actual.apiVersion, "DokkaSourceSet.apiVersion")
assertEquals(expected.noStdlibLink, actual.noStdlibLink, "DokkaSourceSet.noStdlibLink")
assertEquals(expected.noJdkLink, actual.noJdkLink, "DokkaSourceSet.noJdkLink")
assertEquals(expected.suppressedFiles, actual.suppressedFiles, "DokkaSourceSet.suppressedFiles")
assertEquals(expected.analysisPlatform, actual.analysisPlatform, "DokkaSourceSet.analysisPlatform")
assertEquals(
expected.documentedVisibilities,
actual.documentedVisibilities,
"DokkaSourceSet.documentedVisibilities"
)
}
2 changes: 1 addition & 1 deletion dokka-subprojects/core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ dependencies {
}

testImplementation(kotlin("test"))
testImplementation(projects.dokkaSubprojects.coreTestApi)
testImplementation(projects.dokkaSubprojects.dokkaTestApi)
}

tasks.processResources {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,18 @@ public fun interface DokkaConfigurationBuilder<T : Any> {

public fun <T : Any> Iterable<DokkaConfigurationBuilder<T>>.build(): List<T> = this.map { it.build() }

/**
* Represents a unique identifier for a [DokkaConfiguration.DokkaSourceSet].
* It should be unique across the whole project.
*
* @property scopeId The unique identifier of the scope that this source set is placed in.
* Each scope provides only unique source set names.
* E.g. One DokkaTask inside the Gradle plugin represents one source set scope, since there cannot be multiple
* source sets with the same name. However, a Gradle project will not be a proper scope, since there can be
* multiple DokkaTasks that contain source sets with the same name (but different configuration)
* @property sourceSetName The name of the source set.
*/
public data class DokkaSourceSetID(
/**
* Unique identifier of the scope that this source set is placed in.
* Each scope provide only unique source set names.
*
* E.g. One DokkaTask inside the Gradle plugin represents one source set scope, since there cannot be multiple
* source sets with the same name. However, a Gradle project will not be a proper scope, since there can be
* multple DokkaTasks that contain source sets with the same name (but different configuration)
*/
val scopeId: String,
val sourceSetName: String
) : Serializable {
Expand Down Expand Up @@ -170,6 +173,13 @@ public interface DokkaConfiguration : Serializable {
public val values: String
}

/**
* Each [DokkaSourceSet] is uniquely identified by its [sourceSetID].
* This means that if two [DokkaSourceSet]s will have the same [sourceSetID] they will be interchangeable.
* [equals] and [hashCode] must be defined only based on [sourceSetID].
*
* **See Also:** [Dokka#3246](https://github.com/Kotlin/dokka/issues/3246)
*/
public interface DokkaSourceSet : Serializable {
public val sourceSetID: DokkaSourceSetID
public val displayName: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,15 @@ public data class DokkaSourceSetImpl(
override val suppressedFiles: Set<File> = emptySet(),
override val analysisPlatform: Platform = DokkaDefaults.analysisPlatform,
override val documentedVisibilities: Set<DokkaConfiguration.Visibility> = DokkaDefaults.documentedVisibilities,
) : DokkaSourceSet
) : DokkaSourceSet {
override fun equals(other: Any?): Boolean {
return sourceSetID == (other as? DokkaSourceSet)?.sourceSetID
}

override fun hashCode(): Int {
return sourceSetID.hashCode()
}
}

public data class DokkaModuleDescriptionImpl(
override val name: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ package utilities
import org.jetbrains.dokka.DokkaConfigurationImpl
import org.jetbrains.dokka.DokkaSourceSetID
import org.jetbrains.dokka.DokkaSourceSetImpl
import org.jetbrains.dokka.testApi.assertDokkaConfigurationEquals
import org.jetbrains.dokka.toCompactJsonString
import java.io.File
import kotlin.test.Test
import kotlin.test.assertEquals

class DokkaConfigurationJsonTest {
@Test
Expand All @@ -29,7 +29,7 @@ class DokkaConfigurationJsonTest {

val jsonString = configuration.toCompactJsonString()
val parsedConfiguration = DokkaConfigurationImpl(jsonString)
assertEquals(configuration, parsedConfiguration)
assertDokkaConfigurationEquals(configuration, parsedConfiguration)
}

@Test
Expand All @@ -53,7 +53,7 @@ class DokkaConfigurationJsonTest {
""".trimIndent()

val parsedConfiguration = DokkaConfigurationImpl(json)
assertEquals(
assertDokkaConfigurationEquals(
DokkaConfigurationImpl(
moduleName = "moduleName",
outputDir = File("customOutputDir"),
Expand All @@ -66,7 +66,7 @@ class DokkaConfigurationJsonTest {
)
)
),
parsedConfiguration
parsedConfiguration,
)
}
}
2 changes: 1 addition & 1 deletion dokka-subprojects/plugin-all-modules-page/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@ dependencies {
testImplementation(projects.dokkaSubprojects.pluginGfm)
testImplementation(projects.dokkaSubprojects.pluginGfmTemplateProcessing)
testImplementation(projects.dokkaSubprojects.coreContentMatcherTestUtils)
testImplementation(projects.dokkaSubprojects.coreTestApi)
testImplementation(projects.dokkaSubprojects.dokkaTestApi)
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ dependencies {

testImplementation(kotlin("test"))
testImplementation(projects.dokkaSubprojects.pluginBase)
testImplementation(projects.dokkaSubprojects.coreTestApi)
testImplementation(projects.dokkaSubprojects.dokkaTestApi)

symbolsTestImplementation(project(path = ":dokka-subprojects:analysis-kotlin-symbols", configuration = "shadow"))
descriptorsTestImplementation(project(path = ":dokka-subprojects:analysis-kotlin-descriptors", configuration = "shadow"))
Expand Down
4 changes: 2 additions & 2 deletions dokka-subprojects/plugin-base-test-utils/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ dependencies {
implementation(libs.jsoup)

implementation(kotlin("test"))
implementation(projects.dokkaSubprojects.coreTestApi)
implementation(projects.dokkaSubprojects.dokkaTestApi)

testImplementation(kotlin("test"))
testImplementation(projects.dokkaSubprojects.coreTestApi)
testImplementation(projects.dokkaSubprojects.dokkaTestApi)
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ public class BaseDokkaTestGenerator(

val singleModuleGeneration = context.single(CoreExtensions.generation) as SingleModuleGeneration

verificationStage { singleModuleGeneration.validityCheck(context) }

val modulesFromPlatforms = singleModuleGeneration.createDocumentationModels()
documentablesCreationStage(modulesFromPlatforms)

verificationStage { singleModuleGeneration.validityCheck(context) }

val filteredModules = singleModuleGeneration.transformDocumentationModelBeforeMerge(modulesFromPlatforms)
documentablesFirstTransformationStep(filteredModules)

Expand Down Expand Up @@ -91,7 +91,7 @@ public data class BaseTestMethods(

public class BaseTestBuilder : TestBuilder<BaseTestMethods>() {
public var pluginsSetupStage: (DokkaContext) -> Unit = {}
public var verificationStage: (() -> Unit) -> Unit = {}
public var verificationStage: (() -> Unit) -> Unit = { it() }
public var documentablesCreationStage: (List<DModule>) -> Unit = {}
public var preMergeDocumentablesTransformationStage: (List<DModule>) -> Unit = {}
public var documentablesMergingStage: (DModule) -> Unit = {}
Expand Down
2 changes: 1 addition & 1 deletion dokka-subprojects/plugin-base/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ dependencies {
exclude(module = "analysis-kotlin-descriptors")
}
testImplementation(projects.dokkaSubprojects.coreContentMatcherTestUtils)
testImplementation(projects.dokkaSubprojects.coreTestApi)
testImplementation(projects.dokkaSubprojects.dokkaTestApi)
testImplementation(projects.dokkaSubprojects.analysisKotlinApi)

dokkaHtmlFrontendFiles(projects.dokkaSubprojects.pluginBaseFrontend) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package org.jetbrains.dokka.base

import org.jetbrains.dokka.CoreExtensions
import org.jetbrains.dokka.base.generation.SingleModuleGeneration
import org.jetbrains.dokka.base.generation.SourceSetIdUniquenessChecker
import org.jetbrains.dokka.base.renderers.*
import org.jetbrains.dokka.base.renderers.html.*
import org.jetbrains.dokka.base.renderers.html.command.consumers.PathToRootConsumer
Expand Down Expand Up @@ -262,6 +263,10 @@ public class DokkaBase : DokkaPlugin() {
htmlPreprocessors providing ::SearchbarDataInstaller order { after(sourceLinksTransformer) }
}

internal val sourceSetIdUniquenessChecker by extending {
CoreExtensions.preGenerationCheck providing ::SourceSetIdUniquenessChecker
}

//<editor-fold desc="Deprecated API left for compatibility">
@Suppress("DEPRECATION_ERROR")
@Deprecated(message = org.jetbrains.dokka.base.deprecated.ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
Expand Down
Loading

0 comments on commit f524273

Please sign in to comment.