diff --git a/build.gradle.kts b/build.gradle.kts index bf8bc0385d8..97d20de94d3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1208,7 +1208,8 @@ val Jar.outputFile: File val Project.sourceSetsOrNull: SourceSetContainer? get() = convention.findPlugin(JavaPluginConvention::class.java)?.sourceSets -val disableVerificationTasks = System.getProperty("disable.verification.tasks") == "true" +val disableVerificationTasks = providers.systemProperty("disable.verification.tasks") + .forUseAtConfigurationTime().orNull?.toBoolean() ?: false if (disableVerificationTasks) { gradle.taskGraph.whenReady { allTasks.forEach { diff --git a/buildSrc/src/main/kotlin/instrument.kt b/buildSrc/src/main/kotlin/instrument.kt index 27e2a29a3f0..dd2bcf1e01e 100644 --- a/buildSrc/src/main/kotlin/instrument.kt +++ b/buildSrc/src/main/kotlin/instrument.kt @@ -22,6 +22,7 @@ import org.gradle.api.artifacts.ProjectDependency import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.FileCollection import org.gradle.api.file.FileSystemOperations +import org.gradle.api.file.RegularFileProperty import org.gradle.api.internal.ConventionTask import org.gradle.api.plugins.ExtensionAware import org.gradle.api.tasks.* @@ -31,6 +32,51 @@ import java.io.File import javax.inject.Inject fun Project.configureFormInstrumentation() { + plugins.matching { it::class.java.canonicalName.startsWith("org.jetbrains.kotlin.gradle.plugin") }.configureEach { + // When we change the output classes directory, Gradle will automatically configure + // the test compile tasks to use the instrumented classes. Normally this is fine, + // however, it causes problems for Kotlin projects: + + // The "internal" modifier can be used to restrict access to the same module. + // To make it possible to use internal methods from the main source set in test classes, + // the Kotlin Gradle plugin adds the original output directory of the Java task + // as "friendly directory" which makes it possible to access internal members + // of the main module. Also this directory should be available on classpath during compilation + + // This fails when we change the classes dir. The easiest fix is to prepend the + // classes from the "friendly directory" to the compile classpath. + if (!tasks.names.contains("compileTestKotlin")) return@configureEach + + tasks.named("compileTestKotlin") { + val objects = project.objects + val classesDirs = project.mainSourceSet.output.classesDirs + val classesDirsCopy = project.provider { (mainSourceSet as ExtensionAware).extra.get("classesDirsCopy") } + doFirst { + val originalClassesDirs = objects.fileCollection().from(classesDirsCopy) + + classpath = (classpath + - classesDirs + + originalClassesDirs) + + // Since Kotlin 1.3.60, the friend paths available to the test compile task are calculated as the main source set's + // output.classesDirs. Since the classesDirs are excluded from the classpath (replaced by the originalClassesDirs), + // in order to be able to access the internals of 'main', tests need to receive the original classes dirs as a + // -Xfriend-paths compiler argument as well. + fun addFreeCompilerArgs(kotlinCompileTask: AbstractCompile, vararg args: String) { + val getKotlinOptions = kotlinCompileTask::class.java.getMethod("getKotlinOptions") + val kotlinOptions = getKotlinOptions(kotlinCompileTask) + + val getFreeCompilerArgs = kotlinOptions::class.java.getMethod("getFreeCompilerArgs") + val freeCompilerArgs = getFreeCompilerArgs(kotlinOptions) as List<*> + + val setFreeCompilerArgs = kotlinOptions::class.java.getMethod("setFreeCompilerArgs", List::class.java) + setFreeCompilerArgs(kotlinOptions, freeCompilerArgs + args) + } + addFreeCompilerArgs(this as AbstractCompile, "-Xfriend-paths=" + originalClassesDirs.joinToString(",") { it.absolutePath }) + } + } + } + val instrumentationClasspathCfg = configurations.create("instrumentationClasspath") dependencies { @@ -51,56 +97,16 @@ fun Project.configureFormInstrumentation() { val instrumentTask = project.tasks.register(sourceSetParam.getTaskName("instrument", "classes"), IntelliJInstrumentCodeTask::class.java) { dependsOn(sourceSetParam.classesTaskName) - sourceSet = sourceSetParam + compileClasspath.from(sourceSetParam.compileClasspath) + sourceDirs.from(project.files({ sourceSetParam.allSource.srcDirs.filter { !sourceSetParam.resources.contains(it) && it.exists() } })) instrumentationClasspathConfiguration = instrumentationClasspathCfg - originalClassesDirs = classesDirsCopy - output = instrumentedClassesDir - outputs.dir(instrumentedClassesDir) + originalClassesDirs.from(classesDirsCopy) + output.set(instrumentedClassesDir) } // Ensure that our task is invoked when the source set is built sourceSetParam.compiledBy(instrumentTask) } - - plugins.matching { it::class.java.canonicalName.startsWith("org.jetbrains.kotlin.gradle.plugin") }.configureEach { - // When we change the output classes directory, Gradle will automatically configure - // the test compile tasks to use the instrumented classes. Normally this is fine, - // however, it causes problems for Kotlin projects: - - // The "internal" modifier can be used to restrict access to the same module. - // To make it possible to use internal methods from the main source set in test classes, - // the Kotlin Gradle plugin adds the original output directory of the Java task - // as "friendly directory" which makes it possible to access internal members - // of the main module. Also this directory should be available on classpath during compilation - - // This fails when we change the classes dir. The easiest fix is to prepend the - // classes from the "friendly directory" to the compile classpath. - if (!tasks.names.contains("compileTestKotlin")) return@configureEach - - tasks.named("compileTestKotlin").configure { - val originalClassesDirs = project.files((project.mainSourceSet as ExtensionAware).extra.get("classesDirsCopy")) - - classpath = (classpath - - project.mainSourceSet.output.classesDirs - + originalClassesDirs) - - // Since Kotlin 1.3.60, the friend paths available to the test compile task are calculated as the main source set's - // output.classesDirs. Since the classesDirs are excluded from the classpath (replaced by the originalClassesDirs), - // in order to be able to access the internals of 'main', tests need to receive the original classes dirs as a - // -Xfriend-paths compiler argument as well. - fun addFreeCompilerArgs(kotlinCompileTask: AbstractCompile, vararg args: String) { - val getKotlinOptions = kotlinCompileTask::class.java.getMethod("getKotlinOptions") - val kotlinOptions = getKotlinOptions(kotlinCompileTask) - - val getFreeCompilerArgs = kotlinOptions::class.java.getMethod("getFreeCompilerArgs") - val freeCompilerArgs = getFreeCompilerArgs(kotlinOptions) as List<*> - - val setFreeCompilerArgs = kotlinOptions::class.java.getMethod("setFreeCompilerArgs", List::class.java) - setFreeCompilerArgs(kotlinOptions, freeCompilerArgs + args) - } - addFreeCompilerArgs(this, "-Xfriend-paths=" + originalClassesDirs.joinToString(",") { it.absolutePath }) - } - } } } @@ -120,21 +126,17 @@ abstract class IntelliJInstrumentCodeTask : ConventionTask() { instrumentationClasspathConfiguration.asPath } - @InputFiles - @PathSensitive(PathSensitivity.RELATIVE) - @SkipWhenEmpty - lateinit var originalClassesDirs: FileCollection + @get:InputFiles + @get:PathSensitive(PathSensitivity.RELATIVE) + @get:SkipWhenEmpty + abstract val originalClassesDirs: ConfigurableFileCollection @get:Input var instrumentNotNull: Boolean = false - @Transient - @Internal - lateinit var sourceSet: SourceSet - - private val compileClasspath by lazy { - sourceSet.compileClasspath - } + @get:InputFiles + @get:Classpath + abstract val compileClasspath: ConfigurableFileCollection // Instrumentation needs to have access to sources of forms for inclusion private val depSourceDirectorySets by lazy { @@ -144,12 +146,10 @@ abstract class IntelliJInstrumentCodeTask : ConventionTask() { @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) - val sourceDirs: FileCollection by lazy { - project.files(sourceSet.allSource.srcDirs.filter { !sourceSet.resources.contains(it) && it.exists() }) - } + abstract val sourceDirs: ConfigurableFileCollection @get:OutputDirectory - lateinit var output: File + abstract val output: RegularFileProperty @get:Inject abstract val fs: FileSystemOperations @@ -157,11 +157,13 @@ abstract class IntelliJInstrumentCodeTask : ConventionTask() { @TaskAction fun instrumentClasses() { logger.info( - "input files are: ${originalClassesDirs.joinToString( - "; ", - transform = { "'${it.name}'${if (it.exists()) "" else " (does not exists)"}" })}" + "input files are: ${ + originalClassesDirs.joinToString( + "; ", + transform = { "'${it.name}'${if (it.exists()) "" else " (does not exists)"}" }) + }" ) - output.deleteRecursively() + output.asFile.get().deleteRecursively() copyOriginalClasses() val classpath = instrumentationClasspath @@ -203,9 +205,10 @@ abstract class IntelliJInstrumentCodeTask : ConventionTask() { private fun instrumentCode(srcDirs: FileCollection, instrumentNotNull: Boolean) { val headlessOldValue = System.setProperty("java.awt.headless", "true") + val output = output.get().asFile val instrumentationClasspath = - depSourceDirectorySets.fold(compileClasspath) { acc, v -> acc + v }.asPath.also { + depSourceDirectorySets.fold(compileClasspath as FileCollection) { acc, v -> acc + v }.asPath.also { logger.info("Using following dependency source dirs: $it") } diff --git a/buildSrc/src/main/kotlin/tasks.kt b/buildSrc/src/main/kotlin/tasks.kt index 5e41e885271..83e5b3ac6e2 100644 --- a/buildSrc/src/main/kotlin/tasks.kt +++ b/buildSrc/src/main/kotlin/tasks.kt @@ -214,8 +214,8 @@ fun Project.projectTest( if (parallel && !jUnit5Enabled) { maxParallelForks = - project.findProperty("kotlin.test.maxParallelForks")?.toString()?.toInt() - ?: (Runtime.getRuntime().availableProcessors() / if (kotlinBuildProperties.isTeamcityBuild) 2 else 4).coerceAtLeast(1) + project.providers.gradleProperty("kotlin.test.maxParallelForks").forUseAtConfigurationTime().orNull?.toInt() + ?: (Runtime.getRuntime().availableProcessors() / if (project.kotlinBuildProperties.isTeamcityBuild) 2 else 4).coerceAtLeast(1) } }.apply { configure(body) } } diff --git a/idea/performanceTests/build.gradle.kts b/idea/performanceTests/build.gradle.kts index 991f17e8399..6319f63e597 100644 --- a/idea/performanceTests/build.gradle.kts +++ b/idea/performanceTests/build.gradle.kts @@ -33,8 +33,8 @@ dependencies { testImplementation(projectTests(":idea")) testImplementation(project(":idea:idea-gradle")) { isTransitive = false } testImplementation(commonDep("junit:junit")) - testImplementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.11.+") - testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.11.+") + testImplementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.11.4") + testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.11.4") testImplementation("khttp:khttp:1.0.0") testCompileOnly(intellijPluginDep("java"))