Track changes for jar files for non-Android Gradle projects
This commit is contained in:
+2
-1
@@ -22,7 +22,8 @@ data class IncrementalModuleEntry(
|
||||
class IncrementalModuleInfo(
|
||||
val projectRoot: File,
|
||||
val dirToModule: Map<File, IncrementalModuleEntry>,
|
||||
val nameToModules: Map<String, Set<IncrementalModuleEntry>>
|
||||
val nameToModules: Map<String, Set<IncrementalModuleEntry>>,
|
||||
val jarToClassListFile: Map<File, File>
|
||||
) : Serializable {
|
||||
companion object {
|
||||
private const val serialVersionUID = 0L
|
||||
|
||||
@@ -48,8 +48,7 @@ import org.jetbrains.kotlin.daemon.report.RemoteICReporter
|
||||
import org.jetbrains.kotlin.incremental.*
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.incremental.parsing.classesFqNames
|
||||
import org.jetbrains.kotlin.incremental.multiproject.EmptyModulesApiHistory
|
||||
import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistoryImpl
|
||||
import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistoryJvm
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||
import org.jetbrains.kotlin.modules.Module
|
||||
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
||||
@@ -524,9 +523,7 @@ class CompileServiceImpl(
|
||||
workingDir,
|
||||
enabled = true)
|
||||
|
||||
val modulesApiHistory = incrementalCompilationOptions.run {
|
||||
ModulesApiHistoryImpl(modulesInfo)
|
||||
}
|
||||
val modulesApiHistory = ModulesApiHistoryJvm(incrementalCompilationOptions.modulesInfo)
|
||||
|
||||
val compiler = IncrementalJvmCompilerRunner(
|
||||
workingDir,
|
||||
|
||||
+26
-11
@@ -21,10 +21,8 @@ object EmptyModulesApiHistory : ModulesApiHistory {
|
||||
Either.Error("Multi-module IC is not configured")
|
||||
}
|
||||
|
||||
class ModulesApiHistoryImpl(
|
||||
private val modulesInfo: IncrementalModuleInfo
|
||||
) : ModulesApiHistory {
|
||||
private val projectRootPath = Paths.get(modulesInfo.projectRoot.absolutePath)
|
||||
open class ModulesApiHistoryJvm(protected val modulesInfo: IncrementalModuleInfo) : ModulesApiHistory {
|
||||
protected val projectRootPath: Path = Paths.get(modulesInfo.projectRoot.absolutePath)
|
||||
private val dirToHistoryFileCache = HashMap<File, File?>()
|
||||
|
||||
override fun historyFilesForChangedFiles(changedFiles: Set<File>): Either<Set<File>> {
|
||||
@@ -46,9 +44,9 @@ class ModulesApiHistoryImpl(
|
||||
}
|
||||
|
||||
for (jar in jarFiles) {
|
||||
val historyEither = getBuildHistoryForJar(jar)
|
||||
val historyEither = getBuildHistoryFilesForJar(jar)
|
||||
when (historyEither) {
|
||||
is Either.Success<File> -> result.add(historyEither.value)
|
||||
is Either.Success<Set<File>> -> result.addAll(historyEither.value)
|
||||
is Either.Error -> return historyEither
|
||||
}
|
||||
}
|
||||
@@ -78,9 +76,26 @@ class ModulesApiHistoryImpl(
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBuildHistoryForJar(jar: File): Either<File> =
|
||||
Either.Error("Cannot get changes for jar $jar")
|
||||
protected open fun getBuildHistoryFilesForJar(jar: File): Either<Set<File>> {
|
||||
val classListFile = modulesInfo.jarToClassListFile[jar] ?: return Either.Error("Unknown jar: $jar")
|
||||
if (!classListFile.isFile) return Either.Error("Class list file does not exist $classListFile")
|
||||
|
||||
private fun Path.isParentOf(path: Path) = path.startsWith(this)
|
||||
private fun Path.isParentOf(file: File) = this.isParentOf(Paths.get(file.absolutePath))
|
||||
}
|
||||
val classFiles = try {
|
||||
classListFile.readText().split(File.pathSeparator).map(::File)
|
||||
} catch (t: Throwable) {
|
||||
return Either.Error("Could not read class list for $jar from $classListFile: $t")
|
||||
}
|
||||
|
||||
val classFileDirs = classFiles.groupBy { it.parentFile }
|
||||
val result = HashSet<File>()
|
||||
for ((dir, files) in classFileDirs) {
|
||||
val buildHistory = getBuildHistoryForDir(dir)
|
||||
?: return Either.Error("Could not get build history for class files: ${files.joinToString()}")
|
||||
result.add(buildHistory)
|
||||
}
|
||||
return Either.Success(result)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Path.isParentOf(path: Path) = path.startsWith(this)
|
||||
private fun Path.isParentOf(file: File) = this.isParentOf(Paths.get(file.absolutePath))
|
||||
+10
-10
@@ -25,14 +25,14 @@ internal open class GradleCompilerEnvironment(
|
||||
}
|
||||
|
||||
internal class GradleIncrementalCompilerEnvironment(
|
||||
compilerClasspath: List<File>,
|
||||
val changedFiles: ChangedFiles,
|
||||
val workingDir: File,
|
||||
messageCollector: GradleMessageCollector,
|
||||
outputItemsCollector: OutputItemsCollector,
|
||||
compilerArgs: CommonCompilerArguments,
|
||||
val buildHistoryFile: File,
|
||||
val kaptAnnotationsFileUpdater: AnnotationFileUpdater? = null,
|
||||
val usePreciseJavaTracking: Boolean = false,
|
||||
val localStateDirs: List<File> = emptyList()
|
||||
compilerClasspath: List<File>,
|
||||
val changedFiles: ChangedFiles,
|
||||
val workingDir: File,
|
||||
messageCollector: GradleMessageCollector,
|
||||
outputItemsCollector: OutputItemsCollector,
|
||||
compilerArgs: CommonCompilerArguments,
|
||||
val buildHistoryFile: File,
|
||||
val kaptAnnotationsFileUpdater: AnnotationFileUpdater? = null,
|
||||
val usePreciseJavaTracking: Boolean = false,
|
||||
val localStateDirs: List<File> = emptyList()
|
||||
) : GradleCompilerEnvironment(compilerClasspath, messageCollector, outputItemsCollector, compilerArgs)
|
||||
|
||||
+15
-6
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.daemon.common.*
|
||||
import org.jetbrains.kotlin.daemon.common.IncrementalModuleEntry
|
||||
import org.jetbrains.kotlin.daemon.common.IncrementalModuleInfo
|
||||
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
|
||||
import org.jetbrains.kotlin.gradle.tasks.InspectClassesForMultiModuleIC
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import org.jetbrains.kotlin.incremental.*
|
||||
import java.io.ByteArrayOutputStream
|
||||
@@ -356,17 +357,25 @@ internal class GradleCompilerRunner(private val project: Project) : KotlinCompil
|
||||
|
||||
val dirToModule = HashMap<File, IncrementalModuleEntry>()
|
||||
val nameToModules = HashMap<String, HashSet<IncrementalModuleEntry>>()
|
||||
val jarToClassListFile = HashMap<File, File>()
|
||||
|
||||
for (project in gradle.rootProject.allprojects) {
|
||||
for (task in project.tasks.withType(KotlinCompile::class.java)) {
|
||||
val module = IncrementalModuleEntry(project.path, task.moduleName, project.buildDir, task.buildHistoryFile)
|
||||
dirToModule[task.destinationDir] = module
|
||||
task.javaOutputDir?.let { dirToModule[it] = module }
|
||||
nameToModules.getOrPut(module.name) { HashSet() }.add(module)
|
||||
for (task in project.tasks) {
|
||||
when (task) {
|
||||
is KotlinCompile -> {
|
||||
val module = IncrementalModuleEntry(project.path, task.moduleName, project.buildDir, task.buildHistoryFile)
|
||||
dirToModule[task.destinationDir] = module
|
||||
task.javaOutputDir?.let { dirToModule[it] = module }
|
||||
nameToModules.getOrPut(module.name) { HashSet() }.add(module)
|
||||
}
|
||||
is InspectClassesForMultiModuleIC -> {
|
||||
jarToClassListFile[File(task.archivePath)] = task.classesListFile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return IncrementalModuleInfo(gradle.rootProject.projectDir, dirToModule, nameToModules)
|
||||
return IncrementalModuleInfo(gradle.rootProject.projectDir, dirToModule, nameToModules, jarToClassListFile)
|
||||
.also {
|
||||
cachedGradle = WeakReference(gradle)
|
||||
cachedModulesInfo = it
|
||||
|
||||
+20
@@ -23,6 +23,7 @@ import org.gradle.api.plugins.JavaPluginConvention
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.gradle.api.tasks.compile.JavaCompile
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptionsImpl
|
||||
import org.jetbrains.kotlin.gradle.internal.*
|
||||
@@ -358,6 +359,7 @@ internal abstract class AbstractKotlinPlugin(
|
||||
|
||||
configureSourceSetDefaults(project, javaBasePlugin, javaPluginConvention)
|
||||
configureDefaultVersionsResolutionStrategy(project)
|
||||
configureClassInspectionForIC(project)
|
||||
}
|
||||
|
||||
open protected fun configureSourceSetDefaults(
|
||||
@@ -390,6 +392,24 @@ internal abstract class AbstractKotlinPlugin(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun configureClassInspectionForIC(project: Project) {
|
||||
val classesTask = project.tasks.findByName(JavaPlugin.CLASSES_TASK_NAME)
|
||||
val jarTask = project.tasks.findByName(JavaPlugin.JAR_TASK_NAME)
|
||||
|
||||
if (classesTask == null || jarTask !is Jar) {
|
||||
project.logger.info(
|
||||
"Could not configure class inspection task " +
|
||||
"(classes task = ${classesTask?.javaClass?.canonicalName}, " +
|
||||
"jar task = ${classesTask?.javaClass?.canonicalName}"
|
||||
)
|
||||
return
|
||||
}
|
||||
val inspectTask = project.tasks.create("inspectClassesForKotlinIC", InspectClassesForMultiModuleIC::class.java)
|
||||
inspectTask.jarTask = jarTask
|
||||
inspectTask.dependsOn(classesTask)
|
||||
jarTask.dependsOn(inspectTask)
|
||||
}
|
||||
}
|
||||
|
||||
internal open class KotlinPlugin(
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.tasks
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import org.jetbrains.kotlin.gradle.utils.inputsCompatible
|
||||
import org.jetbrains.kotlin.incremental.isClassFile
|
||||
import java.io.File
|
||||
|
||||
internal open class InspectClassesForMultiModuleIC : DefaultTask() {
|
||||
@get:Internal
|
||||
lateinit var jarTask: Jar
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
@get:OutputFile
|
||||
internal val classesListFile: File
|
||||
get() = File(File(project.buildDir, KOTLIN_BUILD_DIR_NAME), "${sanitizeFileName(jarTask.archiveName)}-classes.txt")
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
@get:InputFiles
|
||||
internal val classFiles: FileCollection
|
||||
get() = jarTask.inputsCompatible.files.filter { it.isClassFile() }
|
||||
|
||||
@get:Input
|
||||
internal val archivePath: String
|
||||
get() = jarTask.archivePath.canonicalPath
|
||||
|
||||
@TaskAction
|
||||
fun run() {
|
||||
classesListFile.parentFile.mkdirs()
|
||||
val paths = classFiles.map { it.canonicalPath }.sorted()
|
||||
val text = paths.joinToString(File.pathSeparator)
|
||||
classesListFile.writeText(text)
|
||||
}
|
||||
|
||||
private fun sanitizeFileName(candidate: String): String =
|
||||
candidate.filter { it.isLetterOrDigit() }
|
||||
}
|
||||
Reference in New Issue
Block a user