Implement source sets visibility inference via associate compilations

Add non-public API for the IDE to query additional visible source sets
for each source set.
Implement visibility inference via associate compilation links.
Implement visibility requirements for source sets and requirements
satisfaction checks in Gradle build.
This commit is contained in:
Sergey Igushkin
2019-08-23 16:26:36 +03:00
parent 8c1c687e92
commit 94fd5c2884
5 changed files with 503 additions and 5 deletions
@@ -42,5 +42,8 @@ interface KotlinSourceSet : Named, HasKotlinDependencies {
val customSourceFilesExtensions: Iterable<String> // lazy iterable expected
val requiresVisibilityOf: Set<KotlinSourceSet>
fun requiresVisibilityOf(other: KotlinSourceSet)
fun addCustomSourceFilesExtensions(extensions: List<String>) {}
}
@@ -21,12 +21,13 @@ import org.gradle.api.publish.maven.tasks.AbstractPublishToMaven
import org.gradle.api.tasks.compile.AbstractCompile
import org.gradle.jvm.tasks.Jar
import org.gradle.util.ConfigureUtil
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.dsl.configureOrCreate
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
import org.jetbrains.kotlin.gradle.plugin.sources.checkSourceSetVisibilityRequirements
import org.jetbrains.kotlin.gradle.scripting.internal.ScriptingGradleSubplugin
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
import org.jetbrains.kotlin.gradle.utils.*
@@ -91,8 +92,6 @@ class KotlinMultiplatformPlugin(
setupCompilerPluginOptions(project)
project.pluginManager.apply(ScriptingGradleSubplugin::class.java)
UnusedSourceSetsChecker.checkSourceSets(project)
}
private fun setupCompilerPluginOptions(project: Project) {
@@ -256,6 +255,12 @@ class KotlinMultiplatformPlugin(
sourceSets.findByName(testCompilation.defaultSourceSetName)?.dependsOn(test)
}
}
UnusedSourceSetsChecker.checkSourceSets(project)
project.whenEvaluated {
checkSourceSetVisibilityRequirements(project)
}
}
companion object {
@@ -16,9 +16,8 @@ import org.jetbrains.kotlin.build.DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder
import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultKotlinDependencyHandler
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.GranularMetadataTransformation
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinProjectStructureMetadata
import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
@@ -119,6 +118,15 @@ class DefaultKotlinSourceSet(
internal val dependencyTransformations: MutableMap<KotlinDependencyScope, GranularMetadataTransformation> = mutableMapOf()
private val _requiresVisibilityOf = mutableSetOf<KotlinSourceSet>()
override val requiresVisibilityOf: MutableSet<KotlinSourceSet>
get() = Collections.unmodifiableSet(_requiresVisibilityOf)
override fun requiresVisibilityOf(other: KotlinSourceSet) {
requiresVisibilityOf += other
}
//region IDE import for Granular source sets metadata
data class MetadataDependencyTransformation(
@@ -141,6 +149,10 @@ class DefaultKotlinSourceSet(
return getDependenciesTransformation(scope)
}
@Suppress("unused") // Used in IDE import
fun getAdditionalVisibleSourceSets(): Set<KotlinSourceSet> =
getVisibleSourceSetsFromAssociateCompilations(project, this)
internal fun getDependenciesTransformation(scope: KotlinDependencyScope): Iterable<MetadataDependencyTransformation> {
val metadataDependencyResolutionByModule =
dependencyTransformations[scope]?.metadataDependencyResolutions
@@ -0,0 +1,156 @@
/*
* Copyright 2010-2019 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.
*/
package org.jetbrains.kotlin.gradle.plugin.sources
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.mpp.CompilationSourceSetUtil
import org.jetbrains.kotlin.gradle.plugin.mpp.associateWithTransitiveClosure
fun getSourceSetsFromAssociatedCompilations(fromCompilation: KotlinCompilation<*>): Map<KotlinCompilation<*>, Set<KotlinSourceSet>> =
fromCompilation.associateWithTransitiveClosure.associate { it to it.allKotlinSourceSets }
fun getVisibleSourceSetsFromAssociateCompilations(
project: Project,
sourceSet: KotlinSourceSet
) = getVisibleSourceSetsFromAssociateCompilations(
CompilationSourceSetUtil.compilationsBySourceSets(project).getValue(sourceSet)
)
internal fun getVisibleSourceSetsFromAssociateCompilations(
participatesInCompilations: Set<KotlinCompilation<*>>
): Set<KotlinSourceSet> {
val visibleInCompilations = participatesInCompilations.map {
val sourceSetsInAssociatedCompilations = getSourceSetsFromAssociatedCompilations(it)
when (sourceSetsInAssociatedCompilations.size) {
0 -> emptySet()
1 -> sourceSetsInAssociatedCompilations.values.single()
else -> mutableSetOf<KotlinSourceSet>().apply {
for ((_, sourceSets) in sourceSetsInAssociatedCompilations) {
addAll(sourceSets)
}
}
}
}
// Intersect the sets of source sets from the compilations:
return when (visibleInCompilations.size) {
0 -> emptySet()
1 -> visibleInCompilations.single()
else -> visibleInCompilations.first().toMutableSet().apply {
visibleInCompilations.subList(1, visibleInCompilations.size).forEach { retainAll(it) }
}
}
}
class UnsatisfiedSourceSetVisibilityException(
val sourceSet: KotlinSourceSet,
val compilations: Set<KotlinCompilation<*>>,
val visibleSourceSets: Set<KotlinSourceSet>,
val requiredButNotVisible: Set<KotlinSourceSet>
) : GradleException() {
override val message: String?
get() = buildString {
fun singularOrPlural(collection: Collection<*>, singular: String, plural: String = singular + "s") =
if (collection.size == 1) singular else plural
fun compilationWithTarget(compilation: KotlinCompilation<*>) = "${compilation.name} (target ${compilation.target.name})"
append(
"The source set ${sourceSet.name} requires visibility of the " +
singularOrPlural(requiredButNotVisible, "source set", "source sets:") + " " +
"${requiredButNotVisible.joinToString()}. " +
"This requirement was not satisfied.\n\n"
)
append("${sourceSet.name} takes part in the ${singularOrPlural(compilations, "compilation")}:\n")
fun appendCompilationRecursively(compilation: KotlinCompilation<*>, depth: Int) {
val isAssociatedCompilation = depth > 0
val sourceSetsInAssociatedCompilations =
getSourceSetsFromAssociatedCompilations(compilation)
val allKotlinSourceSets = compilation.allKotlinSourceSets
val indent = " ".repeat(depth + 1)
val prefix = if (isAssociatedCompilation)
"$indent- ${"indirectly ".takeIf { depth > 1 }.orEmpty()}associated with"
else
"$indent-"
append("$prefix ${compilationWithTarget(compilation)}")
append(
if (isAssociatedCompilation)
", which compiles" +
singularOrPlural(allKotlinSourceSets, "source set ", "source sets: ") +
allKotlinSourceSets.joinToString { it.name } +
"\n"
else "\n"
)
compilation.associateWith.forEach { appendCompilationRecursively(it, depth + 1) }
if (!isAssociatedCompilation) {
val missingRequiredSourceSets = requiredButNotVisible.filter { missingSourceSet ->
sourceSetsInAssociatedCompilations.values.none { missingSourceSet in it }
}
if (missingRequiredSourceSets.isEmpty()) {
append("${indent}The compilation ${compilationWithTarget(compilation)} requires no changes.\n")
} else {
append(
"${indent}To ensure the required visibility, the compilation " + compilationWithTarget(compilation) +
"must have a direct or indirect associate that compiles the source " +
singularOrPlural(missingRequiredSourceSets, "set ", "sets: ") +
missingRequiredSourceSets.joinToString() + "\n"
)
}
}
}
compilations.forEach {
appendCompilationRecursively(it, 0)
append("\n")
}
}
}
fun checkSourceSetVisibilityRequirements(
project: Project
) = checkSourceSetVisibilityRequirements(
project.kotlinExtension.sourceSets,
CompilationSourceSetUtil.compilationsBySourceSets(project)
)
internal fun checkSourceSetVisibilityRequirements(
sourceSets: Iterable<KotlinSourceSet>,
compilationsBySourceSet: Map<KotlinSourceSet, Set<KotlinCompilation<*>>>
) {
sourceSets.forEach { sourceSet ->
val requiredVisibility = sourceSet.requiresVisibilityOf
val inferredVisibility =
getVisibleSourceSetsFromAssociateCompilations(compilationsBySourceSet[sourceSet].orEmpty())
val requiredButNotVisible = requiredVisibility - inferredVisibility //TODO minus dependsOn?
if (requiredButNotVisible.isNotEmpty()) {
val compilations = compilationsBySourceSet.getValue(sourceSet)
throw UnsatisfiedSourceSetVisibilityException(
sourceSet,
compilations,
inferredVisibility,
requiredButNotVisible
)
}
}
}
@@ -0,0 +1,322 @@
/*
* Copyright 2010-2019 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.
*/
package org.jetbrains.kotlin.gradle.plugin.sources
import groovy.lang.Closure
import org.gradle.api.attributes.AttributeContainer
import org.gradle.api.file.FileCollection
import org.gradle.api.file.SourceDirectorySet
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
import org.jetbrains.kotlin.gradle.plugin.*
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
class SourceSetVisibilityTest {
@Test
fun testBasicSuccessful(): Unit = with(SourceSetCompilationDsl()) {
val commonMain = sourceSet("commonMain")
val jvmMain = sourceSet("jvmMain", commonMain)
val commonTest = sourceSet("commonTest") {
requiresVisibilityOf(commonMain)
}
val jvmTest = sourceSet("jvmTest", commonTest) {
requiresVisibilityOf(jvmMain)
}
val jvmMainCompilation = compilation("jvm/main", jvmMain)
compilation("jvm/test", jvmTest, jvmMainCompilation)
checkInferredSourceSetsVisibility(jvmTest.name, commonMain.name, jvmMain.name)
// should not throw exception
checkSourceSetVisibilityRequirements(sourceSets, compilationsBySourceSets)
}
@Test
fun testFailureWithNoAssociation(): Unit = with(SourceSetCompilationDsl()) {
val commonMain = sourceSet("commonMain")
val jvmMain = sourceSet("jvmMain", commonMain)
val commonTest = sourceSet("commonTest") {
requiresVisibilityOf(commonMain)
}
val jvmTest = sourceSet("jvmTest", commonTest) {
requiresVisibilityOf(jvmMain)
}
compilation("jvm/main", jvmMain)
val jvmTestCompilation = compilation("jvm/test", jvmTest) // note: no association with jvmMainCompilation
checkInferredSourceSetsVisibility("jvmTest", *arrayOf())
assertFailsWith<UnsatisfiedSourceSetVisibilityException> {
checkSourceSetVisibilityRequirements(setOf(jvmTest), compilationsBySourceSets)
}.apply {
assertEquals(jvmTest, sourceSet)
assertEquals(emptySet(), visibleSourceSets)
assertEquals(setOf(jvmMain), requiredButNotVisible)
assertEquals(setOf(jvmTestCompilation), compilations)
}
assertFailsWith<UnsatisfiedSourceSetVisibilityException> {
checkSourceSetVisibilityRequirements(setOf(commonTest), compilationsBySourceSets)
}.apply {
assertEquals(commonTest, sourceSet)
assertEquals(emptySet(), visibleSourceSets)
assertEquals(setOf(commonMain), requiredButNotVisible)
assertEquals(setOf(jvmTestCompilation), compilations)
}
}
private fun SourceSetCompilationDsl.checkInferredSourceSetsVisibility(
forSourceSetName: String,
vararg expectedVisibleSourceSetNames: String
) = assertEquals(
setOf(*expectedVisibleSourceSetNames),
getVisibleSourceSetsFromAssociateCompilations(
compilationsBySourceSets.getValue(sourceSetsByName.getValue(forSourceSetName))
).mapTo(mutableSetOf<String>()) { it.name }
)
@Test
fun testInferenceForHierarchy() = with(SourceSetCompilationDsl()) {
for (suffix in listOf("Main", "Test")) {
val common = sourceSet("common$suffix")
val jvmAndJs = sourceSet("jvmAndJs$suffix", common) {
sourceSetsByName["jvmAndJsMain"]?.let(this::requiresVisibilityOf)
}
val linuxAndJs = sourceSet("linuxAndJs$suffix", common) {
sourceSetsByName["linuxAndJsMain"]?.let(this::requiresVisibilityOf)
}
val jvm = sourceSet("jvm$suffix", common, jvmAndJs) {
sourceSetsByName["jvmMain"]?.let(this::requiresVisibilityOf)
}
val linux = sourceSet("linux$suffix", common, linuxAndJs) {
sourceSetsByName["linuxMain"]?.let(this::requiresVisibilityOf)
}
val js = sourceSet("js$suffix", common, jvmAndJs, linuxAndJs) {
sourceSetsByName["jsMain"]?.let(this::requiresVisibilityOf)
}
compilation("jvm / $suffix", jvm, *listOfNotNull(compilationsByName["jvm / Main"]).toTypedArray())
compilation("linux / $suffix", linux, *listOfNotNull(compilationsByName["linux / Main"]).toTypedArray())
compilation("js / $suffix", js, *listOfNotNull(compilationsByName["js / Main"]).toTypedArray())
}
checkInferredSourceSetsVisibility("commonMain", *arrayOf())
checkInferredSourceSetsVisibility("jvmMain", *arrayOf())
checkInferredSourceSetsVisibility("jvmAndJsMain", *arrayOf())
checkInferredSourceSetsVisibility("commonTest", "commonMain")
checkInferredSourceSetsVisibility("jvmAndJsTest", "commonMain", "jvmAndJsMain")
checkInferredSourceSetsVisibility("linuxAndJsTest", "commonMain", "linuxAndJsMain")
checkInferredSourceSetsVisibility("jvmTest", "commonMain", "jvmAndJsMain", "jvmMain")
checkSourceSetVisibilityRequirements(sourceSets, compilationsBySourceSets)
}
@Test
fun testInferenceThroughIndirectAssociation(): Unit = with(SourceSetCompilationDsl()) {
for ((previousSuffix, suffix) in listOf(null, "Main", "Test", "IntegrationTest").zipWithNext()) {
val common = sourceSet("common$suffix") {
if (previousSuffix != null) requiresVisibilityOf(sourceSetsByName.getValue("common$previousSuffix"))
}
val jvm = sourceSet("jvm$suffix", common) {
if (previousSuffix != null) requiresVisibilityOf(sourceSetsByName.getValue("jvm$previousSuffix"))
}
val js = sourceSet("js$suffix", common) {
if (previousSuffix != null) requiresVisibilityOf(sourceSetsByName.getValue("js$previousSuffix"))
}
compilation("jvm / $suffix", jvm, *listOfNotNull(compilationsByName["jvm / $previousSuffix"]).toTypedArray())
compilation("js / $suffix", js, *listOfNotNull(compilationsByName["js / $previousSuffix"]).toTypedArray())
}
checkInferredSourceSetsVisibility("commonIntegrationTest", "commonMain", "commonTest")
checkInferredSourceSetsVisibility("jvmIntegrationTest", "commonMain", "jvmMain", "commonTest", "jvmTest")
checkSourceSetVisibilityRequirements(sourceSets, compilationsBySourceSets)
// Now break visibility between *Test and *Main:
compilationsByName.getValue("jvm / Test").associateWith.clear()
compilationsByName.getValue("js / Test").associateWith.clear()
val commonIntegrationTest = sourceSetsByName.getValue("commonIntegrationTest")
commonIntegrationTest.requiresVisibilityOf(sourceSetsByName.getValue("commonMain"))
assertFailsWith<UnsatisfiedSourceSetVisibilityException> {
checkSourceSetVisibilityRequirements(setOf(commonIntegrationTest), compilationsBySourceSets)
}.apply {
assertEquals(commonIntegrationTest, this.sourceSet)
assertEquals(setOf("commonTest"), visibleSourceSets.map { it.name }.toSet())
assertEquals(setOf("commonMain"), requiredButNotVisible.map { it.name }.toSet())
assertEquals(setOf("jvm / IntegrationTest", "js / IntegrationTest"), compilations.map { it.name }.toSet())
}
}
@Test
fun testFailureWithPlatformSpecificRequirement(): Unit = with(SourceSetCompilationDsl()) {
val commonMain = sourceSet("commonMain")
val jvmMain = sourceSet("jvmMain", commonMain)
val jsMain = sourceSet("jvmMain", commonMain)
val commonTest = sourceSet("commonTest") {
requiresVisibilityOf(jvmMain) // <- invalid requirement!
}
val jvmTest = sourceSet("jvmTest", commonTest) {
requiresVisibilityOf(jvmMain)
}
val jsTest = sourceSet("jsTest", commonTest) {
requiresVisibilityOf(jsMain)
}
val jvmMainCompilation = compilation("jvm / main", jvmMain)
val jsMainCompilation = compilation("js / main", jsMain)
val jvmTestCompilation = compilation("jvm / test", jvmTest, jvmMainCompilation)
val jsTestCompilation = compilation("js / test", jsTest, jsMainCompilation)
assertFailsWith<UnsatisfiedSourceSetVisibilityException> {
checkSourceSetVisibilityRequirements(setOf(commonTest), compilationsBySourceSets)
}.apply {
assertEquals(commonTest, this.sourceSet)
assertEquals(setOf(commonMain), visibleSourceSets)
assertEquals(setOf(jvmMain), requiredButNotVisible)
assertEquals(setOf(jvmTestCompilation, jsTestCompilation), compilations)
}
}
}
class SourceSetCompilationDsl {
val compilations: Set<MockKotlinCompilation> get() = compilationsByName.values.toSet()
val sourceSets: Set<MockKotlinSourceSet> get() = sourceSetsByName.values.toSet()
val sourceSetsByName = mutableMapOf<String, MockKotlinSourceSet>()
val compilationsByName = mutableMapOf<String, MockKotlinCompilation>()
val compilationsBySourceSets: Map<KotlinSourceSet, Set<KotlinCompilation<*>>>
get() = mutableMapOf<KotlinSourceSet, MutableSet<KotlinCompilation<*>>>().apply {
compilations.forEach { compilation ->
compilation.allKotlinSourceSets.filterIsInstance<MockKotlinSourceSet>().forEach { sourceSet ->
getOrPut(sourceSet) { mutableSetOf() }.add(compilation)
}
}
}
fun sourceSet(
name: String,
vararg dependsOn: MockKotlinSourceSet,
configure: MockKotlinSourceSet.() -> Unit = { }
) = MockKotlinSourceSet(name).apply {
dependsOn.forEach { dependsOn(it) }
configure()
sourceSetsByName[name] = this
}
fun compilation(
name: String,
defaultSourceSet: KotlinSourceSet,
vararg associateWith: MockKotlinCompilation,
configure: MockKotlinCompilation.() -> Unit = { }
) = MockKotlinCompilation(name, defaultSourceSet).apply {
associateWith.forEach { associateWith(it) }
configure()
compilationsByName[name] = this
}
}
class MockKotlinSourceSet(private val name: String) : KotlinSourceSet {
override fun getName(): String = name
override val dependsOn: MutableSet<KotlinSourceSet> = mutableSetOf()
override val requiresVisibilityOf: MutableSet<KotlinSourceSet> = mutableSetOf()
override fun dependsOn(other: KotlinSourceSet) {
dependsOn += other
}
override fun requiresVisibilityOf(other: KotlinSourceSet) {
requiresVisibilityOf += other
}
//region Not implemented
override val kotlin: SourceDirectorySet get() = throw UnsupportedOperationException()
override fun kotlin(configureClosure: Closure<Any?>): SourceDirectorySet = throw UnsupportedOperationException()
override val resources: SourceDirectorySet get() = throw UnsupportedOperationException()
override val languageSettings: LanguageSettingsBuilder get() = throw UnsupportedOperationException()
override fun languageSettings(configureClosure: Closure<Any?>): LanguageSettingsBuilder = languageSettings
override val apiMetadataConfigurationName: String get() = throw UnsupportedOperationException()
override val implementationMetadataConfigurationName: String get() = throw UnsupportedOperationException()
override val compileOnlyMetadataConfigurationName: String get() = throw UnsupportedOperationException()
override val runtimeOnlyMetadataConfigurationName: String get() = throw UnsupportedOperationException()
override val customSourceFilesExtensions: Iterable<String> get() = throw UnsupportedOperationException()
override fun dependencies(configure: KotlinDependencyHandler.() -> Unit) = throw UnsupportedOperationException()
override fun dependencies(configureClosure: Closure<Any?>) = throw UnsupportedOperationException()
override val apiConfigurationName: String get() = throw UnsupportedOperationException()
override val implementationConfigurationName: String get() = throw UnsupportedOperationException()
override val compileOnlyConfigurationName: String get() = throw UnsupportedOperationException()
override val runtimeOnlyConfigurationName: String get() = throw UnsupportedOperationException()
//endregion
}
class MockKotlinCompilation(
override val compilationName: String,
override val defaultSourceSet: KotlinSourceSet
) : KotlinCompilation<KotlinCommonOptions> {
override val kotlinSourceSets: Set<KotlinSourceSet> = setOf(defaultSourceSet)
override val allKotlinSourceSets: Set<KotlinSourceSet>
get() = mutableSetOf<KotlinSourceSet>().apply {
fun visit(sourceSet: KotlinSourceSet) {
if (add(sourceSet)) {
sourceSet.dependsOn.forEach(::visit)
}
}
visit(defaultSourceSet)
}
override fun source(sourceSet: KotlinSourceSet) = defaultSourceSet.dependsOn(sourceSet)
override fun associateWith(other: KotlinCompilation<*>) {
associateWith += other
}
override val associateWith: MutableSet<KotlinCompilation<*>> = mutableSetOf()
override fun defaultSourceSet(configure: KotlinSourceSet.() -> Unit) = defaultSourceSet.run(configure)
//region Not implemented
override val target: KotlinTarget get() = throw UnsupportedOperationException()
override fun getAttributes(): AttributeContainer = throw UnsupportedOperationException()
override fun dependencies(configure: KotlinDependencyHandler.() -> Unit) = throw UnsupportedOperationException()
override fun dependencies(configureClosure: Closure<Any?>) = throw UnsupportedOperationException()
override val apiConfigurationName: String get() = throw UnsupportedOperationException()
override val implementationConfigurationName: String get() = throw UnsupportedOperationException()
override val compileOnlyConfigurationName: String get() = throw UnsupportedOperationException()
override val runtimeOnlyConfigurationName: String get() = throw UnsupportedOperationException()
override fun defaultSourceSet(configure: Closure<*>) = throw UnsupportedOperationException()
override val compileDependencyConfigurationName: String get() = throw UnsupportedOperationException()
override var compileDependencyFiles: FileCollection
get() = throw UnsupportedOperationException()
set(value) = throw UnsupportedOperationException()
override val output: KotlinCompilationOutput get() = throw UnsupportedOperationException()
override val compileKotlinTaskName: String get() = throw UnsupportedOperationException()
override val compileKotlinTask: KotlinCompile<KotlinCommonOptions> get() = throw UnsupportedOperationException()
override val kotlinOptions: KotlinCommonOptions get() = throw UnsupportedOperationException()
override fun kotlinOptions(configure: KotlinCommonOptions.() -> Unit) = throw UnsupportedOperationException()
override fun kotlinOptions(configure: Closure<*>) = throw UnsupportedOperationException()
override fun attributes(configure: AttributeContainer.() -> Unit) = throw UnsupportedOperationException()
override fun attributes(configure: Closure<*>) = throw UnsupportedOperationException()
override val compileAllTaskName: String get() = throw UnsupportedOperationException()
//endregion
override fun toString(): String = "compilation '${name}'"
}