[FIR] Set targets of annotation classes in FirJavaElementFinder
#KT-60504 Fixed
This commit is contained in:
committed by
Space Team
parent
daa02813c2
commit
81517a3d29
+5
@@ -29,6 +29,11 @@ public class FirOldFrontendLightClassesTestGenerated extends AbstractFirOldFront
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/lightClasses"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/lightClasses"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("annotationTargets.kt")
|
||||||
|
public void testAnnotationTargets() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/lightClasses/annotationTargets.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("genericClasses.kt")
|
@TestMetadata("genericClasses.kt")
|
||||||
public void testGenericClasses() throws Exception {
|
public void testGenericClasses() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/lightClasses/genericClasses.kt");
|
runTest("compiler/fir/analysis-tests/testData/lightClasses/genericClasses.kt");
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
annotation class A1
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
annotation class A2
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.ANNOTATION_CLASS)
|
||||||
|
annotation class A3
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.TYPE_PARAMETER)
|
||||||
|
annotation class A4
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.PROPERTY)
|
||||||
|
annotation class A5
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.FIELD)
|
||||||
|
annotation class A6
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.LOCAL_VARIABLE)
|
||||||
|
annotation class A7
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.VALUE_PARAMETER)
|
||||||
|
annotation class A8
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.CONSTRUCTOR)
|
||||||
|
annotation class A9
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.FUNCTION)
|
||||||
|
annotation class A10
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.PROPERTY_GETTER)
|
||||||
|
annotation class A11
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.PROPERTY_SETTER)
|
||||||
|
annotation class A12
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.TYPE)
|
||||||
|
annotation class A13
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.EXPRESSION)
|
||||||
|
annotation class A14
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.FILE)
|
||||||
|
annotation class A15
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.TYPEALIAS)
|
||||||
|
annotation class A16
|
||||||
|
|
||||||
|
// LIGHT_CLASS_FQ_NAME: A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
public final @interface A1 implements java.lang.annotation.Annotation {
|
||||||
|
}
|
||||||
|
@java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE})
|
||||||
|
public final @interface A2 implements java.lang.annotation.Annotation {
|
||||||
|
}
|
||||||
|
@java.lang.annotation.Target({java.lang.annotation.ElementType.ANNOTATION_TYPE})
|
||||||
|
public final @interface A3 implements java.lang.annotation.Annotation {
|
||||||
|
}
|
||||||
|
@java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE_PARAMETER})
|
||||||
|
public final @interface A4 implements java.lang.annotation.Annotation {
|
||||||
|
}
|
||||||
|
@java.lang.annotation.Target({})
|
||||||
|
public final @interface A5 implements java.lang.annotation.Annotation {
|
||||||
|
}
|
||||||
|
@java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD})
|
||||||
|
public final @interface A6 implements java.lang.annotation.Annotation {
|
||||||
|
}
|
||||||
|
@java.lang.annotation.Target({java.lang.annotation.ElementType.LOCAL_VARIABLE})
|
||||||
|
public final @interface A7 implements java.lang.annotation.Annotation {
|
||||||
|
}
|
||||||
|
@java.lang.annotation.Target({java.lang.annotation.ElementType.PARAMETER})
|
||||||
|
public final @interface A8 implements java.lang.annotation.Annotation {
|
||||||
|
}
|
||||||
|
@java.lang.annotation.Target({java.lang.annotation.ElementType.CONSTRUCTOR})
|
||||||
|
public final @interface A9 implements java.lang.annotation.Annotation {
|
||||||
|
}
|
||||||
|
@java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD})
|
||||||
|
public final @interface A10 implements java.lang.annotation.Annotation {
|
||||||
|
}
|
||||||
|
@java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD})
|
||||||
|
public final @interface A11 implements java.lang.annotation.Annotation {
|
||||||
|
}
|
||||||
|
@java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD})
|
||||||
|
public final @interface A12 implements java.lang.annotation.Annotation {
|
||||||
|
}
|
||||||
|
@java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE_USE})
|
||||||
|
public final @interface A13 implements java.lang.annotation.Annotation {
|
||||||
|
}
|
||||||
|
@java.lang.annotation.Target({})
|
||||||
|
public final @interface A14 implements java.lang.annotation.Annotation {
|
||||||
|
}
|
||||||
|
@java.lang.annotation.Target({})
|
||||||
|
public final @interface A15 implements java.lang.annotation.Annotation {
|
||||||
|
}
|
||||||
|
@java.lang.annotation.Target({})
|
||||||
|
public final @interface A16 implements java.lang.annotation.Annotation {
|
||||||
|
}
|
||||||
@@ -27,11 +27,13 @@ import org.jetbrains.kotlin.descriptors.Visibilities
|
|||||||
import org.jetbrains.kotlin.fir.FirModuleData
|
import org.jetbrains.kotlin.fir.FirModuleData
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.FirSessionComponent
|
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.getTargetAnnotation
|
||||||
import org.jetbrains.kotlin.fir.caches.FirCache
|
import org.jetbrains.kotlin.fir.caches.FirCache
|
||||||
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
||||||
import org.jetbrains.kotlin.fir.caches.getValue
|
import org.jetbrains.kotlin.fir.caches.getValue
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||||
import org.jetbrains.kotlin.fir.moduleData
|
import org.jetbrains.kotlin.fir.moduleData
|
||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
@@ -44,12 +46,14 @@ import org.jetbrains.kotlin.fir.resolve.transformers.SupertypeComputationSession
|
|||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.fir.utils.exceptions.withConeTypeEntry
|
import org.jetbrains.kotlin.fir.utils.exceptions.withConeTypeEntry
|
||||||
|
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||||
import org.jetbrains.kotlin.load.java.structure.impl.NotEvaluatedConstAware
|
import org.jetbrains.kotlin.load.java.structure.impl.NotEvaluatedConstAware
|
||||||
import org.jetbrains.kotlin.name.*
|
import org.jetbrains.kotlin.name.*
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
||||||
import org.jetbrains.kotlin.resolve.jvm.KotlinFinderMarker
|
import org.jetbrains.kotlin.resolve.jvm.KotlinFinderMarker
|
||||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
|
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
|
||||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
|
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
|
||||||
|
import org.jetbrains.kotlin.utils.KOTLIN_TO_JAVA_ANNOTATION_TARGETS
|
||||||
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
|
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
|
||||||
|
|
||||||
val FirSession.javaElementFinder: FirJavaElementFinder? by FirSession.nullableSessionComponentAccessor<FirJavaElementFinder>()
|
val FirSession.javaElementFinder: FirJavaElementFinder? by FirSession.nullableSessionComponentAccessor<FirJavaElementFinder>()
|
||||||
@@ -166,7 +170,20 @@ class FirJavaElementFinder(
|
|||||||
buildFieldStubForConst(it, stub)
|
buildFieldStubForConst(it, stub)
|
||||||
}
|
}
|
||||||
|
|
||||||
PsiModifierListStubImpl(stub, firClass.packFlags())
|
val modifierListStub = PsiModifierListStubImpl(stub, firClass.packFlags())
|
||||||
|
|
||||||
|
if (firClass.classKind == ClassKind.ANNOTATION_CLASS) {
|
||||||
|
val targets = firClass.getTargetAnnotation(session)?.findTargets()
|
||||||
|
if (targets != null) {
|
||||||
|
val annotationString = buildString {
|
||||||
|
append("@${JvmAnnotationNames.TARGET_ANNOTATION}({")
|
||||||
|
targets.mapNotNull { KOTLIN_TO_JAVA_ANNOTATION_TARGETS[it] }
|
||||||
|
.joinTo(this) { "${JvmAnnotationNames.ELEMENT_TYPE_ENUM}.$it" }
|
||||||
|
append("})")
|
||||||
|
}
|
||||||
|
PsiAnnotationStubImpl(modifierListStub, annotationString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
newTypeParameterList(
|
newTypeParameterList(
|
||||||
stub,
|
stub,
|
||||||
@@ -187,6 +204,10 @@ class FirJavaElementFinder(
|
|||||||
return stub
|
return stub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FirAnnotation.findTargets(): List<String> = buildList {
|
||||||
|
forEachAnnotationTarget { add(it.identifier) }
|
||||||
|
}
|
||||||
|
|
||||||
private fun buildFieldStubForConst(firProperty: FirProperty, classStub: PsiClassStubImpl<ClsClassImpl>) {
|
private fun buildFieldStubForConst(firProperty: FirProperty, classStub: PsiClassStubImpl<ClsClassImpl>) {
|
||||||
if (!firProperty.isConst) return
|
if (!firProperty.isConst) return
|
||||||
|
|
||||||
|
|||||||
+13
-7
@@ -78,22 +78,28 @@ fun FirAnnotation.useSiteTargetsFromMetaAnnotation(session: FirSession): Set<Ann
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun FirAnnotation.findUseSiteTargets(): Set<AnnotationUseSiteTarget> = buildSet {
|
private fun FirAnnotation.findUseSiteTargets(): Set<AnnotationUseSiteTarget> = buildSet {
|
||||||
fun addIfMatching(arg: FirExpression) {
|
forEachAnnotationTarget {
|
||||||
if (arg !is FirQualifiedAccessExpression) return
|
USE_SITE_TARGET_NAME_MAP[it.identifier]?.let { addAll(it) }
|
||||||
val callableSymbol = arg.calleeReference.toResolvedCallableSymbol() ?: return
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun FirAnnotation.forEachAnnotationTarget(action: (Name) -> Unit) {
|
||||||
|
fun take(arg: FirExpression) {
|
||||||
|
if (arg !is FirQualifiedAccessExpression) return@take
|
||||||
|
val callableSymbol = arg.calleeReference.toResolvedCallableSymbol() ?: return@take
|
||||||
if (callableSymbol.containingClassLookupTag()?.classId == StandardClassIds.AnnotationTarget) {
|
if (callableSymbol.containingClassLookupTag()?.classId == StandardClassIds.AnnotationTarget) {
|
||||||
USE_SITE_TARGET_NAME_MAP[callableSymbol.callableId.callableName.identifier]?.let { addAll(it) }
|
action(callableSymbol.callableId.callableName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this@findUseSiteTargets is FirAnnotationCall) {
|
if (this is FirAnnotationCall) {
|
||||||
for (arg in argumentList.arguments) {
|
for (arg in argumentList.arguments) {
|
||||||
arg.unwrapAndFlattenArgument(flattenArrays = true).forEach(::addIfMatching)
|
arg.unwrapAndFlattenArgument(flattenArrays = true).forEach(::take)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
argumentMapping.mapping[StandardClassIds.Annotations.ParameterNames.targetAllowedTargets]
|
argumentMapping.mapping[StandardClassIds.Annotations.ParameterNames.targetAllowedTargets]
|
||||||
?.unwrapAndFlattenArgument(flattenArrays = true)
|
?.unwrapAndFlattenArgument(flattenArrays = true)
|
||||||
?.forEach(::addIfMatching)
|
?.forEach(::take)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.utils
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType
|
||||||
|
|
||||||
|
val KOTLIN_TO_JAVA_ANNOTATION_TARGETS: Map<String, String> = mapOf(
|
||||||
|
AnnotationTarget.CLASS.name to ElementType.TYPE.name,
|
||||||
|
AnnotationTarget.ANNOTATION_CLASS.name to ElementType.ANNOTATION_TYPE.name,
|
||||||
|
AnnotationTarget.FIELD.name to ElementType.FIELD.name,
|
||||||
|
AnnotationTarget.LOCAL_VARIABLE.name to ElementType.LOCAL_VARIABLE.name,
|
||||||
|
AnnotationTarget.VALUE_PARAMETER.name to ElementType.PARAMETER.name,
|
||||||
|
AnnotationTarget.CONSTRUCTOR.name to ElementType.CONSTRUCTOR.name,
|
||||||
|
AnnotationTarget.FUNCTION.name to ElementType.METHOD.name,
|
||||||
|
AnnotationTarget.PROPERTY_GETTER.name to ElementType.METHOD.name,
|
||||||
|
AnnotationTarget.PROPERTY_SETTER.name to ElementType.METHOD.name,
|
||||||
|
AnnotationTarget.TYPE_PARAMETER.name to ElementType.TYPE_PARAMETER.name,
|
||||||
|
AnnotationTarget.TYPE.name to ElementType.TYPE_USE.name,
|
||||||
|
)
|
||||||
+4
-13
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
|||||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||||
import org.jetbrains.kotlin.resolve.constants.EnumValue
|
import org.jetbrains.kotlin.resolve.constants.EnumValue
|
||||||
import org.jetbrains.kotlin.resolve.constants.KClassValue
|
import org.jetbrains.kotlin.resolve.constants.KClassValue
|
||||||
|
import org.jetbrains.kotlin.utils.KOTLIN_TO_JAVA_ANNOTATION_TARGETS
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
internal const val KOTLIN_JVM_INTERNAL_REPEATABLE_CONTAINER = "kotlin.jvm.internal.RepeatableContainer"
|
internal const val KOTLIN_JVM_INTERNAL_REPEATABLE_CONTAINER = "kotlin.jvm.internal.RepeatableContainer"
|
||||||
@@ -55,19 +56,9 @@ private fun PsiAnnotation.extractArrayAnnotationFqNames(attributeName: String):
|
|||||||
|
|
||||||
private val targetMapping = run {
|
private val targetMapping = run {
|
||||||
val javaAnnotationElementTypeId = ClassId.fromString(JvmAnnotationNames.ELEMENT_TYPE_ENUM.asString())
|
val javaAnnotationElementTypeId = ClassId.fromString(JvmAnnotationNames.ELEMENT_TYPE_ENUM.asString())
|
||||||
hashMapOf(
|
KOTLIN_TO_JAVA_ANNOTATION_TARGETS.entries.associate { (key, value) ->
|
||||||
"kotlin.annotation.AnnotationTarget.CLASS" to EnumValue(javaAnnotationElementTypeId, Name.identifier("TYPE")),
|
"kotlin.annotation.AnnotationTarget.$key" to EnumValue(javaAnnotationElementTypeId, Name.identifier(value))
|
||||||
"kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS" to EnumValue(javaAnnotationElementTypeId, Name.identifier("ANNOTATION_TYPE")),
|
}
|
||||||
"kotlin.annotation.AnnotationTarget.FIELD" to EnumValue(javaAnnotationElementTypeId, Name.identifier("FIELD")),
|
|
||||||
"kotlin.annotation.AnnotationTarget.LOCAL_VARIABLE" to EnumValue(javaAnnotationElementTypeId, Name.identifier("LOCAL_VARIABLE")),
|
|
||||||
"kotlin.annotation.AnnotationTarget.VALUE_PARAMETER" to EnumValue(javaAnnotationElementTypeId, Name.identifier("PARAMETER")),
|
|
||||||
"kotlin.annotation.AnnotationTarget.CONSTRUCTOR" to EnumValue(javaAnnotationElementTypeId, Name.identifier("CONSTRUCTOR")),
|
|
||||||
"kotlin.annotation.AnnotationTarget.FUNCTION" to EnumValue(javaAnnotationElementTypeId, Name.identifier("METHOD")),
|
|
||||||
"kotlin.annotation.AnnotationTarget.PROPERTY_GETTER" to EnumValue(javaAnnotationElementTypeId, Name.identifier("METHOD")),
|
|
||||||
"kotlin.annotation.AnnotationTarget.PROPERTY_SETTER" to EnumValue(javaAnnotationElementTypeId, Name.identifier("METHOD")),
|
|
||||||
"kotlin.annotation.AnnotationTarget.TYPE_PARAMETER" to EnumValue(javaAnnotationElementTypeId, Name.identifier("TYPE_PARAMETER")),
|
|
||||||
"kotlin.annotation.AnnotationTarget.TYPE" to EnumValue(javaAnnotationElementTypeId, Name.identifier("TYPE_USE")),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun PsiAnnotation.tryConvertAsTarget(): KtLightAbstractAnnotation? {
|
internal fun PsiAnnotation.tryConvertAsTarget(): KtLightAbstractAnnotation? {
|
||||||
|
|||||||
Vendored
+1
-1
@@ -27,7 +27,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
annotation class An
|
annotation class An
|
||||||
|
|
||||||
class B : A {
|
class B : A {
|
||||||
override fun foo(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE("foo; @NotNull() @An() @MyTypeQualifier() fun foo(): @EnhancedNullability String")!>String?<!> = null
|
override fun foo(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE("foo; @NotNull() @An() @MyTypeQualifier() fun foo(): @EnhancedNullability @R|An|() String")!>String?<!> = null
|
||||||
}
|
}
|
||||||
|
|
||||||
@An
|
@An
|
||||||
|
|||||||
Vendored
-45
@@ -1,45 +0,0 @@
|
|||||||
// LL_FIR_DIVERGENCE
|
|
||||||
// KT-60504
|
|
||||||
// LL_FIR_DIVERGENCE
|
|
||||||
// !RENDER_DIAGNOSTICS_MESSAGES
|
|
||||||
// SKIP_JAVAC
|
|
||||||
|
|
||||||
// FILE: A.java
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.METHOD)
|
|
||||||
@javax.annotation.meta.TypeQualifier
|
|
||||||
public @interface MyTypeQualifier {}
|
|
||||||
|
|
||||||
@An
|
|
||||||
public interface A {
|
|
||||||
@NotNull
|
|
||||||
@An
|
|
||||||
@MyTypeQualifier
|
|
||||||
String foo();
|
|
||||||
}
|
|
||||||
|
|
||||||
// FILE: k.kt
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER)
|
|
||||||
annotation class An
|
|
||||||
|
|
||||||
class B : A {
|
|
||||||
override fun foo(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE("foo; @NotNull() @An() @MyTypeQualifier() fun foo(): @EnhancedNullability @R|An|() String")!>String?<!> = null
|
|
||||||
}
|
|
||||||
|
|
||||||
@An
|
|
||||||
public interface C {
|
|
||||||
@NotNull
|
|
||||||
@An
|
|
||||||
fun foo(): String
|
|
||||||
}
|
|
||||||
|
|
||||||
class D : C {
|
|
||||||
override fun foo(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE("foo; @NotNull() @An() fun foo(): String")!>String?<!> = null
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user