OptIn: handle usages via type aliases properly

This commit is contained in:
Mikhail Glukhikh
2021-06-03 18:16:35 +03:00
committed by teamcityserver
parent b4ee116de7
commit eb9c658c1c
5 changed files with 38 additions and 8 deletions
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.types.AbbreviatedType
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.isError import org.jetbrains.kotlin.types.isError
import org.jetbrains.kotlin.utils.SmartSet import org.jetbrains.kotlin.utils.SmartSet
@@ -237,12 +238,19 @@ class ExperimentalUsageChecker(project: Project) : CallChecker {
languageVersionSettings: LanguageVersionSettings, languageVersionSettings: LanguageVersionSettings,
visitedClassifiers: MutableSet<DeclarationDescriptor> visitedClassifiers: MutableSet<DeclarationDescriptor>
): Set<Experimentality> = ): Set<Experimentality> =
if (this?.isError != false) emptySet() when {
else constructor.declarationDescriptor?.loadExperimentalities( this?.isError != false -> emptySet()
moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers this is AbbreviatedType -> abbreviation.constructor.declarationDescriptor?.loadExperimentalities(
).orEmpty() + arguments.flatMap { moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers
if (it.isStarProjection) emptySet() ).orEmpty() + expandedType.loadExperimentalities(
else it.type.loadExperimentalities(moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers) moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers
)
else -> constructor.declarationDescriptor?.loadExperimentalities(
moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers
).orEmpty() + arguments.flatMap {
if (it.isStarProjection) emptySet()
else it.type.loadExperimentalities(moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers)
}
} }
internal fun ClassDescriptor.loadExperimentalityForMarkerAnnotation(): Experimentality? { internal fun ClassDescriptor.loadExperimentalityForMarkerAnnotation(): Experimentality? {
@@ -2,6 +2,7 @@
@RequiresOptIn @RequiresOptIn
@Retention(AnnotationRetention.BINARY) @Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS)
annotation class Marker annotation class Marker
@Marker @Marker
@@ -59,8 +60,17 @@ class A : I
@OptIn(Marker::class) @OptIn(Marker::class)
class B : I class B : I
@OptIn(Marker::class)
typealias MyList = ArrayList<I>
@Marker
typealias YourList = ArrayList<String>
fun main() { fun main() {
val x = listOf(A(), B()) val x = listOf(A(), B())
val y = MyList()
val z = YourList()
YourList().add("")
} }
@Marker @Marker
@@ -2,6 +2,7 @@
@RequiresOptIn @RequiresOptIn
@Retention(AnnotationRetention.BINARY) @Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS)
annotation class Marker annotation class Marker
@Marker @Marker
@@ -59,8 +60,17 @@ class A : I
@OptIn(Marker::class) @OptIn(Marker::class)
class B : I class B : I
@OptIn(Marker::class)
typealias MyList = ArrayList<I>
@Marker
typealias YourList = ArrayList<String>
fun main() { fun main() {
val x = <!EXPERIMENTAL_API_USAGE_ERROR!>listOf<!>(A(), B()) val x = <!EXPERIMENTAL_API_USAGE_ERROR!>listOf<!>(A(), B())
val y = <!EXPERIMENTAL_API_USAGE_ERROR!>MyList<!>()
val z = <!EXPERIMENTAL_API_USAGE_ERROR!>YourList<!>()
<!EXPERIMENTAL_API_USAGE_ERROR!>YourList<!>().add("")
} }
@Marker @Marker
@@ -64,7 +64,7 @@ public final data class DataClass {
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
@kotlin.RequiresOptIn @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class Marker : kotlin.Annotation { @kotlin.RequiresOptIn @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS}) public final annotation class Marker : kotlin.Annotation {
public constructor Marker() public constructor Marker()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean 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 hashCode(): kotlin.Int
@@ -112,4 +112,6 @@ public abstract class User {
public final fun Some?.onSome(): kotlin.Unit public final fun Some?.onSome(): kotlin.Unit
} }
public typealias My = Some public typealias My = Some
@kotlin.OptIn(markerClass = {Marker::class}) public typealias MyList = kotlin.collections.ArrayList<I>
@Marker public typealias YourList = kotlin.collections.ArrayList<kotlin.String>
@@ -75,5 +75,5 @@ fun use() {
<!EXPERIMENTAL_API_USAGE!>function<!>() <!EXPERIMENTAL_API_USAGE!>function<!>()
<!EXPERIMENTAL_API_USAGE!>property<!> <!EXPERIMENTAL_API_USAGE!>property<!>
val s: <!EXPERIMENTAL_API_USAGE!>Typealias<!> = "" val s: <!EXPERIMENTAL_API_USAGE!>Typealias<!> = ""
s.hashCode() <!EXPERIMENTAL_API_USAGE!>s<!>.hashCode()
} }