diff options
12 files changed, 866 insertions, 56 deletions
diff --git a/.run/it-android-0_dokka.run.xml b/.run/it-android-0_dokka.run.xml index 514177ed..305ad77e 100644 --- a/.run/it-android-0_dokka.run.xml +++ b/.run/it-android-0_dokka.run.xml @@ -1,10 +1,10 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="it-android-0:dokkaHtml" type="GradleRunConfiguration" factoryName="Gradle" folderName="sample-projects"> + <configuration default="false" name="it-android-0:dokka" type="GradleRunConfiguration" factoryName="Gradle" folderName="sample-projects"> <ExternalSystemSettings> <option name="executionName" /> <option name="externalProjectPath" value="$PROJECT_DIR$/integration-tests/gradle/projects/it-android-0" /> <option name="externalSystemIdString" value="GRADLE" /> - <option name="scriptParameters" value="--stacktrace -i" /> + <option name="scriptParameters" value="" /> <option name="taskDescriptions"> <list /> </option> diff --git a/core/src/main/kotlin/configuration.kt b/core/src/main/kotlin/configuration.kt index fbe7ccfc..0c877bd4 100644 --- a/core/src/main/kotlin/configuration.kt +++ b/core/src/main/kotlin/configuration.kt @@ -44,6 +44,8 @@ enum class Platform(val key: String) { js.key -> js native.key -> native common.key -> common + "androidjvm", "android" -> jvm + "metadata" -> common else -> throw IllegalArgumentException("Unrecognized platform: $key") } } @@ -129,6 +131,7 @@ interface DokkaConfiguration : Serializable { interface ExternalDocumentationLink : Serializable { val url: URL val packageListUrl: URL + companion object } } diff --git a/integration-tests/gradle/projects/it-basic-groovy/build.gradle b/integration-tests/gradle/projects/it-basic-groovy/build.gradle index 5c6104d5..df2e8624 100644 --- a/integration-tests/gradle/projects/it-basic-groovy/build.gradle +++ b/integration-tests/gradle/projects/it-basic-groovy/build.gradle @@ -17,8 +17,6 @@ dokkaHtml { customSourceSet { sourceRoot(file("src/main/java")) sourceRoot(file("src/main/kotlin")) - - // TODO NOW: Can we get rid of this .set here? displayName.set("custom") reportUndocumented.set(true) } diff --git a/runners/gradle-plugin/build.gradle.kts b/runners/gradle-plugin/build.gradle.kts index 340334b7..398f4abc 100644 --- a/runners/gradle-plugin/build.gradle.kts +++ b/runners/gradle-plugin/build.gradle.kts @@ -23,6 +23,8 @@ dependencies { testImplementation(gradleKotlinDsl()) testImplementation(kotlin("test-junit")) testImplementation("org.jetbrains.kotlin:kotlin-gradle-plugin") + testImplementation("com.android.tools.build:gradle:3.0.0") + constraints { val kotlin_version: String by project diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilder.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilder.kt index 8f0a166b..59c5e9f8 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilder.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilder.kt @@ -13,20 +13,17 @@ import org.gradle.api.provider.Property import org.gradle.api.provider.SetProperty import org.gradle.api.tasks.* import org.gradle.kotlin.dsl.listProperty -import org.gradle.kotlin.dsl.property import org.gradle.kotlin.dsl.setProperty import org.gradle.util.ConfigureUtil import org.jetbrains.dokka.* import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import java.io.File import java.net.URL -import org.jetbrains.kotlin.gradle.model.SourceSet as KotlinModelSourceSet internal fun Task.GradleDokkaSourceSetBuilderFactory(): (name: String) -> GradleDokkaSourceSetBuilder = { name -> GradleDokkaSourceSetBuilder(name, project) } -// TODO NOW: Cover with tests open class GradleDokkaSourceSetBuilder constructor( @Transient @get:Input val name: String, @Transient @get:Internal internal val project: Project @@ -98,34 +95,31 @@ open class GradleDokkaSourceSetBuilder constructor( @Input @Optional - val languageVersion: Property<String?> = project.objects.safeProperty<String>() + val languageVersion: Property<String?> = project.objects.safeProperty() @Input @Optional val apiVersion: Property<String?> = project.objects.safeProperty() @Input - val noStdlibLink: Property<Boolean> = project.objects.property<Boolean>() - .convention(DokkaDefaults.noStdlibLink) + val noStdlibLink: Property<Boolean> = project.objects.safeProperty<Boolean>() + .safeConvention(DokkaDefaults.noStdlibLink) @Input - val noJdkLink: Property<Boolean> = project.objects.property<Boolean>() - .convention(DokkaDefaults.noJdkLink) + val noJdkLink: Property<Boolean> = project.objects.safeProperty<Boolean>() + .safeConvention(DokkaDefaults.noJdkLink) @Input - val noAndroidSdkLink: Property<Boolean> = project.objects.property<Boolean>() - .convention(false) + val noAndroidSdkLink: Property<Boolean> = project.objects.safeProperty<Boolean>() + .safeConvention(false) @InputFiles val suppressedFiles: ConfigurableFileCollection = project.files() @Input @Optional - val analysisPlatform: Property<Platform?> = project.objects.safeProperty() - - @Input - @Optional - val platform: Property<String?> = project.objects.safeProperty() + val platform: Property<Platform> = project.objects.safeProperty<Platform>() + .safeConvention(Platform.DEFAULT) fun DokkaSourceSetID(sourceSetName: String): DokkaSourceSetID { return DokkaSourceSetID(project, sourceSetName) @@ -163,7 +157,7 @@ open class GradleDokkaSourceSetBuilder constructor( sourceRoot(project.file(path)) } - fun sourceLink(c: Closure<Unit>) { + fun sourceLink(c: Closure<in GradleSourceLinkBuilder>) { val configured = ConfigureUtil.configure(c, GradleSourceLinkBuilder(project)) sourceLinks.add(configured) } @@ -174,7 +168,7 @@ open class GradleDokkaSourceSetBuilder constructor( sourceLinks.add(sourceLink) } - fun perPackageOption(c: Closure<Unit>) { + fun perPackageOption(c: Closure<in GradlePackageOptionsBuilder>) { val configured = ConfigureUtil.configure(c, GradlePackageOptionsBuilder(project)) perPackageOptions.add(configured) } @@ -185,7 +179,7 @@ open class GradleDokkaSourceSetBuilder constructor( perPackageOptions.add(option) } - fun externalDocumentationLink(c: Closure<Unit>) { + fun externalDocumentationLink(c: Closure<in GradleExternalDocumentationLinkBuilder>) { val link = ConfigureUtil.configure(c, GradleExternalDocumentationLinkBuilder(project)) externalDocumentationLinks.add(link) } @@ -197,12 +191,7 @@ open class GradleDokkaSourceSetBuilder constructor( } fun externalDocumentationLink(url: String, packageListUrl: String? = null) { - externalDocumentationLinks.add( - GradleExternalDocumentationLinkBuilder(project).apply { - this.url by URL(url) - this.packageListUrl by URL(packageListUrl) - } - ) + externalDocumentationLink(URL(url), packageListUrl = packageListUrl?.let(::URL)) } fun externalDocumentationLink(url: URL, packageListUrl: URL? = null) { @@ -221,9 +210,6 @@ open class GradleDokkaSourceSetBuilder constructor( } } -fun GradleDokkaSourceSetBuilder.dependsOn(sourceSet: KotlinModelSourceSet) { - dependsOn(DokkaSourceSetID(sourceSet.name)) -} fun GradleDokkaSourceSetBuilder.dependsOn(sourceSet: KotlinSourceSet) { dependsOn(DokkaSourceSetID(sourceSet.name)) diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/KotlinSourceSetGist.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/KotlinSourceSetGist.kt index 86551153..f889b5e8 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/KotlinSourceSetGist.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/KotlinSourceSetGist.kt @@ -6,8 +6,6 @@ import org.gradle.api.provider.Provider import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet -// TODO NOW: Test this all - internal data class KotlinSourceSetGist( val name: String, val platform: KotlinPlatformType, @@ -22,7 +20,7 @@ internal fun Project.gistOf(sourceSet: KotlinSourceSet): KotlinSourceSetGist { name = sourceSet.name, platform = platformOf(sourceSet), isMain = isMainSourceSet(sourceSet), - classpath = classpathOf(sourceSet), + classpath = classpathOf(sourceSet).filter { it.exists() }, // TODO: Needs to respect filters. // We probably need to change from "sourceRoots" to support "sourceFiles" // https://github.com/Kotlin/dokka/issues/1215 diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/kotlinCompilationUtils.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/kotlinCompilationUtils.kt index 4de499e9..8fec309a 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/kotlinCompilationUtils.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/kotlinCompilationUtils.kt @@ -20,7 +20,6 @@ internal fun Project.allCompilationsOf( } } -// TODO NOW: Better name, clarify distinction to allCompilationsOf internal fun Project.compilationsOf(sourceSet: KotlinSourceSet): List<KotlinCompilation> { return allCompilationsOf(sourceSet).filter { compilation -> sourceSet in compilation.kotlinSourceSets } } diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/sourceSetKotlinGistConfiguration.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/sourceSetKotlinGistConfiguration.kt index 409f645f..3162b614 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/sourceSetKotlinGistConfiguration.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/sourceSetKotlinGistConfiguration.kt @@ -1,15 +1,16 @@ +@file:Suppress("UnstableApiUsage") + package org.jetbrains.dokka.gradle +import org.jetbrains.dokka.Platform import org.jetbrains.dokka.gradle.kotlin.KotlinSourceSetGist import org.jetbrains.dokka.gradle.kotlin.gistOf import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet -// TODO NOW: Test fun GradleDokkaSourceSetBuilder.configureWithKotlinSourceSet(sourceSet: KotlinSourceSet) { configureWithKotlinSourceSetGist(project.gistOf(sourceSet)) } -// TODO NOW: What about language version? internal fun GradleDokkaSourceSetBuilder.configureWithKotlinSourceSetGist(sourceSet: KotlinSourceSetGist) { val dependentSourceSetIds = sourceSet.dependentSourceSetNames.map { sourceSetNames -> sourceSetNames.map { sourceSetName -> DokkaSourceSetID(sourceSetName) } @@ -17,8 +18,11 @@ internal fun GradleDokkaSourceSetBuilder.configureWithKotlinSourceSetGist(source this.sourceRoots.from(sourceSet.sourceRoots) this.classpath.from(sourceSet.classpath) - this.platform by sourceSet.platform.name + this.platform by Platform.fromString(sourceSet.platform.name) this.dependentSourceSets.set(dependentSourceSetIds) + this.displayName by sourceSet.name.substringBeforeLast( + delimiter = "Main", + missingDelimiterValue = sourceSet.platform.name + ) } - diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/toDokkaSourceSetImpl.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/toDokkaSourceSetImpl.kt index 766f7e55..64d44157 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/toDokkaSourceSetImpl.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/toDokkaSourceSetImpl.kt @@ -3,9 +3,7 @@ package org.jetbrains.dokka.gradle import org.jetbrains.dokka.* import org.jetbrains.dokka.DokkaConfiguration.ExternalDocumentationLink import java.io.File -import java.net.URL -// TODO NOW: Test internal fun GradleDokkaSourceSetBuilder.toDokkaSourceSetImpl(): DokkaSourceSetImpl { return DokkaSourceSetImpl( classpath = classpath.toSet(), @@ -29,7 +27,7 @@ internal fun GradleDokkaSourceSetBuilder.toDokkaSourceSetImpl(): DokkaSourceSetI noStdlibLink = noStdlibLink.getSafe(), noJdkLink = noJdkLink.getSafe(), suppressedFiles = suppressedFilesWithDefaults(), - analysisPlatform = analysisPlatformOrDefault() + analysisPlatform = platform.getSafe() ) } @@ -38,7 +36,12 @@ private fun GradleDokkaSourceSetBuilder.moduleNameOrDefault(): String { } private fun GradleDokkaSourceSetBuilder.displayNameOrDefault(): String { - return displayName.getSafe() ?: name.substringBeforeLast("Main", platform.getSafe().toString()) + displayName.getSafe()?.let { return it } + if (name.endsWith("Main") && name != "Main") { + return name.removeSuffix("Main") + } + + return name } private fun GradleDokkaSourceSetBuilder.externalDocumentationLinksWithDefaults(): Set<ExternalDocumentationLinkImpl> { @@ -60,19 +63,6 @@ private fun GradleDokkaSourceSetBuilder.externalDocumentationLinksWithDefaults() .toSet() } -private fun GradleDokkaSourceSetBuilder.analysisPlatformOrDefault(): Platform { - val analysisPlatform = analysisPlatform.getSafe() - if (analysisPlatform != null) return analysisPlatform - - platform.getSafe()?.let { platform -> - return when (platform.toLowerCase()) { - "androidjvm", "android" -> Platform.jvm - "metadata" -> Platform.common - else -> Platform.fromString(platform) - } - } - return Platform.DEFAULT -} private fun GradleDokkaSourceSetBuilder.suppressedFilesWithDefaults(): Set<File> { val suppressedFilesForAndroid = if (project.isAndroidProject()) { diff --git a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/ConfigureWithKotlinSourceSetGistTest.kt b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/ConfigureWithKotlinSourceSetGistTest.kt new file mode 100644 index 00000000..d8545ab3 --- /dev/null +++ b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/ConfigureWithKotlinSourceSetGistTest.kt @@ -0,0 +1,123 @@ +package org.jetbrains.dokka.gradle + +import org.gradle.api.artifacts.FileCollectionDependency +import org.gradle.kotlin.dsl.get +import org.gradle.testfixtures.ProjectBuilder +import org.jetbrains.dokka.Platform +import org.jetbrains.dokka.gradle.kotlin.KotlinSourceSetGist +import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension +import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType +import kotlin.test.Test +import kotlin.test.assertEquals + +class ConfigureWithKotlinSourceSetGistTest { + @Test + fun `example gist`() { + val project = ProjectBuilder.builder().build() + + val f1Jar = project.file("f1.jar") + val f2Jar = project.file("f2.jar") + check(f1Jar.createNewFile()) + check(f2Jar.createNewFile()) + + val customSourceRoot = project.file("customSourceRoot") + check(customSourceRoot.mkdirs()) + + val gist = KotlinSourceSetGist( + name = "customName", + platform = KotlinPlatformType.common, + isMain = true, + classpath = project.files(f1Jar, f2Jar), + sourceRoots = project.files(customSourceRoot), + dependentSourceSetNames = project.provider { setOf("customRootSourceSet") } + ) + + val sourceSet = GradleDokkaSourceSetBuilder("", project) + sourceSet.configureWithKotlinSourceSetGist(gist) + + assertEquals( + "common", sourceSet.build().displayName, + "Expected platform being used as default displayName for source set" + ) + + assertEquals( + Platform.common, sourceSet.build().analysisPlatform, + "Expected common platform being set" + ) + + assertEquals( + setOf(f1Jar, f2Jar), sourceSet.build().classpath, + "Expected classpath being present" + ) + + assertEquals( + setOf(sourceSet.DokkaSourceSetID("customRootSourceSet")), sourceSet.build().dependentSourceSets, + "Expected customRootSourceSet being present in dependentSourceSets after build" + ) + + assertEquals( + setOf(customSourceRoot), sourceSet.build().sourceRoots, + "Expected customSourceRoot being present in sourceRoots after build" + ) + } + + @Test + fun `display name for source set customMain`() { + val project = ProjectBuilder.builder().build() + + val gist = KotlinSourceSetGist( + name = "customMain", + platform = KotlinPlatformType.common, + isMain = true, + classpath = project.files(), + sourceRoots = project.files(), + dependentSourceSetNames = project.provider { emptySet() } + ) + + val sourceSet = GradleDokkaSourceSetBuilder("", project) + sourceSet.configureWithKotlinSourceSetGist(gist) + + assertEquals( + "custom", sourceSet.build().displayName, + "Expected 'Main' being trimmed from source set name and used as display name" + ) + } + + @Suppress("UnstableApiUsage") + @Test + fun `configuration with kotlin source set is live`() { + val project = ProjectBuilder.builder().build() + project.plugins.apply("org.jetbrains.kotlin.jvm") + val kotlin = project.kotlin as KotlinJvmProjectExtension + val mainSourceSet = kotlin.sourceSets["main"] + + /* Make sure that the source roots exist on filesystem */ + mainSourceSet.kotlin.sourceDirectories.elements.get().map { it.asFile }.forEach { it.mkdirs() } + + /* Make sure to remove dependencies that cannot be resolved during test */ + project.configurations.configureEach { configuration -> + configuration.withDependencies { dependencies -> + dependencies.removeIf { dependency -> dependency !is FileCollectionDependency } + } + } + + val dokkaSourceSet = GradleDokkaSourceSetBuilder("main", project) + dokkaSourceSet.kotlinSourceSet(mainSourceSet) + + assertEquals( + listOf(project.file("src/main/kotlin"), project.file("src/main/java")), + dokkaSourceSet.sourceRoots.elements.get().map { it.asFile }, + "Expected default source roots being present in dokkaSourceSet" + ) + + val customSourceRoot = project.file("src/main/customRoot") + check(customSourceRoot.mkdirs()) + mainSourceSet.kotlin.srcDir(customSourceRoot) + + assertEquals( + listOf(project.file("src/main/kotlin"), project.file("src/main/java"), project.file("src/main/customRoot")), + dokkaSourceSet.sourceRoots.elements.get().map { it.asFile }, + "Expected customRoot being added to source roots in dokkaSourceSet" + ) + } +} diff --git a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilderTest.kt b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilderTest.kt new file mode 100644 index 00000000..26d02fe0 --- /dev/null +++ b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilderTest.kt @@ -0,0 +1,458 @@ +package org.jetbrains.dokka.gradle + +import com.android.build.gradle.internal.api.DefaultAndroidSourceSet +import org.gradle.kotlin.dsl.closureOf +import org.gradle.testfixtures.ProjectBuilder +import org.jetbrains.dokka.* +import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet +import java.net.URL +import kotlin.test.* + +class GradleDokkaSourceSetBuilderTest { + + + private val project = ProjectBuilder.builder().withName("root").build() + + @Test + fun sourceSetId() { + val sourceSet = GradleDokkaSourceSetBuilder("myName", project) + assertEquals( + DokkaSourceSetID(project, "myName"), sourceSet.sourceSetID, + "Expected sourceSet.sourceSetID to match output of DokkaSourceSetID factory function" + ) + + assertEquals( + ":/myName", sourceSet.sourceSetID.toString(), + "Expected SourceSetId's string representation" + ) + } + + @Test + fun classpath() { + val sourceSet = GradleDokkaSourceSetBuilder("", project) + sourceSet.classpath.from(project.file("path/to/file.jar")) + sourceSet.classpath.from(project.file("path/to/other.jar")) + + assertEquals( + listOf(project.file("path/to/file.jar"), project.file("path/to/other.jar")), sourceSet.classpath.toList(), + "Expected both file paths being present in classpath" + ) + + assertEquals( + listOf(project.file("path/to/file.jar"), project.file("path/to/other.jar")), + sourceSet.build().classpath.toList(), + "Expected both file paths being present in built classpath" + ) + } + + @Test + fun moduleDisplayName() { + val sourceSet = GradleDokkaSourceSetBuilder("myName", project) + + assertNull( + sourceSet.moduleDisplayName.getSafe(), + "Expected no ${GradleDokkaSourceSetBuilder::moduleDisplayName.name} being set by default" + ) + + assertEquals( + "root", sourceSet.build().moduleDisplayName, + "Expected project name being used for ${DokkaConfiguration.DokkaSourceSet::moduleDisplayName.name} " + + "after building source set with no ${GradleDokkaSourceSetBuilder::moduleDisplayName.name} being set" + ) + + sourceSet.moduleDisplayName by "displayName" + + assertEquals( + "displayName", sourceSet.build().moduleDisplayName, + "Expected previously set ${GradleDokkaSourceSetBuilder::displayName.name} to be present after build" + ) + } + + @Test + fun displayName() { + val sourceSet = GradleDokkaSourceSetBuilder("myName", project) + assertNull( + sourceSet.displayName.getSafe(), + "Expected no ${GradleDokkaSourceSetBuilder::displayName.name} being set by default" + ) + + assertEquals( + "myName", sourceSet.build().displayName, + "Expected source set name being used for ${DokkaConfiguration.DokkaSourceSet::displayName.name} " + + "after building source set with no ${GradleDokkaSourceSetBuilder::displayName.name} being set" + ) + + sourceSet.displayName by "displayName" + + assertEquals( + "displayName", sourceSet.build().displayName, + "Expected previously set ${GradleDokkaSourceSetBuilder::displayName.name} to be present after build" + ) + } + + @Test + fun `displayName default for sourceSet ending with Main`() { + val sourceSet = GradleDokkaSourceSetBuilder("jvmMain", project) + assertEquals( + "jvm", sourceSet.build().displayName, + "Expected 'Main' being stripped for source set display name after build" + ) + } + + @Test + fun sourceRoots() { + val sourceSet = GradleDokkaSourceSetBuilder("", project) + sourceSet.sourceRoots.from(project.file("root1")) + sourceSet.sourceRoot(project.file("root2")) + sourceSet.sourceRoot(project.file("root3").absolutePath) + sourceSet.sourceRoot("root4") + + assertEquals( + listOf("root1", "root2", "root3", "root4").map(project::file).toSet(), + sourceSet.build().sourceRoots, + "Expected all files being present" + ) + + sourceSet.build().sourceRoots.forEach { root -> + assertTrue( + root.startsWith(project.projectDir), + "Expected all roots to be inside the projectDir\n" + + "projectDir: ${project.projectDir}\n" + + "root: ${root.absolutePath})" + ) + } + } + + @Test + fun dependentSourceSets() { + val sourceSet = GradleDokkaSourceSetBuilder("", project) + assertEquals(emptySet(), sourceSet.build().dependentSourceSets, "Expected no dependent sourceSets by default") + + sourceSet.dependentSourceSets.add(DokkaSourceSetID(project, "s1")) + sourceSet.dependsOn("s2") + sourceSet.dependsOn(DokkaSourceSetID(project, "s3")) + sourceSet.dependsOn(GradleDokkaSourceSetBuilder("s4", project)) + sourceSet.dependsOn(GradleDokkaSourceSetBuilder("s5", project).build()) + sourceSet.dependsOn(DefaultKotlinSourceSet(project, "s6")) + sourceSet.dependsOn(DefaultAndroidSourceSet("s7", project, false)) + + assertEquals( + listOf(":/s1", ":/s2", ":/s3", ":/s4", ":/s5", ":/s6", ":/s7"), + sourceSet.build().dependentSourceSets.map { it.toString() }, + "Expected all source sets being registered" + ) + } + + @Test + fun samples() { + val sourceSet = GradleDokkaSourceSetBuilder("", project) + assertEquals(emptySet(), sourceSet.build().samples, "Expected no default samples") + sourceSet.samples.from(project.file("s1")) + sourceSet.samples.from(project.file("s2")) + assertEquals( + setOf(project.file("s1"), project.file("s2")), sourceSet.build().samples, + "Expected all samples being present after build" + ) + } + + @Test + fun includes() { + val sourceSet = GradleDokkaSourceSetBuilder("", project) + assertEquals(emptySet(), sourceSet.build().includes, "Expected no default includees") + sourceSet.includes.from(project.file("i1")) + sourceSet.includes.from(project.file("i2")) + assertEquals( + setOf(project.file("i1"), project.file("i2")), sourceSet.build().includes, + "Expected all includes being present after build" + ) + } + + @Test + fun includeNonPublic() { + val sourceSet = GradleDokkaSourceSetBuilder("", project) + assertEquals( + DokkaDefaults.includeNonPublic, sourceSet.build().includeNonPublic, + "Expected default value for ${GradleDokkaSourceSetBuilder::includeNonPublic.name}" + ) + + sourceSet.includeNonPublic.set(!DokkaDefaults.includeNonPublic) + assertEquals( + !DokkaDefaults.includeNonPublic, sourceSet.build().includeNonPublic, + "Expected flipped value for ${GradleDokkaSourceSetBuilder::includeNonPublic.name}" + ) + } + + @Test + fun reportUndocumented() { + val sourceSet = GradleDokkaSourceSetBuilder("", project) + assertEquals( + DokkaDefaults.reportUndocumented, sourceSet.build().reportUndocumented, + "Expected default value for ${GradleDokkaSourceSetBuilder::reportUndocumented.name}" + ) + + sourceSet.reportUndocumented.set(!DokkaDefaults.reportUndocumented) + assertEquals( + !DokkaDefaults.reportUndocumented, sourceSet.build().reportUndocumented, + "Expected flipped value for ${GradleDokkaSourceSetBuilder::reportUndocumented.name}" + ) + } + + @Test + fun jdkVersion() { + val sourceSet = GradleDokkaSourceSetBuilder("", project) + assertEquals( + DokkaDefaults.jdkVersion, sourceSet.build().jdkVersion, + "Expected default value for ${GradleDokkaSourceSetBuilder::jdkVersion.name}" + ) + + sourceSet.jdkVersion.set(DokkaDefaults.jdkVersion + 1) + assertEquals( + DokkaDefaults.jdkVersion + 1, sourceSet.build().jdkVersion, + "Expected increased value for ${GradleDokkaSourceSetBuilder::jdkVersion.name}" + ) + } + + @Test + fun sourceLinks() { + val sourceSet = GradleDokkaSourceSetBuilder("", project) + assertEquals(emptySet(), sourceSet.build().sourceLinks, "Expected no default source links") + + sourceSet.sourceLinks.add( + GradleSourceLinkBuilder(project).apply { + this.lineSuffix by "ls1" + this.path by "p1" + this.url by "u1" + }) + + sourceSet.sourceLink { + it.lineSuffix by "ls2" + it.path by "p2" + it.url by "u2" + } + + sourceSet.sourceLink(project.closureOf<GradleSourceLinkBuilder> { + this.lineSuffix by "ls3" + this.path by "p3" + this.url by "u3" + }) + + assertEquals( + setOf( + SourceLinkDefinitionImpl( + lineSuffix = "ls1", + path = "p1", + url = "u1" + ), + SourceLinkDefinitionImpl( + lineSuffix = "ls2", + path = "p2", + url = "u2" + ), + SourceLinkDefinitionImpl( + lineSuffix = "ls3", + path = "p3", + url = "u3" + ) + ), + sourceSet.build().sourceLinks, + "Expected all source links being present after build" + ) + } + + @Test + fun perPackageOptions() { + val sourceSet = GradleDokkaSourceSetBuilder("", project) + assertEquals(emptyList(), sourceSet.build().perPackageOptions, "Expected no default per package options") + + sourceSet.perPackageOptions.add(GradlePackageOptionsBuilder(project).apply { + this.prefix by "p1" + }) + + sourceSet.perPackageOption { + it.prefix by "p2" + } + + sourceSet.perPackageOption(project.closureOf<GradlePackageOptionsBuilder> { + this.prefix by "p3" + }) + + assertEquals( + listOf("p1", "p2", "p3").map { prefix -> + PackageOptionsImpl( + prefix = prefix, + includeNonPublic = DokkaDefaults.includeNonPublic, + reportUndocumented = DokkaDefaults.reportUndocumented, + skipDeprecated = DokkaDefaults.skipDeprecated, + suppress = DokkaDefaults.suppress + ) + }, + sourceSet.build().perPackageOptions, + "Expected all package options being present after build" + ) + } + + @Test + fun externalDocumentationLink() { + val sourceSet = GradleDokkaSourceSetBuilder("", project) + sourceSet.noAndroidSdkLink by true + sourceSet.noJdkLink by true + sourceSet.noStdlibLink by true + assertEquals( + emptySet(), sourceSet.build().externalDocumentationLinks, + "Expected no default external documentation links" + ) + + sourceSet.externalDocumentationLinks.add( + GradleExternalDocumentationLinkBuilder(project).apply { + this.url by URL("https://u1") + this.packageListUrl by URL("https://pl1") + } + ) + + sourceSet.externalDocumentationLink { + it.url by URL("https://u2") + } + + sourceSet.externalDocumentationLink(project.closureOf<GradleExternalDocumentationLinkBuilder> { + url by URL("https://u3") + }) + + sourceSet.externalDocumentationLink(url = "https://u4", packageListUrl = "https://pl4") + sourceSet.externalDocumentationLink(url = URL("https://u5")) + + assertEquals( + setOf( + ExternalDocumentationLinkImpl(URL("https://u1"), URL("https://pl1")), + ExternalDocumentationLinkImpl(URL("https://u2"), URL("https://u2/package-list")), + ExternalDocumentationLinkImpl(URL("https://u3"), URL("https://u3/package-list")), + ExternalDocumentationLinkImpl(URL("https://u4"), URL("https://pl4")), + ExternalDocumentationLinkImpl(URL("https://u5"), URL("https://u5/package-list")) + ), + sourceSet.build().externalDocumentationLinks, + "Expected all external documentation links being present after build" + ) + } + + @Test + fun languageVersion() { + val sourceSet = GradleDokkaSourceSetBuilder("", project) + assertNull(sourceSet.build().languageVersion, "Expected no language version being set by default") + + sourceSet.languageVersion by "JAVA_20" + assertEquals( + "JAVA_20", sourceSet.build().languageVersion, + "Expected previously set language version to be present after build" + ) + } + + @Test + fun apiVersion() { + val sourceSet = GradleDokkaSourceSetBuilder("", project) + assertNull(sourceSet.build().apiVersion, "Expected no api version being set by default") + + sourceSet.apiVersion by "20" + assertEquals( + "20", sourceSet.build().apiVersion, + "Expected previously set api version to be present after build" + ) + } + + @Test + fun noStdlibLink() { + val sourceSet = GradleDokkaSourceSetBuilder("", project) + assertFalse(sourceSet.noStdlibLink.getSafe(), "Expected 'noStdlibLink' to be set to false by default") + + assertEquals(1, sourceSet.build().externalDocumentationLinks.count { + "https://kotlinlang.org/api" in it.url.toURI().toString() + }, "Expected kotlin stdlib in external documentation links") + + sourceSet.noStdlibLink by true + + assertEquals( + 0, sourceSet.build().externalDocumentationLinks.count { + "https://kotlinlang.org/api" in it.url.toURI().toString() + }, "Expected no stdlib in external documentation link" + ) + } + + @Test + fun noJdkLink() { + val sourceSet = GradleDokkaSourceSetBuilder("", project) + assertFalse(sourceSet.noJdkLink.getSafe(), "Expected 'noJdkLink' to be set to false by default") + + assertEquals(1, sourceSet.build().externalDocumentationLinks.count { + "https://docs.oracle.com/" in it.url.toURI().toString() + }, "Expected java jdk in external documentation links") + + sourceSet.noJdkLink by true + + assertEquals( + 0, sourceSet.build().externalDocumentationLinks.count { + "https://docs.oracle.com/" in it.url.toURI().toString() + }, "Expected no java jdk in external documentation link" + ) + } + + + @Test + fun noAndroidSdkLink() { + val sourceSet = GradleDokkaSourceSetBuilder("", project) + assertFalse(sourceSet.noAndroidSdkLink.getSafe(), "Expected 'noAndroidSdkLink' to be set to false by default") + + assertEquals(0, sourceSet.build().externalDocumentationLinks.count { + "https://developer.android.com/reference" in it.url.toURI().toString() + }, "Expected no android sdk in external documentation links (without android plugin)") + + assertEquals(0, sourceSet.build().externalDocumentationLinks.count { + "https://developer.android.com/reference/androidx" in it.packageListUrl.toURI().toString() + }, "Expected no androidx in external documentation links (without android plugin)") + + + project.plugins.apply("com.android.library") + + assertEquals(1, sourceSet.build().externalDocumentationLinks.count { + "https://developer.android.com/reference/package-list" in it.packageListUrl.toURI().toString() + }, "Expected android sdk in external documentation links") + + assertEquals(1, sourceSet.build().externalDocumentationLinks.count { + "https://developer.android.com/reference/androidx" in it.packageListUrl.toURI().toString() + }, "Expected androidx in external documentation links") + + + sourceSet.noAndroidSdkLink by true + + assertEquals(0, sourceSet.build().externalDocumentationLinks.count { + "https://developer.android.com/reference" in it.url.toURI().toString() + }, "Expected no android sdk in external documentation links") + + assertEquals(0, sourceSet.build().externalDocumentationLinks.count { + "https://developer.android.com/reference/androidx" in it.packageListUrl.toURI().toString() + }, "Expected no androidx in external documentation links") + } + + @Test + fun suppressedFiles() { + val sourceSet = GradleDokkaSourceSetBuilder("", project) + assertTrue(sourceSet.build().suppressedFiles.isEmpty(), "Expected no suppressed files by default") + + sourceSet.suppressedFiles.from(project.file("f1")) + sourceSet.suppressedFiles.from("f2") + + assertEquals( + setOf(project.file("f1"), project.file("f2")), sourceSet.build().suppressedFiles, + "Expected all suppressed files to be present after build" + ) + } + + @Test + fun platform() { + val sourceSet = GradleDokkaSourceSetBuilder("", project) + assertEquals(Platform.DEFAULT, sourceSet.build().analysisPlatform, "Expected default platform if not specified") + + sourceSet.platform by Platform.common + assertEquals( + Platform.common, sourceSet.build().analysisPlatform, + "Expected previously set analysis platform being present after build" + ) + } +} diff --git a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/KotlinSourceSetGistTest.kt b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/KotlinSourceSetGistTest.kt new file mode 100644 index 00000000..1996bb16 --- /dev/null +++ b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/KotlinSourceSetGistTest.kt @@ -0,0 +1,249 @@ +package org.jetbrains.dokka.gradle + +import org.gradle.api.artifacts.FileCollectionDependency +import org.gradle.kotlin.dsl.get +import org.gradle.testfixtures.ProjectBuilder +import org.jetbrains.dokka.Platform +import org.jetbrains.dokka.gradle.kotlin.gistOf +import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType +import org.jetbrains.kotlin.gradle.utils.`is` +import java.io.File +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +class KotlinSourceSetGistTest { + + @Test + fun `main source set with kotlin jvm`() { + val project = ProjectBuilder.builder().build() + project.plugins.apply("org.jetbrains.kotlin.jvm") + val kotlin = project.kotlin as KotlinJvmProjectExtension + + val mainSourceSet = kotlin.sourceSets.getByName("main") + val mainSourceSetGist = project.gistOf(mainSourceSet) + + assertEquals( + "main", mainSourceSetGist.name, + "Expected correct source set name" + ) + + assertEquals( + KotlinPlatformType.jvm, mainSourceSetGist.platform, + "Expected correct platform" + ) + + assertTrue( + mainSourceSetGist.isMain, + "Expected main sources to be marked as 'isMain'" + ) + + assertEquals( + emptySet(), mainSourceSetGist.dependentSourceSetNames.get(), + "Expected no dependent source sets" + ) + } + + @Test + fun `test source set with kotlin jvm`() { + val project = ProjectBuilder.builder().build() + project.plugins.apply("org.jetbrains.kotlin.jvm") + val kotlin = project.kotlin as KotlinJvmProjectExtension + + val testSourceSet = kotlin.sourceSets.getByName("test") + val testSourceSetGist = project.gistOf(testSourceSet) + + assertFalse( + testSourceSetGist.isMain, + "Expected test source set not being marked as 'isMain'" + ) + + assertEquals( + emptySet(), + testSourceSetGist.dependentSourceSetNames.get(), + "Expected no dependent source sets" + ) + } + + @Test + fun `sourceRoots of main source set with kotlin jvm`() { + val project = ProjectBuilder.builder().build() + project.plugins.apply("org.jetbrains.kotlin.jvm") + val kotlin = project.kotlin as KotlinJvmProjectExtension + val mainSourceSet = kotlin.sourceSets.getByName("main") + val mainSourceSetGist = project.gistOf(mainSourceSet) + + assertEquals( + emptySet(), mainSourceSetGist.sourceRoots.files, + "Expected no sourceRoots, because default source root does not exist on filesystem yet" + ) + + // Create default source root on filesystem + val defaultSourceRoot = project.file("src/main/kotlin") + defaultSourceRoot.mkdirs() + + assertEquals( + setOf(defaultSourceRoot), mainSourceSetGist.sourceRoots.files, + "Expected default source root in source roots, since it is present on the filesystem" + ) + + // Create custom source set (and make sure it exists on filesystem) + val customSourceRoot = project.file("src/main/custom").also(File::mkdirs) + mainSourceSet.kotlin.srcDir(customSourceRoot) + + assertEquals( + setOf(defaultSourceRoot, customSourceRoot), mainSourceSetGist.sourceRoots.files, + "Expected recently registered custom source root to be present" + ) + + // removing default source root + mainSourceSet.kotlin.setSrcDirs(listOf(customSourceRoot)) + + assertEquals( + setOf(customSourceRoot), mainSourceSetGist.sourceRoots.files, + "Expected only custom source root being present in source roots" + ) + } + + @Suppress("UnstableApiUsage") + @Test + fun `classpath of main source set with kotlin jvm`() { + val project = ProjectBuilder.builder().build() + project.plugins.apply("org.jetbrains.kotlin.jvm") + val kotlin = project.kotlin as KotlinJvmProjectExtension + val mainSourceSet = kotlin.sourceSets.getByName("main") + val mainSourceSetGist = project.gistOf(mainSourceSet) + + /* Only work with file dependencies */ + project.configurations.forEach { configuration -> + configuration.withDependencies { dependencies -> + dependencies.removeIf { dependency -> + dependency !is FileCollectionDependency + } + } + } + + val implementationJar = project.file("implementation.jar") + val compileOnlyJar = project.file("compileOnly.jar") + val apiJar = project.file("api.jar") + val runtimeOnlyJar = project.file("runtimeOnly.jar") + + + mainSourceSet.dependencies { + implementation(project.files(implementationJar)) + compileOnly(project.files(compileOnlyJar)) + api(project.files(apiJar)) + runtimeOnly(project.files(runtimeOnlyJar)) + } + + assertEquals( + emptySet(), mainSourceSetGist.classpath.files, + "Expected no files on the classpath, since no file exists" + ) + + /* Creating dependency files */ + check(implementationJar.createNewFile()) + check(compileOnlyJar.createNewFile()) + check(apiJar.createNewFile()) + check(runtimeOnlyJar.createNewFile()) + + assertEquals( + setOf(implementationJar, compileOnlyJar, apiJar), mainSourceSetGist.classpath.files, + "Expected implementation, compileOnly and api dependencies on classpath" + ) + } + + @Test + fun `common, jvm and macos source sets with kotlin multiplatform`() { + val project = ProjectBuilder.builder().build() + project.plugins.apply("org.jetbrains.kotlin.multiplatform") + val kotlin = project.kotlin as KotlinMultiplatformExtension + kotlin.jvm() + kotlin.macosX64("macos") + + val commonMainSourceSet = kotlin.sourceSets.getByName("commonMain") + val commonMainSourceSetGist = project.gistOf(commonMainSourceSet) + + val jvmMainSourceSet = kotlin.sourceSets.getByName("jvmMain") + val jvmMainSourceSetGist = project.gistOf(jvmMainSourceSet) + + val macosMainSourceSet = kotlin.sourceSets.getByName("macosMain") + val macosMainSourceSetGist = project.gistOf(macosMainSourceSet) + + assertEquals( + "commonMain", commonMainSourceSetGist.name, + "Expected correct source set name" + ) + + assertEquals( + "jvmMain", jvmMainSourceSetGist.name, + "Expected correct source set name" + ) + + assertEquals( + "macosMain", macosMainSourceSetGist.name, + "Expected correct source set name" + ) + + assertEquals( + KotlinPlatformType.common, commonMainSourceSetGist.platform, + "Expected common platform for commonMain source set" + ) + + assertEquals( + KotlinPlatformType.jvm, jvmMainSourceSetGist.platform, + "Expected jvm platform for jvmMain source set" + ) + + assertEquals( + KotlinPlatformType.native, macosMainSourceSetGist.platform, + "Expected native platform for macosMain source set" + ) + + assertTrue( + commonMainSourceSetGist.isMain, + "Expected commonMain to be marked with 'isMain'" + ) + + assertTrue( + jvmMainSourceSetGist.isMain, + "Expected jvmMain to be marked with 'isMain'" + ) + + assertTrue( + macosMainSourceSetGist.isMain, + "Expected macosMain to be marked with 'isMain'" + ) + + assertFalse( + project.gistOf(kotlin.sourceSets["commonTest"]).isMain, + "Expected commonTest not being marked with 'isMain'" + ) + + assertFalse( + project.gistOf(kotlin.sourceSets["jvmTest"]).isMain, + "Expected jvmTest not being marked with 'isMain'" + ) + + assertFalse( + project.gistOf(kotlin.sourceSets["macosTest"]).isMain, + "Expected macosTest not being marked with 'isMain'" + ) + + assertEquals( + setOf("commonMain"), jvmMainSourceSetGist.dependentSourceSetNames.get(), + "Expected jvmMain to depend on commonMain by default" + ) + + /* Why not? */ + jvmMainSourceSet.dependsOn(macosMainSourceSet) + assertEquals( + setOf("commonMain", "macosMain"), jvmMainSourceSetGist.dependentSourceSetNames.get(), + "Expected dependent source set changes to be reflected in gist" + ) + } + +} |