aboutsummaryrefslogtreecommitdiff
path: root/integration-tests
diff options
context:
space:
mode:
Diffstat (limited to 'integration-tests')
-rw-r--r--integration-tests/build.gradle.kts43
-rw-r--r--integration-tests/cli/build.gradle.kts41
-rw-r--r--integration-tests/cli/projects/it-cli/src/main/java/it/basic/java/SampleJavaClass.java17
-rw-r--r--integration-tests/cli/projects/it-cli/src/main/kotlin/it/basic/PublicClass.kt48
-rw-r--r--integration-tests/cli/src/integrationTest/kotlin/org/jetbrains/dokka/it/cli/CliIntegrationTest.kt89
-rw-r--r--integration-tests/cli/src/main/kotlin/org/jetbrains/dokka/it/cli/AbstractCliIntegrationTest.kt36
-rw-r--r--integration-tests/gradle/README.md7
-rw-r--r--integration-tests/gradle/build.gradle.kts16
-rw-r--r--integration-tests/gradle/projects/it-android-0/build.gradle.kts19
-rw-r--r--integration-tests/gradle/projects/it-android-0/gradle.properties2
-rw-r--r--integration-tests/gradle/projects/it-android-0/gradle/wrapper/gradle-wrapper.jarbin0 -> 58695 bytes
-rw-r--r--integration-tests/gradle/projects/it-android-0/gradle/wrapper/gradle-wrapper.properties5
-rwxr-xr-xintegration-tests/gradle/projects/it-android-0/gradlew183
-rw-r--r--integration-tests/gradle/projects/it-android-0/gradlew.bat100
-rw-r--r--integration-tests/gradle/projects/it-android-0/settings.gradle.kts5
-rw-r--r--integration-tests/gradle/projects/it-android-0/src/main/AndroidManifest.xml1
-rw-r--r--integration-tests/gradle/projects/it-android-0/src/main/java/it/android/AndroidSpecificClass.kt16
-rw-r--r--integration-tests/gradle/projects/it-basic-groovy/build.gradle37
-rw-r--r--integration-tests/gradle/projects/it-basic-groovy/gradle.properties1
-rw-r--r--integration-tests/gradle/projects/it-basic-groovy/gradle/wrapper/gradle-wrapper.jarbin0 -> 58910 bytes
-rw-r--r--integration-tests/gradle/projects/it-basic-groovy/gradle/wrapper/gradle-wrapper.properties5
-rwxr-xr-xintegration-tests/gradle/projects/it-basic-groovy/gradlew185
-rw-r--r--integration-tests/gradle/projects/it-basic-groovy/gradlew.bat104
-rw-r--r--integration-tests/gradle/projects/it-basic-groovy/settings.gradle.kts5
-rw-r--r--integration-tests/gradle/projects/it-basic-groovy/src/main/java/it/basic/java/SampleJavaClass.java17
-rw-r--r--integration-tests/gradle/projects/it-basic-groovy/src/main/kotlin/it/basic/PublicClass.kt48
-rw-r--r--integration-tests/gradle/projects/it-basic/build.gradle.kts20
-rw-r--r--integration-tests/gradle/projects/it-basic/gradle.properties1
-rw-r--r--integration-tests/gradle/projects/it-basic/gradle/wrapper/gradle-wrapper.jarbin0 -> 58910 bytes
-rw-r--r--integration-tests/gradle/projects/it-basic/gradle/wrapper/gradle-wrapper.properties5
-rwxr-xr-xintegration-tests/gradle/projects/it-basic/gradlew185
-rw-r--r--integration-tests/gradle/projects/it-basic/gradlew.bat104
-rw-r--r--integration-tests/gradle/projects/it-basic/settings.gradle.kts5
-rw-r--r--integration-tests/gradle/projects/it-basic/src/main/java/it/basic/java/SampleJavaClass.java17
-rw-r--r--integration-tests/gradle/projects/it-basic/src/main/kotlin/it/basic/PublicClass.kt48
-rw-r--r--integration-tests/gradle/projects/it-multimodule-0/build.gradle.kts1
-rw-r--r--integration-tests/gradle/projects/it-multimodule-0/gradle.properties1
-rw-r--r--integration-tests/gradle/projects/it-multimodule-0/gradle/wrapper/gradle-wrapper.jarbin0 -> 58695 bytes
-rw-r--r--integration-tests/gradle/projects/it-multimodule-0/gradle/wrapper/gradle-wrapper.properties5
-rwxr-xr-xintegration-tests/gradle/projects/it-multimodule-0/gradlew183
-rw-r--r--integration-tests/gradle/projects/it-multimodule-0/gradlew.bat100
-rw-r--r--integration-tests/gradle/projects/it-multimodule-0/moduleA/build.gradle.kts6
-rw-r--r--integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleB/README.md2
-rw-r--r--integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleB/build.gradle.kts8
-rw-r--r--integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleB/src/main/kotlin/org/jetbrains/dokka/it/moduleB/ModuleB.kt6
-rw-r--r--integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleC/README.md2
-rw-r--r--integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleC/build.gradle.kts8
-rw-r--r--integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleC/src/main/kotlin/org/jetbrains/dokka/it/moduleC/ModuleC.kt6
-rw-r--r--integration-tests/gradle/projects/it-multimodule-0/settings.gradle.kts5
-rw-r--r--integration-tests/gradle/projects/it-multiplatform-0/build.gradle.kts25
-rw-r--r--integration-tests/gradle/projects/it-multiplatform-0/gradle.properties1
-rw-r--r--integration-tests/gradle/projects/it-multiplatform-0/gradle/wrapper/gradle-wrapper.jarbin0 -> 58695 bytes
-rw-r--r--integration-tests/gradle/projects/it-multiplatform-0/gradle/wrapper/gradle-wrapper.properties5
-rwxr-xr-xintegration-tests/gradle/projects/it-multiplatform-0/gradlew183
-rw-r--r--integration-tests/gradle/projects/it-multiplatform-0/gradlew.bat100
-rw-r--r--integration-tests/gradle/projects/it-multiplatform-0/settings.gradle.kts2
-rw-r--r--integration-tests/gradle/projects/it-multiplatform-0/src/commonMain/kotlin/it/mpp0/CommonMainClass.kt8
-rw-r--r--integration-tests/gradle/projects/it-multiplatform-0/src/commonMain/kotlin/it/mpp0/ExpectedClass.kt5
-rw-r--r--integration-tests/gradle/projects/it-multiplatform-0/src/jsMain/kotlin/it/mpp0/ExpectedClass.kt5
-rw-r--r--integration-tests/gradle/projects/it-multiplatform-0/src/jvmMain/kotlin/it/mpp0/ExpectedClass.kt5
-rw-r--r--integration-tests/gradle/projects/it-multiplatform-0/src/linuxMain/kotlin/it/mpp0/ExpectedClass.kt5
-rw-r--r--integration-tests/gradle/projects/it-multiplatform-0/src/macosMain/kotlin/it/mpp0/ExpectedClass.kt5
-rw-r--r--integration-tests/gradle/projects/template.root.gradle.kts18
-rw-r--r--integration-tests/gradle/projects/template.settings.gradle.kts37
-rw-r--r--integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Android0GradleIntegrationTest.kt77
-rw-r--r--integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/BasicGradleIntegrationTest.kt99
-rw-r--r--integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/BasicGroovyIntegrationTest.kt98
-rw-r--r--integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Multimodule0IntegrationTest.kt61
-rw-r--r--integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Multiplatform0GradleIntegrationTest.kt43
-rw-r--r--integration-tests/gradle/src/main/kotlin/org/jetbrains/dokka/it/gradle/AbstractGradleIntegrationTest.kt74
-rw-r--r--integration-tests/gradle/src/main/kotlin/org/jetbrains/dokka/it/gradle/BuildVersions.kt48
-rw-r--r--integration-tests/maven/build.gradle.kts20
-rw-r--r--integration-tests/maven/projects/it-maven/pom.xml172
-rw-r--r--integration-tests/maven/projects/it-maven/src/main/java/it/basic/java/SampleJavaClass.java22
-rw-r--r--integration-tests/maven/projects/it-maven/src/main/kotlin/it/basic/PublicClass.kt48
-rw-r--r--integration-tests/maven/src/integrationTest/kotlin/org/jetbrains/dokka/it/maven/MavenIntegrationTest.kt132
-rw-r--r--integration-tests/src/main/kotlin/org/jetbrains/dokka/it/AbstractIntegrationTest.kt71
-rw-r--r--integration-tests/src/main/kotlin/org/jetbrains/dokka/it/environmentUtils.kt16
-rw-r--r--integration-tests/src/main/kotlin/org/jetbrains/dokka/it/processUtils.kt51
79 files changed, 3184 insertions, 0 deletions
diff --git a/integration-tests/build.gradle.kts b/integration-tests/build.gradle.kts
new file mode 100644
index 00000000..fb987c36
--- /dev/null
+++ b/integration-tests/build.gradle.kts
@@ -0,0 +1,43 @@
+subprojects {
+ sourceSets {
+ create("integrationTest") {
+ compileClasspath += sourceSets.main.get().output
+ runtimeClasspath += sourceSets.main.get().output
+ }
+ }
+
+ configurations.getByName("integrationTestImplementation") {
+ extendsFrom(configurations.implementation.get())
+ }
+
+ configurations.getByName("integrationTestRuntimeOnly") {
+ extendsFrom(configurations.runtimeOnly.get())
+ }
+
+ dependencies {
+ implementation(project(":integration-tests"))
+ }
+
+ val integrationTest by tasks.register<Test>("integrationTest") {
+ maxHeapSize = "2G"
+ description = "Runs integration tests."
+ group = "verification"
+
+ testClassesDirs = sourceSets["integrationTest"].output.classesDirs
+ classpath = sourceSets["integrationTest"].runtimeClasspath
+
+ useJUnit()
+ }
+
+ tasks.check {
+ dependsOn(integrationTest)
+ }
+}
+
+dependencies {
+ implementation(kotlin("stdlib"))
+ implementation(kotlin("test-junit"))
+ val coroutines_version: String by project
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version")
+ implementation("org.jsoup:jsoup:1.12.1")
+}
diff --git a/integration-tests/cli/build.gradle.kts b/integration-tests/cli/build.gradle.kts
new file mode 100644
index 00000000..d9961f8f
--- /dev/null
+++ b/integration-tests/cli/build.gradle.kts
@@ -0,0 +1,41 @@
+import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
+
+
+plugins {
+ id("com.github.johnrengelman.shadow")
+}
+
+val dokka_version: String by project
+evaluationDependsOn(":runners:cli")
+evaluationDependsOn(":plugins:base")
+
+dependencies {
+ implementation(kotlin("stdlib"))
+ implementation(kotlin("test-junit"))
+}
+
+/* Create a fat base plugin jar for cli tests */
+val basePluginShadow: Configuration by configurations.creating {
+ attributes {
+ attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage::class.java, "java-runtime"))
+ }
+}
+
+dependencies {
+ basePluginShadow(project(":plugins:base"))
+}
+val basePluginShadowJar by tasks.register("basePluginShadowJar", ShadowJar::class) {
+ configurations = listOf(basePluginShadow)
+ archiveFileName.set("fat-base-plugin-$dokka_version.jar")
+ archiveClassifier.set("")
+}
+
+tasks.integrationTest {
+ inputs.dir(file("projects"))
+ val cliJar = tasks.getByPath(":runners:cli:shadowJar") as ShadowJar
+ environment("CLI_JAR_PATH", cliJar.archiveFile.get())
+ environment("BASE_PLUGIN_JAR_PATH", basePluginShadowJar.archiveFile.get())
+ dependsOn(cliJar)
+ dependsOn(basePluginShadowJar)
+}
+
diff --git a/integration-tests/cli/projects/it-cli/src/main/java/it/basic/java/SampleJavaClass.java b/integration-tests/cli/projects/it-cli/src/main/java/it/basic/java/SampleJavaClass.java
new file mode 100644
index 00000000..23b0202c
--- /dev/null
+++ b/integration-tests/cli/projects/it-cli/src/main/java/it/basic/java/SampleJavaClass.java
@@ -0,0 +1,17 @@
+package it.basic.java;
+
+import it.basic.PublicClass;
+
+/**
+ * This class is, unlike {@link PublicClass}, written in Java
+ */
+@SuppressWarnings("unused")
+public class SampleJavaClass {
+
+ /**
+ * @return Empty instance of {@link PublicClass}
+ */
+ public PublicClass publicDocumentedFunction() {
+ return new PublicClass();
+ }
+}
diff --git a/integration-tests/cli/projects/it-cli/src/main/kotlin/it/basic/PublicClass.kt b/integration-tests/cli/projects/it-cli/src/main/kotlin/it/basic/PublicClass.kt
new file mode 100644
index 00000000..71bc7e63
--- /dev/null
+++ b/integration-tests/cli/projects/it-cli/src/main/kotlin/it/basic/PublicClass.kt
@@ -0,0 +1,48 @@
+@file:Suppress("unused")
+
+package it.basic
+
+class PublicClass {
+ /**
+ * This function is public and documented
+ */
+ fun publicDocumentedFunction(): String = ""
+
+ fun publicUndocumentedFunction(): String = ""
+
+ /**
+ * This function is internal and documented
+ */
+ internal fun internalDocumentedFunction(): String = ""
+
+ internal fun internalUndocumentedFunction(): String = ""
+
+ /**
+ * This function is private and documented
+ */
+ private fun privateDocumentedFunction(): String = ""
+
+ private fun privateUndocumentedFunction(): String = ""
+
+
+ /**
+ * This property is public and documented
+ */
+ val publicDocumentedProperty: Int = 0
+
+ val publicUndocumentedProperty: Int = 0
+
+ /**
+ * This property internal and documented
+ */
+ val internalDocumentedProperty: Int = 0
+
+ val internalUndocumentedProperty: Int = 0
+
+ /**
+ * This property private and documented
+ */
+ private val privateDocumentedProperty: Int = 0
+
+ private val privateUndocumentedProperty: Int = 0
+}
diff --git a/integration-tests/cli/src/integrationTest/kotlin/org/jetbrains/dokka/it/cli/CliIntegrationTest.kt b/integration-tests/cli/src/integrationTest/kotlin/org/jetbrains/dokka/it/cli/CliIntegrationTest.kt
new file mode 100644
index 00000000..cfa752d6
--- /dev/null
+++ b/integration-tests/cli/src/integrationTest/kotlin/org/jetbrains/dokka/it/cli/CliIntegrationTest.kt
@@ -0,0 +1,89 @@
+package org.jetbrains.dokka.it.cli
+
+import org.jetbrains.dokka.it.awaitProcessResult
+import java.io.File
+import kotlin.test.BeforeTest
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+
+class CliIntegrationTest : AbstractCliIntegrationTest() {
+
+ @BeforeTest
+ fun copyProject() {
+ val templateProjectDir = File("projects", "it-cli")
+ templateProjectDir.copyRecursively(projectDir)
+ }
+
+ @Test
+ fun runHelp() {
+ val process = ProcessBuilder("java", "-jar", cliJarFile.path, "-h")
+ .redirectErrorStream(true)
+ .start()
+
+ val result = process.awaitProcessResult()
+ assertEquals(0, result.exitCode, "Expected exitCode 0 (Success)")
+ assertTrue("Usage: " in result.output)
+ }
+
+ @Test
+ fun runCli() {
+ val dokkaOutputDir = File(projectDir, "output")
+ assertTrue(dokkaOutputDir.mkdirs())
+ val process = ProcessBuilder(
+ "java", "-jar", cliJarFile.path,
+ "-outputDir", dokkaOutputDir.path,
+ "-pluginsClasspath", basePluginJarFile.path,
+ "-sourceSet",
+ buildString {
+ append(" -moduleName it-cli")
+ append(" -moduleDisplayName CLI-Example")
+ append(" -sourceSetName cliMain")
+ append(" -src ${File(projectDir, "src").path}")
+ append(" -jdkVersion 8")
+ append(" -analysisPlatform jvm")
+ append(" -reportUndocumented")
+ append(" -skipDeprecated")
+ }
+ )
+ .redirectErrorStream(true)
+ .start()
+
+ val result = process.awaitProcessResult()
+ assertEquals(0, result.exitCode, "Expected exitCode 0 (Success)")
+
+ val extensionLoadedRegex = Regex("""Extension: org\.jetbrains\.dokka\.base\.DokkaBase""")
+ val amountOfExtensionsLoaded = extensionLoadedRegex.findAll(result.output).count()
+
+ assertTrue(
+ amountOfExtensionsLoaded > 10,
+ "Expected more than 10 extensions being present (found $amountOfExtensionsLoaded)"
+ )
+
+ val undocumentedReportRegex = Regex("""Undocumented:""")
+ val amountOfUndocumentedReports = undocumentedReportRegex.findAll(result.output).count()
+ assertTrue(
+ amountOfUndocumentedReports > 0,
+ "Expected at least one report of undocumented code (found $amountOfUndocumentedReports)"
+ )
+
+ assertTrue(dokkaOutputDir.isDirectory, "Missing dokka output directory")
+
+ val imagesDir = File(dokkaOutputDir, "images")
+ assertTrue(imagesDir.isDirectory, "Missing images directory")
+
+ val scriptsDir = File(dokkaOutputDir, "scripts")
+ assertTrue(scriptsDir.isDirectory, "Missing scripts directory")
+
+ val stylesDir = File(dokkaOutputDir, "styles")
+ assertTrue(stylesDir.isDirectory, "Missing styles directory")
+
+ val navigationHtml = File(dokkaOutputDir, "navigation.html")
+ assertTrue(navigationHtml.isFile, "Missing navigation.html")
+
+ projectDir.allHtmlFiles().forEach { file ->
+ assertContainsNoErrorClass(file)
+ assertNoUnresolvedLInks(file)
+ }
+ }
+}
diff --git a/integration-tests/cli/src/main/kotlin/org/jetbrains/dokka/it/cli/AbstractCliIntegrationTest.kt b/integration-tests/cli/src/main/kotlin/org/jetbrains/dokka/it/cli/AbstractCliIntegrationTest.kt
new file mode 100644
index 00000000..7f6f9433
--- /dev/null
+++ b/integration-tests/cli/src/main/kotlin/org/jetbrains/dokka/it/cli/AbstractCliIntegrationTest.kt
@@ -0,0 +1,36 @@
+package org.jetbrains.dokka.it.cli
+
+import org.jetbrains.dokka.it.AbstractIntegrationTest
+import java.io.File
+import kotlin.test.BeforeTest
+import kotlin.test.assertTrue
+
+abstract class AbstractCliIntegrationTest : AbstractIntegrationTest() {
+
+ protected val cliJarFile: File by lazy {
+ File(temporaryTestFolder.root, "dokka.jar")
+ }
+
+ protected val basePluginJarFile: File by lazy {
+ File(temporaryTestFolder.root, "base-plugin.jar")
+ }
+
+ @BeforeTest
+ fun copyJarFiles() {
+ val cliJarPathEnvironmentKey = "CLI_JAR_PATH"
+ val cliJarFile = File(System.getenv(cliJarPathEnvironmentKey))
+ assertTrue(
+ cliJarFile.exists() && cliJarFile.isFile,
+ "Missing path to CLI jar System.getenv($cliJarPathEnvironmentKey)"
+ )
+ cliJarFile.copyTo(this.cliJarFile)
+
+ val basePluginPathEnvironmentKey = "BASE_PLUGIN_JAR_PATH"
+ val basePluginJarFile = File(System.getenv(basePluginPathEnvironmentKey))
+ assertTrue(
+ basePluginJarFile.exists() && basePluginJarFile.isFile,
+ "Missing path to base plugin jar System.getenv($basePluginPathEnvironmentKey)"
+ )
+ basePluginJarFile.copyTo(this.basePluginJarFile)
+ }
+}
diff --git a/integration-tests/gradle/README.md b/integration-tests/gradle/README.md
new file mode 100644
index 00000000..45828092
--- /dev/null
+++ b/integration-tests/gradle/README.md
@@ -0,0 +1,7 @@
+### Note
+All Gradle projects inside the `project` subfolder can
+also be imported to the IDE by clicking on the corresponding
+build.gradle.kts file -> "import gradle project".
+
+Before importing: Make sure that you have dokka installed
+locally (`./gradlew publishToMavenLocal`).
diff --git a/integration-tests/gradle/build.gradle.kts b/integration-tests/gradle/build.gradle.kts
new file mode 100644
index 00000000..3da416bb
--- /dev/null
+++ b/integration-tests/gradle/build.gradle.kts
@@ -0,0 +1,16 @@
+import org.jetbrains.dependsOnMavenLocalPublication
+
+dependencies {
+ implementation(kotlin("stdlib"))
+ implementation(kotlin("test-junit"))
+ implementation(gradleTestKit())
+}
+
+tasks.integrationTest {
+ inputs.dir(file("projects"))
+ dependsOnMavenLocalPublication()
+}
+
+tasks.clean {
+ delete(File(buildDir, "gradle-test-kit"))
+}
diff --git a/integration-tests/gradle/projects/it-android-0/build.gradle.kts b/integration-tests/gradle/projects/it-android-0/build.gradle.kts
new file mode 100644
index 00000000..32c5c56c
--- /dev/null
+++ b/integration-tests/gradle/projects/it-android-0/build.gradle.kts
@@ -0,0 +1,19 @@
+plugins {
+ id("com.android.library")
+ id("org.jetbrains.dokka")
+ kotlin("android")
+}
+
+apply(from = "../template.root.gradle.kts")
+
+android {
+ defaultConfig {
+ minSdkVersion(21)
+ setCompileSdkVersion(29)
+ }
+}
+
+dependencies {
+ implementation(kotlin("stdlib"))
+}
+
diff --git a/integration-tests/gradle/projects/it-android-0/gradle.properties b/integration-tests/gradle/projects/it-android-0/gradle.properties
new file mode 100644
index 00000000..1332de19
--- /dev/null
+++ b/integration-tests/gradle/projects/it-android-0/gradle.properties
@@ -0,0 +1,2 @@
+dokka_it_kotlin_version=1.3.72
+dokka_it_android_gradle_plugin_version=4.0.0
diff --git a/integration-tests/gradle/projects/it-android-0/gradle/wrapper/gradle-wrapper.jar b/integration-tests/gradle/projects/it-android-0/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..f3d88b1c
--- /dev/null
+++ b/integration-tests/gradle/projects/it-android-0/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/integration-tests/gradle/projects/it-android-0/gradle/wrapper/gradle-wrapper.properties b/integration-tests/gradle/projects/it-android-0/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..1b16c34a
--- /dev/null
+++ b/integration-tests/gradle/projects/it-android-0/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/integration-tests/gradle/projects/it-android-0/gradlew b/integration-tests/gradle/projects/it-android-0/gradlew
new file mode 100755
index 00000000..2fe81a7d
--- /dev/null
+++ b/integration-tests/gradle/projects/it-android-0/gradlew
@@ -0,0 +1,183 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/integration-tests/gradle/projects/it-android-0/gradlew.bat b/integration-tests/gradle/projects/it-android-0/gradlew.bat
new file mode 100644
index 00000000..24467a14
--- /dev/null
+++ b/integration-tests/gradle/projects/it-android-0/gradlew.bat
@@ -0,0 +1,100 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/integration-tests/gradle/projects/it-android-0/settings.gradle.kts b/integration-tests/gradle/projects/it-android-0/settings.gradle.kts
new file mode 100644
index 00000000..664d2cb7
--- /dev/null
+++ b/integration-tests/gradle/projects/it-android-0/settings.gradle.kts
@@ -0,0 +1,5 @@
+@file:Suppress("LocalVariableName", "UnstableApiUsage")
+
+apply(from = "../template.settings.gradle.kts")
+rootProject.name = "it-android-0"
+
diff --git a/integration-tests/gradle/projects/it-android-0/src/main/AndroidManifest.xml b/integration-tests/gradle/projects/it-android-0/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..a35f86be
--- /dev/null
+++ b/integration-tests/gradle/projects/it-android-0/src/main/AndroidManifest.xml
@@ -0,0 +1 @@
+<manifest package="org.jetbrains.dokka.it.android"/>
diff --git a/integration-tests/gradle/projects/it-android-0/src/main/java/it/android/AndroidSpecificClass.kt b/integration-tests/gradle/projects/it-android-0/src/main/java/it/android/AndroidSpecificClass.kt
new file mode 100644
index 00000000..cb9046b1
--- /dev/null
+++ b/integration-tests/gradle/projects/it-android-0/src/main/java/it/android/AndroidSpecificClass.kt
@@ -0,0 +1,16 @@
+@file:Suppress("unused")
+
+package it.android
+
+import android.content.Context
+import android.util.SparseIntArray
+import android.view.View
+
+/**
+ * This class is specific to android and uses android classes like:
+ * [Context], [SparseIntArray] or [View]
+ */
+class AndroidSpecificClass {
+ fun sparseIntArray() = SparseIntArray()
+ fun createView(context: Context): View = View(context)
+}
diff --git a/integration-tests/gradle/projects/it-basic-groovy/build.gradle b/integration-tests/gradle/projects/it-basic-groovy/build.gradle
new file mode 100644
index 00000000..1ffa75bc
--- /dev/null
+++ b/integration-tests/gradle/projects/it-basic-groovy/build.gradle
@@ -0,0 +1,37 @@
+plugins {
+ id 'org.jetbrains.kotlin.jvm'
+ id("org.jetbrains.dokka")
+}
+
+apply from: '../template.root.gradle.kts'
+
+dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib"
+}
+
+dokkaHtml {
+ outputDirectory = "$buildDir/dokka/customHtml"
+
+ failOnWarning = false
+ dokkaSourceSets {
+ customSourceSet {
+ sourceRoot { path = "$projectDir/src/main/java" }
+ sourceRoot { path = "$projectDir/src/main/kotlin" }
+ displayName = "custom"
+ reportUndocumented = true
+ }
+ }
+}
+
+dokkaJavadoc {
+ outputDirectory = "$buildDir/dokka/customJavadoc"
+}
+
+dokkaGfm {
+ outputDirectory = "$buildDir/dokka/customGfm"
+}
+
+dokkaJekyll {
+ outputDirectory = "$buildDir/dokka/customJekyll"
+}
+
diff --git a/integration-tests/gradle/projects/it-basic-groovy/gradle.properties b/integration-tests/gradle/projects/it-basic-groovy/gradle.properties
new file mode 100644
index 00000000..7ebac3ad
--- /dev/null
+++ b/integration-tests/gradle/projects/it-basic-groovy/gradle.properties
@@ -0,0 +1 @@
+dokka_it_kotlin_version=1.3.72
diff --git a/integration-tests/gradle/projects/it-basic-groovy/gradle/wrapper/gradle-wrapper.jar b/integration-tests/gradle/projects/it-basic-groovy/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..62d4c053
--- /dev/null
+++ b/integration-tests/gradle/projects/it-basic-groovy/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/integration-tests/gradle/projects/it-basic-groovy/gradle/wrapper/gradle-wrapper.properties b/integration-tests/gradle/projects/it-basic-groovy/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..622ab64a
--- /dev/null
+++ b/integration-tests/gradle/projects/it-basic-groovy/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/integration-tests/gradle/projects/it-basic-groovy/gradlew b/integration-tests/gradle/projects/it-basic-groovy/gradlew
new file mode 100755
index 00000000..fbd7c515
--- /dev/null
+++ b/integration-tests/gradle/projects/it-basic-groovy/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/integration-tests/gradle/projects/it-basic-groovy/gradlew.bat b/integration-tests/gradle/projects/it-basic-groovy/gradlew.bat
new file mode 100644
index 00000000..a9f778a7
--- /dev/null
+++ b/integration-tests/gradle/projects/it-basic-groovy/gradlew.bat
@@ -0,0 +1,104 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/integration-tests/gradle/projects/it-basic-groovy/settings.gradle.kts b/integration-tests/gradle/projects/it-basic-groovy/settings.gradle.kts
new file mode 100644
index 00000000..cb6af4e9
--- /dev/null
+++ b/integration-tests/gradle/projects/it-basic-groovy/settings.gradle.kts
@@ -0,0 +1,5 @@
+@file:Suppress("LocalVariableName", "UnstableApiUsage")
+
+apply(from = "../template.settings.gradle.kts")
+rootProject.name = "it-basic-groovy"
+
diff --git a/integration-tests/gradle/projects/it-basic-groovy/src/main/java/it/basic/java/SampleJavaClass.java b/integration-tests/gradle/projects/it-basic-groovy/src/main/java/it/basic/java/SampleJavaClass.java
new file mode 100644
index 00000000..23b0202c
--- /dev/null
+++ b/integration-tests/gradle/projects/it-basic-groovy/src/main/java/it/basic/java/SampleJavaClass.java
@@ -0,0 +1,17 @@
+package it.basic.java;
+
+import it.basic.PublicClass;
+
+/**
+ * This class is, unlike {@link PublicClass}, written in Java
+ */
+@SuppressWarnings("unused")
+public class SampleJavaClass {
+
+ /**
+ * @return Empty instance of {@link PublicClass}
+ */
+ public PublicClass publicDocumentedFunction() {
+ return new PublicClass();
+ }
+}
diff --git a/integration-tests/gradle/projects/it-basic-groovy/src/main/kotlin/it/basic/PublicClass.kt b/integration-tests/gradle/projects/it-basic-groovy/src/main/kotlin/it/basic/PublicClass.kt
new file mode 100644
index 00000000..71bc7e63
--- /dev/null
+++ b/integration-tests/gradle/projects/it-basic-groovy/src/main/kotlin/it/basic/PublicClass.kt
@@ -0,0 +1,48 @@
+@file:Suppress("unused")
+
+package it.basic
+
+class PublicClass {
+ /**
+ * This function is public and documented
+ */
+ fun publicDocumentedFunction(): String = ""
+
+ fun publicUndocumentedFunction(): String = ""
+
+ /**
+ * This function is internal and documented
+ */
+ internal fun internalDocumentedFunction(): String = ""
+
+ internal fun internalUndocumentedFunction(): String = ""
+
+ /**
+ * This function is private and documented
+ */
+ private fun privateDocumentedFunction(): String = ""
+
+ private fun privateUndocumentedFunction(): String = ""
+
+
+ /**
+ * This property is public and documented
+ */
+ val publicDocumentedProperty: Int = 0
+
+ val publicUndocumentedProperty: Int = 0
+
+ /**
+ * This property internal and documented
+ */
+ val internalDocumentedProperty: Int = 0
+
+ val internalUndocumentedProperty: Int = 0
+
+ /**
+ * This property private and documented
+ */
+ private val privateDocumentedProperty: Int = 0
+
+ private val privateUndocumentedProperty: Int = 0
+}
diff --git a/integration-tests/gradle/projects/it-basic/build.gradle.kts b/integration-tests/gradle/projects/it-basic/build.gradle.kts
new file mode 100644
index 00000000..1de92418
--- /dev/null
+++ b/integration-tests/gradle/projects/it-basic/build.gradle.kts
@@ -0,0 +1,20 @@
+import org.jetbrains.dokka.gradle.DokkaTask
+
+plugins {
+ kotlin("jvm")
+ id("org.jetbrains.dokka")
+}
+
+apply(from = "../template.root.gradle.kts")
+
+dependencies {
+ implementation(kotlin("stdlib"))
+}
+
+tasks.withType<DokkaTask> {
+ dokkaSourceSets {
+ configureEach {
+ moduleDisplayName = "Basic Project"
+ }
+ }
+}
diff --git a/integration-tests/gradle/projects/it-basic/gradle.properties b/integration-tests/gradle/projects/it-basic/gradle.properties
new file mode 100644
index 00000000..7ebac3ad
--- /dev/null
+++ b/integration-tests/gradle/projects/it-basic/gradle.properties
@@ -0,0 +1 @@
+dokka_it_kotlin_version=1.3.72
diff --git a/integration-tests/gradle/projects/it-basic/gradle/wrapper/gradle-wrapper.jar b/integration-tests/gradle/projects/it-basic/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..62d4c053
--- /dev/null
+++ b/integration-tests/gradle/projects/it-basic/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/integration-tests/gradle/projects/it-basic/gradle/wrapper/gradle-wrapper.properties b/integration-tests/gradle/projects/it-basic/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..622ab64a
--- /dev/null
+++ b/integration-tests/gradle/projects/it-basic/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/integration-tests/gradle/projects/it-basic/gradlew b/integration-tests/gradle/projects/it-basic/gradlew
new file mode 100755
index 00000000..fbd7c515
--- /dev/null
+++ b/integration-tests/gradle/projects/it-basic/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/integration-tests/gradle/projects/it-basic/gradlew.bat b/integration-tests/gradle/projects/it-basic/gradlew.bat
new file mode 100644
index 00000000..a9f778a7
--- /dev/null
+++ b/integration-tests/gradle/projects/it-basic/gradlew.bat
@@ -0,0 +1,104 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/integration-tests/gradle/projects/it-basic/settings.gradle.kts b/integration-tests/gradle/projects/it-basic/settings.gradle.kts
new file mode 100644
index 00000000..833995e5
--- /dev/null
+++ b/integration-tests/gradle/projects/it-basic/settings.gradle.kts
@@ -0,0 +1,5 @@
+@file:Suppress("LocalVariableName", "UnstableApiUsage")
+
+apply(from = "../template.settings.gradle.kts")
+rootProject.name = "it-basic"
+
diff --git a/integration-tests/gradle/projects/it-basic/src/main/java/it/basic/java/SampleJavaClass.java b/integration-tests/gradle/projects/it-basic/src/main/java/it/basic/java/SampleJavaClass.java
new file mode 100644
index 00000000..23b0202c
--- /dev/null
+++ b/integration-tests/gradle/projects/it-basic/src/main/java/it/basic/java/SampleJavaClass.java
@@ -0,0 +1,17 @@
+package it.basic.java;
+
+import it.basic.PublicClass;
+
+/**
+ * This class is, unlike {@link PublicClass}, written in Java
+ */
+@SuppressWarnings("unused")
+public class SampleJavaClass {
+
+ /**
+ * @return Empty instance of {@link PublicClass}
+ */
+ public PublicClass publicDocumentedFunction() {
+ return new PublicClass();
+ }
+}
diff --git a/integration-tests/gradle/projects/it-basic/src/main/kotlin/it/basic/PublicClass.kt b/integration-tests/gradle/projects/it-basic/src/main/kotlin/it/basic/PublicClass.kt
new file mode 100644
index 00000000..71bc7e63
--- /dev/null
+++ b/integration-tests/gradle/projects/it-basic/src/main/kotlin/it/basic/PublicClass.kt
@@ -0,0 +1,48 @@
+@file:Suppress("unused")
+
+package it.basic
+
+class PublicClass {
+ /**
+ * This function is public and documented
+ */
+ fun publicDocumentedFunction(): String = ""
+
+ fun publicUndocumentedFunction(): String = ""
+
+ /**
+ * This function is internal and documented
+ */
+ internal fun internalDocumentedFunction(): String = ""
+
+ internal fun internalUndocumentedFunction(): String = ""
+
+ /**
+ * This function is private and documented
+ */
+ private fun privateDocumentedFunction(): String = ""
+
+ private fun privateUndocumentedFunction(): String = ""
+
+
+ /**
+ * This property is public and documented
+ */
+ val publicDocumentedProperty: Int = 0
+
+ val publicUndocumentedProperty: Int = 0
+
+ /**
+ * This property internal and documented
+ */
+ val internalDocumentedProperty: Int = 0
+
+ val internalUndocumentedProperty: Int = 0
+
+ /**
+ * This property private and documented
+ */
+ private val privateDocumentedProperty: Int = 0
+
+ private val privateUndocumentedProperty: Int = 0
+}
diff --git a/integration-tests/gradle/projects/it-multimodule-0/build.gradle.kts b/integration-tests/gradle/projects/it-multimodule-0/build.gradle.kts
new file mode 100644
index 00000000..29b7550c
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multimodule-0/build.gradle.kts
@@ -0,0 +1 @@
+apply(from = "../template.root.gradle.kts")
diff --git a/integration-tests/gradle/projects/it-multimodule-0/gradle.properties b/integration-tests/gradle/projects/it-multimodule-0/gradle.properties
new file mode 100644
index 00000000..7ebac3ad
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multimodule-0/gradle.properties
@@ -0,0 +1 @@
+dokka_it_kotlin_version=1.3.72
diff --git a/integration-tests/gradle/projects/it-multimodule-0/gradle/wrapper/gradle-wrapper.jar b/integration-tests/gradle/projects/it-multimodule-0/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..f3d88b1c
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multimodule-0/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/integration-tests/gradle/projects/it-multimodule-0/gradle/wrapper/gradle-wrapper.properties b/integration-tests/gradle/projects/it-multimodule-0/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..1b16c34a
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multimodule-0/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/integration-tests/gradle/projects/it-multimodule-0/gradlew b/integration-tests/gradle/projects/it-multimodule-0/gradlew
new file mode 100755
index 00000000..2fe81a7d
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multimodule-0/gradlew
@@ -0,0 +1,183 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/integration-tests/gradle/projects/it-multimodule-0/gradlew.bat b/integration-tests/gradle/projects/it-multimodule-0/gradlew.bat
new file mode 100644
index 00000000..24467a14
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multimodule-0/gradlew.bat
@@ -0,0 +1,100 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/integration-tests/gradle/projects/it-multimodule-0/moduleA/build.gradle.kts b/integration-tests/gradle/projects/it-multimodule-0/moduleA/build.gradle.kts
new file mode 100644
index 00000000..ab86c333
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multimodule-0/moduleA/build.gradle.kts
@@ -0,0 +1,6 @@
+plugins {
+ // TODO: File bug report for gradle: :moduleA:moduleB:dokkaHtml is missing kotlin gradle plugin from
+ // the runtime classpath during execution without this plugin in the parent project
+ kotlin("jvm")
+ id("org.jetbrains.dokka")
+}
diff --git a/integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleB/README.md b/integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleB/README.md
new file mode 100644
index 00000000..f8c52880
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleB/README.md
@@ -0,0 +1,2 @@
+# Module moduleB
+Here is some description for module B
diff --git a/integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleB/build.gradle.kts b/integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleB/build.gradle.kts
new file mode 100644
index 00000000..9492fdc8
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleB/build.gradle.kts
@@ -0,0 +1,8 @@
+plugins {
+ kotlin("jvm")
+ id("org.jetbrains.dokka")
+}
+
+dependencies {
+ implementation(kotlin("stdlib"))
+}
diff --git a/integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleB/src/main/kotlin/org/jetbrains/dokka/it/moduleB/ModuleB.kt b/integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleB/src/main/kotlin/org/jetbrains/dokka/it/moduleB/ModuleB.kt
new file mode 100644
index 00000000..430e2234
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleB/src/main/kotlin/org/jetbrains/dokka/it/moduleB/ModuleB.kt
@@ -0,0 +1,6 @@
+package org.jetbrains.dokka.it.moduleB
+
+@Suppress("unused")
+class ModuleB {
+ fun undocumentedPublicFunction() {}
+}
diff --git a/integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleC/README.md b/integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleC/README.md
new file mode 100644
index 00000000..4ead5671
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleC/README.md
@@ -0,0 +1,2 @@
+# Module moduleC
+Here is some description for module C
diff --git a/integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleC/build.gradle.kts b/integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleC/build.gradle.kts
new file mode 100644
index 00000000..9492fdc8
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleC/build.gradle.kts
@@ -0,0 +1,8 @@
+plugins {
+ kotlin("jvm")
+ id("org.jetbrains.dokka")
+}
+
+dependencies {
+ implementation(kotlin("stdlib"))
+}
diff --git a/integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleC/src/main/kotlin/org/jetbrains/dokka/it/moduleC/ModuleC.kt b/integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleC/src/main/kotlin/org/jetbrains/dokka/it/moduleC/ModuleC.kt
new file mode 100644
index 00000000..e14d68e0
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multimodule-0/moduleA/moduleC/src/main/kotlin/org/jetbrains/dokka/it/moduleC/ModuleC.kt
@@ -0,0 +1,6 @@
+package org.jetbrains.dokka.it.moduleC
+
+@Suppress("unused")
+class ModuleC {
+ fun undocumentedPublicFunction() {}
+}
diff --git a/integration-tests/gradle/projects/it-multimodule-0/settings.gradle.kts b/integration-tests/gradle/projects/it-multimodule-0/settings.gradle.kts
new file mode 100644
index 00000000..a5c89291
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multimodule-0/settings.gradle.kts
@@ -0,0 +1,5 @@
+apply(from = "../template.settings.gradle.kts")
+rootProject.name = "it-multimodule-0"
+include(":moduleA")
+include(":moduleA:moduleB")
+include(":moduleA:moduleC")
diff --git a/integration-tests/gradle/projects/it-multiplatform-0/build.gradle.kts b/integration-tests/gradle/projects/it-multiplatform-0/build.gradle.kts
new file mode 100644
index 00000000..247e4c15
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multiplatform-0/build.gradle.kts
@@ -0,0 +1,25 @@
+import org.jetbrains.dokka.gradle.DokkaTask
+
+plugins {
+ kotlin("multiplatform")
+ id("org.jetbrains.dokka")
+}
+
+apply(from = "../template.root.gradle.kts")
+
+kotlin {
+ jvm()
+ linuxX64("linux")
+ macosX64("macos")
+ js()
+}
+
+tasks.withType<DokkaTask> {
+ dokkaSourceSets {
+ create("commonMain")
+ create("jvmMain")
+ create("linuxMain")
+ create("macosMain")
+ create("jsMain")
+ }
+}
diff --git a/integration-tests/gradle/projects/it-multiplatform-0/gradle.properties b/integration-tests/gradle/projects/it-multiplatform-0/gradle.properties
new file mode 100644
index 00000000..7ebac3ad
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multiplatform-0/gradle.properties
@@ -0,0 +1 @@
+dokka_it_kotlin_version=1.3.72
diff --git a/integration-tests/gradle/projects/it-multiplatform-0/gradle/wrapper/gradle-wrapper.jar b/integration-tests/gradle/projects/it-multiplatform-0/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..f3d88b1c
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multiplatform-0/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/integration-tests/gradle/projects/it-multiplatform-0/gradle/wrapper/gradle-wrapper.properties b/integration-tests/gradle/projects/it-multiplatform-0/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..1b16c34a
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multiplatform-0/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/integration-tests/gradle/projects/it-multiplatform-0/gradlew b/integration-tests/gradle/projects/it-multiplatform-0/gradlew
new file mode 100755
index 00000000..2fe81a7d
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multiplatform-0/gradlew
@@ -0,0 +1,183 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/integration-tests/gradle/projects/it-multiplatform-0/gradlew.bat b/integration-tests/gradle/projects/it-multiplatform-0/gradlew.bat
new file mode 100644
index 00000000..24467a14
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multiplatform-0/gradlew.bat
@@ -0,0 +1,100 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/integration-tests/gradle/projects/it-multiplatform-0/settings.gradle.kts b/integration-tests/gradle/projects/it-multiplatform-0/settings.gradle.kts
new file mode 100644
index 00000000..1894bed8
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multiplatform-0/settings.gradle.kts
@@ -0,0 +1,2 @@
+apply(from = "../template.settings.gradle.kts")
+rootProject.name = "it-multiplatform-0"
diff --git a/integration-tests/gradle/projects/it-multiplatform-0/src/commonMain/kotlin/it/mpp0/CommonMainClass.kt b/integration-tests/gradle/projects/it-multiplatform-0/src/commonMain/kotlin/it/mpp0/CommonMainClass.kt
new file mode 100644
index 00000000..499a4f1e
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multiplatform-0/src/commonMain/kotlin/it/mpp0/CommonMainClass.kt
@@ -0,0 +1,8 @@
+package it.mpp0
+
+/**
+ * This class is defined in commonMain
+ */
+class CommonMainClass {
+ fun publicFunction(): String = "public"
+}
diff --git a/integration-tests/gradle/projects/it-multiplatform-0/src/commonMain/kotlin/it/mpp0/ExpectedClass.kt b/integration-tests/gradle/projects/it-multiplatform-0/src/commonMain/kotlin/it/mpp0/ExpectedClass.kt
new file mode 100644
index 00000000..e610b09a
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multiplatform-0/src/commonMain/kotlin/it/mpp0/ExpectedClass.kt
@@ -0,0 +1,5 @@
+package it.mpp0
+
+expect class ExpectedClass {
+ val platform: String
+}
diff --git a/integration-tests/gradle/projects/it-multiplatform-0/src/jsMain/kotlin/it/mpp0/ExpectedClass.kt b/integration-tests/gradle/projects/it-multiplatform-0/src/jsMain/kotlin/it/mpp0/ExpectedClass.kt
new file mode 100644
index 00000000..1e4a6d22
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multiplatform-0/src/jsMain/kotlin/it/mpp0/ExpectedClass.kt
@@ -0,0 +1,5 @@
+package it.mpp0
+
+actual class ExpectedClass {
+ actual val platform: String = "js"
+}
diff --git a/integration-tests/gradle/projects/it-multiplatform-0/src/jvmMain/kotlin/it/mpp0/ExpectedClass.kt b/integration-tests/gradle/projects/it-multiplatform-0/src/jvmMain/kotlin/it/mpp0/ExpectedClass.kt
new file mode 100644
index 00000000..8e7fa96e
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multiplatform-0/src/jvmMain/kotlin/it/mpp0/ExpectedClass.kt
@@ -0,0 +1,5 @@
+package it.mpp0
+
+actual class ExpectedClass {
+ actual val platform: String = "jvm"
+}
diff --git a/integration-tests/gradle/projects/it-multiplatform-0/src/linuxMain/kotlin/it/mpp0/ExpectedClass.kt b/integration-tests/gradle/projects/it-multiplatform-0/src/linuxMain/kotlin/it/mpp0/ExpectedClass.kt
new file mode 100644
index 00000000..19070a96
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multiplatform-0/src/linuxMain/kotlin/it/mpp0/ExpectedClass.kt
@@ -0,0 +1,5 @@
+package it.mpp0
+
+actual class ExpectedClass {
+ actual val platform: String = "linux"
+}
diff --git a/integration-tests/gradle/projects/it-multiplatform-0/src/macosMain/kotlin/it/mpp0/ExpectedClass.kt b/integration-tests/gradle/projects/it-multiplatform-0/src/macosMain/kotlin/it/mpp0/ExpectedClass.kt
new file mode 100644
index 00000000..7a4a8f75
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multiplatform-0/src/macosMain/kotlin/it/mpp0/ExpectedClass.kt
@@ -0,0 +1,5 @@
+package it.mpp0
+
+actual class ExpectedClass {
+ actual val platform: String = "macos"
+}
diff --git a/integration-tests/gradle/projects/template.root.gradle.kts b/integration-tests/gradle/projects/template.root.gradle.kts
new file mode 100644
index 00000000..51d199ff
--- /dev/null
+++ b/integration-tests/gradle/projects/template.root.gradle.kts
@@ -0,0 +1,18 @@
+allprojects {
+ repositories {
+ maven("https://dl.bintray.com/kotlin/kotlin-eap/")
+ maven("https://dl.bintray.com/kotlin/kotlin-dev/")
+ jcenter()
+ mavenLocal()
+ mavenCentral()
+ google()
+ }
+}
+
+afterEvaluate {
+ logger.quiet("Gradle version: ${gradle.gradleVersion}")
+ logger.quiet("Kotlin version: ${properties["dokka_it_kotlin_version"]}")
+ properties["dokka_it_android_gradle_plugin_version"]?.let { androidVersion ->
+ logger.quiet("Android version: $androidVersion")
+ }
+}
diff --git a/integration-tests/gradle/projects/template.settings.gradle.kts b/integration-tests/gradle/projects/template.settings.gradle.kts
new file mode 100644
index 00000000..7fe3c510
--- /dev/null
+++ b/integration-tests/gradle/projects/template.settings.gradle.kts
@@ -0,0 +1,37 @@
+@file:Suppress("LocalVariableName", "UnstableApiUsage")
+
+pluginManagement {
+ val dokka_it_kotlin_version: String by settings
+ val dokka_it_android_gradle_plugin_version: String? by settings
+
+ plugins {
+ id("org.jetbrains.kotlin.jvm") version dokka_it_kotlin_version
+ id("org.jetbrains.kotlin.android") version dokka_it_kotlin_version
+ id("org.jetbrains.kotlin.multiplatform") version dokka_it_kotlin_version
+ }
+
+ resolutionStrategy {
+ eachPlugin {
+ if (requested.id.id == "org.jetbrains.dokka") {
+ useModule("org.jetbrains.dokka:dokka-gradle-plugin:for-integration-tests-SNAPSHOT")
+ }
+
+ if (requested.id.id == "com.android.library") {
+ useModule("com.android.tools.build:gradle:$dokka_it_android_gradle_plugin_version")
+ }
+
+ if (requested.id.id == "com.android.application") {
+ useModule("com.android.tools.build:gradle:$dokka_it_android_gradle_plugin_version")
+ }
+ }
+ }
+ repositories {
+ maven("https://dl.bintray.com/kotlin/kotlin-eap")
+ maven("https://dl.bintray.com/kotlin/kotlin-dev/")
+ mavenLocal()
+ mavenCentral()
+ jcenter()
+ gradlePluginPortal()
+ google()
+ }
+}
diff --git a/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Android0GradleIntegrationTest.kt b/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Android0GradleIntegrationTest.kt
new file mode 100644
index 00000000..2a9d7a70
--- /dev/null
+++ b/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Android0GradleIntegrationTest.kt
@@ -0,0 +1,77 @@
+package org.jetbrains.dokka.it.gradle
+
+import org.gradle.testkit.runner.TaskOutcome
+import org.jetbrains.dokka.it.isAndroidSdkInstalled
+import org.jetbrains.dokka.it.isCI
+import org.junit.Assume
+import org.junit.runners.Parameterized.Parameters
+import java.io.File
+import kotlin.test.*
+
+class Android0GradleIntegrationTest(override val versions: BuildVersions) : AbstractGradleIntegrationTest() {
+
+ companion object {
+ @get:JvmStatic
+ @get:Parameters(name = "{0}")
+ val versions = BuildVersions.permutations(
+ gradleVersions = listOf("6.5.1", "5.6.4"),
+ kotlinVersions = listOf("1.3.72", "1.4-M3"),
+ androidGradlePluginVersions = listOf("3.5.3", "3.6.3")
+ ) + BuildVersions.permutations(
+ gradleVersions = listOf("6.5.1", "6.1.1"),
+ kotlinVersions = listOf("1.3.72", "1.4-M3"),
+ androidGradlePluginVersions = listOf("4.0.0")
+ ) + BuildVersions.permutations(
+ gradleVersions = listOf("6.5.1"),
+ kotlinVersions = listOf("1.3.72", "1.4-M3"),
+ androidGradlePluginVersions = listOf("4.1.0-beta02")
+ )
+ }
+
+ @BeforeTest
+ fun assumeAndroidInstallation() {
+ if (isCI) {
+ return
+ }
+ Assume.assumeTrue("Missing ANDROID_SDK_ROOT", isAndroidSdkInstalled)
+ }
+
+ @BeforeTest
+ fun prepareProjectFiles() {
+ val templateProjectDir = File("projects", "it-android-0")
+
+ templateProjectDir.listFiles().orEmpty()
+ .filter { it.isFile }
+ .filterNot { it.name == "local.properties" }
+ .filterNot { it.name.startsWith("gradlew") }
+ .forEach { topLevelFile -> topLevelFile.copyTo(File(projectDir, topLevelFile.name)) }
+
+ File(templateProjectDir, "src").copyRecursively(File(projectDir, "src"))
+ }
+
+ @Test
+ fun execute() {
+ val result = createGradleRunner("dokkaHtml", "-i", "-s").buildRelaxed()
+ assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":dokkaHtml")).outcome)
+
+ val htmlOutputDir = File(projectDir, "build/dokka/html")
+ assertTrue(htmlOutputDir.isDirectory, "Missing html output directory")
+
+ assertTrue(
+ htmlOutputDir.allHtmlFiles().count() > 0,
+ "Expected html files in html output directory"
+ )
+
+ htmlOutputDir.allHtmlFiles().forEach { file ->
+ assertContainsNoErrorClass(file)
+ assertNoUnresolvedLInks(file)
+ assertNoHrefToMissingLocalFileOrDirectory(file)
+ }
+
+ assertTrue(
+ htmlOutputDir.allHtmlFiles().any { file ->
+ "https://developer.android.com/reference/android/content/Context.html" in file.readText()
+ }, "Expected link to developer.android.com"
+ )
+ }
+}
diff --git a/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/BasicGradleIntegrationTest.kt b/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/BasicGradleIntegrationTest.kt
new file mode 100644
index 00000000..30b560e7
--- /dev/null
+++ b/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/BasicGradleIntegrationTest.kt
@@ -0,0 +1,99 @@
+package org.jetbrains.dokka.it.gradle
+
+import org.gradle.testkit.runner.TaskOutcome
+import org.junit.runners.Parameterized.Parameters
+import java.io.File
+import kotlin.test.*
+
+class BasicGradleIntegrationTest(override val versions: BuildVersions) : AbstractGradleIntegrationTest() {
+
+ companion object {
+ @get:JvmStatic
+ @get:Parameters(name = "{0}")
+ val versions = BuildVersions.permutations(
+ gradleVersions = listOf("6.5.1", "6.4.1", "6.3", "6.2.2", "6.1.1", "6.0", "5.6.4"),
+ kotlinVersions = listOf("1.3.30", "1.3.72", "1.4-M3")
+ )
+ }
+
+ @BeforeTest
+ fun prepareProjectFiles() {
+ val templateProjectDir = File("projects", "it-basic")
+
+ templateProjectDir.listFiles().orEmpty()
+ .filter { it.isFile }
+ .forEach { topLevelFile -> topLevelFile.copyTo(File(projectDir, topLevelFile.name)) }
+
+ File(templateProjectDir, "src").copyRecursively(File(projectDir, "src"))
+ }
+
+ @Test
+ fun execute() {
+ val result = createGradleRunner("dokkaHtml", "dokkaJavadoc", "dokkaGfm", "dokkaJekyll", "-i", "-s")
+ .buildRelaxed()
+
+ assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":dokkaHtml")).outcome)
+ assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":dokkaJavadoc")).outcome)
+ assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":dokkaGfm")).outcome)
+ assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":dokkaJekyll")).outcome)
+
+ File(projectDir, "build/dokka/html").assertKdocOutputDir()
+ File(projectDir, "build/dokka/javadoc").assertJavadocOutputDir()
+ File(projectDir, "build/dokka/gfm").assertGfmOutputDir()
+ File(projectDir, "build/dokka/jekyll").assertJekyllOutputDir()
+ }
+
+ private fun File.assertKdocOutputDir() {
+ assertTrue(isDirectory, "Missing dokka html output directory")
+
+ val imagesDir = File(this, "images")
+ assertTrue(imagesDir.isDirectory, "Missing images directory")
+
+ val scriptsDir = File(this, "scripts")
+ assertTrue(scriptsDir.isDirectory, "Missing scripts directory")
+
+ val stylesDir = File(this, "styles")
+ assertTrue(stylesDir.isDirectory, "Missing styles directory")
+
+ val navigationHtml = File(this, "navigation.html")
+ assertTrue(navigationHtml.isFile, "Missing navigation.html")
+
+ val moduleOutputDir = File(this, "-basic -project")
+ assertTrue(moduleOutputDir.isDirectory, "Missing module directory")
+
+ val moduleIndexHtml = File(moduleOutputDir, "index.html")
+ assertTrue(moduleIndexHtml.isFile, "Missing module index.html")
+
+ val modulePackageDir = File(moduleOutputDir, "it.basic")
+ assertTrue(modulePackageDir.isDirectory, "Missing it.basic package directory")
+
+ val modulePackageIndexHtml = File(modulePackageDir, "index.html")
+ assertTrue(modulePackageIndexHtml.isFile, "Missing module package index.html")
+
+ val moduleJavaPackageDir = File(moduleOutputDir, "it.basic.java")
+ assertTrue(moduleJavaPackageDir.isDirectory, "Missing it.basic.java package directory")
+
+ allHtmlFiles().forEach { file ->
+ assertContainsNoErrorClass(file)
+ assertNoUnresolvedLInks(file)
+ assertNoHrefToMissingLocalFileOrDirectory(file)
+ }
+
+ assertTrue(
+ allHtmlFiles().any { file -> "Basic Project" in file.readText() },
+ "Expected configured moduleDisplayName to be present in html"
+ )
+ }
+
+ private fun File.assertJavadocOutputDir() {
+ assertTrue(isDirectory, "Missing dokka javadoc output directory")
+ }
+
+ private fun File.assertGfmOutputDir() {
+ assertTrue(isDirectory, "Missing dokka gfm output directory")
+ }
+
+ private fun File.assertJekyllOutputDir() {
+ assertTrue(isDirectory, "Missing dokka jekyll output directory")
+ }
+}
diff --git a/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/BasicGroovyIntegrationTest.kt b/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/BasicGroovyIntegrationTest.kt
new file mode 100644
index 00000000..92b7ec40
--- /dev/null
+++ b/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/BasicGroovyIntegrationTest.kt
@@ -0,0 +1,98 @@
+package org.jetbrains.dokka.it.gradle
+
+import org.gradle.testkit.runner.TaskOutcome
+import org.junit.runners.Parameterized
+import java.io.File
+import kotlin.test.assertEquals
+import kotlin.test.assertNotNull
+import kotlin.test.assertTrue
+import kotlin.test.BeforeTest
+import kotlin.test.Test
+
+class BasicGroovyIntegrationTest(override val versions: BuildVersions) : AbstractGradleIntegrationTest() {
+
+ companion object {
+ @get:JvmStatic
+ @get:Parameterized.Parameters(name = "{0}")
+ val versions = BuildVersions.permutations(
+ gradleVersions = listOf("6.5.1", "5.6.4"),
+ kotlinVersions = listOf("1.4-M3")
+ )
+ }
+
+ @BeforeTest
+ fun prepareProjectFiles() {
+ val templateProjectDir = File("projects", "it-basic-groovy")
+
+ templateProjectDir.listFiles().orEmpty()
+ .filter { it.isFile }
+ .forEach { topLevelFile -> topLevelFile.copyTo(File(projectDir, topLevelFile.name)) }
+
+ File(templateProjectDir, "src").copyRecursively(File(projectDir, "src"))
+ }
+
+ @Test
+ fun execute() {
+ val result = createGradleRunner("dokkaHtml", "dokkaJavadoc", "dokkaGfm", "dokkaJekyll", "-i", "-s")
+ .buildRelaxed()
+
+ assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":dokkaHtml")).outcome)
+ assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":dokkaJavadoc")).outcome)
+ assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":dokkaGfm")).outcome)
+ assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":dokkaJekyll")).outcome)
+
+ File(projectDir, "build/dokka/customHtml").assertKdocOutputDir()
+ File(projectDir, "build/dokka/customJavadoc").assertJavadocOutputDir()
+ File(projectDir, "build/dokka/customGfm").assertGfmOutputDir()
+ File(projectDir, "build/dokka/customJekyll").assertJekyllOutputDir()
+ }
+
+ private fun File.assertKdocOutputDir() {
+ assertTrue(isDirectory, "Missing dokka html output directory")
+
+ val imagesDir = File(this, "images")
+ assertTrue(imagesDir.isDirectory, "Missing images directory")
+
+ val scriptsDir = File(this, "scripts")
+ assertTrue(scriptsDir.isDirectory, "Missing scripts directory")
+
+ val stylesDir = File(this, "styles")
+ assertTrue(stylesDir.isDirectory, "Missing styles directory")
+
+ val navigationHtml = File(this, "navigation.html")
+ assertTrue(navigationHtml.isFile, "Missing navigation.html")
+
+ val moduleOutputDir = File(this, "it-basic-groovy")
+ assertTrue(moduleOutputDir.isDirectory, "Missing module directory")
+
+ val moduleIndexHtml = File(moduleOutputDir, "index.html")
+ assertTrue(moduleIndexHtml.isFile, "Missing module index.html")
+
+ val modulePackageDir = File(moduleOutputDir, "it.basic")
+ assertTrue(modulePackageDir.isDirectory, "Missing it.basic package directory")
+
+ val modulePackageIndexHtml = File(modulePackageDir, "index.html")
+ assertTrue(modulePackageIndexHtml.isFile, "Missing module package index.html")
+
+ val moduleJavaPackageDir = File(moduleOutputDir, "it.basic.java")
+ assertTrue(moduleJavaPackageDir.isDirectory, "Missing it.basic.java package directory")
+
+ allHtmlFiles().forEach { file ->
+ assertContainsNoErrorClass(file)
+ assertNoUnresolvedLInks(file)
+ assertNoHrefToMissingLocalFileOrDirectory(file)
+ }
+ }
+
+ private fun File.assertJavadocOutputDir() {
+ assertTrue(isDirectory, "Missing dokka javadoc output directory")
+ }
+
+ private fun File.assertGfmOutputDir() {
+ assertTrue(isDirectory, "Missing dokka gfm output directory")
+ }
+
+ private fun File.assertJekyllOutputDir() {
+ assertTrue(isDirectory, "Missing dokka jekyll output directory")
+ }
+}
diff --git a/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Multimodule0IntegrationTest.kt b/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Multimodule0IntegrationTest.kt
new file mode 100644
index 00000000..390db3a0
--- /dev/null
+++ b/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Multimodule0IntegrationTest.kt
@@ -0,0 +1,61 @@
+package org.jetbrains.dokka.it.gradle
+
+import org.gradle.testkit.runner.TaskOutcome
+import org.junit.runners.Parameterized
+import java.io.File
+import kotlin.test.*
+
+class Multimodule0IntegrationTest(override val versions: BuildVersions) : AbstractGradleIntegrationTest() {
+ companion object {
+ @get:JvmStatic
+ @get:Parameterized.Parameters(name = "{0}")
+ val versions = BuildVersions.permutations(
+ gradleVersions = listOf("6.5.1", "6.1.1"),
+ kotlinVersions = listOf("1.4-M3")
+ )
+ }
+
+ @BeforeTest
+ fun prepareProjectFiles() {
+ val templateProjectDir = File("projects", "it-multimodule-0")
+ templateProjectDir.listFiles().orEmpty()
+ .filter { it.isFile }
+ .forEach { topLevelFile -> topLevelFile.copyTo(File(projectDir, topLevelFile.name)) }
+ File(templateProjectDir, "moduleA").copyRecursively(File(projectDir, "moduleA"))
+ }
+
+ @Test
+ fun execute() {
+ val result = createGradleRunner(":moduleA:dokkaHtmlMultimodule", "-i","-s").buildRelaxed()
+
+ assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":moduleA:dokkaHtmlMultimodule")).outcome)
+
+ val outputDir = File(projectDir, "moduleA/build/dokka/htmlMultimodule")
+ assertTrue(outputDir.isDirectory, "Missing dokka output directory")
+
+ assertTrue(
+ outputDir.allHtmlFiles().any(),
+ "Expected at least one html file being generated"
+ )
+
+ outputDir.allHtmlFiles().forEach { file ->
+ assertContainsNoErrorClass(file)
+ assertNoUnresolvedLInks(file)
+ assertNoHrefToMissingLocalFileOrDirectory(file)
+ }
+
+ val modulesFile = File(outputDir, "-modules.html")
+ assertTrue(modulesFile.isFile, "Missing -modules.html file")
+
+ val modulesFileText = modulesFile.readText()
+ assertTrue(
+ "moduleB" in modulesFileText,
+ "Expected moduleB being mentioned in -modules.html"
+ )
+ assertTrue(
+ "moduleC" in modulesFileText,
+ "Expected moduleC being mentioned in -modules.html"
+ )
+
+ }
+}
diff --git a/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Multiplatform0GradleIntegrationTest.kt b/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Multiplatform0GradleIntegrationTest.kt
new file mode 100644
index 00000000..6a3b9c83
--- /dev/null
+++ b/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Multiplatform0GradleIntegrationTest.kt
@@ -0,0 +1,43 @@
+package org.jetbrains.dokka.it.gradle
+
+import org.gradle.testkit.runner.TaskOutcome
+import org.junit.runners.Parameterized
+import java.io.File
+import kotlin.test.*
+
+class Multiplatform0GradleIntegrationTest(override val versions: BuildVersions) : AbstractGradleIntegrationTest() {
+
+ companion object {
+ @get:JvmStatic
+ @get:Parameterized.Parameters(name = "{0}")
+ val versions = BuildVersions.permutations(
+ gradleVersions = listOf("6.5.1", "6.1.1"),
+ kotlinVersions = listOf("1.3.30", "1.3.72", "1.4-M3")
+ )
+ }
+
+ @BeforeTest
+ fun prepareProjectFiles() {
+ val templateProjectDir = File("projects", "it-multiplatform-0")
+ templateProjectDir.listFiles().orEmpty()
+ .filter { it.isFile }
+ .forEach { topLevelFile -> topLevelFile.copyTo(File(projectDir, topLevelFile.name)) }
+ File(templateProjectDir, "src").copyRecursively(File(projectDir, "src"))
+ }
+
+ @Test
+ fun execute() {
+ val result = createGradleRunner("dokkaHtml", "-i", "-s").buildRelaxed()
+
+ assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":dokkaHtml")).outcome)
+
+ val dokkaOutputDir = File(projectDir, "build/dokka/html")
+ assertTrue(dokkaOutputDir.isDirectory, "Missing dokka output directory")
+
+ dokkaOutputDir.allHtmlFiles().forEach { file ->
+ assertContainsNoErrorClass(file)
+ assertNoUnresolvedLInks(file)
+ assertNoHrefToMissingLocalFileOrDirectory(file)
+ }
+ }
+}
diff --git a/integration-tests/gradle/src/main/kotlin/org/jetbrains/dokka/it/gradle/AbstractGradleIntegrationTest.kt b/integration-tests/gradle/src/main/kotlin/org/jetbrains/dokka/it/gradle/AbstractGradleIntegrationTest.kt
new file mode 100644
index 00000000..f852dc8b
--- /dev/null
+++ b/integration-tests/gradle/src/main/kotlin/org/jetbrains/dokka/it/gradle/AbstractGradleIntegrationTest.kt
@@ -0,0 +1,74 @@
+package org.jetbrains.dokka.it.gradle
+
+import org.gradle.testkit.runner.BuildResult
+import org.gradle.testkit.runner.GradleRunner
+import org.gradle.testkit.runner.internal.DefaultGradleRunner
+import org.gradle.tooling.GradleConnectionException
+import org.jetbrains.dokka.it.AbstractIntegrationTest
+import org.junit.Assume
+import org.junit.Assume.assumeFalse
+import org.junit.AssumptionViolatedException
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import java.io.File
+import kotlin.test.BeforeTest
+
+@RunWith(Parameterized::class)
+abstract class AbstractGradleIntegrationTest : AbstractIntegrationTest() {
+
+ abstract val versions: BuildVersions
+
+ @BeforeTest
+ fun copyTemplates() {
+ File("projects").listFiles().orEmpty()
+ .filter { it.isFile }
+ .filter { it.name.startsWith("template.") }
+ .forEach { file -> file.copyTo(File(temporaryTestFolder.root, file.name)) }
+ }
+
+ fun createGradleRunner(
+ vararg arguments: String
+ ): GradleRunner {
+ return GradleRunner.create()
+ .withProjectDir(projectDir)
+ .withGradleVersion(versions.gradleVersion.version)
+ .forwardOutput()
+ .withTestKitDir(File("build", "gradle-test-kit").absoluteFile)
+ .withArguments(
+ listOfNotNull(
+ "-Pkotlin_version=${versions.kotlinVersion}",
+ "-Pdokka_it_kotlin_version=${versions.kotlinVersion}",
+ versions.androidGradlePluginVersion?.let { androidVersion ->
+ "-Pdokka_it_android_gradle_plugin_version=$androidVersion"
+ },
+ * arguments
+ )
+ ).run { this as DefaultGradleRunner }
+ .withJvmArguments("-Xmx4G", "-XX:MaxMetaspaceSize=2G")
+ }
+
+ fun GradleRunner.buildRelaxed(): BuildResult {
+ return try {
+ build()
+ } catch (e: Throwable) {
+ val gradleConnectionException = e.withAllCauses().find { it is GradleConnectionException }
+ if (gradleConnectionException != null) {
+ gradleConnectionException.printStackTrace()
+ throw AssumptionViolatedException("Assumed Gradle connection", gradleConnectionException)
+
+ }
+ throw e
+ }
+ }
+}
+
+private fun Throwable.withAllCauses(): Sequence<Throwable> {
+ val root = this
+ return sequence {
+ yield(root)
+ val cause = root.cause
+ if (cause != null && cause != root) {
+ yieldAll(cause.withAllCauses())
+ }
+ }
+}
diff --git a/integration-tests/gradle/src/main/kotlin/org/jetbrains/dokka/it/gradle/BuildVersions.kt b/integration-tests/gradle/src/main/kotlin/org/jetbrains/dokka/it/gradle/BuildVersions.kt
new file mode 100644
index 00000000..84a7f1e8
--- /dev/null
+++ b/integration-tests/gradle/src/main/kotlin/org/jetbrains/dokka/it/gradle/BuildVersions.kt
@@ -0,0 +1,48 @@
+package org.jetbrains.dokka.it.gradle
+
+import org.gradle.util.GradleVersion
+
+data class BuildVersions(
+ val gradleVersion: GradleVersion,
+ val kotlinVersion: String,
+ val androidGradlePluginVersion: String? = null,
+) {
+ constructor(
+ gradleVersion: String,
+ kotlinVersion: String,
+ androidGradlePluginVersion: String? = null
+ ) : this(
+ gradleVersion = GradleVersion.version(gradleVersion),
+ kotlinVersion = kotlinVersion,
+ androidGradlePluginVersion = androidGradlePluginVersion
+ )
+
+ override fun toString(): String {
+ return buildString {
+ append("Gradle ${gradleVersion.version}, Kotlin $kotlinVersion")
+ if (androidGradlePluginVersion != null) {
+ append(", Android $androidGradlePluginVersion")
+ }
+ }
+ }
+
+ companion object {
+ fun permutations(
+ gradleVersions: List<String>,
+ kotlinVersions: List<String>,
+ androidGradlePluginVersions: List<String?> = listOf(null)
+ ): List<BuildVersions> {
+ return gradleVersions.distinct().flatMap { gradleVersion ->
+ kotlinVersions.distinct().flatMap { kotlinVersion ->
+ androidGradlePluginVersions.distinct().map { androidVersion ->
+ BuildVersions(
+ gradleVersion = gradleVersion,
+ kotlinVersion = kotlinVersion,
+ androidGradlePluginVersion = androidVersion
+ )
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/integration-tests/maven/build.gradle.kts b/integration-tests/maven/build.gradle.kts
new file mode 100644
index 00000000..1c747bbc
--- /dev/null
+++ b/integration-tests/maven/build.gradle.kts
@@ -0,0 +1,20 @@
+import org.jetbrains.SetupMaven
+import org.jetbrains.dependsOnMavenLocalPublication
+
+evaluationDependsOn(":runners:maven-plugin")
+
+dependencies {
+ implementation(kotlin("stdlib"))
+ implementation(kotlin("test-junit"))
+}
+
+tasks.integrationTest {
+ dependsOnMavenLocalPublication()
+
+ val setupMavenTask = project(":runners:maven-plugin").tasks.withType<SetupMaven>().single()
+ dependsOn(setupMavenTask)
+
+ val dokka_version: String by project
+ environment("DOKKA_VERSION", dokka_version)
+ environment("MVN_BINARY_PATH", setupMavenTask.mvn.absolutePath)
+}
diff --git a/integration-tests/maven/projects/it-maven/pom.xml b/integration-tests/maven/projects/it-maven/pom.xml
new file mode 100644
index 00000000..c6e0ef45
--- /dev/null
+++ b/integration-tests/maven/projects/it-maven/pom.xml
@@ -0,0 +1,172 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.jetbrains.dokka</groupId>
+ <artifactId>it-maven</artifactId>
+ <version>1.0-SNAPSHOT</version>
+
+ <properties>
+ <kotlin.version>1.3.72</kotlin.version>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-maven-plugin</artifactId>
+ <version>${kotlin.version}</version>
+ <executions>
+ <execution>
+ <id>compile</id>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ <configuration>
+ <sourceDirs>
+ <sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
+ <sourceDir>${project.basedir}/src/main/java</sourceDir>
+ </sourceDirs>
+ </configuration>
+ </execution>
+ <execution>
+ <id>test-compile</id>
+ <goals>
+ <goal>test-compile</goal>
+ </goals>
+ <configuration>
+ <sourceDirs>
+ <sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
+ <sourceDir>${project.basedir}/src/test/java</sourceDir>
+ </sourceDirs>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.5.1</version>
+ <executions>
+ <!-- Replacing default-compile as it is treated specially by maven -->
+ <execution>
+ <id>default-compile</id>
+ <phase>none</phase>
+ </execution>
+ <!-- Replacing default-testCompile as it is treated specially by maven -->
+ <execution>
+ <id>default-testCompile</id>
+ <phase>none</phase>
+ </execution>
+ <execution>
+ <id>java-compile</id>
+ <phase>compile</phase>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>java-test-compile</id>
+ <phase>test-compile</phase>
+ <goals>
+ <goal>testCompile</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.jetbrains.dokka</groupId>
+ <artifactId>dokka-maven-plugin</artifactId>
+ <version>$dokka_version</version>
+ <executions>
+ <execution>
+ <phase>pre-site</phase>
+ <goals>
+ <goal>dokka</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+
+ <!-- Set to true to skip dokka task, default: false -->
+ <skip>false</skip>
+
+ <!-- Default: ${project.artifactId} -->
+ <moduleDisplayName>Maven Integration Test Module</moduleDisplayName>
+
+ <!-- Default: ${project.basedir}/target/dokka -->
+ <outputDir>${project.basedir}/output</outputDir>
+
+ <!-- Use default or set to custom path to cache directory to enable package-list caching. -->
+ <!-- When set to default, caches stored in $USER_HOME/.cache/dokka -->
+ <cacheRoot>default</cacheRoot>
+
+
+ <!-- Used for linking to JDK, default: 6 -->
+ <jdkVersion>8</jdkVersion>
+
+ <!-- Do not output deprecated members, applies globally, can be overridden by packageOptions -->
+ <skipDeprecated>false</skipDeprecated>
+ <!-- Emit warnings about not documented members, applies globally, also can be overridden by packageOptions -->
+ <reportUndocumented>true</reportUndocumented>
+ <!-- Do not create index pages for empty packages -->
+ <skipEmptyPackages>true</skipEmptyPackages>
+
+ <!-- Short form list of sourceRoots, by default, set to ${project.compileSourceRoots} -->
+ <sourceDirectories>
+ <dir>${project.basedir}/src/main/kotlin</dir>
+ <dir>${project.basedir}/src/main/java</dir>
+ </sourceDirectories>
+
+
+ <!-- Disable linking to online kotlin-stdlib documentation -->
+ <noStdlibLink>false</noStdlibLink>
+
+ <!-- Disable linking to online JDK documentation -->
+ <noJdkLink>false</noJdkLink>
+
+ <!-- Allows to customize documentation generation options on a per-package basis -->
+ <perPackageOptions>
+ <packageOptions>
+ <!-- Will match kotlin and all sub-packages of it -->
+ <prefix>kotlin</prefix>
+
+ <!-- All options are optional, default values are below: -->
+ <skipDeprecated>false</skipDeprecated>
+ <!-- Emit warnings about not documented members -->
+ <reportUndocumented>true</reportUndocumented>
+ <includeNonPublic>false</includeNonPublic>
+ </packageOptions>
+ </perPackageOptions>
+ </configuration>
+ </plugin>
+ </plugins>
+ <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
+ <testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
+ </build>
+
+ <pluginRepositories>
+ <pluginRepository>
+ <id>kotlin-eap</id>
+ <url>https://dl.bintray.com/kotlin/kotlin-eap/</url>
+ </pluginRepository>
+ <pluginRepository>
+ <id>kotlin-dev</id>
+ <url>https://dl.bintray.com/kotlin/kotlin-dev/</url>
+ </pluginRepository>
+ <pluginRepository>
+ <id>jcenter</id>
+ <name>JCenter</name>
+ <url>https://jcenter.bintray.com/</url>
+ </pluginRepository>
+ </pluginRepositories>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-stdlib</artifactId>
+ <version>${kotlin.version}</version>
+ </dependency>
+ </dependencies>
+
+
+</project>
diff --git a/integration-tests/maven/projects/it-maven/src/main/java/it/basic/java/SampleJavaClass.java b/integration-tests/maven/projects/it-maven/src/main/java/it/basic/java/SampleJavaClass.java
new file mode 100644
index 00000000..e08bb66a
--- /dev/null
+++ b/integration-tests/maven/projects/it-maven/src/main/java/it/basic/java/SampleJavaClass.java
@@ -0,0 +1,22 @@
+package it.basic.java;
+
+import it.basic.PublicClass;
+
+/**
+ * This class is, unlike {@link PublicClass}, written in Java
+ */
+@SuppressWarnings("unused")
+public class SampleJavaClass {
+
+ /**
+ * @return Empty instance of {@link PublicClass}
+ */
+ public PublicClass publicDocumentedFunction() {
+ return new PublicClass();
+ }
+
+
+ public PublicClass publicUndocumentedFunction() {
+ return new PublicClass();
+ }
+}
diff --git a/integration-tests/maven/projects/it-maven/src/main/kotlin/it/basic/PublicClass.kt b/integration-tests/maven/projects/it-maven/src/main/kotlin/it/basic/PublicClass.kt
new file mode 100644
index 00000000..71bc7e63
--- /dev/null
+++ b/integration-tests/maven/projects/it-maven/src/main/kotlin/it/basic/PublicClass.kt
@@ -0,0 +1,48 @@
+@file:Suppress("unused")
+
+package it.basic
+
+class PublicClass {
+ /**
+ * This function is public and documented
+ */
+ fun publicDocumentedFunction(): String = ""
+
+ fun publicUndocumentedFunction(): String = ""
+
+ /**
+ * This function is internal and documented
+ */
+ internal fun internalDocumentedFunction(): String = ""
+
+ internal fun internalUndocumentedFunction(): String = ""
+
+ /**
+ * This function is private and documented
+ */
+ private fun privateDocumentedFunction(): String = ""
+
+ private fun privateUndocumentedFunction(): String = ""
+
+
+ /**
+ * This property is public and documented
+ */
+ val publicDocumentedProperty: Int = 0
+
+ val publicUndocumentedProperty: Int = 0
+
+ /**
+ * This property internal and documented
+ */
+ val internalDocumentedProperty: Int = 0
+
+ val internalUndocumentedProperty: Int = 0
+
+ /**
+ * This property private and documented
+ */
+ private val privateDocumentedProperty: Int = 0
+
+ private val privateUndocumentedProperty: Int = 0
+}
diff --git a/integration-tests/maven/src/integrationTest/kotlin/org/jetbrains/dokka/it/maven/MavenIntegrationTest.kt b/integration-tests/maven/src/integrationTest/kotlin/org/jetbrains/dokka/it/maven/MavenIntegrationTest.kt
new file mode 100644
index 00000000..86cc2f41
--- /dev/null
+++ b/integration-tests/maven/src/integrationTest/kotlin/org/jetbrains/dokka/it/maven/MavenIntegrationTest.kt
@@ -0,0 +1,132 @@
+package org.jetbrains.dokka.it.maven
+
+import org.jetbrains.dokka.it.AbstractIntegrationTest
+import org.jetbrains.dokka.it.awaitProcessResult
+import org.jetbrains.dokka.it.ProcessResult
+import java.io.File
+import kotlin.test.BeforeTest
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+
+class MavenIntegrationTest : AbstractIntegrationTest() {
+
+ private val currentDokkaVersion: String = checkNotNull(System.getenv("DOKKA_VERSION"))
+
+ private val mavenBinaryFile: File = File(checkNotNull(System.getenv("MVN_BINARY_PATH")))
+
+ @BeforeTest
+ fun prepareProjectFiles() {
+ val templateProjectDir = File("projects", "it-maven")
+ templateProjectDir.copyRecursively(projectDir)
+ val pomXml = File(projectDir, "pom.xml")
+ assertTrue(pomXml.isFile)
+ pomXml.apply {
+ writeText(readText().replace("\$dokka_version", currentDokkaVersion))
+ }
+ }
+
+ @Test
+ fun `dokka dokka`() {
+ val result = ProcessBuilder().directory(projectDir)
+ .command(mavenBinaryFile.absolutePath, "dokka:dokka", "-U", "-e").start().awaitProcessResult()
+
+ diagnosticAsserts(result)
+
+ val dokkaOutputDir = File(projectDir, "output")
+ assertTrue(dokkaOutputDir.isDirectory, "Missing dokka output directory")
+
+ val imagesDir = File(dokkaOutputDir, "images")
+ assertTrue(imagesDir.isDirectory, "Missing images directory")
+
+ val scriptsDir = File(dokkaOutputDir, "scripts")
+ assertTrue(scriptsDir.isDirectory, "Missing scripts directory")
+
+ val stylesDir = File(dokkaOutputDir, "styles")
+ assertTrue(stylesDir.isDirectory, "Missing styles directory")
+
+ val navigationHtml = File(dokkaOutputDir, "navigation.html")
+ assertTrue(navigationHtml.isFile, "Missing navigation.html")
+
+ projectDir.allHtmlFiles().forEach { file ->
+ assertContainsNoErrorClass(file)
+ assertNoUnresolvedLInks(file)
+ }
+ }
+
+ @Test
+ fun `dokka javadoc`() {
+ val result = ProcessBuilder().directory(projectDir)
+ .command(mavenBinaryFile.absolutePath, "dokka:javadoc", "-U", "-e").start().awaitProcessResult()
+
+ diagnosticAsserts(result)
+
+ val dokkaOutputDir = File(projectDir, "output")
+ assertTrue(dokkaOutputDir.isDirectory, "Missing dokka output directory")
+
+ val scriptsDir = File(dokkaOutputDir, "jquery")
+ assertTrue(scriptsDir.isDirectory, "Missing jquery directory")
+
+ val stylesDir = File(dokkaOutputDir, "resources")
+ assertTrue(stylesDir.isDirectory, "Missing resources directory")
+
+ projectDir.allHtmlFiles().forEach { file ->
+ assertContainsNoErrorClass(file)
+ assertNoUnresolvedLInks(file)
+ }
+ }
+
+ @Test
+ fun `dokka javadocJar`() {
+ val result = ProcessBuilder().directory(projectDir)
+ .command(mavenBinaryFile.absolutePath, "dokka:javadocJar", "-U", "-e").start().awaitProcessResult()
+
+ diagnosticAsserts(result)
+
+ val dokkaOutputDir = File(projectDir, "output")
+ assertTrue(dokkaOutputDir.isDirectory, "Missing dokka output directory")
+
+ val scriptsDir = File(dokkaOutputDir, "jquery")
+ assertTrue(scriptsDir.isDirectory, "Missing jquery directory")
+
+ val stylesDir = File(dokkaOutputDir, "resources")
+ assertTrue(stylesDir.isDirectory, "Missing resources directory")
+
+ val dokkaTargetDir = File(projectDir, "target")
+ assertTrue(dokkaOutputDir.isDirectory, "Missing dokka target directory")
+
+ val jarFile = File(dokkaTargetDir, "it-maven-1.0-SNAPSHOT-javadoc.jar")
+ assertTrue(jarFile.isFile, "Missing dokka jar file")
+
+ projectDir.allHtmlFiles().forEach { file ->
+ assertContainsNoErrorClass(file)
+ assertNoUnresolvedLInks(file)
+ }
+ }
+
+ private fun diagnosticAsserts(result: ProcessResult) {
+ assertEquals(0, result.exitCode, "Expected exitCode 0 (Success)")
+
+ val extensionLoadedRegex = Regex("""Extension: org\.jetbrains\.dokka\.base\.DokkaBase""")
+ val amountOfExtensionsLoaded = extensionLoadedRegex.findAll(result.output).count()
+
+ assertTrue(
+ amountOfExtensionsLoaded > 10,
+ "Expected more than 10 extensions being present (found $amountOfExtensionsLoaded)"
+ )
+
+ val undocumentedReportRegex = Regex("""Undocumented:""")
+ val amountOfUndocumentedReports = undocumentedReportRegex.findAll(result.output).count()
+ assertTrue(
+ amountOfUndocumentedReports > 0,
+ "Expected at least one report of undocumented code (found $amountOfUndocumentedReports)"
+ )
+
+ val undocumentedJavaReportRegex = Regex("""Undocumented: it\.basic\.java""")
+ val amountOfUndocumentedJavaReports = undocumentedJavaReportRegex.findAll(result.output).count()
+ assertTrue(
+ amountOfUndocumentedJavaReports > 0,
+ "Expected at least one report of undocumented java code (found $amountOfUndocumentedJavaReports)"
+ )
+ }
+}
diff --git a/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/AbstractIntegrationTest.kt b/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/AbstractIntegrationTest.kt
new file mode 100644
index 00000000..aeebe552
--- /dev/null
+++ b/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/AbstractIntegrationTest.kt
@@ -0,0 +1,71 @@
+package org.jetbrains.dokka.it
+
+import org.jsoup.Jsoup
+import org.junit.Rule
+import org.junit.rules.TemporaryFolder
+import java.io.File
+import kotlin.test.assertFalse
+import kotlin.test.assertTrue
+
+abstract class AbstractIntegrationTest {
+
+ @get:Rule
+ val temporaryTestFolder = TemporaryFolder()
+
+ val projectDir get() = File(temporaryTestFolder.root, "project")
+
+ fun File.allDescendentsWithExtension(extension: String): Sequence<File> {
+ return this.walkTopDown().filter { it.isFile && it.extension == extension }
+ }
+
+ fun File.allHtmlFiles(): Sequence<File> {
+ return allDescendentsWithExtension("html")
+ }
+
+ protected fun assertContainsNoErrorClass(file: File) {
+ val fileText = file.readText()
+ assertFalse(
+ fileText.contains("ERROR CLASS", ignoreCase = true),
+ "Unexpected `ERROR CLASS` in ${file.path}\n" + fileText
+ )
+ }
+
+ protected fun assertNoUnresolvedLInks(file: File) {
+ val regex = Regex("[\"']#[\"']")
+ val fileText = file.readText()
+ assertFalse(
+ fileText.contains(regex),
+ "Unexpected unresolved link in ${file.path}\n" + fileText
+ )
+ }
+
+ protected fun assertNoHrefToMissingLocalFileOrDirectory(
+ file: File, fileExtensions: Set<String> = setOf("html")
+ ) {
+ val fileText = file.readText()
+ val html = Jsoup.parse(fileText)
+ html.allElements.toList().forEach { element ->
+ val href = (element.attr("href") ?: return@forEach)
+ if (href.startsWith("https")) return@forEach
+ if (href.startsWith("http")) return@forEach
+
+ val hrefWithoutAnchors = if (href.contains("#")) {
+ val hrefSplits = href.split("#")
+ if (hrefSplits.count() != 2) return@forEach
+ hrefSplits.first()
+ } else href
+
+ val targetFile = File(file.parent, hrefWithoutAnchors)
+ if (targetFile.extension.isNotEmpty() && targetFile.extension !in fileExtensions) return@forEach
+
+ if (
+ targetFile.extension.isEmpty() || targetFile.extension == "html" && !href.startsWith("#")) {
+ assertTrue(
+ targetFile.exists(),
+ "${file.relativeTo(projectDir).path}: href=\"$href\"\n" +
+ "file does not exist: ${targetFile.relativeTo(projectDir).path}"
+ )
+ }
+ }
+ }
+}
diff --git a/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/environmentUtils.kt b/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/environmentUtils.kt
new file mode 100644
index 00000000..eadf5a8c
--- /dev/null
+++ b/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/environmentUtils.kt
@@ -0,0 +1,16 @@
+package org.jetbrains.dokka.it
+
+import java.io.File
+
+/**
+ * Indicating whether or not the current machine executing the test is a CI
+ */
+val isCI: Boolean get() = System.getenv("CI") == "true"
+
+val isAndroidSdkInstalled: Boolean = System.getenv("ANDROID_SDK_ROOT") != null ||
+ System.getenv("ANDROID_HOME") != null
+
+val isMavenInstalled: Boolean = System.getenv("PATH").orEmpty()
+ .split(File.pathSeparator)
+ .flatMap { pathElement -> File(pathElement).listFiles().orEmpty().toList() }
+ .any { pathElement -> "mvn" == pathElement.name }
diff --git a/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/processUtils.kt b/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/processUtils.kt
new file mode 100644
index 00000000..d2c048ac
--- /dev/null
+++ b/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/processUtils.kt
@@ -0,0 +1,51 @@
+package org.jetbrains.dokka.it
+
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.async
+import kotlinx.coroutines.runBlocking
+import kotlin.concurrent.thread
+
+class ProcessResult(
+ val exitCode: Int,
+ val output: String
+)
+
+fun Process.awaitProcessResult() = runBlocking {
+ val exitCode = async { awaitExitCode() }
+ val output = async { awaitOutput() }
+ ProcessResult(
+ exitCode.await(),
+ output.await()
+ )
+}
+
+private suspend fun Process.awaitExitCode(): Int {
+ val deferred = CompletableDeferred<Int>()
+ thread {
+ try {
+ deferred.complete(this.waitFor())
+ } catch (e: Throwable) {
+ deferred.completeExceptionally(e)
+ }
+ }
+
+ return deferred.await()
+}
+
+private suspend fun Process.awaitOutput(): String {
+ val deferred = CompletableDeferred<String>()
+ thread {
+ try {
+ var string = ""
+ this.inputStream.bufferedReader().forEachLine { line ->
+ println(line)
+ string += line + System.lineSeparator()
+ }
+ deferred.complete(string)
+ } catch (e: Throwable) {
+ deferred.completeExceptionally(e)
+ }
+ }
+
+ return deferred.await()
+}