From b474c2de37e86802a53049a25fd6b9c1b3515a79 Mon Sep 17 00:00:00 2001 From: Cedric Beust Date: Tue, 2 Feb 2016 22:58:53 +0400 Subject: [PATCH] Mixed language projects. --- .../main/kotlin/com/beust/kobalt/Variant.kt | 16 ++-- .../beust/kobalt/api/ICompilerContributor.kt | 3 +- .../kotlin/com/beust/kobalt/api/Project.kt | 1 - .../com/beust/kobalt/internal/ActorUtils.kt | 7 ++ .../kobalt/internal/JvmCompilerPlugin.kt | 84 +++++++++---------- .../com/beust/kobalt/internal/ProjectInfo.kt | 10 +-- .../beust/kobalt/plugin/java/JavaPlugin.kt | 5 +- .../kobalt/plugin/java/JavaProjectInfo.kt | 3 +- .../kobalt/plugin/kotlin/KotlinPlugin.kt | 5 +- .../kobalt/plugin/kotlin/KotlinProjectInfo.kt | 3 +- .../plugin/packaging/PackagingPlugin.kt | 2 +- 11 files changed, 73 insertions(+), 66 deletions(-) diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/Variant.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/Variant.kt index 12a2c01b..f6e6274c 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/Variant.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/Variant.kt @@ -1,6 +1,7 @@ package com.beust.kobalt import com.beust.kobalt.api.* +import com.beust.kobalt.internal.ActorUtils import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.log import java.io.File @@ -34,11 +35,14 @@ class Variant(val initialProductFlavor: ProductFlavorConfig? = null, return result } - fun resDirectories(project: Project) : List = sourceDirectories(project, "res") - - fun sourceDirectories(project: Project) = project.projectInfo.sourceSuffixes.flatMap { + fun sourceDirectories(project: Project, context: KobaltContext) : List { + val compilers = ActorUtils.selectAffinityActors(project, context, context.pluginInfo.compilerContributors) + val sourceSuffixes = compilers.flatMap { it.sourceSuffixes } + val result = sourceSuffixes.flatMap { sourceDirectories(project, it) - } + }.toHashSet() + return result.toList() + } /** * suffix is either "java" (to find source files) or "res" (to find resources) @@ -141,7 +145,9 @@ class Variant(val initialProductFlavor: ProductFlavorConfig? = null, // that directory will be added when trying to find recursively all the sources in it generatedSourceDirectory = File(result.relativeTo(File(project.directory))) val outputGeneratedSourceDirectory = File(result, pkg.replace('.', File.separatorChar)) - val outputDir = File(outputGeneratedSourceDirectory, "BuildConfig" + project.sourceSuffix) + val compilers = ActorUtils.selectAffinityActors(project, context, context.pluginInfo.compilerContributors) + val outputDir = File(outputGeneratedSourceDirectory, + "BuildConfig" + compilers[0].sourceSuffixes[0]) KFiles.saveFile(outputDir, code) log(2, "Generated ${outputDir.path}") return result diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/ICompilerContributor.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/ICompilerContributor.kt index 1de85643..4372d1ec 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/ICompilerContributor.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/ICompilerContributor.kt @@ -1,9 +1,8 @@ package com.beust.kobalt.api import com.beust.kobalt.TaskResult -import com.beust.kobalt.api.IClasspathDependency -import java.io.File interface ICompilerContributor : IProjectAffinity { + val sourceSuffixes: List fun compile(project: Project, context: KobaltContext, info: CompilerActionInfo) : TaskResult } diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/Project.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/Project.kt index 17dca103..a01ad682 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/Project.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/Project.kt @@ -16,7 +16,6 @@ open class Project( @Directive open var artifactId: String? = null, @Directive open var packaging: String? = null, @Directive open var dependencies: Dependencies? = null, - @Directive open var sourceSuffix : String = "", @Directive open var description : String = "", @Directive open var scm : Scm? = null, @Directive open var url: String? = null, diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/ActorUtils.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/ActorUtils.kt index 6216ecfb..42aac9e2 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/ActorUtils.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/ActorUtils.kt @@ -13,6 +13,13 @@ class ActorUtils { fun selectAffinityActor(project: Project, context: KobaltContext, actors: List) = actors.maxBy { it.affinity(project, context) } + /** + * Return all the plug-in actors with a non zero affinity sorted from the highest to the lowest. + */ + fun selectAffinityActors(project: Project, context: KobaltContext, actors: List) + = actors.filter { it.affinity(project, context) > 0 } + .sortedByDescending { it.affinity(project, context) } + /** * Return the plug-in actor with the highest affinity. */ diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt index bd74d8a2..e96d1764 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt @@ -138,34 +138,6 @@ abstract class JvmCompilerPlugin @Inject constructor( project.projectProperties.put(COMPILER_ARGS, arrayListOf(*args)) } - fun isOutdated(project: Project, context: KobaltContext, actionInfo: CompilerActionInfo): Boolean { - fun stripSourceDir(sourceFile: String): String { - project.sourceDirectories.forEach { - val d = listOf(project.directory, it).joinToString("/") - if (sourceFile.startsWith(d)) return sourceFile.substring(d.length + 1) - } - throw KobaltException("Couldn't strip source dir from $sourceFile") - } - - fun stripSuffix(sourceFile: String): String { - val index = sourceFile.indexOf(project.sourceSuffix) - if (index >= 0) return sourceFile.substring(0, index) - else return sourceFile - } - - actionInfo.sourceFiles.map { it.replace("\\", "/") }.forEach { sourceFile -> - val stripped = stripSourceDir(sourceFile) - val classFile = File(KFiles.joinDir(project.directory, project.classesDir(context), - toClassFile(stripSuffix(stripped)))) - if (!classFile.exists() || File(sourceFile).lastModified() > classFile.lastModified()) { - log(2, "Outdated $sourceFile $classFile " + Date(File(sourceFile).lastModified()) + - " " + classFile.lastModified()) - return true - } - } - return false - } - @IncrementalTask(name = JvmCompilerPlugin.TASK_COMPILE, description = "Compile the project") fun taskCompile(project: Project): IncrementalTaskInfo { val inputChecksum = Md5.toMd5Directories(project.sourceDirectories.map { @@ -182,18 +154,32 @@ abstract class JvmCompilerPlugin @Inject constructor( private fun doTaskCompile(project: Project): TaskResult { // Set up the source files now that we have the variant - sourceDirectories.addAll(context.variant.sourceDirectories(project)) + sourceDirectories.addAll(context.variant.sourceDirectories(project, context)) val sourceDirectory = context.variant.maybeGenerateBuildConfig(project, context) if (sourceDirectory != null) { sourceDirectories.add(sourceDirectory) } - val info = createCompilerActionInfo(project, context, isTest = false) - val compiler = ActorUtils.selectAffinityActor(project, context, context.pluginInfo.compilerContributors) - if (compiler != null) { - return compiler.compile(project, context, info) - } else { +// val info = createCompilerActionInfo(project, context, isTest = false) +// val compiler = ActorUtils.selectAffinityActor(project, context, context.pluginInfo.compilerContributors) + val results = arrayListOf() + val compilers = ActorUtils.selectAffinityActors(project, context, context.pluginInfo.compilerContributors) + + var failedResult: TaskResult? = null + if (compilers.isEmpty()) { throw KobaltException("Couldn't find any compiler for project ${project.name}") + } else { + compilers.forEach { compiler -> + val info = createCompilerActionInfo(project, context, isTest = false, + sourceSuffixes = compiler.sourceSuffixes) + val thisResult = compiler.compile(project, context, info) + results.add(thisResult) + if (! thisResult.success && failedResult == null) { + failedResult = thisResult + } + } + return if (failedResult != null) failedResult!! + else results[0] } } @@ -214,8 +200,13 @@ abstract class JvmCompilerPlugin @Inject constructor( fun taskJavadoc(project: Project): TaskResult { val docGenerator = ActorUtils.selectAffinityActor(project, context, context.pluginInfo.docContributors) if (docGenerator != null) { - return docGenerator.generateDoc(project, context, createCompilerActionInfo(project, context, - isTest = false)) + val compilers = ActorUtils.selectAffinityActors(project, context, context.pluginInfo.compilerContributors) + var result: TaskResult? = null + compilers.forEach { compiler -> + result = docGenerator.generateDoc(project, context, createCompilerActionInfo(project, context, + isTest = false, sourceSuffixes = compiler.sourceSuffixes)) + } + return result!! } else { warn("Couldn't find any doc contributor for project ${project.name}") return TaskResult() @@ -234,8 +225,8 @@ abstract class JvmCompilerPlugin @Inject constructor( * Create a CompilerActionInfo (all the information that a compiler needs to know) for the given parameters. * Runs all the contributors and interceptors relevant to that task. */ - protected fun createCompilerActionInfo(project: Project, context: KobaltContext, isTest: Boolean): - CompilerActionInfo { + protected fun createCompilerActionInfo(project: Project, context: KobaltContext, isTest: Boolean, + sourceSuffixes: List): CompilerActionInfo { copyResources(project, JvmCompilerPlugin.SOURCE_SET_MAIN) val fullClasspath = if (isTest) dependencyManager.testDependencies(project, context) @@ -271,14 +262,23 @@ abstract class JvmCompilerPlugin @Inject constructor( File(project.directory, it.path).exists() } - // Now that we have the final list of source dirs, find source files in them val sourceFiles = files.findRecursively(projectDirectory, sourceDirectories, - { it.endsWith(project.sourceSuffix) }) + { file -> sourceSuffixes.any { file.endsWith(it) }}) .map { File(projectDirectory, it).path } + // Special treatment if we are compiling Kotlin files and the project also has a java source + // directory. In this case, also pass that java source directory to the Kotlin compiler as is + // so that it can parse its symbols + val extraSourceFiles = arrayListOf() + if (sourceSuffixes.any { it.contains("kt")}) { + project.sourceDirectories.forEach { + if (it.contains("java")) extraSourceFiles.add(it) + } + } + // Finally, alter the info with the compiler interceptors before returning it - val initialActionInfo = CompilerActionInfo(projectDirectory.path, classpath, sourceFiles, buildDirectory, - emptyList()) + val initialActionInfo = CompilerActionInfo(projectDirectory.path, classpath, sourceFiles + extraSourceFiles, + buildDirectory, emptyList()) val result = context.pluginInfo.compilerInterceptors.fold(initialActionInfo, { ai, interceptor -> interceptor.intercept(project, context, ai) }) diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/ProjectInfo.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/ProjectInfo.kt index 81971559..093bc45e 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/ProjectInfo.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/ProjectInfo.kt @@ -7,16 +7,10 @@ import com.beust.kobalt.api.KobaltContext import com.beust.kobalt.api.Project import java.util.* -class LanguageInfo(val name: String, val suffix : String = name) - /** * Data that is useful for projects to have but should not be specified in the DSL. */ interface IProjectInfo { - val languageInfos: List - - val sourceSuffixes: List - val defaultSourceDirectories: HashSet val defaultTestDirectories: HashSet @@ -40,11 +34,9 @@ interface IProjectInfo { fun dependsOnDirtyProjects(project: Project) = project.projectInfo.dependsOn.any { it.projectInfo.isDirty } } -abstract class BaseProjectInfo(override val languageInfos: List) : IProjectInfo { +abstract class BaseProjectInfo : IProjectInfo { abstract fun generate(field: BuildConfigField) : String - override val sourceSuffixes = languageInfos.map { it.suffix } - fun generate(type: String, name: String, value: Any) = generate(BuildConfigField(type, name, value)) fun generateFieldsFromContributors(project: Project, context: KobaltContext) diff --git a/src/main/kotlin/com/beust/kobalt/plugin/java/JavaPlugin.kt b/src/main/kotlin/com/beust/kobalt/plugin/java/JavaPlugin.kt index 2b3b1aa1..f9590864 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/java/JavaPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/java/JavaPlugin.kt @@ -52,12 +52,15 @@ class JavaPlugin @Inject constructor( override fun doTaskCompileTest(project: Project): TaskResult { copyResources(project, JvmCompilerPlugin.SOURCE_SET_TEST) - val compilerActionInfo = createCompilerActionInfo(project, context, isTest = true) + val compilerActionInfo = createCompilerActionInfo(project, context, isTest = true, + sourceSuffixes = sourceSuffixes) val result = javaCompiler.compile(project, context, compilerActionInfo) return result } // ICompilerContributor + override val sourceSuffixes = listOf("java") + override fun compile(project: Project, context: KobaltContext, info: CompilerActionInfo) : TaskResult { val result = if (info.sourceFiles.size > 0) { diff --git a/src/main/kotlin/com/beust/kobalt/plugin/java/JavaProjectInfo.kt b/src/main/kotlin/com/beust/kobalt/plugin/java/JavaProjectInfo.kt index 11f55760..4f47d9ec 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/java/JavaProjectInfo.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/java/JavaProjectInfo.kt @@ -6,11 +6,10 @@ import com.beust.kobalt.api.BuildConfigField import com.beust.kobalt.api.KobaltContext import com.beust.kobalt.api.Project import com.beust.kobalt.internal.BaseProjectInfo -import com.beust.kobalt.internal.LanguageInfo import com.google.inject.Singleton @Singleton -class JavaProjectInfo : BaseProjectInfo(listOf(LanguageInfo("java", "java"))) { +class JavaProjectInfo : BaseProjectInfo() { override val defaultSourceDirectories = hashSetOf("src/main/java", "src/main/resources", "src/main/res") override val defaultTestDirectories = hashSetOf("src/test/java", "src/test/resources", "src/test/res") diff --git a/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinPlugin.kt b/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinPlugin.kt index 6158236c..b0870435 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinPlugin.kt @@ -76,8 +76,9 @@ class KotlinPlugin @Inject constructor( copyResources(project, JvmCompilerPlugin.SOURCE_SET_TEST) val projectDir = File(project.directory) + val sourceFiles = files.findRecursively(projectDir, project.sourceDirectoriesTest.map { File(it) }) - { it: String -> it.endsWith(project.sourceSuffix) } + { file: String -> sourceSuffixes.any { file.endsWith(it) } } .map { File(projectDir, it).absolutePath } val result = @@ -124,6 +125,8 @@ class KotlinPlugin @Inject constructor( // ICompilerContributor + override val sourceSuffixes = listOf("kt") + override fun affinity(project: Project, context: KobaltContext) = if (project.sourceDirectories.any { it.contains("kotlin") }) 2 else 0 diff --git a/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinProjectInfo.kt b/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinProjectInfo.kt index 9d951583..8ba851bd 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinProjectInfo.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinProjectInfo.kt @@ -6,11 +6,10 @@ import com.beust.kobalt.api.BuildConfigField import com.beust.kobalt.api.KobaltContext import com.beust.kobalt.api.Project import com.beust.kobalt.internal.BaseProjectInfo -import com.beust.kobalt.internal.LanguageInfo import com.google.inject.Singleton @Singleton -class KotlinProjectInfo : BaseProjectInfo(listOf(LanguageInfo("kotlin", "kt"))) { +class KotlinProjectInfo : BaseProjectInfo() { override val defaultSourceDirectories = hashSetOf("src/main/kotlin", "src/main/resources", "src/main/res") override val defaultTestDirectories = hashSetOf("src/test/kotlin", "src/test/resources", "src/test/res") diff --git a/src/main/kotlin/com/beust/kobalt/plugin/packaging/PackagingPlugin.kt b/src/main/kotlin/com/beust/kobalt/plugin/packaging/PackagingPlugin.kt index 8121c861..96550cdd 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/packaging/PackagingPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/packaging/PackagingPlugin.kt @@ -276,7 +276,7 @@ class PackageConfig(val project: Project) : AttributeHolder { jar { name = "${project.name}-${project.version}-sources.jar" project.sourceDirectories.forEach { - include(from(it), to(""), glob("**${project.sourceSuffix}")) + include(from(it), to(""), glob("src/**")) } } jar {