K1: report errors related to SubClassOptInRequired annotation

Related to KT-41886
This commit is contained in:
Mikhail Glukhikh
2022-07-12 14:55:35 +02:00
committed by teamcity
parent 84291181af
commit c67c5cad27
11 changed files with 261 additions and 36 deletions
@@ -37548,6 +37548,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/overrideInAnonymousObject.kt");
}
@Test
@TestMetadata("subClassOptInRequired.kt")
public void testSubClassOptInRequired() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/subClassOptInRequired.kt");
}
@Test
@TestMetadata("topLevel.kt")
public void testTopLevel() throws Exception {
@@ -37548,6 +37548,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/overrideInAnonymousObject.kt");
}
@Test
@TestMetadata("subClassOptInRequired.kt")
public void testSubClassOptInRequired() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/subClassOptInRequired.kt");
}
@Test
@TestMetadata("topLevel.kt")
public void testTopLevel() throws Exception {
@@ -37548,6 +37548,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/overrideInAnonymousObject.kt");
}
@Test
@TestMetadata("subClassOptInRequired.kt")
public void testSubClassOptInRequired() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/subClassOptInRequired.kt");
}
@Test
@TestMetadata("topLevel.kt")
public void testTopLevel() throws Exception {
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.config.AnalysisFlags
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory2
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.diagnostics.reportDiagnosticOnce
@@ -41,6 +42,7 @@ import org.jetbrains.kotlin.resolve.checkers.OptInNames.OPT_IN_FQ_NAME
import org.jetbrains.kotlin.resolve.checkers.OptInNames.OPT_IN_FQ_NAMES
import org.jetbrains.kotlin.resolve.checkers.OptInNames.REQUIRES_OPT_IN_FQ_NAME
import org.jetbrains.kotlin.resolve.checkers.OptInNames.REQUIRES_OPT_IN_FQ_NAMES
import org.jetbrains.kotlin.resolve.checkers.OptInNames.SUBCLASS_OPT_IN_REQUIRED_FQ_NAME
import org.jetbrains.kotlin.resolve.checkers.OptInNames.USE_EXPERIMENTAL_ANNOTATION_CLASS
import org.jetbrains.kotlin.resolve.checkers.OptInNames.WAS_EXPERIMENTAL_FQ_NAME
import org.jetbrains.kotlin.resolve.constants.ArrayValue
@@ -84,7 +86,9 @@ class OptInUsageChecker(project: Project) : CallChecker {
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
val resultingDescriptor = resolvedCall.resultingDescriptor
val optIns = resultingDescriptor.loadOptIns(moduleAnnotationsResolver, context.languageVersionSettings)
val bindingContext = context.trace.bindingContext
val languageVersionSettings = context.languageVersionSettings
val optIns = resultingDescriptor.loadOptIns(moduleAnnotationsResolver, bindingContext, languageVersionSettings)
if (resultingDescriptor is FunctionDescriptor &&
resultingDescriptor.kind == CallableMemberDescriptor.Kind.SYNTHESIZED
) {
@@ -92,7 +96,7 @@ class OptInUsageChecker(project: Project) : CallChecker {
if (propertyDescriptor != null) {
reportNotAllowedOptIns(
optIns + propertyDescriptor.loadOptIns(
moduleAnnotationsResolver, context.languageVersionSettings
moduleAnnotationsResolver, bindingContext, languageVersionSettings
), reportOn, context
)
return
@@ -101,9 +105,9 @@ class OptInUsageChecker(project: Project) : CallChecker {
if (resultingDescriptor is SamConstructorDescriptor) {
// KT-47708 special case (warning only)
val methodDescriptor = resultingDescriptor.getSingleAbstractMethod()
val samOptIns = methodDescriptor.loadOptIns(moduleAnnotationsResolver, context.languageVersionSettings)
val samOptIns = methodDescriptor.loadOptIns(moduleAnnotationsResolver, bindingContext, languageVersionSettings)
.map { (fqName, _, message) ->
OptInDescription(fqName, OptInDescription.Severity.WARNING, message)
OptInDescription(fqName, OptInDescription.Severity.WARNING, message, subclassesOnly = false)
}
reportNotAllowedOptIns(samOptIns, reportOn, context)
}
@@ -162,8 +166,8 @@ class OptInUsageChecker(project: Project) : CallChecker {
trace: BindingTrace,
diagnostics: OptInReporterMultiplexer
) {
for ((annotationFqName, severity, message) in descriptions) {
if (!element.isOptInAllowed(annotationFqName, languageVersionSettings, trace.bindingContext)) {
for ((annotationFqName, severity, message, subclassesOnly) in descriptions) {
if (!element.isOptInAllowed(annotationFqName, languageVersionSettings, trace.bindingContext, subclassesOnly)) {
val diagnostic = when (severity) {
OptInDescription.Severity.WARNING -> diagnostics.warning
OptInDescription.Severity.ERROR -> diagnostics.error
@@ -176,10 +180,12 @@ class OptInUsageChecker(project: Project) : CallChecker {
fun DeclarationDescriptor.loadOptIns(
moduleAnnotationsResolver: ModuleAnnotationsResolver,
context: BindingContext,
languageVersionSettings: LanguageVersionSettings,
visited: MutableSet<DeclarationDescriptor> = mutableSetOf(),
useFutureError: Boolean = false,
useMarkersFromContainer: Boolean = true,
fromSupertype: Boolean = false,
): Set<OptInDescription> {
if (!visited.add(this)) return emptySet()
val result = SmartSet.create<OptInDescription>()
@@ -188,6 +194,7 @@ class OptInUsageChecker(project: Project) : CallChecker {
result.addAll(
overridden.loadOptIns(
moduleAnnotationsResolver,
context,
languageVersionSettings,
visited,
useFutureError = !languageVersionSettings.supportsFeature(LanguageFeature.OptInContagiousSignatures),
@@ -197,7 +204,7 @@ class OptInUsageChecker(project: Project) : CallChecker {
if (useMarkersFromContainer) {
(containingDeclaration as? ClassDescriptor)?.let {
result.addAll(
it.loadOptIns(moduleAnnotationsResolver, languageVersionSettings, visited, useFutureError)
it.loadOptIns(moduleAnnotationsResolver, context, languageVersionSettings, visited, useFutureError)
)
}
}
@@ -206,23 +213,26 @@ class OptInUsageChecker(project: Project) : CallChecker {
}
for (annotation in annotations) {
result.addIfNotNull(annotation.annotationClass?.loadOptInForMarkerAnnotation(useFutureError))
result.addIfNotNull(
annotation.annotationClass?.loadOptInForMarkerAnnotation(useFutureError)
?: if (fromSupertype) annotation.loadSubclassOptInRequired(context) else null
)
}
if (this is CallableDescriptor && this !is ClassConstructorDescriptor) {
result.addAll(
returnType.loadOptIns(moduleAnnotationsResolver, languageVersionSettings, visited)
returnType.loadOptIns(moduleAnnotationsResolver, context, languageVersionSettings, visited)
)
result.addAll(
extensionReceiverParameter?.type.loadOptIns(
moduleAnnotationsResolver, languageVersionSettings, visited
moduleAnnotationsResolver, context, languageVersionSettings, visited
)
)
if (this is FunctionDescriptor) {
valueParameters.forEach {
result.addAll(
it.type.loadOptIns(
moduleAnnotationsResolver, languageVersionSettings, visited
moduleAnnotationsResolver, context, languageVersionSettings, visited
)
)
}
@@ -230,7 +240,7 @@ class OptInUsageChecker(project: Project) : CallChecker {
}
if (this is TypeAliasDescriptor) {
result.addAll(expandedType.loadOptIns(moduleAnnotationsResolver, languageVersionSettings, visited))
result.addAll(expandedType.loadOptIns(moduleAnnotationsResolver, context, languageVersionSettings, visited))
}
if (annotations.any { it.fqName == WAS_EXPERIMENTAL_FQ_NAME }) {
@@ -242,7 +252,7 @@ class OptInUsageChecker(project: Project) : CallChecker {
val container = containingDeclaration
if (useMarkersFromContainer && container is ClassDescriptor && this !is ConstructorDescriptor) {
result.addAll(container.loadOptIns(moduleAnnotationsResolver, languageVersionSettings, visited, useFutureError))
result.addAll(container.loadOptIns(moduleAnnotationsResolver, context, languageVersionSettings, visited, useFutureError))
}
return result
@@ -250,27 +260,31 @@ class OptInUsageChecker(project: Project) : CallChecker {
private fun KotlinType?.loadOptIns(
moduleAnnotationsResolver: ModuleAnnotationsResolver,
context: BindingContext,
languageVersionSettings: LanguageVersionSettings,
visitedClassifiers: MutableSet<DeclarationDescriptor>
): Set<OptInDescription> =
when {
this?.isError != false -> emptySet()
this is AbbreviatedType -> abbreviation.constructor.declarationDescriptor?.loadOptIns(
moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers,
moduleAnnotationsResolver, context, languageVersionSettings, visitedClassifiers,
useFutureError = !languageVersionSettings.supportsFeature(LanguageFeature.OptInContagiousSignatures)
).orEmpty() + expandedType.loadOptIns(
moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers
moduleAnnotationsResolver, context, languageVersionSettings, visitedClassifiers
)
else -> constructor.declarationDescriptor?.loadOptIns(
moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers,
moduleAnnotationsResolver, context, languageVersionSettings, visitedClassifiers,
useFutureError = !languageVersionSettings.supportsFeature(LanguageFeature.OptInContagiousSignatures)
).orEmpty() + arguments.flatMap {
if (it.isStarProjection) emptySet()
else it.type.loadOptIns(moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers)
else it.type.loadOptIns(moduleAnnotationsResolver, context, languageVersionSettings, visitedClassifiers)
}
}
internal fun ClassDescriptor.loadOptInForMarkerAnnotation(useFutureError: Boolean = false): OptInDescription? {
internal fun ClassDescriptor.loadOptInForMarkerAnnotation(
useFutureError: Boolean = false,
subclassesOnly: Boolean = false
): OptInDescription? {
val optInAnnotationDescriptor =
annotations.findAnnotation(REQUIRES_OPT_IN_FQ_NAME)
?: annotations.findAnnotation(OLD_EXPERIMENTAL_FQ_NAME)
@@ -289,11 +303,21 @@ class OptInUsageChecker(project: Project) : CallChecker {
val message = (arguments[MESSAGE] as? StringValue)?.value
return OptInDescription(fqNameSafe, severity, message)
return OptInDescription(fqNameSafe, severity, message, subclassesOnly)
}
private fun PsiElement.isOptInAllowed(annotationFqName: FqName, context: CheckerContext): Boolean =
isOptInAllowed(annotationFqName, context.languageVersionSettings, context.trace.bindingContext)
private fun AnnotationDescriptor.loadSubclassOptInRequired(context: BindingContext?): OptInDescription? {
if (this.fqName != SUBCLASS_OPT_IN_REQUIRED_FQ_NAME) return null
val markerClass = allValueArguments[USE_EXPERIMENTAL_ANNOTATION_CLASS]
if (markerClass !is KClassValue) return null
val value = markerClass.value
if (value !is KClassValue.Value.NormalClass) return null
val markerDescriptor = context?.get(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, value.classId.asSingleFqName().toUnsafe())
return markerDescriptor?.loadOptInForMarkerAnnotation(subclassesOnly = true)
}
private fun PsiElement.isOptInAllowed(annotationFqName: FqName, context: CheckerContext, subclassesOnly: Boolean): Boolean =
isOptInAllowed(annotationFqName, context.languageVersionSettings, context.trace.bindingContext, subclassesOnly)
/**
* Checks whether there's an element lexically above in the tree, annotated with `@UseExperimental(X::class)`, or a declaration
@@ -302,13 +326,17 @@ class OptInUsageChecker(project: Project) : CallChecker {
fun PsiElement.isOptInAllowed(
annotationFqName: FqName,
languageVersionSettings: LanguageVersionSettings,
bindingContext: BindingContext
): Boolean =
annotationFqName.asString() in languageVersionSettings.getFlag(AnalysisFlags.optIn) ||
anyParentMatches { element ->
element.isDeclarationAnnotatedWith(annotationFqName, bindingContext) ||
element.isElementAnnotatedWithOptIn(annotationFqName, bindingContext)
}
bindingContext: BindingContext,
subclassesOnly: Boolean
): Boolean {
if (annotationFqName.asString() in languageVersionSettings.getFlag(AnalysisFlags.optIn)) return true
val isSubclass = subclassesOnly && getParentOfType<KtSuperTypeListEntry>(strict = true) != null
return anyParentMatches { element ->
element.isDeclarationAnnotatedWith(annotationFqName, bindingContext) ||
element.isElementAnnotatedWithOptIn(annotationFqName, bindingContext) ||
isSubclass && element.isElementAnnotatedWithSubclassOptInRequired(annotationFqName, bindingContext)
}
}
private fun PsiElement.isDeclarationAnnotatedWith(annotationFqName: FqName, bindingContext: BindingContext): Boolean {
if (this !is KtDeclaration) return false
@@ -332,6 +360,22 @@ class OptInUsageChecker(project: Project) : CallChecker {
}
}
private fun PsiElement.isElementAnnotatedWithSubclassOptInRequired(
annotationFqName: FqName,
bindingContext: BindingContext
): Boolean {
return this is KtAnnotated && annotationEntries.any { entry ->
val descriptor = bindingContext.get(BindingContext.ANNOTATION, entry)
if (descriptor != null && descriptor.fqName == SUBCLASS_OPT_IN_REQUIRED_FQ_NAME) {
val annotationClass = descriptor.allValueArguments[USE_EXPERIMENTAL_ANNOTATION_CLASS]
annotationClass is KClassValue && annotationClass.value.let { value ->
value is KClassValue.Value.NormalClass &&
value.classId.asSingleFqName() == annotationFqName && value.arrayDimensions == 0
}
} else false
}
}
private inline fun PsiElement.anyParentMatches(predicate: (element: PsiElement) -> Boolean): Boolean {
var element = this
while (true) {
@@ -406,9 +450,10 @@ class OptInUsageChecker(project: Project) : CallChecker {
is TypeAliasDescriptor -> targetDescriptor.classDescriptor
else -> null
}
val bindingContext = context.trace.bindingContext
if (targetClass != null && targetClass.loadOptInForMarkerAnnotation() != null) {
if (!element.isUsageAsAnnotationOrImport() &&
!element.isUsageAsOptInArgument(context.trace.bindingContext)
!element.isUsageAsOptInArgument(bindingContext)
) {
context.trace.report(
Errors.OPT_IN_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_OPT_IN.on(element)
@@ -417,7 +462,12 @@ class OptInUsageChecker(project: Project) : CallChecker {
}
if (element.getParentOfType<KtImportDirective>(false) == null) {
val descriptions = targetDescriptor.loadOptIns(moduleAnnotationsResolver, context.languageVersionSettings)
val descriptions = targetDescriptor.loadOptIns(
moduleAnnotationsResolver,
bindingContext,
context.languageVersionSettings,
fromSupertype = element.getParentOfType<KtSuperTypeListEntry>(strict = true) != null
)
reportNotAllowedOptIns(descriptions, element, context)
}
}
@@ -456,7 +506,8 @@ class OptInUsageChecker(project: Project) : CallChecker {
parent.parent.parent is KtValueArgumentList &&
parent.parent.parent.parent.let { entry ->
entry is KtAnnotationEntry && bindingContext.get(BindingContext.ANNOTATION, entry)?.let { annotation ->
annotation.fqName in OPT_IN_FQ_NAMES || annotation.fqName == WAS_EXPERIMENTAL_FQ_NAME
annotation.fqName in OPT_IN_FQ_NAMES || annotation.fqName == WAS_EXPERIMENTAL_FQ_NAME ||
annotation.fqName == SUBCLASS_OPT_IN_REQUIRED_FQ_NAME
} == true
}
}
@@ -469,12 +520,12 @@ class OptInUsageChecker(project: Project) : CallChecker {
if (descriptor !is CallableMemberDescriptor) return
val optInOverriddenDescriptorMap = descriptor.overriddenDescriptors.flatMap { overriddenMember ->
overriddenMember.loadOptIns(moduleAnnotationsResolver, context.languageVersionSettings)
overriddenMember.loadOptIns(moduleAnnotationsResolver, context.trace.bindingContext, context.languageVersionSettings)
.map { description -> description to overriddenMember }
}.toMap()
for ((description, overriddenMember) in optInOverriddenDescriptorMap) {
if (!declaration.isOptInAllowed(description.annotationFqName, context)) {
if (!declaration.isOptInAllowed(description.annotationFqName, context, description.subclassesOnly)) {
val reportOn = (declaration as? KtNamedDeclaration)?.nameIdentifier ?: declaration
val (diagnostic, defaultMessageVerb) = when (description.severity) {
@@ -324,7 +324,7 @@ class ConstantExpressionEvaluator(
with(OptInUsageChecker) {
val descriptor = constantType.constructor.declarationDescriptor ?: return
val optInDescriptions = descriptor.loadOptIns(moduleAnnotationsResolver, languageVersionSettings)
val optInDescriptions = descriptor.loadOptIns(moduleAnnotationsResolver, trace.bindingContext, languageVersionSettings)
reportNotAllowedOptIns(
optInDescriptions, expression, languageVersionSettings, trace, EXPERIMENTAL_UNSIGNED_LITERALS_DIAGNOSTICS
@@ -117,7 +117,9 @@ class DeprecationResolver(
return if (callElement != null && bindingContext != null) {
with(OptInUsageChecker) {
sinceKotlinAccessibility.markerClasses.any { classDescriptor ->
!callElement.isOptInAllowed(classDescriptor.fqNameSafe, languageVersionSettings, bindingContext)
!callElement.isOptInAllowed(
classDescriptor.fqNameSafe, languageVersionSettings, bindingContext, subclassesOnly = false
)
}
}
} else {
@@ -0,0 +1,35 @@
@RequiresOptIn
annotation class Marker
@SubclassOptInRequired(Marker::class)
open class Base
@Marker
class DerivedFirst : Base()
@OptIn(Marker::class)
class DerivedSecond : Base()
@SubclassOptInRequired(Marker::class)
open class DerivedThird : Base()
open class DerivedFourth : Base()
class GrandDerivedThird : DerivedThird()
// Question: should we have an error also here?
class GrandDerivedFourth : DerivedFourth()
@Marker
open class Marked
@SubclassOptInRequired(Marker::class)
class DerivedMarked : <!OPT_IN_USAGE_ERROR!>Marked<!>()
fun test() {
val b = Base()
val d1 = <!OPT_IN_USAGE_ERROR!>DerivedFirst<!>()
val d2 = DerivedSecond()
val d3 = DerivedThird()
val d4 = DerivedFourth()
}
@@ -0,0 +1,35 @@
@RequiresOptIn
annotation class Marker
@SubclassOptInRequired(Marker::class)
open class Base
@Marker
class DerivedFirst : Base()
@OptIn(Marker::class)
class DerivedSecond : Base()
@SubclassOptInRequired(Marker::class)
open class DerivedThird : Base()
open class DerivedFourth : <!OPT_IN_USAGE_ERROR!>Base<!>()
class GrandDerivedThird : <!OPT_IN_USAGE_ERROR!>DerivedThird<!>()
// Question: should we have an error also here?
class GrandDerivedFourth : DerivedFourth()
@Marker
open class Marked
@SubclassOptInRequired(Marker::class)
class DerivedMarked : <!OPT_IN_USAGE_ERROR!>Marked<!>()
fun test() {
val b = Base()
val d1 = <!OPT_IN_USAGE_ERROR!>DerivedFirst<!>()
val d2 = DerivedSecond()
val d3 = DerivedThird()
val d4 = DerivedFourth()
}
@@ -0,0 +1,73 @@
package
public fun test(): kotlin.Unit
@kotlin.SubclassOptInRequired(markerClass = Marker::class) public open class Base {
public constructor Base()
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
}
@Marker public final class DerivedFirst : Base {
public constructor DerivedFirst()
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 open class DerivedFourth : Base {
public constructor DerivedFourth()
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 DerivedMarked : Marked {
public constructor DerivedMarked()
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 DerivedSecond : Base {
public constructor DerivedSecond()
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 DerivedThird : Base {
public constructor DerivedThird()
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 class GrandDerivedFourth : DerivedFourth {
public constructor GrandDerivedFourth()
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 class GrandDerivedThird : DerivedThird {
public constructor GrandDerivedThird()
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
}
@Marker public open class Marked {
public constructor Marked()
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
}
@@ -37638,6 +37638,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/overrideInAnonymousObject.kt");
}
@Test
@TestMetadata("subClassOptInRequired.kt")
public void testSubClassOptInRequired() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/experimental/subClassOptInRequired.kt");
}
@Test
@TestMetadata("topLevel.kt")
public void testTopLevel() throws Exception {
@@ -8,7 +8,12 @@ package org.jetbrains.kotlin.resolve.checkers
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.name.FqName
data class OptInDescription(val annotationFqName: FqName, val severity: Severity, val message: String?) {
data class OptInDescription(
val annotationFqName: FqName,
val severity: Severity,
val message: String?,
val subclassesOnly: Boolean,
) {
enum class Severity { WARNING, ERROR, FUTURE_ERROR }
companion object {