[Gradle] Overwrite setupCompilerArgs methods in compile tasks...

... to ensure compatibility with reflection code
in IDEs < 2023.2 which is looking for setupCompilerArgs methods
with specific compiler arguments type instead of a
generic function

KTIJ-25227
This commit is contained in:
Sebastian Sellmair
2023-04-13 10:58:21 +02:00
committed by Space Team
parent 9309a864ce
commit 0f5f4fd8fa
6 changed files with 126 additions and 5 deletions
@@ -419,6 +419,13 @@ internal constructor(
private val isAllowCommonizer: Boolean by lazy { project.isAllowCommonizer() }
// endregion.
@Suppress("DeprecatedCallableAddReplaceWith")
@Deprecated("KTIJ-25227: Necessary override for IDEs < 2023.2", level = DeprecationLevel.ERROR)
override fun setupCompilerArgs(args: K2NativeCompilerArguments, defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) {
@Suppress("DEPRECATION_ERROR")
super.setupCompilerArgs(args, defaultsOnly, ignoreClasspathResolutionErrors)
}
override fun createCompilerArguments(context: CreateCompilerArgumentsContext) = context.create<K2NativeCompilerArguments> {
val sharedCompilationData = createSharedCompilationDataOrNull()
@@ -126,6 +126,13 @@ abstract class Kotlin2JsCompile @Inject constructor(
@get:Nested
override val multiplatformStructure: K2MultiplatformStructure = objectFactory.newInstance()
@Suppress("DeprecatedCallableAddReplaceWith")
@Deprecated("KTIJ-25227: Necessary override for IDEs < 2023.2", level = DeprecationLevel.ERROR)
override fun setupCompilerArgs(args: K2JSCompilerArguments, defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) {
@Suppress("DEPRECATION_ERROR")
super.setupCompilerArgs(args, defaultsOnly, ignoreClasspathResolutionErrors)
}
override fun createCompilerArguments(context: CreateCompilerArgumentsContext) = context.create<K2JSCompilerArguments> {
primitive { args ->
args.multiPlatform = multiPlatformEnabled.get()
@@ -359,4 +366,4 @@ abstract class Kotlin2JsCompile @Inject constructor(
)
}
}
}
}
@@ -223,6 +223,13 @@ abstract class KotlinCompile @Inject constructor(
@get:Internal
internal var executionTimeFreeCompilerArgs: List<String>? = null
@Suppress("DeprecatedCallableAddReplaceWith")
@Deprecated("KTIJ-25227: Necessary override for IDEs < 2023.2", level = DeprecationLevel.ERROR)
override fun setupCompilerArgs(args: K2JVMCompilerArguments, defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) {
@Suppress("DEPRECATION_ERROR")
super.setupCompilerArgs(args, defaultsOnly, ignoreClasspathResolutionErrors)
}
override fun createCompilerArguments(
context: KotlinCompilerArgumentsProducer.CreateCompilerArgumentsContext
): K2JVMCompilerArguments = context.create<K2JVMCompilerArguments> {
@@ -500,4 +507,4 @@ abstract class KotlinCompile @Inject constructor(
}
}
}
}
}
@@ -66,6 +66,13 @@ abstract class KotlinCompileCommon @Inject constructor(
@get:Internal
internal var executionTimeFreeCompilerArgs: List<String>? = null
@Suppress("DeprecatedCallableAddReplaceWith")
@Deprecated("KTIJ-25227: Necessary override for IDEs < 2023.2", level = DeprecationLevel.ERROR)
override fun setupCompilerArgs(args: K2MetadataCompilerArguments, defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) {
@Suppress("DEPRECATION_ERROR")
super.setupCompilerArgs(args, defaultsOnly, ignoreClasspathResolutionErrors)
}
override fun createCompilerArguments(context: CreateCompilerArgumentsContext) = context.create<K2MetadataCompilerArguments> {
primitive { args ->
args.multiPlatform = multiPlatformEnabled.get()
@@ -31,9 +31,7 @@ import org.jetbrains.kotlin.compilerRunner.ArgumentUtils
import org.jetbrains.kotlin.compilerRunner.runToolInSeparateProcess
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.dsl.KotlinJsDce
import org.jetbrains.kotlin.gradle.dsl.KotlinJsDceCompilerToolOptionsDefault
import org.jetbrains.kotlin.gradle.logging.GradleKotlinLogger
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerArgumentsProducer
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerArgumentsProducer.CreateCompilerArgumentsContext
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerArgumentsProducer.CreateCompilerArgumentsContext.Companion.create
import org.jetbrains.kotlin.gradle.utils.absolutePathWithoutExtension
@@ -158,4 +156,11 @@ abstract class KotlinJsDce @Inject constructor(
const val strategyAllArg = "-Xdev-mode-overwriting-strategy=${DevModeOverwritingStrategies.ALL}"
const val strategyOlderArg = "-Xdev-mode-overwriting-strategy=${DevModeOverwritingStrategies.OLDER}"
}
}
@Suppress("DeprecatedCallableAddReplaceWith")
@Deprecated("KTIJ-25227: Necessary override for IDEs < 2023.2", level = DeprecationLevel.ERROR)
override fun setupCompilerArgs(args: K2JSDceArguments, defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) {
@Suppress("DEPRECATION_ERROR")
super.setupCompilerArgs(args, defaultsOnly, ignoreClasspathResolutionErrors)
}
}
@@ -0,0 +1,88 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("FunctionName")
package org.jetbrains.kotlin.gradle.regressionTests
import org.gradle.api.Task
import org.jetbrains.kotlin.gradle.dsl.kotlinJvmExtension
import org.jetbrains.kotlin.gradle.regressionTests.KTIJ25227CompilerArgumentsIdeCompatibilityTest.IdePluginCodeMock.IdeReflectionCodeMock.get
import org.jetbrains.kotlin.gradle.regressionTests.KTIJ25227CompilerArgumentsIdeCompatibilityTest.IdePluginCodeMock.IdeReflectionCodeMock.getMethodOrNull
import org.jetbrains.kotlin.gradle.regressionTests.KTIJ25227CompilerArgumentsIdeCompatibilityTest.IdePluginCodeMock.checkExtractCompilerArgumentsFromTask
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.util.buildProjectWithJvm
import org.jetbrains.kotlin.gradle.util.main
import org.junit.Test
import java.lang.reflect.Method
import kotlin.test.fail
class KTIJ25227CompilerArgumentsIdeCompatibilityTest {
@Test
fun `test - jvm compile task - is compatible with old CompilerArgumentsExtractor in older IDEs`() {
val project = buildProjectWithJvm()
project.evaluate()
val kotlin = project.kotlinJvmExtension
val mainCompilation = kotlin.target.compilations.main
val mainCompileTask = mainCompilation.compileTaskProvider.get() as KotlinCompile
checkExtractCompilerArgumentsFromTask(mainCompileTask)
}
/*
Code from CompilerArgumentsExtractor inside intellij.git with injected asssertions
*/
private object IdePluginCodeMock {
const val CREATE_COMPILER_ARGS = "createCompilerArgs"
const val SETUP_COMPILER_ARGS = "setupCompilerArgs"
fun checkExtractCompilerArgumentsFromTask(compileTask: Task, defaultsOnly: Boolean = false): Any {
val compileTaskClass = compileTask.javaClass
val compilerArguments = compileTask[CREATE_COMPILER_ARGS] ?: fail("Missing $CREATE_COMPILER_ARGS method")
compileTaskClass.getMethodOrNull(SETUP_COMPILER_ARGS, compilerArguments::class.java, Boolean::class.java, Boolean::class.java)
?.doSetupCompilerArgs(compileTask, compilerArguments, defaultsOnly, false) ?: compileTaskClass
.getMethodOrNull(SETUP_COMPILER_ARGS, compilerArguments::class.java, Boolean::class.java)
?.doSetupCompilerArgs(compileTask, compilerArguments, defaultsOnly)
?: fail("Missing $SETUP_COMPILER_ARGS method")
return compilerArguments
}
private fun Method.doSetupCompilerArgs(
compileTask: Task,
compilerArgs: Any,
defaultsOnly: Boolean,
ignoreClasspathIssues: Boolean? = null
) {
try {
ignoreClasspathIssues?.also { invoke(compileTask, compilerArgs, defaultsOnly, it) }
?: invoke(compileTask, compilerArgs, defaultsOnly)
} catch (e: Exception) {
ignoreClasspathIssues?.also { if (!it) doSetupCompilerArgs(compileTask, compilerArgs, defaultsOnly, true) }
}
}
private object IdeReflectionCodeMock {
operator fun Any?.get(methodName: String, vararg params: Any): Any? {
return this[methodName, params.map { it.javaClass }, params.toList()]
}
operator fun Any?.get(methodName: String, paramTypes: List<Class<*>>, params: List<Any?>): Any? {
if (this == null) return null
return this::class.java.getMethodOrNull(methodName, *paramTypes.toTypedArray())
?.invoke(this, *params.toTypedArray())
}
fun Class<*>.getMethodOrNull(name: String, vararg parameterTypes: Class<*>) =
try {
getMethod(name, *parameterTypes)
} catch (e: Exception) {
null
}
}
}
}