diff options
Diffstat (limited to 'runners/gradle-plugin/src')
3 files changed, 209 insertions, 0 deletions
diff --git a/runners/gradle-plugin/src/main/kotlin/logger.kt b/runners/gradle-plugin/src/main/kotlin/logger.kt new file mode 100644 index 00000000..715c1f04 --- /dev/null +++ b/runners/gradle-plugin/src/main/kotlin/logger.kt @@ -0,0 +1,18 @@ +package org.jetbrains.dokka.gradle + +import org.gradle.api.logging.Logger +import org.jetbrains.dokka.DokkaLogger + +class DokkaGradleLogger(val logger: Logger) : DokkaLogger { + override fun error(message: String) { + logger.error(message) + } + + override fun info(message: String) { + logger.info(message) + } + + override fun warn(message: String) { + logger.warn(message) + } +}
\ No newline at end of file diff --git a/runners/gradle-plugin/src/main/kotlin/main.kt b/runners/gradle-plugin/src/main/kotlin/main.kt new file mode 100644 index 00000000..49c3b8ba --- /dev/null +++ b/runners/gradle-plugin/src/main/kotlin/main.kt @@ -0,0 +1,190 @@ +package org.jetbrains.dokka.gradle + +import groovy.lang.Closure +import org.gradle.api.DefaultTask +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.file.FileCollection +import org.gradle.api.plugins.JavaBasePlugin +import org.gradle.api.plugins.JavaPluginConvention +import org.gradle.api.tasks.* +import org.jetbrains.dokka.DocumentationOptions +import org.jetbrains.dokka.DokkaGenerator +import org.jetbrains.dokka.SourceLinkDefinition +import java.io.File +import java.io.Serializable +import java.util.* + +open class DokkaPlugin : Plugin<Project> { + override fun apply(project: Project) { + project.tasks.create("dokka", DokkaTask::class.java).apply { + moduleName = project.name + outputDirectory = File(project.buildDir, "dokka").absolutePath + } + } +} + +open class DokkaTask : DefaultTask() { + init { + group = JavaBasePlugin.DOCUMENTATION_GROUP + description = "Generates dokka documentation for Kotlin" + } + + @Input + var moduleName: String = "" + @Input + var outputFormat: String = "html" + var outputDirectory: String = "" + @Input + var processConfigurations: List<Any?> = arrayListOf("compile") + @Input + var includes: List<Any?> = arrayListOf() + @Input + var linkMappings: ArrayList<LinkMapping> = arrayListOf() + @Input + var samples: List<Any?> = arrayListOf() + @Input + var jdkVersion: Int = 6 + @Input + var sourceDirs: Iterable<File> = emptyList() + + protected open val sdkProvider: SdkProvider? = null + + fun linkMapping(closure: Closure<Any?>) { + val mapping = LinkMapping() + closure.delegate = mapping + closure.call() + + if (mapping.dir.isEmpty()) { + throw IllegalArgumentException("Link mapping should have dir") + } + if (mapping.url.isEmpty()) { + throw IllegalArgumentException("Link mapping should have url") + } + + linkMappings.add(mapping) + } + + @TaskAction + fun generate() { + val project = project + val sdkProvider = sdkProvider + val sourceDirectories = getSourceDirectories() + val allConfigurations = project.configurations + + val classpath = + if (sdkProvider != null && sdkProvider.isValid) sdkProvider.classpath else emptyList<File>() + + processConfigurations + .map { allConfigurations?.getByName(it.toString()) ?: throw IllegalArgumentException("No configuration $it found") } + .flatMap { it } + + if (sourceDirectories.isEmpty()) { + logger.warn("No source directories found: skipping dokka generation") + return + } + + DokkaGenerator( + DokkaGradleLogger(logger), + classpath.map { it.absolutePath }, + sourceDirectories.map { it.absolutePath }, + samples.filterNotNull().map { project.file(it).absolutePath }, + includes.filterNotNull().map { project.file(it).absolutePath }, + moduleName, + DocumentationOptions(outputDirectory, outputFormat, + sourceLinks = linkMappings.map { SourceLinkDefinition(project.file(it.dir).absolutePath, it.url, it.suffix) }, + jdkVersion = jdkVersion) + ).generate() + } + + fun getSourceDirectories(): Collection<File> { + val provider = sdkProvider + val sourceDirs = if (sourceDirs.any()) { + logger.info("Dokka: Taking source directories provided by the user") + sourceDirs.toSet() + } else if (provider != null && provider.isValid) { + logger.info("Dokka: Taking source directories from ${provider.name} sdk provider") + provider.sourceDirs + } else { + logger.info("Dokka: Taking source directories from default java plugin") + val javaPluginConvention = project.convention.getPlugin(JavaPluginConvention::class.java) + val sourceSets = javaPluginConvention.sourceSets?.findByName(SourceSet.MAIN_SOURCE_SET_NAME) + sourceSets?.allSource?.srcDirs + } + + return sourceDirs?.filter { it.exists() } ?: emptyList() + } + + @InputFiles + @SkipWhenEmpty + fun getInputFiles(): FileCollection = + project.files(getSourceDirectories().map { project.fileTree(it) }) + + project.files(includes) + + project.files(samples.map { project.fileTree(it) }) + + @OutputDirectory + fun getOutputDirectoryAsFile(): File = project.file(outputDirectory) +} + +open class LinkMapping : Serializable { + var dir: String = "" + var url: String = "" + var suffix: String? = null + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other?.javaClass != javaClass) return false + + other as LinkMapping + + if (dir != other.dir) return false + if (url != other.url) return false + if (suffix != other.suffix) return false + + return true + } + + override fun hashCode(): Int { + var result = dir.hashCode() + result = 31 * result + url.hashCode() + result = 31 * result + (suffix?.hashCode() ?: 0) + return result + } + + companion object { + const val serialVersionUID: Long = -8133501684312445981L + } +} + +/** + * A provider for SDKs that can be used if a project uses classes that live outside the JDK or uses a + * different method to determine the source directories. + * + * For example an Android library project configures its sources through the Android extension instead + * of the basic java convention. Also it has its custom classes located in the SDK installation directory. + */ +interface SdkProvider { + /** + * The name of this provider. Only used for logging purposes. + */ + val name: String + + /** + * Checks whether this provider has everything it needs to provide the source directories. + */ + val isValid: Boolean + + /** + * Provides additional classpath files where Dokka should search for external classes. + * The file list is injected **after** JDK Jars and **before** project dependencies. + * + * This is only called if [isValid] returns `true`. + */ + val classpath: List<File> + + /** + * Provides a list of directories where Dokka should search for source files. + * + * This is only called if [isValid] returns `true`. + */ + val sourceDirs: Set<File>? +} diff --git a/runners/gradle-plugin/src/main/resources/META-INF/gradle-plugins/org.jetbrains.dokka.properties b/runners/gradle-plugin/src/main/resources/META-INF/gradle-plugins/org.jetbrains.dokka.properties new file mode 100644 index 00000000..b42cfe9f --- /dev/null +++ b/runners/gradle-plugin/src/main/resources/META-INF/gradle-plugins/org.jetbrains.dokka.properties @@ -0,0 +1 @@ +implementation-class=org.jetbrains.dokka.gradle.DokkaPlugin
\ No newline at end of file |