From 9e737156dd8a31ec1f547c566ae67cfc84132fea Mon Sep 17 00:00:00 2001 From: "nataliya.valtman" Date: Mon, 13 Apr 2020 12:10:29 +0300 Subject: [PATCH] KT-37720 Replace ArtifactTransform with TransformAction --- .../kapt/Kapt3KotlinGradleSubplugin.kt | 20 +++--- .../kapt/incremental/ClasspathAnalyzer.kt | 19 ++++-- .../internal/ScriptingGradleSubplugin.kt | 51 +++++++-------- .../kapt/incremental/ClasspathAnalyzerTest.kt | 63 +++++++++++++++---- 4 files changed, 100 insertions(+), 53 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt index e8776c19782..836813e9270 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt @@ -26,12 +26,12 @@ import org.gradle.tooling.provider.model.ToolingModelBuilder import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions import org.jetbrains.kotlin.gradle.internal.kapt.incremental.CLASS_STRUCTURE_ARTIFACT_TYPE -import org.jetbrains.kotlin.gradle.internal.kapt.incremental.StructureArtifactTransform +import org.jetbrains.kotlin.gradle.internal.kapt.incremental.StructureTransformAction import org.jetbrains.kotlin.gradle.model.builder.KaptModelBuilder import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation -import org.jetbrains.kotlin.gradle.tasks.KotlinCompileTaskData import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.jetbrains.kotlin.gradle.tasks.KotlinCompileTaskData import org.jetbrains.kotlin.gradle.tasks.locateTask import org.jetbrains.kotlin.gradle.tasks.registerTask import java.io.ByteArrayOutputStream @@ -507,15 +507,14 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To private fun maybeRegisterTransform(project: Project) { if (!project.extensions.extraProperties.has("KaptStructureTransformAdded")) { - project.dependencies.registerTransform { variantTransform -> - variantTransform.artifactTransform(StructureArtifactTransform::class.java) - variantTransform.from.attribute(artifactType, "jar") - variantTransform.to.attribute(artifactType, CLASS_STRUCTURE_ARTIFACT_TYPE) + project.dependencies.registerTransform(StructureTransformAction::class.java) { transformSpec -> + transformSpec.from.attribute(artifactType, "jar") + transformSpec.to.attribute(artifactType, CLASS_STRUCTURE_ARTIFACT_TYPE) } - project.dependencies.registerTransform { variantTransform -> - variantTransform.artifactTransform(StructureArtifactTransform::class.java) - variantTransform.from.attribute(artifactType, "directory") - variantTransform.to.attribute(artifactType, CLASS_STRUCTURE_ARTIFACT_TYPE) + + project.dependencies.registerTransform(StructureTransformAction::class.java) { transformSpec -> + transformSpec.from.attribute(artifactType, "directory") + transformSpec.to.attribute(artifactType, CLASS_STRUCTURE_ARTIFACT_TYPE) } project.extensions.extraProperties["KaptStructureTransformAdded"] = true @@ -590,6 +589,7 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To override fun getPluginArtifact(): SubpluginArtifact = JetBrainsSubpluginArtifact(artifactId = KAPT_ARTIFACT_NAME) } + private val artifactType = Attribute.of("artifactType", String::class.java) // Don't reference the BaseVariant type in the Kapt plugin signatures, as those type references will fail to link when there's no Android diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/incremental/ClasspathAnalyzer.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/incremental/ClasspathAnalyzer.kt index 958b4671091..28202efb262 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/incremental/ClasspathAnalyzer.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/incremental/ClasspathAnalyzer.kt @@ -5,7 +5,12 @@ package org.jetbrains.kotlin.gradle.internal.kapt.incremental -import org.gradle.api.artifacts.transform.ArtifactTransform +import org.gradle.api.artifacts.transform.InputArtifact +import org.gradle.api.artifacts.transform.TransformAction +import org.gradle.api.artifacts.transform.TransformOutputs +import org.gradle.api.artifacts.transform.TransformParameters +import org.gradle.api.file.FileSystemLocation +import org.gradle.api.provider.Provider import org.jetbrains.org.objectweb.asm.ClassReader import org.jetbrains.org.objectweb.asm.ClassWriter import java.io.* @@ -15,19 +20,23 @@ import java.util.zip.ZipFile const val CLASS_STRUCTURE_ARTIFACT_TYPE = "class-structure" private const val MODULE_INFO = "module-info.class" -class StructureArtifactTransform : ArtifactTransform() { - override fun transform(input: File): MutableList { +abstract class StructureTransformAction : TransformAction { + @get:InputArtifact + abstract val inputArtifact: File + + override fun transform(outputs: TransformOutputs) { try { + val input = inputArtifact + val data = if (input.isDirectory) { visitDirectory(input) } else { visitJar(input) } - val dataFile = outputDirectory.resolve("output.bin") + val dataFile = outputs.file("output.bin") data.saveTo(dataFile) - return mutableListOf(dataFile) } catch (e: Throwable) { throw e } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/scripting/internal/ScriptingGradleSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/scripting/internal/ScriptingGradleSubplugin.kt index d2ac70c7bd0..bf46240ee00 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/scripting/internal/ScriptingGradleSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/scripting/internal/ScriptingGradleSubplugin.kt @@ -10,8 +10,12 @@ package org.jetbrains.kotlin.gradle.scripting.internal import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.artifacts.Configuration -import org.gradle.api.artifacts.transform.ArtifactTransform +import org.gradle.api.artifacts.transform.InputArtifact +import org.gradle.api.artifacts.transform.TransformAction +import org.gradle.api.artifacts.transform.TransformOutputs +import org.gradle.api.artifacts.transform.TransformParameters import org.gradle.api.attributes.Attribute +import org.gradle.api.file.FileSystemLocation import org.gradle.api.plugins.JavaPluginConvention import org.gradle.api.provider.Provider import org.gradle.api.tasks.compile.AbstractCompile @@ -25,7 +29,6 @@ import org.jetbrains.kotlin.gradle.scripting.ScriptingExtension import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.scripting.compiler.plugin.impl.reporter import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsFromClasspathDiscoverySource -import java.io.File import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration private const val SCRIPTING_LOG_PREFIX = "kotlin scripting plugin:" @@ -149,46 +152,45 @@ private fun configureDiscoveryTransformation( } } -internal class DiscoverScriptExtensionsTransform : ArtifactTransform() { +internal abstract class DiscoverScriptExtensionsTransformAction : TransformAction { + @InputArtifact + abstract fun getInputArtifact(): Provider + + override fun transform(outputs: TransformOutputs) { + val input = getInputArtifact().get().asFile - override fun transform(input: File): List { val definitions = ScriptDefinitionsFromClasspathDiscoverySource( listOf(input), defaultJvmScriptingHostConfiguration, PrintingMessageCollector(System.out, MessageRenderer.WITHOUT_PATHS, false).reporter ).definitions + val extensions = definitions.mapTo(arrayListOf()) { it.fileExtension } - return if (extensions.isNotEmpty()) { - val outputFile = outputDirectory.resolve("${input.nameWithoutExtension}.discoveredScriptsExtensions.txt") + + if (extensions.isNotEmpty()) { + val outputFile = outputs.file("${input.nameWithoutExtension}.discoveredScriptsExtensions.txt") outputFile.writeText(extensions.joinToString("\n")) listOf(outputFile) - } else emptyList() + } } } -private -fun Project.registerDiscoverScriptExtensionsTransform() { +private fun Project.registerDiscoverScriptExtensionsTransform() { dependencies.apply { - registerTransform { - with(it) { - from.attribute(artifactType, "jar") - to.attribute(artifactType, scriptFilesExtensions) - artifactTransform(DiscoverScriptExtensionsTransform::class.java) - } + registerTransform(DiscoverScriptExtensionsTransformAction::class.java) { transformSpec -> + transformSpec.from.attribute(artifactType, "jar") + transformSpec.to.attribute(artifactType, scriptFilesExtensions) + } - registerTransform { - with(it) { - from.attribute(artifactType, "classes") - to.attribute(artifactType, scriptFilesExtensions) - artifactTransform(DiscoverScriptExtensionsTransform::class.java) - } + registerTransform(DiscoverScriptExtensionsTransformAction::class.java) { transformSpec -> + transformSpec.from.attribute(artifactType, "classes") + transformSpec.to.attribute(artifactType, scriptFilesExtensions) } } } -private -fun Project.withRegisteredDiscoverScriptExtensionsTransform(block: () -> T): T { +private fun Project.withRegisteredDiscoverScriptExtensionsTransform(block: () -> T): T { if (!project.extensions.extraProperties.has("DiscoverScriptExtensionsTransform")) { registerDiscoverScriptExtensionsTransform() project.extensions.extraProperties["DiscoverScriptExtensionsTransform"] = true @@ -200,8 +202,7 @@ private val artifactType = Attribute.of("artifactType", String::class.java) private val scriptFilesExtensions = "script-files-extensions" -private -fun Configuration.discoverScriptExtensionsFiles() = +private fun Configuration.discoverScriptExtensionsFiles() = incoming.artifactView { attributes { it.attribute(artifactType, scriptFilesExtensions) diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/incremental/ClasspathAnalyzerTest.kt b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/incremental/ClasspathAnalyzerTest.kt index de9f0b6629f..f9dbcf47e32 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/incremental/ClasspathAnalyzerTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/incremental/ClasspathAnalyzerTest.kt @@ -5,12 +5,20 @@ package org.jetbrains.kotlin.gradle.internal.kapt.incremental +import org.gradle.api.artifacts.transform.TransformOutputs +import org.gradle.api.artifacts.transform.TransformParameters +import org.gradle.api.file.FileSystemLocation +import org.gradle.api.internal.file.DefaultFileSystemLocation +import org.gradle.api.internal.provider.DefaultProvider +import org.gradle.api.provider.Provider import org.jetbrains.org.objectweb.asm.ClassWriter import org.jetbrains.org.objectweb.asm.Opcodes import org.junit.Assert.* import org.junit.Rule import org.junit.Test import org.junit.rules.TemporaryFolder +import java.io.File +import java.util.concurrent.Callable import java.util.zip.ZipEntry import java.util.zip.ZipOutputStream @@ -32,10 +40,10 @@ class ClasspathAnalyzerTest { it.writeBytes(emptyClass("A")) } } - val transform = StructureArtifactTransform().also { it.outputDirectory = tmp.newFolder() } - val outputs = transform.transform(classesDir) + val outputs = TransformOutputsMock(tmp.newFolder()) + StructureTransformTestAction(classesDir).transform(outputs) - val data = ClasspathEntryData.ClasspathEntrySerializer.loadFrom(outputs.single()) + val data = ClasspathEntryData.ClasspathEntrySerializer.loadFrom(outputs.createdOutputs.single()) assertEquals(setOf("test/A", "test/B"), data.classAbiHash.keys) assertEquals(setOf("test/A", "test/B"), data.classDependencies.keys) assertEquals(emptySet(), data.classDependencies["test/A"]!!.abiTypes) @@ -68,10 +76,10 @@ class ClasspathAnalyzerTest { it.closeEntry() } } - val transform = StructureArtifactTransform().also { it.outputDirectory = tmp.newFolder() } - val outputs = transform.transform(inputJar) + val outputs = TransformOutputsMock(tmp.newFolder()) + StructureTransformTestAction(inputJar).transform(outputs) - val data = ClasspathEntryData.ClasspathEntrySerializer.loadFrom(outputs.single()) + val data = ClasspathEntryData.ClasspathEntrySerializer.loadFrom(outputs.createdOutputs.single()) assertEquals(setOf("test/A", "test/B"), data.classAbiHash.keys) assertEquals(setOf("test/A", "test/B"), data.classDependencies.keys) assertEquals(emptySet(), data.classDependencies["test/A"]!!.abiTypes) @@ -94,7 +102,8 @@ class ClasspathAnalyzerTest { it.closeEntry() } } - val outputA = StructureArtifactTransform().also { it.outputDirectory = tmp.newFolder() }.transform(jarA).single() + val outputsA = TransformOutputsMock(tmp.newFolder()) + StructureTransformTestAction(jarA).transform(outputsA) val jarB = tmp.newFile("inputB.jar").also { jar -> ZipOutputStream(jar.outputStream()).use { @@ -107,18 +116,20 @@ class ClasspathAnalyzerTest { it.closeEntry() } } - val outputB = StructureArtifactTransform().also { it.outputDirectory = tmp.newFolder() }.transform(jarB).single() + val outputsB = TransformOutputsMock(tmp.newFolder()) + StructureTransformTestAction(jarB).transform(outputsB) - assertArrayEquals(outputA.readBytes(), outputB.readBytes()) + assertArrayEquals(outputsA.createdOutputs.single().readBytes(), outputsB.createdOutputs.single().readBytes()) } @Test fun emptyInput() { - val inputDir = tmp.newFolder("input") - val transform = StructureArtifactTransform().also { it.outputDirectory = tmp.newFolder() } - val outputs = transform.transform(inputDir) + val transformAction = StructureTransformTestAction(tmp.newFolder("input")) + val outputs = TransformOutputsMock(tmp.newFolder()) - val data = ClasspathEntryData.ClasspathEntrySerializer.loadFrom(outputs.single()) + transformAction.transform(outputs) + + val data = ClasspathEntryData.ClasspathEntrySerializer.loadFrom(outputs.createdOutputs.single()) assertTrue(data.classAbiHash.isEmpty()) assertTrue(data.classDependencies.isEmpty()) } @@ -128,4 +139,30 @@ class ClasspathAnalyzerTest { writer.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, internalName, null, "java/lang/Object", emptyArray()) return writer.toByteArray() } +} + +class StructureTransformTestAction(val input: File) : StructureTransformAction() { + override val inputArtifact: File = input + + override fun getParameters(): TransformParameters.None? { + //no need for StructureTransformAction and so for test + return null + } +} + +class TransformOutputsMock(val outputDir: File) : TransformOutputs { + val createdOutputs = mutableListOf() + + override fun file(name: Any): File { + val newFile = outputDir.resolve(name as String) + createdOutputs.add(newFile) + return newFile + } + + override fun dir(name: Any): File { + val newDir = outputDir.resolve(name as String) + createdOutputs.add(newDir) + return newDir + } + } \ No newline at end of file