ExperimentalFixesFactory: OptIn shouldn't be added for old version

#KT-36478
This commit is contained in:
Dmitry Gridin
2020-03-02 13:18:20 +07:00
parent 08dc03a704
commit ecb7478794
2 changed files with 29 additions and 8 deletions
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.idea.quickfix
import com.intellij.codeInsight.intention.IntentionAction
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.descriptors.resolveClassByFqName
import org.jetbrains.kotlin.diagnostics.Diagnostic
@@ -16,6 +17,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.core.toDescriptor
import org.jetbrains.kotlin.idea.util.projectStructure.module
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypesAndPredicate
@@ -36,8 +38,7 @@ object ExperimentalFixesFactory : KotlinIntentionActionsFactory() {
!KtPsiUtil.isLocal(it)
} ?: return emptyList()
val factory = diagnostic.factory
val annotationFqName = when (factory) {
val annotationFqName = when (diagnostic.factory) {
EXPERIMENTAL_API_USAGE -> EXPERIMENTAL_API_USAGE.cast(diagnostic).a
EXPERIMENTAL_API_USAGE_ERROR -> EXPERIMENTAL_API_USAGE_ERROR.cast(diagnostic).a
EXPERIMENTAL_OVERRIDE -> EXPERIMENTAL_OVERRIDE.cast(diagnostic).a
@@ -71,7 +72,7 @@ object ExperimentalFixesFactory : KotlinIntentionActionsFactory() {
}
result.add(
AddAnnotationFix(
containingDeclaration, ExperimentalUsageChecker.OPT_IN_FQ_NAME, suffix, annotationFqName
containingDeclaration, moduleDescriptor.OPT_IN_FQ_NAME, suffix, annotationFqName
)
)
}
@@ -84,7 +85,7 @@ object ExperimentalFixesFactory : KotlinIntentionActionsFactory() {
} else {
result.add(
AddAnnotationFix(
containingClassOrObject, ExperimentalUsageChecker.OPT_IN_FQ_NAME, suffix, annotationFqName
containingClassOrObject, moduleDescriptor.OPT_IN_FQ_NAME, suffix, annotationFqName
)
)
}
@@ -100,4 +101,11 @@ object ExperimentalFixesFactory : KotlinIntentionActionsFactory() {
return result
}
private val ModuleDescriptor.OPT_IN_FQ_NAME: FqName
get() = ExperimentalUsageChecker.OPT_IN_FQ_NAME.takeIf { fqNameIsExisting(it) }
?: ExperimentalUsageChecker.OLD_USE_EXPERIMENTAL_FQ_NAME
fun ModuleDescriptor.fqNameIsExisting(fqName: FqName): Boolean = resolveClassByFqName(fqName, NoLookupLocation.FROM_IDE) != null
}
@@ -13,10 +13,12 @@ import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.config.CompilerSettings
import org.jetbrains.kotlin.config.additionalArgumentsAsList
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.idea.caches.project.toDescriptor
import org.jetbrains.kotlin.idea.configuration.BuildSystemType
import org.jetbrains.kotlin.idea.configuration.getBuildSystemType
import org.jetbrains.kotlin.idea.facet.KotlinFacet
import org.jetbrains.kotlin.idea.facet.getOrCreateFacet
import org.jetbrains.kotlin.idea.quickfix.ExperimentalFixesFactory.fqNameIsExisting
import org.jetbrains.kotlin.idea.roots.invalidateProjectRoots
import org.jetbrains.kotlin.idea.util.projectStructure.module
import org.jetbrains.kotlin.name.FqName
@@ -28,11 +30,16 @@ class MakeModuleExperimentalFix(
private val module: Module,
private val annotationFqName: FqName
) : KotlinQuickFixAction<KtFile>(file) {
override fun getText(): String = "Add '-Xopt-in=$annotationFqName' to module ${module.name} compiler arguments"
private val experimentalPrefix = if (module.toDescriptor()?.fqNameIsExisting(ExperimentalUsageChecker.REQUIRES_OPT_IN_FQ_NAME) == true)
"opt-in"
else
"use-experimental"
override fun getText(): String = "Add '$compilerArgument' to module ${module.name} compiler arguments"
override fun getFamilyName(): String = "Add an opt-in requirement marker compiler argument"
private val compilerArgument = "-Xopt-in=$annotationFqName"
private val compilerArgument = "-X$experimentalPrefix=$annotationFqName"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val modelsProvider = IdeModifiableModelsProviderImpl(project)
@@ -56,7 +63,7 @@ class MakeModuleExperimentalFix(
val facet = KotlinFacet.get(module) ?: return true
val facetSettings = facet.configuration.settings
val compilerSettings = facetSettings.compilerSettings ?: return true
return if (annotationFqName != ExperimentalUsageChecker.REQUIRES_OPT_IN_FQ_NAME) {
return if (annotationFqName != ExperimentalUsageChecker.REQUIRES_OPT_IN_FQ_NAME && annotationFqName != ExperimentalUsageChecker.OLD_EXPERIMENTAL_FQ_NAME) {
compilerArgument !in compilerSettings.additionalArgumentsAsList
} else {
compilerSettings.additionalArgumentsAsList.none {
@@ -69,7 +76,13 @@ class MakeModuleExperimentalFix(
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val containingKtFile = diagnostic.psiElement.containingFile as? KtFile ?: return null
val module = containingKtFile.module ?: return null
return MakeModuleExperimentalFix(containingKtFile, module, ExperimentalUsageChecker.REQUIRES_OPT_IN_FQ_NAME)
return MakeModuleExperimentalFix(
containingKtFile,
module,
ExperimentalUsageChecker.REQUIRES_OPT_IN_FQ_NAME.takeIf {
module.toDescriptor()?.fqNameIsExisting(it) == true
} ?: ExperimentalUsageChecker.OLD_EXPERIMENTAL_FQ_NAME
)
}
}
}