From 8ae751926cda59114ed6f5e9751cce2e55ab88b2 Mon Sep 17 00:00:00 2001 From: Kirill Rakhman Date: Fri, 4 Aug 2023 10:08:08 +0200 Subject: [PATCH] [FIR] Let OptIn LV checker only run on last module in HMPP compilation This fixes an issue where the opt-in annotation is defined in one of the source sets of the compilation but opt-ins are defined for the whole compilation which leads to false-positive "Opt-in requirement marker is unresolved" in (e.g. common) source sets that don't have a dependency on the module that contains the annotation. #KT-60755 Fixed --- .../cli/common/FirSessionConstructionUtils.kt | 31 ++++++++++++++----- .../CommonLanguageVersionSettingsCheckers.kt | 5 ++- .../OptInLanguageVersionSettingsCheckers.kt | 15 +++++++++ .../org/jetbrains/kotlin/gradle/K2Tests.kt | 18 +++++++++++ .../build.gradle.kts | 22 +++++++++++++ .../gradle.properties | 1 + .../src/jvmMain/kotlin/MyOptIn.kt | 9 ++++++ 7 files changed, 91 insertions(+), 10 deletions(-) create mode 100644 compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/OptInLanguageVersionSettingsCheckers.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/k2-mpp-opt-in-in-platform/build.gradle.kts create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/k2-mpp-opt-in-in-platform/gradle.properties create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/k2-mpp-opt-in-in-platform/src/jvmMain/kotlin/MyOptIn.kt diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/FirSessionConstructionUtils.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/FirSessionConstructionUtils.kt index 682815ac8d8..1ec8294b455 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/FirSessionConstructionUtils.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/FirSessionConstructionUtils.kt @@ -8,11 +8,14 @@ package org.jetbrains.kotlin.cli.common import org.jetbrains.kotlin.KtSourceFile import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices import org.jetbrains.kotlin.config.* -import org.jetbrains.kotlin.fir.* +import org.jetbrains.kotlin.fir.DependencyListForCliModule +import org.jetbrains.kotlin.fir.FirModuleData +import org.jetbrains.kotlin.fir.FirModuleDataImpl +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.analysis.checkers.OptInLanguageVersionSettingsCheckers import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider -import org.jetbrains.kotlin.fir.resolve.providers.impl.FirExtensionSyntheticFunctionInterfaceProvider import org.jetbrains.kotlin.fir.session.* import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope @@ -24,7 +27,6 @@ import org.jetbrains.kotlin.load.kotlin.PackageAndMetadataPartProvider import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.platform.CommonPlatforms import org.jetbrains.kotlin.platform.TargetPlatform -import org.jetbrains.kotlin.platform.WasmPlatform import org.jetbrains.kotlin.platform.js.JsPlatforms import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.platform.konan.NativePlatforms @@ -359,7 +361,10 @@ private inline fun createSingleSession( analyzerServices ) - val session = createFirSession(files, platformModuleData, sessionProvider, sessionConfigurator) + val session = createFirSession(files, platformModuleData, sessionProvider) { + sessionConfigurator() + useCheckers(OptInLanguageVersionSettingsCheckers) + } return SessionWithSources(session, files) } @@ -399,7 +404,12 @@ private inline fun createSessionsForLegacyMppProject( } val commonSession = createFirSession(commonFiles, commonModuleData, sessionProvider, sessionConfigurator) - val platformSession = createFirSession(platformFiles, platformModuleData, sessionProvider, sessionConfigurator) + val platformSession = createFirSession(platformFiles, platformModuleData, sessionProvider) { + sessionConfigurator() + // The CLI session might contain an opt-in for an annotation that's defined in the platform module. + // Therefore, only run the opt-in LV checker on the platform module. + useCheckers(OptInLanguageVersionSettingsCheckers) + } return listOf( SessionWithSources(commonSession, commonFiles), @@ -436,10 +446,17 @@ private inline fun createSessionsForHmppProject( moduleDataForHmppModule[module] = moduleData } - return hmppModuleStructure.modules.map { module -> + return hmppModuleStructure.modules.mapIndexed { i, module -> val moduleData = moduleDataForHmppModule.getValue(module) val sources = files.filter { fileBelongsToModule(it, module.name) } - val session = createFirSession(sources, moduleData, sessionProvider, sessionConfigurator) + val session = createFirSession(sources, moduleData, sessionProvider) { + sessionConfigurator() + // The CLI session might contain an opt-in for an annotation that's defined in one of the modules. + // The only module that's guaranteed to have a dependency on this module is the last one. + if (i == hmppModuleStructure.modules.lastIndex) { + useCheckers(OptInLanguageVersionSettingsCheckers) + } + } SessionWithSources(session, sources) } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonLanguageVersionSettingsCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonLanguageVersionSettingsCheckers.kt index fa709f72cf1..953adcc28d0 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonLanguageVersionSettingsCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonLanguageVersionSettingsCheckers.kt @@ -6,10 +6,9 @@ package org.jetbrains.kotlin.fir.analysis.checkers import org.jetbrains.kotlin.fir.analysis.checkers.config.FirLanguageVersionSettingsChecker -import org.jetbrains.kotlin.fir.analysis.checkers.config.FirOptInLanguageVersionSettingsChecker object CommonLanguageVersionSettingsCheckers : LanguageVersionSettingsCheckers() { override val languageVersionSettingsCheckers: Set - get() = setOf(FirOptInLanguageVersionSettingsChecker) -} \ No newline at end of file + get() = setOf() +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/OptInLanguageVersionSettingsCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/OptInLanguageVersionSettingsCheckers.kt new file mode 100644 index 00000000000..513578f2ef5 --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/OptInLanguageVersionSettingsCheckers.kt @@ -0,0 +1,15 @@ +/* + * 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. + */ + +package org.jetbrains.kotlin.fir.analysis.checkers + +import org.jetbrains.kotlin.fir.analysis.checkers.config.FirLanguageVersionSettingsChecker +import org.jetbrains.kotlin.fir.analysis.checkers.config.FirOptInLanguageVersionSettingsChecker + +object OptInLanguageVersionSettingsCheckers : LanguageVersionSettingsCheckers() { + + override val languageVersionSettingsCheckers: Set + get() = setOf(FirOptInLanguageVersionSettingsChecker) +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/K2Tests.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/K2Tests.kt index 3ab540fee13..0a6ff8a2169 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/K2Tests.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/K2Tests.kt @@ -137,4 +137,22 @@ class CustomK2Tests : KGPBaseTest() { } } } + + @GradleTest + @DisplayName("All source sets have opt-in for annotation defined in platform source set. KT-60755") + fun kt60755OptInDefinedInPlatform(gradleVersion: GradleVersion) { + with( + project( + "k2-mpp-opt-in-in-platform", + gradleVersion, + buildOptions = defaultBuildOptions.copy(languageVersion = "2.0"), + ) + ) { + val taskToExecute = ":compileKotlinJvm" + build(taskToExecute) { + assertTasksExecuted(taskToExecute) + assertOutputDoesNotContain("Opt-in requirement marker foo.bar.MyOptIn is unresolved") + } + } + } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/k2-mpp-opt-in-in-platform/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/k2-mpp-opt-in-in-platform/build.gradle.kts new file mode 100644 index 00000000000..820395f36c8 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/k2-mpp-opt-in-in-platform/build.gradle.kts @@ -0,0 +1,22 @@ +import org.jetbrains.kotlin.gradle.dsl.KotlinVersion +import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask + +plugins { + kotlin("multiplatform") +} + +repositories { + mavenLocal() + mavenCentral() +} + +kotlin { + jvm() + + sourceSets { + all { + languageSettings.optIn("foo.bar.MyOptIn") + } + } +} + diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/k2-mpp-opt-in-in-platform/gradle.properties b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/k2-mpp-opt-in-in-platform/gradle.properties new file mode 100644 index 00000000000..0480fdcf3dd --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/k2-mpp-opt-in-in-platform/gradle.properties @@ -0,0 +1 @@ +kotlin.stdlib.default.dependency=false \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/k2-mpp-opt-in-in-platform/src/jvmMain/kotlin/MyOptIn.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/k2-mpp-opt-in-in-platform/src/jvmMain/kotlin/MyOptIn.kt new file mode 100644 index 00000000000..e48b0228dac --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/k2-mpp-opt-in-in-platform/src/jvmMain/kotlin/MyOptIn.kt @@ -0,0 +1,9 @@ +/* + * 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. + */ + +package foo.bar + +@RequiresOptIn(level = RequiresOptIn.Level.ERROR) +annotation class MyOptIn