Add applicability checks & tests for SubclassOptInRequired
This commit is contained in:
committed by
teamcity
parent
66e710704a
commit
80a9f22052
+7
@@ -1041,6 +1041,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.SUBCLASS_OPT_IN_INAPPLICABLE) { firDiagnostic ->
|
||||
SubclassOptInInapplicableImpl(
|
||||
firDiagnostic.a,
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE) { firDiagnostic ->
|
||||
ExposedTypealiasExpandedTypeImpl(
|
||||
firDiagnostic.a,
|
||||
|
||||
+5
@@ -751,6 +751,11 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = OptInMarkerOnOverrideWarning::class
|
||||
}
|
||||
|
||||
abstract class SubclassOptInInapplicable : KtFirDiagnostic<KtAnnotationEntry>() {
|
||||
override val diagnosticClass get() = SubclassOptInInapplicable::class
|
||||
abstract val target: String
|
||||
}
|
||||
|
||||
abstract class ExposedTypealiasExpandedType : KtFirDiagnostic<KtNamedDeclaration>() {
|
||||
override val diagnosticClass get() = ExposedTypealiasExpandedType::class
|
||||
abstract val elementVisibility: EffectiveVisibility
|
||||
|
||||
+6
@@ -902,6 +902,12 @@ internal class OptInMarkerOnOverrideWarningImpl(
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.OptInMarkerOnOverrideWarning(), KtAbstractFirDiagnostic<KtAnnotationEntry>
|
||||
|
||||
internal class SubclassOptInInapplicableImpl(
|
||||
override val target: String,
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.SubclassOptInInapplicable(), KtAbstractFirDiagnostic<KtAnnotationEntry>
|
||||
|
||||
internal class ExposedTypealiasExpandedTypeImpl(
|
||||
override val elementVisibility: EffectiveVisibility,
|
||||
override val restrictingDeclaration: KtSymbol,
|
||||
|
||||
+6
@@ -37548,6 +37548,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/overrideInAnonymousObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("subClassOptInModality.kt")
|
||||
public void testSubClassOptInModality() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/subClassOptInModality.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("subClassOptInRequired.kt")
|
||||
public void testSubClassOptInRequired() throws Exception {
|
||||
|
||||
+6
@@ -37548,6 +37548,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/overrideInAnonymousObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("subClassOptInModality.kt")
|
||||
public void testSubClassOptInModality() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/subClassOptInModality.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("subClassOptInRequired.kt")
|
||||
public void testSubClassOptInRequired() throws Exception {
|
||||
|
||||
+6
@@ -37548,6 +37548,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/overrideInAnonymousObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("subClassOptInModality.kt")
|
||||
public void testSubClassOptInModality() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/subClassOptInModality.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("subClassOptInRequired.kt")
|
||||
public void testSubClassOptInRequired() throws Exception {
|
||||
|
||||
+4
-2
@@ -15,8 +15,6 @@ import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
|
||||
import org.jetbrains.kotlin.diagnostics.deprecationError2
|
||||
import org.jetbrains.kotlin.diagnostics.error0
|
||||
import org.jetbrains.kotlin.fir.FirModuleData
|
||||
import org.jetbrains.kotlin.fir.PrivateForInline
|
||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.*
|
||||
@@ -328,6 +326,10 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
}
|
||||
val OPT_IN_MARKER_ON_OVERRIDE by error<KtAnnotationEntry>()
|
||||
val OPT_IN_MARKER_ON_OVERRIDE_WARNING by warning<KtAnnotationEntry>()
|
||||
|
||||
val SUBCLASS_OPT_IN_INAPPLICABLE by error<KtAnnotationEntry> {
|
||||
parameter<String>("target")
|
||||
}
|
||||
}
|
||||
|
||||
val EXPOSED_VISIBILITY by object : DiagnosticGroup("Exposed visibility") {
|
||||
|
||||
@@ -271,6 +271,7 @@ object FirErrors {
|
||||
val OPT_IN_MARKER_ON_WRONG_TARGET by error1<KtAnnotationEntry, String>()
|
||||
val OPT_IN_MARKER_ON_OVERRIDE by error0<KtAnnotationEntry>()
|
||||
val OPT_IN_MARKER_ON_OVERRIDE_WARNING by warning0<KtAnnotationEntry>()
|
||||
val SUBCLASS_OPT_IN_INAPPLICABLE by error1<KtAnnotationEntry, String>()
|
||||
|
||||
// Exposed visibility
|
||||
val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3<KtNamedDeclaration, EffectiveVisibility, FirBasedSymbol<*>, EffectiveVisibility>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
|
||||
+55
-11
@@ -8,18 +8,28 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||
import org.jetbrains.kotlin.KtSourceElement
|
||||
import org.jetbrains.kotlin.config.AnalysisFlags
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.extractClassesFromArgument
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirOptInUsageBaseChecker.loadExperimentalityForMarkerAnnotation
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.extractClassFromArgument
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.modality
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.findArgumentByName
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isFun
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.expressions.arguments
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||
import org.jetbrains.kotlin.resolve.checkers.OptInNames
|
||||
import org.jetbrains.kotlin.resolve.checkers.OptInNames.USE_EXPERIMENTAL_ANNOTATION_CLASS
|
||||
|
||||
object FirOptInAnnotationCallChecker : FirAnnotationCallChecker() {
|
||||
override fun check(expression: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
@@ -27,6 +37,7 @@ object FirOptInAnnotationCallChecker : FirAnnotationCallChecker() {
|
||||
val classId = lookupTag.classId
|
||||
val isRequiresOptIn = classId == OptInNames.REQUIRES_OPT_IN_CLASS_ID
|
||||
val isOptIn = classId == OptInNames.OPT_IN_CLASS_ID
|
||||
val isSubclassOptIn = classId == OptInNames.SUBCLASS_OPT_IN_REQUIRED_CLASS_ID
|
||||
if (isRequiresOptIn || isOptIn) {
|
||||
checkOptInIsEnabled(expression.source, context, reporter)
|
||||
if (isOptIn) {
|
||||
@@ -34,21 +45,36 @@ object FirOptInAnnotationCallChecker : FirAnnotationCallChecker() {
|
||||
if (arguments.isEmpty()) {
|
||||
reporter.reportOn(expression.source, FirErrors.OPT_IN_WITHOUT_ARGUMENTS, context)
|
||||
} else {
|
||||
val annotationClasses = expression.findArgumentByName(OptInNames.USE_EXPERIMENTAL_ANNOTATION_CLASS)
|
||||
val annotationClasses = expression.findArgumentByName(USE_EXPERIMENTAL_ANNOTATION_CLASS)
|
||||
for (classSymbol in annotationClasses?.extractClassesFromArgument().orEmpty()) {
|
||||
with(FirOptInUsageBaseChecker) {
|
||||
if (classSymbol.loadExperimentalityForMarkerAnnotation() == null) {
|
||||
reporter.reportOn(
|
||||
expression.source,
|
||||
FirErrors.OPT_IN_ARGUMENT_IS_NOT_MARKER,
|
||||
classSymbol.classId.asSingleFqName(),
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
checkOptInArgumentIsMarker(classSymbol, expression.source, reporter, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (isSubclassOptIn) {
|
||||
val declaration = context.containingDeclarations.lastOrNull() as? FirClass
|
||||
if (declaration != null) {
|
||||
val kind = declaration.classKind
|
||||
if (kind == ClassKind.ENUM_CLASS || kind == ClassKind.OBJECT || kind == ClassKind.ANNOTATION_CLASS) {
|
||||
reporter.reportOn(expression.source, FirErrors.SUBCLASS_OPT_IN_INAPPLICABLE, kind.toString(), context)
|
||||
return
|
||||
}
|
||||
val modality = declaration.modality()
|
||||
if (modality == Modality.FINAL || modality == Modality.SEALED) {
|
||||
reporter.reportOn(expression.source, FirErrors.SUBCLASS_OPT_IN_INAPPLICABLE, "$modality $kind", context)
|
||||
return
|
||||
}
|
||||
if (declaration.isFun) {
|
||||
reporter.reportOn(expression.source, FirErrors.SUBCLASS_OPT_IN_INAPPLICABLE, "fun interface", context)
|
||||
return
|
||||
}
|
||||
if (declaration.isLocal) {
|
||||
reporter.reportOn(expression.source, FirErrors.SUBCLASS_OPT_IN_INAPPLICABLE, "local $kind", context)
|
||||
return
|
||||
}
|
||||
}
|
||||
val classSymbol = expression.findArgumentByName(USE_EXPERIMENTAL_ANNOTATION_CLASS)?.extractClassFromArgument() ?: return
|
||||
checkOptInArgumentIsMarker(classSymbol, expression.source, reporter, context)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,4 +91,22 @@ object FirOptInAnnotationCallChecker : FirAnnotationCallChecker() {
|
||||
reporter.reportOn(element, FirErrors.OPT_IN_IS_NOT_ENABLED, context)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkOptInArgumentIsMarker(
|
||||
classSymbol: FirRegularClassSymbol,
|
||||
source: KtSourceElement?,
|
||||
reporter: DiagnosticReporter,
|
||||
context: CheckerContext
|
||||
) {
|
||||
with(FirOptInUsageBaseChecker) {
|
||||
if (classSymbol.loadExperimentalityForMarkerAnnotation() == null) {
|
||||
reporter.reportOn(
|
||||
source,
|
||||
FirErrors.OPT_IN_ARGUMENT_IS_NOT_MARKER,
|
||||
classSymbol.classId.asSingleFqName(),
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -469,6 +469,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SETTER_VISIBILITY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SINGLETON_IN_SUPERTYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SMARTCAST_IMPOSSIBLE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SPREAD_OF_NULLABLE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUBCLASS_OPT_IN_INAPPLICABLE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPES_FOR_ANNOTATION_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_APPEARS_TWICE
|
||||
@@ -865,6 +866,8 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
OPT_IN_MARKER_ON_OVERRIDE_WARNING,
|
||||
"Opt-in requirement marker annotation on override makes no sense without the same marker on base declaration"
|
||||
)
|
||||
map.put(SUBCLASS_OPT_IN_INAPPLICABLE, "@SubclassOptInRequired is inapplicable on {0}", STRING)
|
||||
|
||||
map.put(NOT_A_CLASS, "Not a class")
|
||||
map.put(
|
||||
WRONG_EXTENSION_FUNCTION_TYPE,
|
||||
|
||||
@@ -11,7 +11,6 @@ import com.intellij.psi.impl.source.tree.LeafPsiElement;
|
||||
import kotlin.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.config.LanguageFeature;
|
||||
import org.jetbrains.kotlin.config.LanguageVersion;
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.DeclarationWithDiagnosticComponents;
|
||||
@@ -27,7 +26,6 @@ import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.VarianceConflictDiagnosticData;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableTypeConstructor;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.WrongResolutionToClassifier;
|
||||
import org.jetbrains.kotlin.resolve.calls.util.BuilderLambdaLabelingInfo;
|
||||
@@ -43,7 +41,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.kotlin.config.LanguageFeature.ReportTypeVarianceConflictOnQualifierArguments;
|
||||
import static org.jetbrains.kotlin.diagnostics.ClassicPositioningStrategies.ACTUAL_DECLARATION_NAME;
|
||||
import static org.jetbrains.kotlin.diagnostics.ClassicPositioningStrategies.INCOMPATIBLE_DECLARATION;
|
||||
import static org.jetbrains.kotlin.diagnostics.PositioningStrategies.*;
|
||||
@@ -339,6 +336,8 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtAnnotationEntry> OPT_IN_MARKER_ON_OVERRIDE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtAnnotationEntry> OPT_IN_MARKER_ON_OVERRIDE_WARNING = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
DiagnosticFactory1<KtAnnotationEntry, String> SUBCLASS_OPT_IN_INAPPLICABLE = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
DiagnosticFactory1<PsiElement, String> EXPERIMENTAL_UNSIGNED_LITERALS = DiagnosticFactory1.create(WARNING);
|
||||
DiagnosticFactory1<PsiElement, String> EXPERIMENTAL_UNSIGNED_LITERALS_ERROR = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
|
||||
+2
@@ -180,6 +180,8 @@ public class DefaultErrorMessages {
|
||||
MAP.put(OPT_IN_MARKER_ON_OVERRIDE, "Opt-in requirement marker annotation on override requires the same marker on base declaration");
|
||||
MAP.put(OPT_IN_MARKER_ON_OVERRIDE_WARNING, "Opt-in requirement marker annotation on override makes no sense without the same marker on base declaration");
|
||||
|
||||
MAP.put(SUBCLASS_OPT_IN_INAPPLICABLE, "@SubclassOptInRequired is inapplicable on {0}", STRING);
|
||||
|
||||
MAP.put(EXPERIMENTAL_UNSIGNED_LITERALS, "{0}", STRING);
|
||||
MAP.put(EXPERIMENTAL_UNSIGNED_LITERALS_ERROR, "{0}", STRING);
|
||||
|
||||
|
||||
+54
-2
@@ -8,14 +8,15 @@ package org.jetbrains.kotlin.resolve.checkers
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.*
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.KtAnnotated
|
||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.AdditionalAnnotationChecker
|
||||
import org.jetbrains.kotlin.resolve.AnnotationChecker
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
@@ -47,6 +48,11 @@ class OptInMarkerDeclarationAnnotationChecker(private val module: ModuleDescript
|
||||
.safeAs<ArrayValue>()?.value.orEmpty()
|
||||
checkOptInUsage(annotationClasses, trace, entry)
|
||||
}
|
||||
OptInNames.SUBCLASS_OPT_IN_REQUIRED_FQ_NAME -> {
|
||||
val annotationClass =
|
||||
annotation.allValueArguments[OptInNames.USE_EXPERIMENTAL_ANNOTATION_CLASS]
|
||||
checkSubclassOptInUsage(annotated, listOfNotNull(annotationClass), trace, entry)
|
||||
}
|
||||
in OptInNames.REQUIRES_OPT_IN_FQ_NAMES -> {
|
||||
hasOptIn = true
|
||||
}
|
||||
@@ -89,7 +95,53 @@ class OptInMarkerDeclarationAnnotationChecker(private val module: ModuleDescript
|
||||
trace.report(Errors.OPT_IN_WITHOUT_ARGUMENTS.on(entry))
|
||||
return
|
||||
}
|
||||
checkArgumentsAreMarkers(annotationClasses, trace, entry)
|
||||
}
|
||||
|
||||
private fun checkSubclassOptInUsage(
|
||||
annotated: KtAnnotated?,
|
||||
annotationClasses: List<ConstantValue<*>>,
|
||||
trace: BindingTrace,
|
||||
entry: KtAnnotationEntry
|
||||
) {
|
||||
when (annotated) {
|
||||
is KtAnnotatedExpression -> {
|
||||
if (annotated.baseExpression is KtObjectLiteralExpression) {
|
||||
trace.report(Errors.SUBCLASS_OPT_IN_INAPPLICABLE.on(entry, "object"))
|
||||
}
|
||||
return
|
||||
}
|
||||
is KtClassOrObject -> {
|
||||
val descriptor = trace[BindingContext.CLASS, annotated]
|
||||
if (descriptor != null) {
|
||||
val kind = descriptor.kind
|
||||
if (kind == ClassKind.OBJECT || kind == ClassKind.ENUM_CLASS || kind == ClassKind.ANNOTATION_CLASS) {
|
||||
trace.report(Errors.SUBCLASS_OPT_IN_INAPPLICABLE.on(entry, kind.toString()))
|
||||
return
|
||||
}
|
||||
if (kind != ClassKind.ENUM_ENTRY) {
|
||||
// ^ We don't report anything on enum entries because it's anyway inapplicable target
|
||||
val modality = descriptor.modality
|
||||
if (modality != Modality.ABSTRACT && modality != Modality.OPEN) {
|
||||
trace.report(Errors.SUBCLASS_OPT_IN_INAPPLICABLE.on(entry, "$modality $kind"))
|
||||
return
|
||||
}
|
||||
if (descriptor.isFun) {
|
||||
trace.report(Errors.SUBCLASS_OPT_IN_INAPPLICABLE.on(entry, "fun interface"))
|
||||
return
|
||||
}
|
||||
if (annotated.isLocal) {
|
||||
trace.report(Errors.SUBCLASS_OPT_IN_INAPPLICABLE.on(entry, "local $kind"))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
checkArgumentsAreMarkers(annotationClasses, trace, entry)
|
||||
}
|
||||
|
||||
private fun checkArgumentsAreMarkers(annotationClasses: List<ConstantValue<*>>, trace: BindingTrace, entry: KtAnnotationEntry) {
|
||||
for (annotationClass in annotationClasses) {
|
||||
val classDescriptor =
|
||||
(annotationClass as? KClassValue)?.getArgumentType(module)?.constructor?.declarationDescriptor as? ClassDescriptor
|
||||
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
// FIR_IDENTICAL
|
||||
@RequiresOptIn
|
||||
annotation class Marker
|
||||
|
||||
// Error!
|
||||
<!SUBCLASS_OPT_IN_INAPPLICABLE!>@SubclassOptInRequired(Marker::class)<!>
|
||||
class Final
|
||||
|
||||
// Error!
|
||||
<!SUBCLASS_OPT_IN_INAPPLICABLE!>@SubclassOptInRequired(Marker::class)<!>
|
||||
sealed class SealedClass {
|
||||
<!SUBCLASS_OPT_IN_INAPPLICABLE!>@SubclassOptInRequired(Marker::class)<!>
|
||||
object O : SealedClass()
|
||||
}
|
||||
|
||||
// Error!
|
||||
<!SUBCLASS_OPT_IN_INAPPLICABLE!>@SubclassOptInRequired(Marker::class)<!>
|
||||
sealed interface SealedInterface
|
||||
|
||||
// Error!
|
||||
<!SUBCLASS_OPT_IN_INAPPLICABLE!>@SubclassOptInRequired(Marker::class)<!>
|
||||
fun interface FunInterface {
|
||||
fun doIt()
|
||||
}
|
||||
|
||||
sealed class Normal
|
||||
|
||||
// Ok!
|
||||
@SubclassOptInRequired(Marker::class)
|
||||
open class NormalOpen : Normal()
|
||||
|
||||
// Ok!
|
||||
@SubclassOptInRequired(Marker::class)
|
||||
abstract class NormalAbstract : Normal()
|
||||
|
||||
// Error!
|
||||
<!SUBCLASS_OPT_IN_INAPPLICABLE!>@SubclassOptInRequired(Marker::class)<!>
|
||||
sealed class ErrorSealed : Normal()
|
||||
|
||||
// Error!
|
||||
<!SUBCLASS_OPT_IN_INAPPLICABLE!>@SubclassOptInRequired(Marker::class)<!>
|
||||
class ErrorFinal : Normal()
|
||||
|
||||
// Ok!
|
||||
@SubclassOptInRequired(Marker::class)
|
||||
abstract class Abstract
|
||||
|
||||
// Error! Should be replaced with OptIn
|
||||
<!SUBCLASS_OPT_IN_INAPPLICABLE!>@SubclassOptInRequired(Marker::class)<!>
|
||||
class Derived1 : Abstract()
|
||||
|
||||
// Ok!
|
||||
@OptIn(Marker::class)
|
||||
class Derived2 : Abstract()
|
||||
|
||||
// Error!
|
||||
<!SUBCLASS_OPT_IN_INAPPLICABLE!>@SubclassOptInRequired(Marker::class)<!>
|
||||
object Obj
|
||||
|
||||
// Error!
|
||||
<!SUBCLASS_OPT_IN_INAPPLICABLE!>@SubclassOptInRequired(Marker::class)<!>
|
||||
enum class E1 {
|
||||
FIRST;
|
||||
}
|
||||
|
||||
enum class E2 {
|
||||
// Error!
|
||||
<!WRONG_ANNOTATION_TARGET!>@SubclassOptInRequired(Marker::class)<!>
|
||||
SECOND;
|
||||
}
|
||||
|
||||
// Error!
|
||||
<!SUBCLASS_OPT_IN_INAPPLICABLE!>@SubclassOptInRequired(Marker::class)<!>
|
||||
annotation class A
|
||||
|
||||
// Local stuff
|
||||
fun foo() {
|
||||
// Error!
|
||||
val v = <!SUBCLASS_OPT_IN_INAPPLICABLE!>@SubclassOptInRequired(Marker::class)<!> object : Any() {
|
||||
|
||||
}
|
||||
|
||||
// Error!
|
||||
<!SUBCLASS_OPT_IN_INAPPLICABLE!>@SubclassOptInRequired(Marker::class)<!>
|
||||
open class OpenLocal
|
||||
|
||||
// Ok!
|
||||
@OptIn(Marker::class)
|
||||
class DerivedLocal : OpenLocal()
|
||||
|
||||
// Error!
|
||||
<!SUBCLASS_OPT_IN_INAPPLICABLE!>@SubclassOptInRequired(Marker::class)<!>
|
||||
class Local
|
||||
}
|
||||
|
||||
// Common rules with OptIn
|
||||
|
||||
annotation class Simple
|
||||
|
||||
// Error! Opt-in marker required
|
||||
<!OPT_IN_ARGUMENT_IS_NOT_MARKER!>@SubclassOptInRequired(Simple::class)<!>
|
||||
open class Some
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
package
|
||||
|
||||
public fun foo(): kotlin.Unit
|
||||
|
||||
@kotlin.SubclassOptInRequired(markerClass = Marker::class) public final annotation class A : kotlin.Annotation {
|
||||
public constructor A()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.SubclassOptInRequired(markerClass = Marker::class) public abstract class Abstract {
|
||||
public constructor Abstract()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.SubclassOptInRequired(markerClass = Marker::class) public final class Derived1 : Abstract {
|
||||
public constructor Derived1()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.OptIn(markerClass = {Marker::class}) public final class Derived2 : Abstract {
|
||||
public constructor Derived2()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.SubclassOptInRequired(markerClass = Marker::class) public final enum class E1 : kotlin.Enum<E1> {
|
||||
enum entry FIRST
|
||||
|
||||
private constructor E1()
|
||||
@kotlin.internal.IntrinsicConstEvaluation public final override /*1*/ /*fake_override*/ val name: kotlin.String
|
||||
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
|
||||
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
|
||||
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: E1): kotlin.Int
|
||||
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
|
||||
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<E1!>!
|
||||
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): E1
|
||||
public final /*synthesized*/ fun values(): kotlin.Array<E1>
|
||||
}
|
||||
|
||||
public final enum class E2 : kotlin.Enum<E2> {
|
||||
@kotlin.SubclassOptInRequired(markerClass = Marker::class) enum entry SECOND
|
||||
|
||||
private constructor E2()
|
||||
@kotlin.internal.IntrinsicConstEvaluation public final override /*1*/ /*fake_override*/ val name: kotlin.String
|
||||
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
|
||||
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
|
||||
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: E2): kotlin.Int
|
||||
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
|
||||
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<E2!>!
|
||||
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): E2
|
||||
public final /*synthesized*/ fun values(): kotlin.Array<E2>
|
||||
}
|
||||
|
||||
@kotlin.SubclassOptInRequired(markerClass = Marker::class) public final class ErrorFinal : Normal {
|
||||
public constructor ErrorFinal()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.SubclassOptInRequired(markerClass = Marker::class) public sealed class ErrorSealed : Normal {
|
||||
protected constructor ErrorSealed()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.SubclassOptInRequired(markerClass = Marker::class) public final class Final {
|
||||
public constructor Final()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.SubclassOptInRequired(markerClass = Marker::class) public fun interface FunInterface {
|
||||
public abstract fun doIt(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.RequiresOptIn public final annotation class Marker : kotlin.Annotation {
|
||||
public constructor Marker()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public sealed class Normal {
|
||||
protected constructor Normal()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.SubclassOptInRequired(markerClass = Marker::class) public abstract class NormalAbstract : Normal {
|
||||
public constructor NormalAbstract()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.SubclassOptInRequired(markerClass = Marker::class) public open class NormalOpen : Normal {
|
||||
public constructor NormalOpen()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.SubclassOptInRequired(markerClass = Marker::class) public object Obj {
|
||||
private constructor Obj()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.SubclassOptInRequired(markerClass = Marker::class) public sealed class SealedClass {
|
||||
protected constructor SealedClass()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
@kotlin.SubclassOptInRequired(markerClass = Marker::class) public object O : SealedClass {
|
||||
private constructor O()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
@kotlin.SubclassOptInRequired(markerClass = Marker::class) public sealed interface SealedInterface {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final annotation class Simple : kotlin.Annotation {
|
||||
public constructor Simple()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.SubclassOptInRequired(markerClass = Simple::class) public open class Some {
|
||||
public constructor Some()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
Generated
+6
@@ -37638,6 +37638,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/overrideInAnonymousObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("subClassOptInModality.kt")
|
||||
public void testSubClassOptInModality() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/subClassOptInModality.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("subClassOptInRequired.kt")
|
||||
public void testSubClassOptInRequired() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user