diff --git a/compiler/build-tools/kotlin-build-tools-api-tests/src/testCommon/kotlin/compilation/model/JvmModule.kt b/compiler/build-tools/kotlin-build-tools-api-tests/src/testCommon/kotlin/compilation/model/JvmModule.kt index e9d12ec6b5b..e5fa425a52e 100644 --- a/compiler/build-tools/kotlin-build-tools-api-tests/src/testCommon/kotlin/compilation/model/JvmModule.kt +++ b/compiler/build-tools/kotlin-build-tools-api-tests/src/testCommon/kotlin/compilation/model/JvmModule.kt @@ -6,13 +6,9 @@ package org.jetbrains.kotlin.buildtools.api.tests.compilation.model import org.jetbrains.kotlin.buildtools.api.CompilationResult -import org.jetbrains.kotlin.buildtools.api.CompilationService import org.jetbrains.kotlin.buildtools.api.CompilerExecutionStrategyConfiguration import org.jetbrains.kotlin.buildtools.api.SourcesChanges -import org.jetbrains.kotlin.buildtools.api.jvm.AccessibleClassSnapshot -import org.jetbrains.kotlin.buildtools.api.jvm.ClassSnapshotGranularity -import org.jetbrains.kotlin.buildtools.api.jvm.ClasspathSnapshotBasedIncrementalCompilationApproachParameters -import org.jetbrains.kotlin.buildtools.api.jvm.JvmCompilationConfiguration +import org.jetbrains.kotlin.buildtools.api.jvm.* import org.jetbrains.kotlin.buildtools.api.tests.buildToolsVersion import org.jetbrains.kotlin.buildtools.api.tests.compilation.model.Module import org.jetbrains.kotlin.tooling.core.KotlinToolingVersion @@ -83,6 +79,7 @@ class JvmModule( forceOutput: LogLevel?, forceNonIncrementalCompilation: Boolean, compilationConfigAction: (JvmCompilationConfiguration) -> Unit, + incrementalCompilationConfigAction: (IncrementalJvmCompilationConfiguration<*>) -> Unit, assertions: context(Module) CompilationOutcome.() -> Unit, ): CompilationResult { return compile(strategyConfig, forceOutput, { compilationConfig -> @@ -108,12 +105,15 @@ class JvmModule( options.forceNonIncrementalMode() } + incrementalCompilationConfigAction(options) + compilationConfig.useIncrementalCompilation( icCachesDir.toFile(), sourcesChanges, params, options, ) + compilationConfigAction(compilationConfig) }, assertions) } } \ No newline at end of file diff --git a/compiler/build-tools/kotlin-build-tools-api-tests/src/testCommon/kotlin/compilation/model/Module.kt b/compiler/build-tools/kotlin-build-tools-api-tests/src/testCommon/kotlin/compilation/model/Module.kt index ea1615f3930..afb0511fbb6 100644 --- a/compiler/build-tools/kotlin-build-tools-api-tests/src/testCommon/kotlin/compilation/model/Module.kt +++ b/compiler/build-tools/kotlin-build-tools-api-tests/src/testCommon/kotlin/compilation/model/Module.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.buildtools.api.tests.compilation.model import org.jetbrains.kotlin.buildtools.api.CompilationResult import org.jetbrains.kotlin.buildtools.api.CompilerExecutionStrategyConfiguration import org.jetbrains.kotlin.buildtools.api.SourcesChanges +import org.jetbrains.kotlin.buildtools.api.jvm.IncrementalJvmCompilationConfiguration import org.jetbrains.kotlin.buildtools.api.jvm.JvmCompilationConfiguration import java.nio.file.Path @@ -34,6 +35,7 @@ interface Module : Dependency { forceOutput: LogLevel? = null, forceNonIncrementalCompilation: Boolean = false, compilationConfigAction: (JvmCompilationConfiguration) -> Unit = {}, + incrementalCompilationConfigAction: (IncrementalJvmCompilationConfiguration<*>) -> Unit = {}, assertions: context(Module) CompilationOutcome.() -> Unit = {}, ): CompilationResult } \ No newline at end of file diff --git a/compiler/build-tools/kotlin-build-tools-api-tests/src/testCommon/kotlin/compilation/scenario/Scenario.kt b/compiler/build-tools/kotlin-build-tools-api-tests/src/testCommon/kotlin/compilation/scenario/Scenario.kt index 5faa4393f0e..3c756b5a929 100644 --- a/compiler/build-tools/kotlin-build-tools-api-tests/src/testCommon/kotlin/compilation/scenario/Scenario.kt +++ b/compiler/build-tools/kotlin-build-tools-api-tests/src/testCommon/kotlin/compilation/scenario/Scenario.kt @@ -5,10 +5,30 @@ package org.jetbrains.kotlin.buildtools.api.tests.compilation.scenario +import org.jetbrains.kotlin.buildtools.api.jvm.IncrementalJvmCompilationConfiguration +import org.jetbrains.kotlin.buildtools.api.jvm.JvmCompilationConfiguration +import org.jetbrains.kotlin.buildtools.api.tests.compilation.model.Module + interface Scenario { + /** + * Creates a module for a scenario. + * + * Modules with the same combination of [Module.scenarioDslCacheKey], [compilationOptionsModifier], and [incrementalCompilationOptionsModifier] are compiled initially only once per tests run. + * + * In the case you are using custom values for [compilationOptionsModifier] or [incrementalCompilationOptionsModifier], consider sharing the same lambda between tests for better cacheability results. + * + * @param moduleName The name of the module. + * @param dependencies (optional) The list of scenario modules that this module depends on. Defaults to an empty list. + * @param additionalCompilationArguments (optional) The list of additional compilation arguments for this module. Defaults to an empty list. + * @param compilationOptionsModifier (optional) A function that can be used to modify the compilation configuration for this module. + * @param incrementalCompilationOptionsModifier (optional) A function that can be used to modify the incremental compilation configuration for this module. + * @return The created scenario module in the compiled state. + */ fun module( moduleName: String, dependencies: List = emptyList(), additionalCompilationArguments: List = emptyList(), + compilationOptionsModifier: ((JvmCompilationConfiguration) -> Unit)? = null, + incrementalCompilationOptionsModifier: ((IncrementalJvmCompilationConfiguration<*>) -> Unit)? = null, ): ScenarioModule } \ No newline at end of file diff --git a/compiler/build-tools/kotlin-build-tools-api-tests/src/testCommon/kotlin/compilation/scenario/scenarioDsl.kt b/compiler/build-tools/kotlin-build-tools-api-tests/src/testCommon/kotlin/compilation/scenario/scenarioDsl.kt index 825447b04ad..cf7087a4e18 100644 --- a/compiler/build-tools/kotlin-build-tools-api-tests/src/testCommon/kotlin/compilation/scenario/scenarioDsl.kt +++ b/compiler/build-tools/kotlin-build-tools-api-tests/src/testCommon/kotlin/compilation/scenario/scenarioDsl.kt @@ -7,6 +7,8 @@ package org.jetbrains.kotlin.buildtools.api.tests.compilation.scenario import org.jetbrains.kotlin.buildtools.api.CompilerExecutionStrategyConfiguration import org.jetbrains.kotlin.buildtools.api.SourcesChanges +import org.jetbrains.kotlin.buildtools.api.jvm.IncrementalJvmCompilationConfiguration +import org.jetbrains.kotlin.buildtools.api.jvm.JvmCompilationConfiguration import org.jetbrains.kotlin.buildtools.api.tests.compilation.assertions.assertOutputs import org.jetbrains.kotlin.buildtools.api.tests.compilation.model.* import java.nio.file.Files @@ -18,6 +20,8 @@ private class ScenarioModuleImpl( val module: Module, val outputs: MutableSet, private val strategyConfig: CompilerExecutionStrategyConfiguration, + private val compilationOptionsModifier: ((JvmCompilationConfiguration) -> Unit)?, + private val incrementalCompilationOptionsModifier: ((IncrementalJvmCompilationConfiguration<*>) -> Unit)?, ) : ScenarioModule { override fun changeFile( fileName: String, @@ -61,12 +65,17 @@ private class ScenarioModuleImpl( forceOutput: LogLevel?, assertions: context(Module) CompilationOutcome.() -> Unit, ) { - module.compileIncrementally(strategyConfig, sourcesChanges, forceOutput, assertions = { - assertions(module, this) - assertOutputs(outputs) - }) + module.compileIncrementally( + strategyConfig, + sourcesChanges, + forceOutput, + compilationConfigAction = { compilationOptionsModifier?.invoke(it) }, + incrementalCompilationConfigAction = { incrementalCompilationOptionsModifier?.invoke(it) }, + assertions = { + assertions(module, this) + assertOutputs(outputs) + }) } - } private class ScenarioDsl( @@ -78,11 +87,13 @@ private class ScenarioDsl( moduleName: String, dependencies: List, additionalCompilationArguments: List, + compilationOptionsModifier: ((JvmCompilationConfiguration) -> Unit)?, + incrementalCompilationOptionsModifier: ((IncrementalJvmCompilationConfiguration<*>) -> Unit)?, ): ScenarioModule { val transformedDependencies = dependencies.map { (it as ScenarioModuleImpl).module } val module = project.module(moduleName, transformedDependencies, additionalCompilationArguments) - return GlobalCompiledProjectsCache.getProjectFromCache(module, strategyConfig) - ?: GlobalCompiledProjectsCache.putProjectIntoCache(module, strategyConfig) + return GlobalCompiledProjectsCache.getProjectFromCache(module, strategyConfig, compilationOptionsModifier, incrementalCompilationOptionsModifier) + ?: GlobalCompiledProjectsCache.putProjectIntoCache(module, strategyConfig, compilationOptionsModifier, incrementalCompilationOptionsModifier) } } @@ -90,20 +101,45 @@ fun BaseCompilationTest.scenario(strategyConfig: CompilerExecutionStrategyConfig action(ScenarioDsl(Project(workingDirectory), strategyConfig)) } +private data class GlobalCompiledProjectsCacheKey( + val moduleKey: DependencyScenarioDslCacheKey, + val compilationOptionsModifier: ((JvmCompilationConfiguration) -> Unit)?, + val incrementalCompilationOptionsModifier: ((IncrementalJvmCompilationConfiguration<*>) -> Unit)?, +) + private object GlobalCompiledProjectsCache { private val globalTempDirectory = Files.createTempDirectory("compiled-test-projects-cache").apply { toFile().deleteOnExit() } - private val compiledProjectsCache = mutableMapOf, Path>>() + private val compiledProjectsCache = mutableMapOf, Path>>() - fun getProjectFromCache(module: Module, strategyConfig: CompilerExecutionStrategyConfiguration): ScenarioModuleImpl? { - val (initialOutputs, cachedBuildDirPath) = compiledProjectsCache[module.scenarioDslCacheKey] ?: return null + fun getProjectFromCache( + module: Module, + strategyConfig: CompilerExecutionStrategyConfiguration, + compilationOptionsModifier: ((JvmCompilationConfiguration) -> Unit)?, + incrementalCompilationOptionsModifier: ((IncrementalJvmCompilationConfiguration<*>) -> Unit)?, + ): ScenarioModuleImpl? { + val (initialOutputs, cachedBuildDirPath) = compiledProjectsCache[GlobalCompiledProjectsCacheKey( + module.scenarioDslCacheKey, + compilationOptionsModifier, + incrementalCompilationOptionsModifier + )] ?: return null cachedBuildDirPath.copyToRecursively(module.buildDirectory, followLinks = false, overwrite = true) - return ScenarioModuleImpl(module, initialOutputs, strategyConfig) + return ScenarioModuleImpl(module, initialOutputs, strategyConfig, compilationOptionsModifier, incrementalCompilationOptionsModifier) } - fun putProjectIntoCache(module: Module, strategyConfig: CompilerExecutionStrategyConfiguration): ScenarioModuleImpl { - module.compileIncrementally(strategyConfig, SourcesChanges.Unknown) + fun putProjectIntoCache( + module: Module, + strategyConfig: CompilerExecutionStrategyConfiguration, + compilationOptionsModifier: ((JvmCompilationConfiguration) -> Unit)?, + incrementalCompilationOptionsModifier: ((IncrementalJvmCompilationConfiguration<*>) -> Unit)?, + ): ScenarioModuleImpl { + module.compileIncrementally( + strategyConfig, + SourcesChanges.Unknown, + compilationConfigAction = { compilationOptionsModifier?.invoke(it) }, + incrementalCompilationConfigAction = { incrementalCompilationOptionsModifier?.invoke(it) } + ) val initialOutputs = mutableSetOf() for (file in module.outputDirectory.walk()) { if (!file.isRegularFile()) continue @@ -111,7 +147,11 @@ private object GlobalCompiledProjectsCache { } val moduleCacheDirectory = globalTempDirectory.resolve(UUID.randomUUID().toString()) module.buildDirectory.copyToRecursively(moduleCacheDirectory, followLinks = false, overwrite = false) - compiledProjectsCache[module.scenarioDslCacheKey] = Pair(initialOutputs, moduleCacheDirectory) - return ScenarioModuleImpl(module, initialOutputs, strategyConfig) + compiledProjectsCache[GlobalCompiledProjectsCacheKey( + module.scenarioDslCacheKey, + compilationOptionsModifier, + incrementalCompilationOptionsModifier + )] = Pair(initialOutputs, moduleCacheDirectory) + return ScenarioModuleImpl(module, initialOutputs, strategyConfig, compilationOptionsModifier, incrementalCompilationOptionsModifier) } } \ No newline at end of file