Fixes after review

This commit is contained in:
Andrey Breslav
2013-03-04 19:45:36 +04:00
parent 25decd1c7a
commit 01203f6be3
14 changed files with 204 additions and 143 deletions
@@ -0,0 +1,5 @@
<root>
<item name='com.google.common.base.Joiner com.google.common.base.Joiner on(java.lang.String)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>
@@ -0,0 +1,5 @@
<root>
<item name='com.google.common.io.Files java.io.File createTempDir()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>
@@ -0,0 +1,5 @@
<root>
<item name='org.apache.commons.io.FilenameUtils java.lang.String getExtension(java.lang.String)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>
@@ -4,4 +4,10 @@
<val name="value" val="&quot;fun apply(p0 : T) : Unit&quot;"/>
</annotation>
</item>
<item name='org.gradle.api.Project org.gradle.api.plugins.PluginContainer getPlugins()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='org.gradle.api.Project org.gradle.api.plugins.Convention getConvention()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>
@@ -0,0 +1,5 @@
<root>
<item name='org.gradle.api.file.FileCollection org.gradle.api.file.FileCollection filter(org.gradle.api.specs.Spec&lt;? super java.io.File&gt;)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>
@@ -5,8 +5,6 @@
</annotation>
</item>
<item name='org.gradle.api.internal.AbstractTask org.gradle.api.logging.Logger getLogger()'>
<annotation name='jet.runtime.typeinfo.KotlinSignature'>
<val name="value" val="&quot;fun getLogger() : Logger?&quot;"/>
</annotation>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>
@@ -0,0 +1,5 @@
<root>
<item name='org.gradle.api.internal.project.ProjectInternal org.gradle.api.internal.tasks.TaskContainerInternal getTasks()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>
@@ -10,4 +10,13 @@
<val name="value" val="&quot;fun getExtensionsAsDynamicObject() : DynamicObject&quot;"/>
</annotation>
</item>
<item name='org.gradle.api.plugins.PluginContainer org.gradle.api.Plugin apply(java.lang.String)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='org.gradle.api.plugins.PluginContainer T apply(java.lang.Class&lt;T&gt;)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='org.gradle.api.plugins.Convention T getPlugin(java.lang.Class&lt;T&gt;)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>
@@ -0,0 +1,5 @@
<root>
<item name='org.gradle.api.tasks.compile.AbstractCompile org.gradle.api.file.FileCollection getClasspath()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>
+24 -11
View File
@@ -21,16 +21,27 @@
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>gradle-api</artifactId>
<version>1.4</version>
<scope>provided</scope>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>12.0</version>
</dependency>
<dependency>
<groupId>org.apache.directory.studio</groupId>
<artifactId>org.apache.commons.io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>gradle-api</artifactId>
<version>1.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-compiler</artifactId>
@@ -43,15 +54,9 @@
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-runtime</artifactId>
<artifactId>kotlin-stdlib</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.8</version>
<scope>test</scope>
</dependency>
</dependencies>
@@ -94,6 +99,7 @@
</executions>
</plugin>
<plugin>
<!-- Invoker plugin maintains local maven repository in local-repo for gradle integration tests -->
<artifactId>maven-invoker-plugin</artifactId>
<version>1.8</version>
<configuration>
@@ -125,4 +131,11 @@
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>jetbrains-utils</id>
<url>http://repository.jetbrains.com/utils</url>
</repository>
</repositories>
</project>
@@ -6,31 +6,26 @@ import org.gradle.api.internal.file.FileResolver
import org.gradle.api.internal.file.DefaultSourceDirectorySet
import org.gradle.util.ConfigureUtil
/**
* Created by Nikita.Skvortsov
* Date: 2/21/13, 5:51 PM
*/
trait KotlinSourceSet {
open fun getKotlin() : SourceDirectorySet
open fun kotlin(configureClosure : Closure<Any?>?) : KotlinSourceSet
fun getKotlin(): SourceDirectorySet
fun kotlin(configureClosure: Closure<Any?>?): KotlinSourceSet
}
open class KotlinSourceSetImpl(displayName : String?, resolver : FileResolver?) : KotlinSourceSet {
open class KotlinSourceSetImpl(displayName: String?, resolver: FileResolver?): KotlinSourceSet {
private val kotlin : DefaultSourceDirectorySet = DefaultSourceDirectorySet(displayName + " Kotlin source", resolver);
private val kotlin: DefaultSourceDirectorySet = DefaultSourceDirectorySet(displayName + " Kotlin source", resolver);
{
kotlin.getFilter()?.include("**/*.java", "**/*.kt")
}
override fun getKotlin() : SourceDirectorySet {
override fun getKotlin(): SourceDirectorySet {
return kotlin
}
override fun kotlin(configureClosure : Closure<Any?>?) : KotlinSourceSet {
override fun kotlin(configureClosure: Closure<Any?>?): KotlinSourceSet {
ConfigureUtil.configure(configureClosure, getKotlin())
return this
}
@@ -25,33 +25,28 @@ import org.gradle.api.Action
import org.gradle.api.tasks.compile.AbstractCompile
import java.util.Arrays
/**
* Created by Nikita.Skvortsov
* Date: 2/21/13, 5:55 PM
*/
open class KotlinPlugin : Plugin<Project> {
open class KotlinPlugin: Plugin<Project> {
public override fun apply(project: Project) {
val javaBasePlugin = project.getPlugins()?.apply(javaClass<JavaBasePlugin>())!!
val javaPluginConvention = project.getConvention()?.getPlugin(javaClass<JavaPluginConvention>())!!
val javaBasePlugin = project.getPlugins().apply(javaClass<JavaBasePlugin>())
val javaPluginConvention = project.getConvention().getPlugin(javaClass<JavaPluginConvention>())
project.getPlugins()?.apply(javaClass<JavaPlugin>())
project.getPlugins().apply(javaClass<JavaPlugin>())
configureSourceSetDefaults(project as ProjectInternal, javaBasePlugin, javaPluginConvention)
configureKDoc(project, javaPluginConvention)
}
private fun configureSourceSetDefaults( project: ProjectInternal,
javaBasePlugin: JavaBasePlugin,
javaPluginConvention: JavaPluginConvention) {
private fun configureSourceSetDefaults(project: ProjectInternal,
javaBasePlugin: JavaBasePlugin,
javaPluginConvention: JavaPluginConvention) {
javaPluginConvention.getSourceSets()?.all(object : Action<SourceSet> {
override fun execute(sourceSet : SourceSet?) {
override fun execute(sourceSet: SourceSet?) {
if (sourceSet is HasConvention) {
val sourceSetName = sourceSet.getName()
val kotlinSourceSet = KotlinSourceSetImpl(sourceSetName, project.getFileResolver())
val kotlinDirSet = kotlinSourceSet.getKotlin()
kotlinDirSet.srcDir(project.file("src/${sourceSetName}/kotlin"))
@@ -59,22 +54,22 @@ open class KotlinPlugin : Plugin<Project> {
sourceSet.getAllSource()?.source(kotlinDirSet)
sourceSet.getConvention().getPlugins().put("kotlin", kotlinSourceSet)
sourceSet.getResources()?.getFilter()?.exclude(KSpec({ (elem: FileTreeElement) ->
sourceSet.getResources()?.getFilter()?.exclude(KSpec({ elem ->
kotlinDirSet.contains(elem.getFile())
}))
val kotlinTaskName = sourceSet.getCompileTaskName("kotlin")
val kotlinTask : KotlinCompile = project.getTasks()?.add(kotlinTaskName , javaClass<KotlinCompile>())!!
val kotlinTask: KotlinCompile = project.getTasks().add(kotlinTaskName, javaClass<KotlinCompile>())!!
javaBasePlugin.configureForSourceSet(sourceSet, kotlinTask)
kotlinTask setDescription "Compiles the $sourceSet.kotlin."
kotlinTask source kotlinDirSet
kotlinTask.setDescription("Compiles the $sourceSet.kotlin.")
kotlinTask.source(kotlinDirSet)
val javaTask = project.getTasks()?.findByName(sourceSet.getCompileJavaTaskName()) as AbstractCompile?
val javaTask = project.getTasks().findByName(sourceSet.getCompileJavaTaskName()) as AbstractCompile?
javaTask?.dependsOn(kotlinTaskName)
val sourceSetCompileConfigurationName = if (sourceSetName.equals("main")) {
val sourceSetCompileConfigurationName = if (sourceSetName == SourceSet.MAIN_SOURCE_SET_NAME) {
"compile"
} else {
"${sourceSetName}Compile"
@@ -83,21 +78,21 @@ open class KotlinPlugin : Plugin<Project> {
project.getDependencies()?.add(sourceSetCompileConfigurationName, project.files(kotlinTask.getDestinationDir()))
}
}
});
})
}
private fun configureKDoc(project: Project, javaPluginConvention: JavaPluginConvention) {
val mainSourceSet : HasConvention = javaPluginConvention.getSourceSets()?.getByName(SourceSet.MAIN_SOURCE_SET_NAME)!! as HasConvention
val mainSourceSet = javaPluginConvention.getSourceSets()?.getByName(SourceSet.MAIN_SOURCE_SET_NAME)!! as HasConvention
val kdoc : KDoc = project.getTasks()?.add(KDOC_TASK_NAME, javaClass<KDoc>())!!
val kdoc = project.getTasks()?.add(KDOC_TASK_NAME, javaClass<KDoc>())!!
kdoc.setDescription("Generates KDoc API documentation for the main source code.")
kdoc.setGroup(JavaBasePlugin.DOCUMENTATION_GROUP)
kdoc.setSource(mainSourceSet.getConvention().getExtensionsAsDynamicObject().getProperty("kotlin"))
project.getTasks()?.withType(javaClass<KDoc>(), object : Action<KDoc> {
override fun execute(param : KDoc?) {
override fun execute(param: KDoc?) {
param?.getConventionMapping()?.map("destinationDir", object : Callable<Any> {
override fun call() : Any {
override fun call(): Any {
return File(javaPluginConvention.getDocsDir(), "kdoc");
}
})
@@ -105,11 +100,11 @@ open class KotlinPlugin : Plugin<Project> {
})
}
public val KDOC_TASK_NAME : String = "kdoc"
public val KDOC_TASK_NAME: String = "kdoc"
}
open class KSpec<T : Any?>(val predicate : (T) -> Boolean) : Spec<T> {
open class KSpec<T: Any?>(val predicate: (T) -> Boolean): Spec<T> {
public override fun isSatisfiedBy(p0: T?): Boolean {
return p0 != null && predicate(p0)
}
@@ -21,20 +21,21 @@ import java.net.URL
import com.google.common.io.Files
import org.gradle.api.file.SourceDirectorySet
import com.google.common.base.Joiner
import java.util.ArrayList
import org.apache.commons.io.FilenameUtils
import org.jetbrains.jet.cli.common.messages.MessageCollector
import org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.jet.cli.common.messages.CompilerMessageLocation
import org.gradle.api.logging.Logger
/**
* Created by Nikita.Skvortsov
* Date: 2/22/13, 2:56 PM
*/
open class KotlinCompile() : AbstractCompile() {
public open class KotlinCompile(): AbstractCompile() {
val srcDirsRoots = HashSet<File>()
val compiler = K2JVMCompiler()
val logger = getLogger()
// override setSource to track source directory sets
override fun setSource(source : Any?) {
override fun setSource(source: Any?) {
srcDirsRoots.clear()
if (source is SourceDirectorySet) {
srcDirsRoots.addAll(source.getSrcDirs())
@@ -43,7 +44,7 @@ open class KotlinCompile() : AbstractCompile() {
}
// override source to track source directory sets
override fun source(vararg sources : Any?) : SourceTask? {
override fun source(vararg sources: Any?): SourceTask? {
for (source in sources) {
if (source is SourceDirectorySet) {
srcDirsRoots.addAll(source.getSrcDirs())
@@ -52,142 +53,144 @@ open class KotlinCompile() : AbstractCompile() {
return super.source(sources)
}
fun findSrcDirRoot(file : File) : String {
fun findSrcDirRoot(file: File): File? {
val absPath = file.getAbsolutePath()
for (root in srcDirsRoots) {
val rootAbsPath = root.getAbsolutePath()
if (absPath.contains(rootAbsPath)) {
return rootAbsPath
if (FilenameUtils.directoryContains(rootAbsPath, absPath)) {
return root
}
}
return ""
return null
}
override fun compile() {
val args = K2JVMCompilerArguments();
val javaSrcRoots = HashSet<String>()
val args = K2JVMCompilerArguments()
val sources : MutableList<String> = LinkedList<String>()
val javaSrcRoots = HashSet<File>()
val sources = ArrayList<File>()
// collect source directory roots for all java files to allow cross compilation
getSource().mapTo(sources, { (f : File) : String ->
if (f.getName().endsWith(".java")) {
val javaRoot = findSrcDirRoot(f)
if (javaRoot.length() > 0) {
for (file in getSource()) {
if (FilenameUtils.getExtension(file.getName()).equalsIgnoreCase("java")) {
val javaRoot = findSrcDirRoot(file)
if (javaRoot != null) {
javaSrcRoots.add(javaRoot)
}
""
} else {
f.getAbsolutePath()
sources.add(file)
}
})
args.setSourceDirs(sources.filter { it.length() > 0 })
val joiner = Joiner.on(File.pathSeparator)!!
val gradleClasspath = getClasspath()?.filter(KSpec<File?>({ it != null && it.isAbsolute() }))?.getAsPath()
val javaSrcClasspath = joiner.join(javaSrcRoots)
val effectiveClassPath = joiner.join(javaSrcClasspath, gradleClasspath)
if (effectiveClassPath != null && effectiveClassPath.length() > 0) {
args.setClasspath(effectiveClassPath)
}
args.outputDir = (getDestinationDir()?.getPath())
if (sources.empty) {
getLogger().warn("No Kotlin files found, skipping Kotlin compiler task")
return
}
args.setSourceDirs(sources.map { it.getAbsolutePath() })
// todo: WTF absolute == gradle class path?
val gradleClasspath = getClasspath().filter(KSpec { it != null && it.isAbsolute() })
val effectiveClassPath = (javaSrcRoots + gradleClasspath).makeString(File.pathSeparator)
args.setClasspath(effectiveClassPath)
val embeddedAnnotations = getAnnotations()
args.outputDir = getDestinationDir()?.getPath()
args.noJdkAnnotations = true
args.annotations = getAnnotations()
args.annotations = embeddedAnnotations.getPath()
args.noStdlib = true
val exitCode = compiler.exec(System.err, args)
val messageCollector = GradleMessageCollector(getLogger())
val exitCode = compiler.exec(messageCollector, args)
if (embeddedAnnotations.getParentFile()?.delete() != true) {
throw GradleException("Can't delete extracted annotations " + embeddedAnnotations)
}
when (exitCode) {
ExitCode.COMPILATION_ERROR -> throw GradleException("Compilation error. See log for more details")
ExitCode.INTERNAL_ERROR -> throw GradleException("Internal compiler error. See log for more details")
else -> ""
else -> {}
}
}
fun getAnnotations() : String? {
val jdkAnnotations : String = "kotlin-jdk-annotations.jar"
val jdkAnnotationsResource : URL? = Resources.getResource(jdkAnnotations)
if (jdkAnnotationsResource == null) {
return null
}
fun getAnnotations(): File {
val jdkAnnotations: String = "kotlin-jdk-annotations.jar"
val jdkAnnotationsResource = Resources.getResource(jdkAnnotations) ?:
throw GradleException(jdkAnnotations + " not found in Kotlin gradle plugin classpath")
// todo fix leak of deleteOnExit handlers
val jdkAnnotationsTempDir : File? = Files.createTempDir()
jdkAnnotationsTempDir?.deleteOnExit()
val jdkAnnotationsFile : File = File(jdkAnnotationsTempDir, jdkAnnotations)
val jdkAnnotationsTempDir = Files.createTempDir()
val jdkAnnotationsFile = File(jdkAnnotationsTempDir, jdkAnnotations)
Files.copy(Resources.newInputStreamSupplier(jdkAnnotationsResource), jdkAnnotationsFile)
return jdkAnnotationsFile.getPath()
return jdkAnnotationsFile
}
}
open class KDoc() : SourceTask() {
public open class KDoc(): SourceTask() {
/**
* Returns the directory to use to output the API docs
*/
public var destinationDir : String = ""
public var destinationDir: String = ""
/**
* Returns the name of the documentation set
*/
public var title : String = ""
public var title: String = ""
/**
* Returns the version name of the documentation set
*/
public var version : String = ""
public var version: String = ""
/**
* Returns a map of the package prefix to the HTML URL for the root of the apidoc using javadoc/kdoc style
* directory layouts so that this API doc report can link to external packages
*/
public var packagePrefixToUrls : Map<String, String> = HashMap()
public var packagePrefixToUrls: Map<String, String> = HashMap()
/**
* Returns a Set of the package name prefixes to ignore from the KDoc report
*/
public var ignorePackages : Set<String> = HashSet()
public var ignorePackages: Set<String> = HashSet()
/**
* Returns true if a warning should be generated if there are no comments
* on documented function or property
*/
public var warnNoComments : Boolean = true
public var warnNoComments: Boolean = true
/**
* Returns the HTTP URL of the root directory of source code that we should link to
*/
public var sourceRootHref : String = ""
public var sourceRootHref: String = ""
/**
* The root project directory used to deduce relative file names when linking to source code
*/
public var projectRootDir : String = ""
public var projectRootDir: String = ""
/**
* A map of package name to html or markdown files used to describe the package. If none is
* speciied we will look for a package.html or package.md file in the source tree
* specified we will look for a package.html or package.md file in the source tree
*/
public var packageDescriptionFiles : Map<String,String> = HashMap()
public var packageDescriptionFiles: Map<String, String> = HashMap()
/**
* A map of package name to summary text used in the package overviews
*/
public var packageSummaryText : Map<String,String> = HashMap()
public var packageSummaryText: Map<String, String> = HashMap()
TaskAction fun generateDocs() {
val args : KDocArguments = KDocArguments()
val cfg : KDocConfig = args.docConfig
val args = KDocArguments()
val cfg = args.docConfig
cfg.docOutputDir = destinationDir
cfg.title = title
@@ -200,16 +203,32 @@ open class KDoc() : SourceTask() {
cfg.packageDescriptionFiles.putAll(packageDescriptionFiles)
cfg.packageSummaryText.putAll(packageSummaryText)
val compiler : KDocCompiler = KDocCompiler()
val compiler = KDocCompiler()
val exitCode = compiler.exec(System.err, args);
val messageCollector = GradleMessageCollector(getLogger())
val exitCode = compiler.exec(messageCollector, args);
when (exitCode) {
ExitCode.COMPILATION_ERROR -> throw GradleException("Failed to generate kdoc. See log for more details")
ExitCode.INTERNAL_ERROR -> throw GradleException("Internal generation error. See log for more details")
else -> ""
else -> {}
}
}
}
class GradleMessageCollector(val logger : Logger): MessageCollector {
public override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation) {
val path = location.getPath()
val position = if (path != null) (path + ": (" + location.getLine() + ", " + location.getColumn() + ") ") else ""
val text = position + message
when (severity) {
in CompilerMessageSeverity.VERBOSE -> logger.debug(text)
in CompilerMessageSeverity.ERRORS -> logger.error(text)
CompilerMessageSeverity.INFO -> logger.info(text)
else -> logger.warn(text)
}
}
}
@@ -5,29 +5,25 @@ import com.intellij.openapi.util.SystemInfo
import java.io.File
import java.util.Arrays
import java.util.Scanner
import org.testng.Assert.*
import org.testng.annotations.AfterMethod
import org.testng.annotations.BeforeMethod
import org.testng.annotations.Test
import org.junit.Before
import org.junit.After
import org.junit.Test
import kotlin.test.assertTrue
import kotlin.test.assertEquals
import kotlin.test.fail
/**
* Created by Nikita.Skvortsov
* Date: 2/27/13, 5:02 PM
*/
class BasicKotlinGradleIntegrationTest {
var workingDir: File = File(".")
class BasicKotlinGradleIT {
var workingDir : File = File(".")
BeforeMethod fun setUp() {
workingDir = Files.createTempDir()!!
Before fun setUp() {
workingDir = Files.createTempDir()
workingDir.mkdirs()
copyRecursively(File("src/test/resources/testProject/alfa"), workingDir)
}
AfterMethod fun tearDown() {
After fun tearDown() {
deleteRecursively(workingDir)
}
@@ -35,19 +31,19 @@ class BasicKotlinGradleIT {
val projectDir = File(workingDir, "alfa")
val pathToKotlinPlugin = "-PpathToKotlinPlugin=" + File("target/local-repo").getAbsolutePath()
val cmd = if (SystemInfo.isWindows)
Arrays.asList("cmd", "/C", "gradlew.bat", "clean", "compileDeployKotlin", "build", pathToKotlinPlugin, "--no-daemon")
else
Arrays.asList("./gradlew", "clean", "compileDeployKotlin", "build", pathToKotlinPlugin, "--no-daemon")
val cmd = if (SystemInfo.isWindows)
listOf("cmd", "/C", "gradlew.bat", "clean", "compileDeployKotlin", "build", pathToKotlinPlugin, "--no-daemon", "--debug")
else
listOf("/bin/sh", "./gradlew", "clean", "compileDeployKotlin", "build", pathToKotlinPlugin, "--no-daemon", "--debug")
val builder : ProcessBuilder = ProcessBuilder(cmd)
val builder = ProcessBuilder(cmd)
builder.directory(projectDir)
builder.redirectErrorStream(true)
val process : Process = builder.start()
val process = builder.start()
val s : Scanner = Scanner(process.getInputStream()!!)
val text : StringBuilder = StringBuilder()
val s = Scanner(process.getInputStream()!!)
val text = StringBuilder()
while (s.hasNextLine()) {
text append s.nextLine()
text append "\n"
@@ -74,7 +70,7 @@ class BasicKotlinGradleIT {
val array = source.listFiles()
if (array != null) {
for (child in array) {
copyRecursively(child,targetFile)
copyRecursively(child, targetFile)
}
}
} else {
@@ -83,7 +79,7 @@ class BasicKotlinGradleIT {
}
fun deleteRecursively(f : File): Unit {
fun deleteRecursively(f: File): Unit {
if (f.isDirectory()) {
val children = f.listFiles()
if (children != null) {