aboutsummaryrefslogtreecommitdiff
path: root/runners
diff options
context:
space:
mode:
authorSimon Ogorodnik <Simon.Ogorodnik@jetbrains.com>2017-06-16 22:47:52 +0300
committerSimon Ogorodnik <Simon.Ogorodnik@jetbrains.com>2017-06-20 16:15:48 +0300
commit60858d8697231674c055bd30b34950d9859a6f32 (patch)
tree225117ac760bd952ac7e35125d596339158a7ecf /runners
parent558c6b67fafb73c97db9ce1eeadfd4fcbb911134 (diff)
downloaddokka-60858d8697231674c055bd30b34950d9859a6f32.tar.gz
dokka-60858d8697231674c055bd30b34950d9859a6f32.tar.bz2
dokka-60858d8697231674c055bd30b34950d9859a6f32.zip
Add gradle integration tests
Diffstat (limited to 'runners')
-rw-r--r--runners/android-gradle-plugin/build.gradle2
-rw-r--r--runners/build.gradle2
-rw-r--r--runners/gradle-integration-tests/build.gradle45
-rw-r--r--runners/gradle-integration-tests/src/test/java/com/intellij/rt/execution/junit/FileComparisonFailure.java39
-rw-r--r--runners/gradle-integration-tests/src/test/java/com/intellij/rt/execution/junit/KnownException.java6
-rw-r--r--runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaGradleTest.kt106
-rw-r--r--runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/BasicTest.kt51
-rw-r--r--runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/MultiProjectSingleOutTest.kt54
-rw-r--r--runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/Utils.kt59
-rw-r--r--runners/gradle-integration-tests/testData/basic/build.gradle39
-rw-r--r--runners/gradle-integration-tests/testData/basic/fileTree.txt30
-rw-r--r--runners/gradle-integration-tests/testData/basic/settings.gradle1
-rw-r--r--runners/gradle-integration-tests/testData/basic/src/main/kotlin/demo/HelloWorld.kt41
-rw-r--r--runners/gradle-integration-tests/testData/multiProjectSingleOut/build.gradle32
-rw-r--r--runners/gradle-integration-tests/testData/multiProjectSingleOut/fileTree.txt33
-rw-r--r--runners/gradle-integration-tests/testData/multiProjectSingleOut/settings.gradle3
-rw-r--r--runners/gradle-integration-tests/testData/multiProjectSingleOut/subA/build.gradle6
-rw-r--r--runners/gradle-integration-tests/testData/multiProjectSingleOut/subA/src/main/kotlin/module.kt31
-rw-r--r--runners/gradle-integration-tests/testData/multiProjectSingleOut/subB/build.gradle7
-rw-r--r--runners/gradle-integration-tests/testData/multiProjectSingleOut/subB/src/main/kotlin/module.kt31
20 files changed, 615 insertions, 3 deletions
diff --git a/runners/android-gradle-plugin/build.gradle b/runners/android-gradle-plugin/build.gradle
index 01b9d3f0..dc3d2ce3 100644
--- a/runners/android-gradle-plugin/build.gradle
+++ b/runners/android-gradle-plugin/build.gradle
@@ -26,8 +26,6 @@ dependencies {
provided gradleApi()
provided localGroovy()
-
- provided 'com.android.tools.build:gradle:2.3.0'
}
task sourceJar(type: Jar) {
diff --git a/runners/build.gradle b/runners/build.gradle
index e171800b..f1d2873c 100644
--- a/runners/build.gradle
+++ b/runners/build.gradle
@@ -6,7 +6,7 @@ configure([project("ant"), project("cli"), project("fatjar"), project("maven-plu
}
}
-configure([project("gradle-plugin"), project("android-gradle-plugin")]) {
+configure([project("gradle-plugin"), project("android-gradle-plugin"), project("gradle-integration-tests")]) {
buildscript {
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_for_gradle_version"
diff --git a/runners/gradle-integration-tests/build.gradle b/runners/gradle-integration-tests/build.gradle
new file mode 100644
index 00000000..179b6455
--- /dev/null
+++ b/runners/gradle-integration-tests/build.gradle
@@ -0,0 +1,45 @@
+
+
+apply plugin: 'kotlin'
+
+
+configurations {
+ dokkaPlugin
+ dokkaAndroidPlugin
+ dokkaFatJar
+}
+
+dependencies {
+
+ testCompile group: 'org.jetbrains.kotlin', name: 'kotlin-runtime', version: kotlin_for_gradle_version
+ testCompile group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: kotlin_for_gradle_version
+ testCompile group: 'org.jetbrains.kotlin', name: 'kotlin-test', version: kotlin_for_gradle_version
+
+ dokkaPlugin project(path: ':runners:gradle-plugin', configuration: 'shadow')
+ dokkaAndroidPlugin project(path: ':runners:android-gradle-plugin', configuration: 'shadow')
+ dokkaFatJar project(path: ":runners:fatjar", configuration: 'shadow')
+
+ testCompile group: 'junit', name: 'junit', version: '4.12'
+ testCompile gradleTestKit()
+}
+
+
+
+task createClasspathManifest {
+ def outputDir = file("$buildDir/$name")
+
+ inputs.files(configurations.dokkaPlugin + configurations.dokkaAndroidPlugin + configurations.dokkaFatJar)
+ outputs.dir outputDir
+
+ doLast {
+ outputDir.mkdirs()
+ file("$outputDir/dokka-plugin-classpath.txt").text = configurations.dokkaPlugin.join("\n")
+ file("$outputDir/android-dokka-plugin-classpath.txt").text = configurations.dokkaAndroidPlugin.join("\n")
+ file("$outputDir/fatjar.txt").text = configurations.dokkaFatJar.join("\n")
+ }
+}
+
+
+createClasspathManifest.mustRunAfter project(":runners:fatjar").shadowJar
+testClasses.dependsOn project(":runners:fatjar").shadowJar
+testClasses.dependsOn createClasspathManifest \ No newline at end of file
diff --git a/runners/gradle-integration-tests/src/test/java/com/intellij/rt/execution/junit/FileComparisonFailure.java b/runners/gradle-integration-tests/src/test/java/com/intellij/rt/execution/junit/FileComparisonFailure.java
new file mode 100644
index 00000000..cbb1cc3c
--- /dev/null
+++ b/runners/gradle-integration-tests/src/test/java/com/intellij/rt/execution/junit/FileComparisonFailure.java
@@ -0,0 +1,39 @@
+
+package com.intellij.rt.execution.junit;
+
+import junit.framework.ComparisonFailure;
+
+public class FileComparisonFailure extends ComparisonFailure implements KnownException {
+ private final String myExpected;
+ private final String myActual;
+ private final String myFilePath;
+ private final String myActualFilePath;
+
+ public FileComparisonFailure(String message, String expected, String actual, String filePath) {
+ this(message, expected, actual, filePath, (String)null);
+ }
+
+ public FileComparisonFailure(String message, String expected, String actual, String expectedFilePath, String actualFilePath) {
+ super(message, expected, actual);
+ this.myExpected = expected;
+ this.myActual = actual;
+ this.myFilePath = expectedFilePath;
+ this.myActualFilePath = actualFilePath;
+ }
+
+ public String getFilePath() {
+ return this.myFilePath;
+ }
+
+ public String getActualFilePath() {
+ return this.myActualFilePath;
+ }
+
+ public String getExpected() {
+ return this.myExpected;
+ }
+
+ public String getActual() {
+ return this.myActual;
+ }
+}
diff --git a/runners/gradle-integration-tests/src/test/java/com/intellij/rt/execution/junit/KnownException.java b/runners/gradle-integration-tests/src/test/java/com/intellij/rt/execution/junit/KnownException.java
new file mode 100644
index 00000000..c24653ea
--- /dev/null
+++ b/runners/gradle-integration-tests/src/test/java/com/intellij/rt/execution/junit/KnownException.java
@@ -0,0 +1,6 @@
+
+package com.intellij.rt.execution.junit;
+
+interface KnownException {
+
+}
diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaGradleTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaGradleTest.kt
new file mode 100644
index 00000000..f93e1868
--- /dev/null
+++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaGradleTest.kt
@@ -0,0 +1,106 @@
+package org.jetbrains.dokka.gradle
+
+
+import com.intellij.rt.execution.junit.FileComparisonFailure
+import org.gradle.testkit.runner.GradleRunner
+import org.junit.Rule
+import org.junit.rules.TemporaryFolder
+import java.io.File
+import java.nio.file.Files
+import java.nio.file.Paths
+
+
+val testDataFolder = Paths.get("testData")
+
+val pluginClasspathData = Paths.get("build", "createClasspathManifest", "dokka-plugin-classpath.txt")
+val androidPluginClasspathData = pluginClasspathData.resolveSibling("android-dokka-plugin-classpath.txt")
+
+val dokkaFatJarPathData = pluginClasspathData.resolveSibling("fatjar.txt")
+
+abstract class AbstractDokkaGradleTest {
+ @get:Rule val testProjectDir = TemporaryFolder()
+
+ open val pluginClasspath: List<File> = pluginClasspathData.toFile().readLines().map { File(it) }
+
+ fun checkOutputStructure(expected: String, actualSubpath: String) {
+ val expectedPath = testDataFolder.resolve(expected)
+ val actualPath = testProjectDir.root.toPath().resolve(actualSubpath).normalize()
+
+ assertEqualsIgnoringSeparators(expectedPath.toFile(), buildString {
+ actualPath.toFile().writeStructure(this, File(actualPath.toFile(), "."))
+ })
+ }
+
+ fun checkNoErrorClasses(actualSubpath: String, extension: String = "html", errorClassMarker: String = "ERROR CLASS") {
+ val actualPath = testProjectDir.root.toPath().resolve(actualSubpath).normalize()
+ var checked = 0
+ Files.walk(actualPath).filter { Files.isRegularFile(it) && it.fileName.toString().endsWith(".$extension") }.forEach {
+ val text = it.toFile().readText()
+
+ val noErrorClasses = text.replace(errorClassMarker, "?!")
+
+ if (noErrorClasses != text) {
+ throw FileComparisonFailure("", noErrorClasses, text, null)
+ }
+
+ checked++
+ }
+ println("$checked files checked for error classes")
+ }
+
+ fun checkNoUnresolvedLinks(actualSubpath: String, extension: String = "html", marker: Regex = "[\"']#[\"']".toRegex()) {
+ val actualPath = testProjectDir.root.toPath().resolve(actualSubpath).normalize()
+ var checked = 0
+ Files.walk(actualPath).filter { Files.isRegularFile(it) && it.fileName.toString().endsWith(".$extension") }.forEach {
+ val text = it.toFile().readText()
+
+ val noErrorClasses = text.replace(marker, "?!")
+
+ if (noErrorClasses != text) {
+ throw FileComparisonFailure("", noErrorClasses, text, null)
+ }
+
+ checked++
+ }
+ println("$checked files checked for unresolved links")
+ }
+
+ fun checkExternalLink(actualSubpath: String, linkBody: String, fullLink: String, extension: String = "html") {
+ val match = "!!match!!"
+ val notMatch = "!!not-match!!"
+
+ val actualPath = testProjectDir.root.toPath().resolve(actualSubpath).normalize()
+ var checked = 0
+ var totalEntries = 0
+ Files.walk(actualPath).filter { Files.isRegularFile(it) && it.fileName.toString().endsWith(".$extension") }.forEach {
+ val text = it.toFile().readText()
+
+ val textWithoutMatches = text.replace(fullLink, match)
+
+ val textWithoutNonMatches = textWithoutMatches.replace(linkBody, notMatch)
+
+ if (textWithoutNonMatches != textWithoutMatches) {
+
+ val expected = textWithoutNonMatches.replace(notMatch, fullLink).replace(match, fullLink)
+ val actual = textWithoutMatches.replace(match, fullLink)
+
+ throw FileComparisonFailure("", expected, actual, null)
+ }
+ if (text != textWithoutMatches)
+ totalEntries++
+
+ checked++
+ }
+ println("$checked files checked for valid external links '$linkBody', found $totalEntries links")
+ }
+
+ fun configure(gradleVersion: String = "3.5", kotlinVersion: String = "1.1.2", arguments: Array<String>): GradleRunner {
+ val fatjar = dokkaFatJarPathData.toFile().readText()
+
+ return GradleRunner.create().withProjectDir(testProjectDir.root)
+ .withArguments("-Pdokka_fatjar=$fatjar", "-Ptest_kotlin_version=$kotlinVersion", *arguments)
+ .withPluginClasspath(pluginClasspath)
+ .withGradleVersion(gradleVersion)
+ .withDebug(true)
+ }
+} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/BasicTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/BasicTest.kt
new file mode 100644
index 00000000..f9801c82
--- /dev/null
+++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/BasicTest.kt
@@ -0,0 +1,51 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.testkit.runner.TaskOutcome
+import org.junit.Test
+import kotlin.test.assertEquals
+
+class BasicTest : AbstractDokkaGradleTest() {
+
+ fun prepareTestData(testDataRootPath: String) {
+ val testDataRoot = testDataFolder.resolve(testDataRootPath)
+ val tmpRoot = testProjectDir.root.toPath()
+
+ testDataRoot.resolve("src").copy(tmpRoot.resolve("src"))
+ testDataRoot.resolve("build.gradle").copy(tmpRoot.resolve("build.gradle"))
+ testDataRoot.resolve("settings.gradle").copy(tmpRoot.resolve("settings.gradle"))
+ }
+
+ private fun doTest(gradleVersion: String, kotlinVersion: String) {
+
+ prepareTestData("basic")
+
+ val result = configure(gradleVersion, kotlinVersion, arguments = arrayOf("dokka", "--stacktrace")).build()
+
+ println(result.output)
+
+ assertEquals(TaskOutcome.SUCCESS, result.task(":dokka")?.outcome)
+
+ val docsOutput = "build/dokka"
+
+ checkOutputStructure("basic/fileTree.txt", docsOutput)
+
+ checkNoErrorClasses(docsOutput)
+ checkNoUnresolvedLinks(docsOutput)
+
+ checkExternalLink(docsOutput, "<span class=\"identifier\">String</span>",
+ """<a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html"><span class="identifier">String</span></a>""")
+ }
+
+ @Test fun `test kotlin 1_1_2 and gradle 3_5`() {
+ doTest("3.5", "1.1.2")
+ }
+
+ @Test fun `test kotlin 1_0_7 and gradle 2_14_1`() {
+ doTest("2.14.1", "1.0.7")
+ }
+
+ @Test fun `test kotlin 1_1_2 and gradle 4_0`() {
+ doTest("4.0", "1.1.2")
+ }
+
+} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/MultiProjectSingleOutTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/MultiProjectSingleOutTest.kt
new file mode 100644
index 00000000..13c7c37e
--- /dev/null
+++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/MultiProjectSingleOutTest.kt
@@ -0,0 +1,54 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.testkit.runner.TaskOutcome
+import org.junit.Test
+import kotlin.test.assertEquals
+
+class MultiProjectSingleOutTest : AbstractDokkaGradleTest() {
+
+ fun prepareTestData(testDataRootPath: String) {
+ val testDataRoot = testDataFolder.resolve(testDataRootPath)
+ val tmpRoot = testProjectDir.root.toPath()
+
+ testDataRoot.apply {
+ resolve("build.gradle").copy(tmpRoot.resolve("build.gradle"))
+ resolve("settings.gradle").copy(tmpRoot.resolve("settings.gradle"))
+ resolve("subA").copy(tmpRoot.resolve("subA"))
+ resolve("subB").copy(tmpRoot.resolve("subB"))
+ }
+ }
+
+ private fun doTest(gradleVersion: String, kotlinVersion: String) {
+
+ prepareTestData("multiProjectSingleOut")
+
+ val result = configure(gradleVersion, kotlinVersion, arguments = arrayOf("dokka", "--stacktrace")).build()
+
+ println(result.output)
+
+ assertEquals(TaskOutcome.SUCCESS, result.task(":dokka")?.outcome)
+
+ val docsOutput = "build/dokka"
+
+ checkOutputStructure("multiProjectSingleOut/fileTree.txt", docsOutput)
+
+ checkNoErrorClasses(docsOutput)
+ checkNoUnresolvedLinks(docsOutput)
+
+ checkExternalLink(docsOutput, "<span class=\"identifier\">String</span>",
+ """<a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html"><span class="identifier">String</span></a>""")
+ }
+
+ @Test fun `test kotlin 1_1_2 and gradle 3_5`() {
+ doTest("3.5", "1.1.2")
+ }
+
+ @Test fun `test kotlin 1_0_7 and gradle 2_14_1`() {
+ doTest("2.14.1", "1.0.7")
+ }
+
+ @Test fun `test kotlin 1_1_2 and gradle 4_0`() {
+ doTest("4.0", "1.1.2")
+ }
+
+} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/Utils.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/Utils.kt
new file mode 100644
index 00000000..d44459b1
--- /dev/null
+++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/Utils.kt
@@ -0,0 +1,59 @@
+package org.jetbrains.dokka.gradle
+
+import com.intellij.rt.execution.junit.FileComparisonFailure
+import java.io.File
+import java.io.IOException
+import java.nio.file.FileVisitResult
+import java.nio.file.Files
+import java.nio.file.Path
+import java.nio.file.SimpleFileVisitor
+import java.nio.file.attribute.BasicFileAttributes
+
+
+fun File.writeStructure(builder: StringBuilder, relativeTo: File = this, spaces: Int = 0) {
+ builder.append(" ".repeat(spaces))
+ val out = if (this != relativeTo) this.relativeTo(relativeTo) else this
+
+ builder.append(out)
+ if (this.isDirectory) {
+ builder.appendln("/")
+ this.listFiles().sortedBy { it.name }.forEach { it.writeStructure(builder, this, spaces + 4) }
+ } else {
+ builder.appendln()
+ }
+}
+
+fun assertEqualsIgnoringSeparators(expectedFile: File, output: String) {
+ if (!expectedFile.exists()) expectedFile.createNewFile()
+ val expectedText = expectedFile.readText().replace("\r\n", "\n")
+ val actualText = output.replace("\r\n", "\n")
+
+ if (expectedText != actualText)
+ throw FileComparisonFailure("", expectedText, actualText, expectedFile.canonicalPath)
+}
+
+class CopyFileVisitor(private var sourcePath: Path?, private val targetPath: Path) : SimpleFileVisitor<Path>() {
+
+ @Throws(IOException::class)
+ override fun preVisitDirectory(dir: Path,
+ attrs: BasicFileAttributes): FileVisitResult {
+ if (sourcePath == null) {
+ sourcePath = dir
+ } else {
+ Files.createDirectories(targetPath.resolve(sourcePath?.relativize(dir)))
+ }
+ return FileVisitResult.CONTINUE
+ }
+
+ @Throws(IOException::class)
+ override fun visitFile(file: Path,
+ attrs: BasicFileAttributes): FileVisitResult {
+ Files.copy(file, targetPath.resolve(sourcePath?.relativize(file)))
+ return FileVisitResult.CONTINUE
+ }
+}
+
+fun Path.copy(to: Path) {
+ Files.walkFileTree(this, CopyFileVisitor(this, to))
+}
+
diff --git a/runners/gradle-integration-tests/testData/basic/build.gradle b/runners/gradle-integration-tests/testData/basic/build.gradle
new file mode 100644
index 00000000..bc20e1cf
--- /dev/null
+++ b/runners/gradle-integration-tests/testData/basic/build.gradle
@@ -0,0 +1,39 @@
+buildscript {
+ repositories {
+ mavenCentral()
+ jcenter()
+ maven { url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" }
+ maven { url "https://dl.bintray.com/kotlin/kotlin-dev" }
+ }
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$test_kotlin_version"
+ }
+}
+
+plugins {
+ id 'org.jetbrains.dokka'
+}
+
+apply plugin: 'kotlin'
+apply plugin: 'org.jetbrains.dokka'
+
+repositories {
+ mavenCentral()
+ jcenter()
+ maven {
+ url "http://dl.bintray.com/kotlin/kotlin-eap-1.1"
+ }
+ maven {
+ url "https://dl.bintray.com/kotlin/kotlin-dev"
+ }
+}
+
+dependencies {
+ compile group: 'org.jetbrains.kotlin', name: 'kotlin-runtime', version: test_kotlin_version
+ compile group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: test_kotlin_version
+}
+
+
+dokka {
+ dokkaFatJar = new File(dokka_fatjar)
+} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/testData/basic/fileTree.txt b/runners/gradle-integration-tests/testData/basic/fileTree.txt
new file mode 100644
index 00000000..1a483d4e
--- /dev/null
+++ b/runners/gradle-integration-tests/testData/basic/fileTree.txt
@@ -0,0 +1,30 @@
+/
+ basic/
+ alltypes/
+ index.html
+ demo/
+ -a/
+ -init-.html
+ index.html
+ p.html
+ -greeter/
+ -init-.html
+ greet.html
+ index.html
+ name.html
+ -some-interface.html
+ -some-sub-type/
+ -init-.html
+ index.html
+ -some-type/
+ -init-.html
+ index.html
+ constructor.html
+ index.html
+ main.html
+ str.html
+ x.html
+ index-outline.html
+ index.html
+ package-list
+ style.css
diff --git a/runners/gradle-integration-tests/testData/basic/settings.gradle b/runners/gradle-integration-tests/testData/basic/settings.gradle
new file mode 100644
index 00000000..c36a146c
--- /dev/null
+++ b/runners/gradle-integration-tests/testData/basic/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = "basic" \ No newline at end of file
diff --git a/runners/gradle-integration-tests/testData/basic/src/main/kotlin/demo/HelloWorld.kt b/runners/gradle-integration-tests/testData/basic/src/main/kotlin/demo/HelloWorld.kt
new file mode 100644
index 00000000..7492e2a8
--- /dev/null
+++ b/runners/gradle-integration-tests/testData/basic/src/main/kotlin/demo/HelloWorld.kt
@@ -0,0 +1,41 @@
+package demo
+
+/**
+ * This class supports greeting people by name.
+ *
+ * @property name The name of the person to be greeted.
+ */
+class Greeter(val name: String) {
+
+ /**
+ * Prints the greeting to the standard output.
+ */
+ fun greet() {
+ println("Hello $name!")
+ }
+}
+
+fun main(args: Array<String>) {
+ Greeter(args[0]).greet()
+}
+
+val str = "Hello! ".repeat(4)
+val x: (a: String, b: Int) -> Int = { a, b -> 0 }
+
+interface SomeInterface
+private class SomeImpl : SomeInterface
+
+fun SomeInterface.constructor(): SomeInterface {
+ return SomeImpl()
+}
+
+open class SomeType
+class SomeSubType : SomeType()
+
+fun SomeType.constructor(): SomeType {
+ return SomeSubType()
+}
+
+
+annotation class A(val p: String)
+
diff --git a/runners/gradle-integration-tests/testData/multiProjectSingleOut/build.gradle b/runners/gradle-integration-tests/testData/multiProjectSingleOut/build.gradle
new file mode 100644
index 00000000..68d93e30
--- /dev/null
+++ b/runners/gradle-integration-tests/testData/multiProjectSingleOut/build.gradle
@@ -0,0 +1,32 @@
+plugins {
+ id 'org.jetbrains.dokka'
+}
+
+subprojects {
+ buildscript {
+ repositories {
+ mavenCentral()
+ jcenter()
+ maven { url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" }
+ maven { url "https://dl.bintray.com/kotlin/kotlin-dev" }
+ }
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$test_kotlin_version"
+ }
+ }
+ repositories {
+ mavenCentral()
+ jcenter()
+ maven { url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" }
+ maven { url "https://dl.bintray.com/kotlin/kotlin-dev" }
+ }
+}
+
+apply plugin: 'org.jetbrains.dokka'
+
+dokka {
+ kotlinTasks {
+ [":subA:compileKotlin", ":subB:compileKotlin"]
+ }
+ dokkaFatJar = new File(dokka_fatjar)
+} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/testData/multiProjectSingleOut/fileTree.txt b/runners/gradle-integration-tests/testData/multiProjectSingleOut/fileTree.txt
new file mode 100644
index 00000000..5624fca6
--- /dev/null
+++ b/runners/gradle-integration-tests/testData/multiProjectSingleOut/fileTree.txt
@@ -0,0 +1,33 @@
+/
+ multi-project-root/
+ alltypes/
+ index.html
+ index-outline.html
+ index.html
+ package-list
+ s1/
+ -my-class/
+ -init-.html
+ index.html
+ otherworks.html
+ -super/
+ -init-.html
+ bar.html
+ foo.html
+ index.html
+ index.html
+ some-cool-thing.html
+ s2/
+ -cooler/
+ -init-.html
+ a.html
+ coolest.html
+ index.html
+ my-class.html
+ -superful/
+ -init-.html
+ bar.html
+ index.html
+ index.html
+ main.html
+ style.css
diff --git a/runners/gradle-integration-tests/testData/multiProjectSingleOut/settings.gradle b/runners/gradle-integration-tests/testData/multiProjectSingleOut/settings.gradle
new file mode 100644
index 00000000..283cc526
--- /dev/null
+++ b/runners/gradle-integration-tests/testData/multiProjectSingleOut/settings.gradle
@@ -0,0 +1,3 @@
+rootProject.name = "multiProjectRoot"
+
+include 'subA', 'subB' \ No newline at end of file
diff --git a/runners/gradle-integration-tests/testData/multiProjectSingleOut/subA/build.gradle b/runners/gradle-integration-tests/testData/multiProjectSingleOut/subA/build.gradle
new file mode 100644
index 00000000..0600411e
--- /dev/null
+++ b/runners/gradle-integration-tests/testData/multiProjectSingleOut/subA/build.gradle
@@ -0,0 +1,6 @@
+apply plugin: 'kotlin'
+
+dependencies {
+ compile group: 'org.jetbrains.kotlin', name: 'kotlin-runtime', version: test_kotlin_version
+ compile group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: test_kotlin_version
+}
diff --git a/runners/gradle-integration-tests/testData/multiProjectSingleOut/subA/src/main/kotlin/module.kt b/runners/gradle-integration-tests/testData/multiProjectSingleOut/subA/src/main/kotlin/module.kt
new file mode 100644
index 00000000..126d7f3e
--- /dev/null
+++ b/runners/gradle-integration-tests/testData/multiProjectSingleOut/subA/src/main/kotlin/module.kt
@@ -0,0 +1,31 @@
+package s1
+
+/**
+ * Coolest one
+ */
+fun someCoolThing(s: String) = s.repeat(2)
+
+/**
+ * Just a class
+ */
+class MyClass {
+ /**
+ * Ultimate answer to all questions
+ */
+ fun otherworks(): Int = 42
+}
+
+/**
+ * Just a SUPER class
+ */
+open class Super {
+ /**
+ * Same as [MyClass.otherworks]
+ */
+ fun foo(i: Int = 21) = i * 2
+
+ /**
+ * magic
+ */
+ open fun bar() = foo()
+} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/testData/multiProjectSingleOut/subB/build.gradle b/runners/gradle-integration-tests/testData/multiProjectSingleOut/subB/build.gradle
new file mode 100644
index 00000000..7b8ff9f3
--- /dev/null
+++ b/runners/gradle-integration-tests/testData/multiProjectSingleOut/subB/build.gradle
@@ -0,0 +1,7 @@
+apply plugin: 'kotlin'
+
+dependencies {
+ compile group: 'org.jetbrains.kotlin', name: 'kotlin-runtime', version: test_kotlin_version
+ compile group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: test_kotlin_version
+ compile project(":subA")
+}
diff --git a/runners/gradle-integration-tests/testData/multiProjectSingleOut/subB/src/main/kotlin/module.kt b/runners/gradle-integration-tests/testData/multiProjectSingleOut/subB/src/main/kotlin/module.kt
new file mode 100644
index 00000000..8a87590a
--- /dev/null
+++ b/runners/gradle-integration-tests/testData/multiProjectSingleOut/subB/src/main/kotlin/module.kt
@@ -0,0 +1,31 @@
+package s2
+
+import s1.Super
+import s1.MyClass
+import s1.someCoolThing
+
+/**
+ * Just an entry-point
+ */
+fun main(args: Array<String>) {
+
+}
+
+/**
+ * Take a glass of hot water
+ */
+class Cooler {
+ val myClass = MyClass()
+ val a = myClass.otherworks()
+ val coolest = someCoolThing()
+}
+
+/**
+ * Powerful
+ */
+class Superful : Super() {
+ /**
+ * Overriden magic
+ */
+ override fun bar() = foo(20) * 2
+} \ No newline at end of file