[Build] Fix configuration cache issues (part 3)

* Make IntelliJInstrumentCodeTask compatible with configuration cache
* Make CoreXmlShadingTransformer compatible with configuration cache
* Make :kotlin-reflect:relocateCoreSources compatible with configuration cache
* Copy some properties to not capture it's owning object into lambda to support configuration cache
Relates to #KT-44611
This commit is contained in:
Alexander Likhachev
2021-02-14 10:39:26 +03:00
parent 0e4e90dc13
commit 5f10c98a38
5 changed files with 42 additions and 15 deletions
+18 -11
View File
@@ -21,12 +21,14 @@ import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ProjectDependency import org.gradle.api.artifacts.ProjectDependency
import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.FileCollection import org.gradle.api.file.FileCollection
import org.gradle.api.file.FileSystemOperations
import org.gradle.api.internal.ConventionTask import org.gradle.api.internal.ConventionTask
import org.gradle.api.plugins.ExtensionAware import org.gradle.api.plugins.ExtensionAware
import org.gradle.api.tasks.* import org.gradle.api.tasks.*
import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.api.tasks.compile.AbstractCompile
import org.gradle.kotlin.dsl.* import org.gradle.kotlin.dsl.*
import java.io.File import java.io.File
import javax.inject.Inject
fun Project.configureFormInstrumentation() { fun Project.configureFormInstrumentation() {
plugins.matching { it::class.java.canonicalName.startsWith("org.jetbrains.kotlin.gradle.plugin") }.all { plugins.matching { it::class.java.canonicalName.startsWith("org.jetbrains.kotlin.gradle.plugin") }.all {
@@ -76,7 +78,7 @@ fun Project.configureFormInstrumentation() {
} }
afterEvaluate { afterEvaluate {
sourceSets.all { sourceSetParam -> sourceSets.forEach { sourceSetParam ->
// This copy will ignore filters, but they are unlikely to be used. // This copy will ignore filters, but they are unlikely to be used.
val classesDirs = (sourceSetParam.output.classesDirs as ConfigurableFileCollection).from as Collection<Any> val classesDirs = (sourceSetParam.output.classesDirs as ConfigurableFileCollection).from as Collection<Any>
@@ -88,7 +90,7 @@ fun Project.configureFormInstrumentation() {
(sourceSetParam.output.classesDirs as ConfigurableFileCollection).setFrom(instrumentedClassesDir) (sourceSetParam.output.classesDirs as ConfigurableFileCollection).setFrom(instrumentedClassesDir)
val instrumentTask = val instrumentTask =
project.tasks.register(sourceSetParam.getTaskName("instrument", "classes"), IntelliJInstrumentCodeTask::class.java) { project.tasks.register(sourceSetParam.getTaskName("instrument", "classes"), IntelliJInstrumentCodeTask::class.java) {
dependsOn(sourceSetParam.classesTaskName).onlyIf { !classesDirsCopy.isEmpty } dependsOn(sourceSetParam.classesTaskName)
sourceSet = sourceSetParam sourceSet = sourceSetParam
instrumentationClasspathConfiguration = instrumentationClasspathCfg instrumentationClasspathConfiguration = instrumentationClasspathCfg
originalClassesDirs = classesDirsCopy originalClassesDirs = classesDirsCopy
@@ -98,14 +100,12 @@ fun Project.configureFormInstrumentation() {
// Ensure that our task is invoked when the source set is built // Ensure that our task is invoked when the source set is built
sourceSetParam.compiledBy(instrumentTask) sourceSetParam.compiledBy(instrumentTask)
@Suppress("UNUSED_EXPRESSION")
true
} }
} }
} }
@CacheableTask @CacheableTask
open class IntelliJInstrumentCodeTask : ConventionTask() { abstract class IntelliJInstrumentCodeTask : ConventionTask() {
companion object { companion object {
private const val FILTER_ANNOTATION_REGEXP_CLASS = "com.intellij.ant.ClassFilterAnnotationRegexp" private const val FILTER_ANNOTATION_REGEXP_CLASS = "com.intellij.ant.ClassFilterAnnotationRegexp"
private const val LOADER_REF = "java2.loader" private const val LOADER_REF = "java2.loader"
@@ -122,7 +122,8 @@ open class IntelliJInstrumentCodeTask : ConventionTask() {
@InputFiles @InputFiles
@PathSensitive(PathSensitivity.RELATIVE) @PathSensitive(PathSensitivity.RELATIVE)
var originalClassesDirs: FileCollection? = null @SkipWhenEmpty
lateinit var originalClassesDirs: FileCollection
@get:Input @get:Input
var instrumentNotNull: Boolean = false var instrumentNotNull: Boolean = false
@@ -135,6 +136,12 @@ open class IntelliJInstrumentCodeTask : ConventionTask() {
sourceSet.compileClasspath sourceSet.compileClasspath
} }
// Instrumentation needs to have access to sources of forms for inclusion
private val depSourceDirectorySets by lazy {
project.configurations["compile"].dependencies.withType(ProjectDependency::class.java)
.map { p -> p.dependencyProject.mainSourceSet.allSource.sourceDirectories }
}
@get:InputFiles @get:InputFiles
@get:PathSensitive(PathSensitivity.RELATIVE) @get:PathSensitive(PathSensitivity.RELATIVE)
val sourceDirs: FileCollection by lazy { val sourceDirs: FileCollection by lazy {
@@ -144,10 +151,13 @@ open class IntelliJInstrumentCodeTask : ConventionTask() {
@get:OutputDirectory @get:OutputDirectory
lateinit var output: File lateinit var output: File
@get:Inject
abstract val fs: FileSystemOperations
@TaskAction @TaskAction
fun instrumentClasses() { fun instrumentClasses() {
logger.info( logger.info(
"input files are: ${originalClassesDirs?.joinToString( "input files are: ${originalClassesDirs.joinToString(
"; ", "; ",
transform = { "'${it.name}'${if (it.exists()) "" else " (does not exists)"}" })}" transform = { "'${it.name}'${if (it.exists()) "" else " (does not exists)"}" })}"
) )
@@ -174,7 +184,7 @@ open class IntelliJInstrumentCodeTask : ConventionTask() {
} }
private fun copyOriginalClasses() { private fun copyOriginalClasses() {
project.copy { fs.copy {
from(originalClassesDirs) from(originalClassesDirs)
into(output) into(output)
} }
@@ -194,9 +204,6 @@ open class IntelliJInstrumentCodeTask : ConventionTask() {
private fun instrumentCode(srcDirs: FileCollection, instrumentNotNull: Boolean) { private fun instrumentCode(srcDirs: FileCollection, instrumentNotNull: Boolean) {
val headlessOldValue = System.setProperty("java.awt.headless", "true") val headlessOldValue = System.setProperty("java.awt.headless", "true")
// Instrumentation needs to have access to sources of forms for inclusion
val depSourceDirectorySets = project.configurations["compile"].dependencies.withType(ProjectDependency::class.java)
.map { p -> p.dependencyProject.mainSourceSet.allSource.sourceDirectories }
val instrumentationClasspath = val instrumentationClasspath =
depSourceDirectorySets.fold(compileClasspath) { acc, v -> acc + v }.asPath.also { depSourceDirectorySets.fold(compileClasspath) { acc, v -> acc + v }.asPath.also {
logger.info("Using following dependency source dirs: $it") logger.info("Using following dependency source dirs: $it")
+6 -1
View File
@@ -4,6 +4,7 @@ import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer
import com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext import com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext
import kotlinx.metadata.jvm.KmModuleVisitor import kotlinx.metadata.jvm.KmModuleVisitor
import kotlinx.metadata.jvm.KotlinModuleMetadata import kotlinx.metadata.jvm.KotlinModuleMetadata
import org.gradle.kotlin.dsl.support.serviceOf
import shadow.org.apache.tools.zip.ZipEntry import shadow.org.apache.tools.zip.ZipEntry
import shadow.org.apache.tools.zip.ZipOutputStream import shadow.org.apache.tools.zip.ZipOutputStream
@@ -157,8 +158,12 @@ val proguard by task<CacheableProguardTask> {
} }
val relocateCoreSources by task<Copy> { val relocateCoreSources by task<Copy> {
val relocatedCoreSrc = relocatedCoreSrc
val fs = serviceOf<FileSystemOperations>()
doFirst { doFirst {
delete(relocatedCoreSrc) fs.delete {
delete(relocatedCoreSrc)
}
} }
from("$core/descriptors/src") from("$core/descriptors/src")
+3
View File
@@ -76,6 +76,9 @@ val jsMainSources by task<Sync> {
into("$buildDir/jsMainSources") into("$buildDir/jsMainSources")
val unimplementedNativeBuiltIns = unimplementedNativeBuiltIns
val buildDir = buildDir
val builtInsHeader = builtInsHeader
doLast { doLast {
unimplementedNativeBuiltIns.forEach { path -> unimplementedNativeBuiltIns.forEach { path ->
val file = File("$buildDir/jsMainSources/$path") val file = File("$buildDir/jsMainSources/$path")
+12 -3
View File
@@ -50,25 +50,34 @@ class CoreXmlShadingTransformer : Transformer {
private const val XML_NAME = "META-INF/extensions/core.xml" private const val XML_NAME = "META-INF/extensions/core.xml"
} }
private val content = StringBuilder() @kotlin.jvm.Transient
private var content: StringBuilder? = StringBuilder()
private fun ensureStringBuilderExist() {
if (content == null) {
content = StringBuilder()
}
}
override fun canTransformResource(element: FileTreeElement): Boolean { override fun canTransformResource(element: FileTreeElement): Boolean {
return (element.name == XML_NAME) return (element.name == XML_NAME)
} }
override fun transform(context: TransformerContext) { override fun transform(context: TransformerContext) {
ensureStringBuilderExist()
val text = context.`is`.bufferedReader().lines() val text = context.`is`.bufferedReader().lines()
.map { it.replace("com.intellij.psi", "org.jetbrains.kotlin.com.intellij.psi") } .map { it.replace("com.intellij.psi", "org.jetbrains.kotlin.com.intellij.psi") }
.collect(Collectors.joining("\n")) .collect(Collectors.joining("\n"))
content.appendln(text) content!!.appendln(text)
context.`is`.close() context.`is`.close()
} }
override fun hasTransformedResource(): Boolean { override fun hasTransformedResource(): Boolean {
return content.isNotEmpty() return content?.isNotEmpty() ?: false
} }
override fun modifyOutputStream(outputStream: ZipOutputStream, preserveFileTimestamps: Boolean) { override fun modifyOutputStream(outputStream: ZipOutputStream, preserveFileTimestamps: Boolean) {
if (content == null) return
val entry = ZipEntry(XML_NAME) val entry = ZipEntry(XML_NAME)
outputStream.putNextEntry(entry) outputStream.putNextEntry(entry)
outputStream.write(content.toString().toByteArray()) outputStream.write(content.toString().toByteArray())
@@ -13,6 +13,9 @@ val markdownVersion = findProperty("versions.markdown").toString()
val writeVersions by tasks.registering { val writeVersions by tasks.registering {
val versionFile = File(versionFilePath) val versionFile = File(versionFilePath)
val ideaVersion = ideaVersion
val markdownVersion = markdownVersion
inputs.property("ideaVersion", ideaVersion) inputs.property("ideaVersion", ideaVersion)
inputs.property("markdownVersion", markdownVersion) inputs.property("markdownVersion", markdownVersion)