From b47b9c2ae1f3eec0576cf796eeee9e64e4f71b6e Mon Sep 17 00:00:00 2001 From: Anastasia Pikalova Date: Wed, 18 Sep 2024 00:32:58 +0200 Subject: [PATCH] [kotlin] Error/warning message for @SubclassOptInRequired-annotated class should provide more context ^KT-70407 Fixed GitOrigin-RevId: 1a45214c9c4ffc983e1e16affc6828733b45f8e3 --- .../compiler/K1KotlinCompilerIdeAllowedErrorFilter.kt | 1 + .../compiler/K2KotlinCompilerIdeAllowedErrorFilter.kt | 1 + .../k2/codeinsight/fixes/KotlinK2QuickFixRegistrar.kt | 4 ++++ .../k2/codeinsight/fixes/OptInFileLevelFixFactories.kt | 8 ++++++++ .../kotlin/idea/k2/codeinsight/fixes/OptInFixFactories.kt | 8 ++++++++ .../kotlin/idea/k2/codeinsight/fixes/OptInFixUtils.kt | 2 ++ .../org/jetbrains/kotlin/idea/quickfix/OptInFixesUtils.kt | 2 ++ .../jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt | 4 ++++ .../idea/tests/testData/quickfix/optIn/propagateOptIn8.kt | 2 +- .../tests/testData/quickfix/optIn/propagateOptIn8Fir.kt | 2 +- .../quickfix/optIn/propagateSubclassOptInRequired2.kt | 2 +- .../optIn/propagateSubclassOptInRequired2.kt.after | 2 +- .../quickfix/optIn/scripts/general/propagateOptIn8.kts | 2 +- .../scripts/general/propagateSubclassOptInRequired2.kts | 2 +- .../general/propagateSubclassOptInRequired2.kts.after | 2 +- .../debugger/evaluate/K1KotlinCodeFragmentCompiler.kt | 1 + 16 files changed, 38 insertions(+), 7 deletions(-) diff --git a/plugins/kotlin/base/fe10/code-insight/src/org/jetbrains/kotlin/idea/base/fe10/codeInsight/compiler/K1KotlinCompilerIdeAllowedErrorFilter.kt b/plugins/kotlin/base/fe10/code-insight/src/org/jetbrains/kotlin/idea/base/fe10/codeInsight/compiler/K1KotlinCompilerIdeAllowedErrorFilter.kt index 627c11e6c4bc..cb5030548e45 100644 --- a/plugins/kotlin/base/fe10/code-insight/src/org/jetbrains/kotlin/idea/base/fe10/codeInsight/compiler/K1KotlinCompilerIdeAllowedErrorFilter.kt +++ b/plugins/kotlin/base/fe10/code-insight/src/org/jetbrains/kotlin/idea/base/fe10/codeInsight/compiler/K1KotlinCompilerIdeAllowedErrorFilter.kt @@ -15,6 +15,7 @@ class K1KotlinCompilerIdeAllowedErrorFilter : KotlinCompilerIdeAllowedErrorFilte Errors.DIVISION_BY_ZERO, Errors.OPT_IN_USAGE_ERROR, Errors.OPT_IN_OVERRIDE_ERROR, + Errors.OPT_IN_TO_INHERITANCE_ERROR, Errors.UNSAFE_CALL, Errors.UNSAFE_OPERATOR_CALL, Errors.ITERATOR_ON_NULLABLE, diff --git a/plugins/kotlin/base/fir/code-insight/src/org/jetbrains/kotlin/idea/base/fir/codeInsight/compiler/K2KotlinCompilerIdeAllowedErrorFilter.kt b/plugins/kotlin/base/fir/code-insight/src/org/jetbrains/kotlin/idea/base/fir/codeInsight/compiler/K2KotlinCompilerIdeAllowedErrorFilter.kt index 83260686f759..6010395de873 100644 --- a/plugins/kotlin/base/fir/code-insight/src/org/jetbrains/kotlin/idea/base/fir/codeInsight/compiler/K2KotlinCompilerIdeAllowedErrorFilter.kt +++ b/plugins/kotlin/base/fir/code-insight/src/org/jetbrains/kotlin/idea/base/fir/codeInsight/compiler/K2KotlinCompilerIdeAllowedErrorFilter.kt @@ -13,6 +13,7 @@ internal class K2KotlinCompilerIdeAllowedErrorFilter : KotlinCompilerIdeAllowedE FirErrors.DEPRECATION_ERROR, FirErrors.DIVISION_BY_ZERO, FirErrors.OPT_IN_USAGE_ERROR, + FirErrors.OPT_IN_TO_INHERITANCE_ERROR, FirErrors.OPT_IN_OVERRIDE_ERROR, FirErrors.UNSAFE_CALL, FirErrors.UNSAFE_IMPLICIT_INVOKE_CALL, diff --git a/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/KotlinK2QuickFixRegistrar.kt b/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/KotlinK2QuickFixRegistrar.kt index 445326bbc8bc..fcfc4b2263ac 100644 --- a/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/KotlinK2QuickFixRegistrar.kt +++ b/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/KotlinK2QuickFixRegistrar.kt @@ -518,10 +518,14 @@ class KotlinK2QuickFixRegistrar : KotlinQuickFixRegistrar() { registerFactory(OptInModuleLevelFixFactories.optInIsNotEnabledFactory) registerFactory(OptInFileLevelFixFactories.optInUsageFactory) registerFactory(OptInFileLevelFixFactories.optInUsageErrorFactory) + registerFactory(OptInFileLevelFixFactories.optInUsageInheritanceFactory) + registerFactory(OptInFileLevelFixFactories.optInUsageInheritanceErrorFactory) registerFactory(OptInFileLevelFixFactories.optInOverrideFactory) registerFactory(OptInFileLevelFixFactories.optInOverrideErrorFactory) registerFactory(OptInFixFactories.optInUsageFactory) + registerFactory(OptInFixFactories.optInToInheritanceFactory) registerFactory(OptInFixFactories.optInUsageErrorFactory) + registerFactory(OptInFixFactories.optInToInheritanceErrorFactory) registerFactory(OptInFixFactories.optInOverrideFactory) registerFactory(OptInFixFactories.optInOverrideErrorFactory) } diff --git a/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/OptInFileLevelFixFactories.kt b/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/OptInFileLevelFixFactories.kt index 2693a0ef1557..383055bc54dc 100644 --- a/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/OptInFileLevelFixFactories.kt +++ b/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/OptInFileLevelFixFactories.kt @@ -28,6 +28,14 @@ internal object OptInFileLevelFixFactories { createQuickFix(diagnostic) } + val optInUsageInheritanceFactory = KotlinQuickFixFactory.IntentionBased { diagnostic: KaFirDiagnostic.OptInToInheritance -> + createQuickFix(diagnostic) + } + + val optInUsageInheritanceErrorFactory = KotlinQuickFixFactory.IntentionBased { diagnostic: KaFirDiagnostic.OptInToInheritanceError -> + createQuickFix(diagnostic) + } + val optInOverrideFactory = KotlinQuickFixFactory.IntentionBased { diagnostic: KaFirDiagnostic.OptInOverride -> createQuickFix(diagnostic) } diff --git a/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/OptInFixFactories.kt b/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/OptInFixFactories.kt index 18c4773c9464..47d5a2f96b8e 100644 --- a/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/OptInFixFactories.kt +++ b/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/OptInFixFactories.kt @@ -36,6 +36,14 @@ internal object OptInFixFactories { createQuickFix(diagnostic) } + val optInToInheritanceFactory = KotlinQuickFixFactory.IntentionBased { diagnostic: KaFirDiagnostic.OptInToInheritance -> + createQuickFix(diagnostic) + } + + val optInToInheritanceErrorFactory = KotlinQuickFixFactory.IntentionBased { diagnostic: KaFirDiagnostic.OptInToInheritanceError -> + createQuickFix(diagnostic) + } + val optInOverrideFactory = KotlinQuickFixFactory.IntentionBased { diagnostic: KaFirDiagnostic.OptInOverride -> createQuickFix(diagnostic) } diff --git a/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/OptInFixUtils.kt b/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/OptInFixUtils.kt index b51062a20a71..20691ad2caf3 100644 --- a/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/OptInFixUtils.kt +++ b/plugins/kotlin/code-insight/fixes-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/fixes/OptInFixUtils.kt @@ -16,6 +16,8 @@ internal object OptInFixUtils { fun optInMarkerClassId(diagnostic: KaFirDiagnostic): ClassId? = when (diagnostic) { is KaFirDiagnostic.OptInUsage -> diagnostic.optInMarkerClassId is KaFirDiagnostic.OptInUsageError -> diagnostic.optInMarkerClassId + is KaFirDiagnostic.OptInToInheritance -> diagnostic.optInMarkerClassId + is KaFirDiagnostic.OptInToInheritanceError -> diagnostic.optInMarkerClassId is KaFirDiagnostic.OptInOverride -> diagnostic.optInMarkerClassId is KaFirDiagnostic.OptInOverrideError -> diagnostic.optInMarkerClassId else -> null diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/OptInFixesUtils.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/OptInFixesUtils.kt index 0970e215c417..8a48881e71b9 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/OptInFixesUtils.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/OptInFixesUtils.kt @@ -22,6 +22,8 @@ internal object OptInFixesUtils { fun annotationFqName(diagnostic: Diagnostic) = when (diagnostic.factory) { OPT_IN_USAGE -> OPT_IN_USAGE.cast(diagnostic).a OPT_IN_USAGE_ERROR -> OPT_IN_USAGE_ERROR.cast(diagnostic).a + OPT_IN_TO_INHERITANCE -> OPT_IN_TO_INHERITANCE.cast(diagnostic).a + OPT_IN_TO_INHERITANCE_ERROR -> OPT_IN_TO_INHERITANCE_ERROR.cast(diagnostic).a OPT_IN_OVERRIDE -> OPT_IN_OVERRIDE.cast(diagnostic).a OPT_IN_OVERRIDE_ERROR -> OPT_IN_OVERRIDE_ERROR.cast(diagnostic).a else -> null diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index 15a4e6315da3..37b47c76b6a9 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -677,6 +677,10 @@ class QuickFixRegistrar : QuickFixContributor { OPT_IN_USAGE.registerFactory(OptInFileLevelFixesFactory) OPT_IN_USAGE_ERROR.registerFactory(OptInFixesFactory) OPT_IN_USAGE_ERROR.registerFactory(OptInFileLevelFixesFactory) + OPT_IN_TO_INHERITANCE.registerFactory(OptInFixesFactory) + OPT_IN_TO_INHERITANCE.registerFactory(OptInFileLevelFixesFactory) + OPT_IN_TO_INHERITANCE_ERROR.registerFactory(OptInFixesFactory) + OPT_IN_TO_INHERITANCE_ERROR.registerFactory(OptInFileLevelFixesFactory) OPT_IN_OVERRIDE.registerFactory(OptInFixesFactory) OPT_IN_OVERRIDE.registerFactory(OptInFileLevelFixesFactory) OPT_IN_OVERRIDE_ERROR.registerFactory(OptInFixesFactory) diff --git a/plugins/kotlin/idea/tests/testData/quickfix/optIn/propagateOptIn8.kt b/plugins/kotlin/idea/tests/testData/quickfix/optIn/propagateOptIn8.kt index 3b1773e5f268..b4ab627030ed 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/optIn/propagateOptIn8.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/optIn/propagateOptIn8.kt @@ -1,6 +1,6 @@ // "Propagate 'SubclassOptInRequired(UnstableApi::class)' opt-in requirement to 'SomeImplementation'" "false" // IGNORE_K2 -// ERROR: This declaration needs opt-in. Its usage must be marked with '@UnstableApi' or '@OptIn(UnstableApi::class)' +// ERROR: This class or interface requires opt-in to be implemented. Its usage must be marked with '@UnstableApi', '@OptIn(UnstableApi::class)' or '@SubclassOptInRequired(UnstableApi::class)' // ACTION: Introduce import alias // ACTION: Opt in for 'UnstableApi' in containing file 'propagateOptIn8.kt' // ACTION: Opt in for 'UnstableApi' in module 'light_idea_test_case' diff --git a/plugins/kotlin/idea/tests/testData/quickfix/optIn/propagateOptIn8Fir.kt b/plugins/kotlin/idea/tests/testData/quickfix/optIn/propagateOptIn8Fir.kt index 59d9956559d9..51b01b92e177 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/optIn/propagateOptIn8Fir.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/optIn/propagateOptIn8Fir.kt @@ -1,6 +1,6 @@ // "Propagate 'SubclassOptInRequired(UnstableApi::class)' opt-in requirement to 'SomeImplementation'" "false" // IGNORE_K1 -// ERROR: This declaration needs opt-in. Its usage must be marked with '@UnstableApi' or '@OptIn(UnstableApi::class)' +// ERROR: This class or interface requires opt-in to be implemented. Its usage must be marked with '@UnstableApi', '@OptIn(UnstableApi::class)' or '@SubclassOptInRequired(UnstableApi::class)' // ACTION: Opt in for 'UnstableApi' in containing file 'propagateOptIn8Fir.kt' // ACTION: Opt in for 'UnstableApi' in module 'light_idea_test_case' // ACTION: Opt in for 'UnstableApi' on 'foo' diff --git a/plugins/kotlin/idea/tests/testData/quickfix/optIn/propagateSubclassOptInRequired2.kt b/plugins/kotlin/idea/tests/testData/quickfix/optIn/propagateSubclassOptInRequired2.kt index 3c9b2bfbbbd2..13cfb5eb1433 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/optIn/propagateSubclassOptInRequired2.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/optIn/propagateSubclassOptInRequired2.kt @@ -1,5 +1,5 @@ // "Propagate 'SubclassOptInRequired(A::class)' opt-in requirement to 'SomeImplementation'" "true" -// ERROR: This declaration needs opt-in. Its usage must be marked with '@B' or '@OptIn(B::class)' +// ERROR: This class or interface requires opt-in to be implemented. Its usage must be marked with '@B', '@OptIn(B::class)' or '@SubclassOptInRequired(B::class)' @file:OptIn(ExperimentalSubclassOptIn::class) @RequiresOptIn diff --git a/plugins/kotlin/idea/tests/testData/quickfix/optIn/propagateSubclassOptInRequired2.kt.after b/plugins/kotlin/idea/tests/testData/quickfix/optIn/propagateSubclassOptInRequired2.kt.after index c235256c1131..da8690566838 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/optIn/propagateSubclassOptInRequired2.kt.after +++ b/plugins/kotlin/idea/tests/testData/quickfix/optIn/propagateSubclassOptInRequired2.kt.after @@ -1,5 +1,5 @@ // "Propagate 'SubclassOptInRequired(A::class)' opt-in requirement to 'SomeImplementation'" "true" -// ERROR: This declaration needs opt-in. Its usage must be marked with '@B' or '@OptIn(B::class)' +// ERROR: This class or interface requires opt-in to be implemented. Its usage must be marked with '@B', '@OptIn(B::class)' or '@SubclassOptInRequired(B::class)' @file:OptIn(ExperimentalSubclassOptIn::class) @RequiresOptIn diff --git a/plugins/kotlin/idea/tests/testData/quickfix/optIn/scripts/general/propagateOptIn8.kts b/plugins/kotlin/idea/tests/testData/quickfix/optIn/scripts/general/propagateOptIn8.kts index 005051a79a4e..949b1f01b6d2 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/optIn/scripts/general/propagateOptIn8.kts +++ b/plugins/kotlin/idea/tests/testData/quickfix/optIn/scripts/general/propagateOptIn8.kts @@ -1,5 +1,5 @@ // "Propagate 'SubclassOptInRequired(UnstableApi::class)' opt-in requirement to 'LocalClass'" "false" -// ERROR: This declaration needs opt-in. Its usage must be marked with '@PropagateOptIn8.UnstableApi' or '@OptIn(PropagateOptIn8.UnstableApi::class)' +// ERROR: This class or interface requires opt-in to be implemented. Its usage must be marked with '@PropagateOptIn8.UnstableApi', '@OptIn(PropagateOptIn8.UnstableApi::class)' or '@SubclassOptInRequired(PropagateOptIn8.UnstableApi::class)' // ACTION: Add full qualifier // ACTION: Introduce import alias // ACTION: Opt in for 'UnstableApi' in containing file 'propagateOptIn8.kts' diff --git a/plugins/kotlin/idea/tests/testData/quickfix/optIn/scripts/general/propagateSubclassOptInRequired2.kts b/plugins/kotlin/idea/tests/testData/quickfix/optIn/scripts/general/propagateSubclassOptInRequired2.kts index a2151c3c9ca5..144f3fd5818a 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/optIn/scripts/general/propagateSubclassOptInRequired2.kts +++ b/plugins/kotlin/idea/tests/testData/quickfix/optIn/scripts/general/propagateSubclassOptInRequired2.kts @@ -7,7 +7,7 @@ // ACTION: Opt in for 'A' in module 'light_idea_test_case' // ACTION: Opt in for 'A' on 'SomeImplementation' // ACTION: Propagate 'SubclassOptInRequired(A::class)' opt-in requirement to 'SomeImplementation' -// ERROR: This declaration needs opt-in. Its usage must be marked with '@PropagateSubclassOptInRequired2.B' or '@OptIn(PropagateSubclassOptInRequired2.B::class)' +// ERROR: This class or interface requires opt-in to be implemented. Its usage must be marked with '@PropagateSubclassOptInRequired2.B', '@OptIn(PropagateSubclassOptInRequired2.B::class)' or '@SubclassOptInRequired(PropagateSubclassOptInRequired2.B::class)' // RUNTIME_WITH_SCRIPT_RUNTIME @file:OptIn(ExperimentalSubclassOptIn::class) diff --git a/plugins/kotlin/idea/tests/testData/quickfix/optIn/scripts/general/propagateSubclassOptInRequired2.kts.after b/plugins/kotlin/idea/tests/testData/quickfix/optIn/scripts/general/propagateSubclassOptInRequired2.kts.after index fe8152baa667..0681ab68e581 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/optIn/scripts/general/propagateSubclassOptInRequired2.kts.after +++ b/plugins/kotlin/idea/tests/testData/quickfix/optIn/scripts/general/propagateSubclassOptInRequired2.kts.after @@ -7,7 +7,7 @@ // ACTION: Opt in for 'A' in module 'light_idea_test_case' // ACTION: Opt in for 'A' on 'SomeImplementation' // ACTION: Propagate 'SubclassOptInRequired(A::class)' opt-in requirement to 'SomeImplementation' -// ERROR: This declaration needs opt-in. Its usage must be marked with '@PropagateSubclassOptInRequired2.B' or '@OptIn(PropagateSubclassOptInRequired2.B::class)' +// ERROR: This class or interface requires opt-in to be implemented. Its usage must be marked with '@PropagateSubclassOptInRequired2.B', '@OptIn(PropagateSubclassOptInRequired2.B::class)' or '@SubclassOptInRequired(PropagateSubclassOptInRequired2.B::class)' // RUNTIME_WITH_SCRIPT_RUNTIME @file:OptIn(ExperimentalSubclassOptIn::class) diff --git a/plugins/kotlin/jvm-debugger/evaluation/k1/src/org/jetbrains/kotlin/idea/debugger/evaluate/K1KotlinCodeFragmentCompiler.kt b/plugins/kotlin/jvm-debugger/evaluation/k1/src/org/jetbrains/kotlin/idea/debugger/evaluate/K1KotlinCodeFragmentCompiler.kt index eb2a0e07b416..0181f7be7e42 100644 --- a/plugins/kotlin/jvm-debugger/evaluation/k1/src/org/jetbrains/kotlin/idea/debugger/evaluate/K1KotlinCodeFragmentCompiler.kt +++ b/plugins/kotlin/jvm-debugger/evaluation/k1/src/org/jetbrains/kotlin/idea/debugger/evaluate/K1KotlinCodeFragmentCompiler.kt @@ -117,6 +117,7 @@ class K1KotlinCodeFragmentCompiler : KotlinCodeFragmentCompiler { private val IGNORED_DIAGNOSTICS: Set> = Errors.INVISIBLE_REFERENCE_DIAGNOSTICS + setOf( Errors.OPT_IN_USAGE_ERROR, + Errors.OPT_IN_TO_INHERITANCE_ERROR, Errors.MISSING_DEPENDENCY_SUPERCLASS, Errors.IR_WITH_UNSTABLE_ABI_COMPILED_CLASS, Errors.FIR_COMPILED_CLASS,