Skip to content
This repository has been archived by the owner on Aug 19, 2020. It is now read-only.

Commit

Permalink
Include documentation in generated API extensions
Browse files Browse the repository at this point in the history
See: #117
  • Loading branch information
bamboo committed Sep 2, 2016
1 parent 2407b8d commit bf1c22a
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,38 +22,61 @@ import org.gradle.script.lang.kotlin.support.zipTo

import java.io.File

fun generateActionExtensionsJar(outputFile: File, inputApiJar: File) {
val tempDir = tempDirFor(outputFile)
compileExtensionsTo(tempDir, inputApiJar)
zipTo(outputFile, tempDir)
fun generateActionExtensionsJar(outputFile: File, apiJar: File) {
ApiExtensionsJarGenerator().generate(outputFile, apiJar)
}

private fun tempDirFor(outputFile: File): File =
createTempDir(outputFile.nameWithoutExtension, outputFile.extension).apply {
deleteOnExit()
interface KotlinFileCompiler {
fun compileToDirectory(outputDirectory: File, sourceFile: File, classPath: List<File>)
}

class ApiExtensionsJarGenerator(val compiler: KotlinFileCompiler = StandardKotlinFileCompiler) {

fun generate(outputFile: File, inputApiJar: File) {
val tempDir = tempDirFor(outputFile)
compileExtensionsTo(tempDir, inputApiJar)
zipTo(outputFile, tempDir)
}

private fun compileExtensionsTo(outputDir: File, inputApiJar: File) {
val sourceFile = File(outputDir, extensionsSourceFileName())
writeActionExtensionsTo(sourceFile, inputApiJar)
compileToDirectory(
outputDir,
sourceFile,
loggerFor<ActionExtensionWriter>(),
classPath = listOf(inputApiJar))
}
private fun tempDirFor(outputFile: File): File =
createTempDir(outputFile.nameWithoutExtension, outputFile.extension).apply {
deleteOnExit()
}

private fun extensionsSourceFileName() =
ActionExtensionWriter.packageName.replace('.', '/') + "/ActionExtensions.kt"
private fun compileExtensionsTo(outputDir: File, inputApiJar: File) {
val sourceFile = File(outputDir, extensionsSourceFileName())
writeActionExtensionsTo(sourceFile, inputApiJar)
compiler.compileToDirectory(
outputDir,
sourceFile,
classPath = listOf(inputApiJar))
}

private fun writeActionExtensionsTo(kotlinFile: File, inputApiJar: File) {
kotlinFile.apply { parentFile.mkdirs() }.bufferedWriter().use { writer ->
val extensionWriter = ActionExtensionWriter(writer)
forEachZipEntryIn(inputApiJar) {
if (isApiClassEntry()) {
val classNode = classNodeFor(zipInputStream)
extensionWriter.writeExtensionsFor(classNode)
private fun extensionsSourceFileName() =
ActionExtensionWriter.packageName.replace('.', '/') + "/ActionExtensions.kt"

private fun writeActionExtensionsTo(kotlinFile: File, inputApiJar: File) {
kotlinFile.apply { parentFile.mkdirs() }.bufferedWriter().use { writer ->
val extensionWriter = ActionExtensionWriter(writer, docProvider())
forEachZipEntryIn(inputApiJar) {
if (isApiClassEntry()) {
val classNode = classNodeFor(zipInputStream)
extensionWriter.writeExtensionsFor(classNode)
}
}
}
}

private fun docProvider() =
MarkdownKDocProvider.fromResource("/doc/ActionExtensions.md")
}

object StandardKotlinFileCompiler : KotlinFileCompiler {
override fun compileToDirectory(outputDirectory: File, sourceFile: File, classPath: List<File>) {
compileToDirectory(
outputDirectory,
sourceFile,
loggerFor<StandardKotlinFileCompiler>(),
classPath = classPath)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ object MarkdownKDocProvider {
fun from(markdown: String): KDocProvider =
{ signature -> findKDocIn(markdown, signature) }

fun fromResource(resourcePath: String) =
from(javaClass.getResource(resourcePath).readText())

private fun findKDocIn(markdown: String, signature: String): KDoc? {
val signatureStart = markdown.indexOf("# $signature")
return if (signatureStart >= 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ The behavior is similar to [org.gradle.api.plugins.PluginContainer.withType].

@param pluginId The id of the plugin
@param action The action

# org.gradle.api.artifacts.result.ResolutionResult.allDependencies(org.gradle.api.artifacts.result.DependencyResult.() -> Unit)

Lorem ipsum.
Expand Down Expand Up @@ -267,7 +267,7 @@ Lorem ipsum.
Lorem ipsum.

@param action

# org.gradle.api.artifacts.ComponentSelectionRules.all(org.gradle.api.artifacts.ComponentSelection.() -> Unit)

Lorem ipsum.
Expand Down
13 changes: 13 additions & 0 deletions src/test/kotlin/org/gradle/script/lang/kotlin/TestWithTempFiles.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.gradle.script.lang.kotlin

import org.junit.Rule
import org.junit.rules.TemporaryFolder

abstract class TestWithTempFiles {

@JvmField
@Rule val tempDir = TemporaryFolder()

protected fun tempFile(fileName: String) =
tempDir.newFile(fileName)!!
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.gradle.script.lang.kotlin.codegen

import org.gradle.script.lang.kotlin.TestWithTempFiles

import org.gradle.script.lang.kotlin.support.classEntriesFor
import org.gradle.script.lang.kotlin.support.zipTo

import org.hamcrest.CoreMatchers.containsString
import org.hamcrest.MatcherAssert.assertThat

import org.junit.Test
import java.io.File

import java.util.jar.JarFile

class ApiExtensionsJarGeneratorTest : TestWithTempFiles() {

@Test
fun `includes source with documentation taken from ActionExtensions resource`() {

val inputFile = apiJarWith(org.gradle.api.Project::class.java, org.gradle.api.Action::class.java)
val outputFile = tempFile("extensions.jar")

ApiExtensionsJarGenerator(NullCompiler).generate(outputFile, inputFile)

assertThat(
textForEntryOf(outputFile, "org/gradle/script/lang/kotlin/ActionExtensions.kt"),
containsString(
kdocFor("org.gradle.api.Project.allprojects(org.gradle.api.Project.() -> Unit)")))
}

object NullCompiler : KotlinFileCompiler {
override fun compileToDirectory(outputDirectory: File, sourceFile: File, classPath: List<File>) = Unit
}

private fun apiJarWith(vararg classes: Class<*>): File {
val inputFile = tempFile("api.jar")
zipTo(inputFile, classEntriesFor(*classes))
return inputFile
}

private fun textForEntryOf(outputFile: File, entryName: String): String =
JarFile(outputFile).use { outputJar ->
val sourceFileEntry = outputJar.getEntry(entryName)
outputJar.getInputStream(sourceFileEntry).bufferedReader().readText()
}

private fun kdocFor(signature: String): String =
MarkdownKDocProvider
.fromResource("/doc/ActionExtensions.md")
.invoke(signature)!!
.format()
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
package org.gradle.script.lang.kotlin.support

import org.gradle.script.lang.kotlin.TestWithTempFiles
import org.gradle.script.lang.kotlin.loggerFor

import org.hamcrest.CoreMatchers.equalTo
import org.hamcrest.MatcherAssert.assertThat

import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder

import java.io.File

import java.net.URLClassLoader

class KotlinCompilerTest {

@JvmField
@Rule val tempDir = TemporaryFolder()
class KotlinCompilerTest : TestWithTempFiles() {

@Test
fun `can compile Kotlin source file into jar`() {
Expand Down Expand Up @@ -47,9 +43,6 @@ class KotlinCompilerTest {
equalTo<Any>(42))
}

private fun tempFile(fileName: String) =
tempDir.newFile(fileName)

private fun classLoaderFor(outputJar: File) =
URLClassLoader.newInstance(
arrayOf(outputJar.toURI().toURL()))
Expand Down

0 comments on commit bf1c22a

Please sign in to comment.