diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/annotations/symbolAnnotationsUtils.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/annotations/symbolAnnotationsUtils.kt index 84bec0d5b76..38735cf2f1c 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/annotations/symbolAnnotationsUtils.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/annotations/symbolAnnotationsUtils.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.annotations.* import org.jetbrains.kotlin.analysis.api.annotations.KtKClassAnnotationValue.KtNonLocalKClassAnnotationValue import org.jetbrains.kotlin.analysis.api.components.buildClassType +import org.jetbrains.kotlin.analysis.api.symbols.KtDeclarationSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol import org.jetbrains.kotlin.analysis.api.symbols.markers.KtAnnotatedSymbol @@ -21,6 +22,7 @@ import org.jetbrains.kotlin.asJava.classes.annotateByTypeAnnotationProvider import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassBase +import org.jetbrains.kotlin.light.classes.symbol.getContainingSymbolsWithSelf import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.JvmStandardClassIds import org.jetbrains.kotlin.name.JvmStandardClassIds.JVM_OVERLOADS_CLASS_ID @@ -91,6 +93,28 @@ internal fun KtAnnotatedSymbol.hasJvmStaticAnnotation( internal fun KtAnnotatedSymbol.hasInlineOnlyAnnotation(): Boolean = hasAnnotation(StandardClassIds.Annotations.InlineOnly) +context(KtAnalysisSession) +internal fun KtDeclarationSymbol.suppressWildcardMode( + declarationFilter: (KtDeclarationSymbol) -> Boolean = { true }, +): Boolean? { + return getContainingSymbolsWithSelf().firstNotNullOfOrNull { symbol -> + symbol.takeIf(declarationFilter)?.suppressWildcard() + } +} + +internal fun KtAnnotatedSymbol.suppressWildcard(): Boolean? { + if (hasJvmWildcardAnnotation()) return true + return getJvmSuppressWildcardsFromAnnotation() +} + +internal fun KtAnnotatedSymbol.getJvmSuppressWildcardsFromAnnotation(): Boolean? { + return annotationsByClassId(JvmStandardClassIds.Annotations.JvmSuppressWildcards).firstOrNull()?.let { annoApp -> + (annoApp.arguments.firstOrNull()?.expression as? KtConstantAnnotationValue)?.constantValue?.value as? Boolean + } +} + +internal fun KtAnnotatedSymbol.hasJvmWildcardAnnotation(): Boolean = hasAnnotation(JvmStandardClassIds.Annotations.JvmWildcard) + internal fun KtAnnotatedSymbol.findAnnotation( classId: ClassId, useSiteTargetFilter: AnnotationUseSiteTargetFilter = AnyAnnotationUseSiteTargetFilter, diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForProperty.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForProperty.kt index 53c794413fe..3ea3682a547 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForProperty.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForProperty.kt @@ -80,6 +80,7 @@ internal class SymbolLightFieldForProperty private constructor( this@SymbolLightFieldForProperty, allowErrorTypes = true, typeMappingMode, + suppressWildcards = propertySymbol.suppressWildcardMode(), ) } ?: nonExistentType() } diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightAccessorMethod.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightAccessorMethod.kt index 5a84ed9ac81..e926912996b 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightAccessorMethod.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightAccessorMethod.kt @@ -269,12 +269,20 @@ internal class SymbolLightAccessorMethod private constructor( allowErrorTypes = true, typeMappingMode, containingClass.isAnnotationType, + suppressWildcards(), ) } ?: nonExistentType() } override fun getReturnType(): PsiType = _returnedType + override fun suppressWildcards(): Boolean? = + withAccessorSymbol { accessorSymbol -> + accessorSymbol.suppressWildcardMode { parent -> + parent !is KtPropertySymbol + } + } + override fun isEquivalentTo(another: PsiElement?): Boolean { return super.isEquivalentTo(another) || basicIsEquivalentTo(this, another as? PsiField) } diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightMethod.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightMethod.kt index b899cdbfe12..2cc01b87014 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightMethod.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightMethod.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.asJava.classes.lazyPub import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier import org.jetbrains.kotlin.light.classes.symbol.annotations.computeThrowsList import org.jetbrains.kotlin.light.classes.symbol.annotations.hasDeprecatedAnnotation +import org.jetbrains.kotlin.light.classes.symbol.annotations.suppressWildcardMode import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassBase import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForInterfaceDefaultImpls import org.jetbrains.kotlin.light.classes.symbol.compareSymbolPointers @@ -157,4 +158,9 @@ internal abstract class SymbolLightMethod private } override fun hashCode(): Int = kotlinOrigin.hashCode() + + override fun suppressWildcards(): Boolean? = + withFunctionSymbol { functionSymbol -> + functionSymbol.suppressWildcardMode() + } } diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightMethodBase.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightMethodBase.kt index f5c84e078d2..90979272a01 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightMethodBase.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightMethodBase.kt @@ -134,4 +134,6 @@ internal abstract class SymbolLightMethodBase( } abstract fun isOverride(): Boolean + + internal open fun suppressWildcards(): Boolean? = null } diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightSimpleMethod.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightSimpleMethod.kt index 0d002517d78..38384404e9e 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightSimpleMethod.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightSimpleMethod.kt @@ -234,6 +234,7 @@ internal class SymbolLightSimpleMethod( allowErrorTypes = true, typeMappingMode, this@SymbolLightSimpleMethod.containingClass.isAnnotationType, + suppressWildcards = suppressWildcards(), )?.let { annotateByKtType(it.type, ktType, it, modifierList) } diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightParameterCommon.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightParameterCommon.kt index ab17e03bc93..57c8e23ea1c 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightParameterCommon.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightParameterCommon.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.light.classes.symbol.* import org.jetbrains.kotlin.light.classes.symbol.annotations.annotateByKtType +import org.jetbrains.kotlin.light.classes.symbol.annotations.suppressWildcardMode import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightMethodBase import org.jetbrains.kotlin.psi.KtParameter @@ -80,7 +81,8 @@ internal abstract class SymbolLightParameterCommon( ktType.asPsiTypeElement( this@SymbolLightParameterCommon, allowErrorTypes = true, - ktType.typeMappingMode() + ktType.typeMappingMode(), + suppressWildcards = parameterSymbol.suppressWildcardMode(), )?.let { annotateByKtType(it.type, ktType, it, modifierList) } diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightParameterForReceiver.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightParameterForReceiver.kt index 4ec92de830d..00ed9ba6352 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightParameterForReceiver.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightParameterForReceiver.kt @@ -90,7 +90,8 @@ internal class SymbolLightParameterForReceiver private constructor( val psiType = ktType.asPsiTypeElement( this, allowErrorTypes = true, - ktType.typeMappingMode() + ktType.typeMappingMode(), + suppressWildcards = receiver.suppressWildcard() ?: method.suppressWildcards(), )?.let { annotateByKtType(it.type, ktType, it, modifierList) } diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/symbolLightUtils.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/symbolLightUtils.kt index 07f208b01d4..e79fefb4734 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/symbolLightUtils.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/symbolLightUtils.kt @@ -44,6 +44,10 @@ import java.util.* internal fun L.invalidAccess(): Nothing = error("Cls delegate shouldn't be accessed for symbol light classes! Qualified name: ${javaClass.name}") +context(KtAnalysisSession) +internal fun KtDeclarationSymbol.getContainingSymbolsWithSelf(): Sequence = + generateSequence(this) { it.getContainingSymbol() } + internal fun KtAnalysisSession.mapType( type: KtType, psiContext: PsiElement, diff --git a/compiler/testData/asJava/lightClasses/lightClassByPsi/facades/jvmWildcardAnnotations.fir.java b/compiler/testData/asJava/lightClasses/lightClassByPsi/facades/jvmWildcardAnnotations.fir.java index 5e96e710ada..ec3ce71f06d 100644 --- a/compiler/testData/asJava/lightClasses/lightClassByPsi/facades/jvmWildcardAnnotations.fir.java +++ b/compiler/testData/asJava/lightClasses/lightClassByPsi/facades/jvmWildcardAnnotations.fir.java @@ -13,10 +13,10 @@ public final class Inv /* Inv*/ { public final class JvmWildcardAnnotationsKt /* JvmWildcardAnnotationsKt*/ { @kotlin.jvm.JvmSuppressWildcards(suppress = false) @org.jetbrains.annotations.NotNull() - public static final Out bar();// bar() + public static final Out bar();// bar() @kotlin.jvm.JvmSuppressWildcards(suppress = false) - public static final int foo(boolean, @org.jetbrains.annotations.NotNull() Out);// foo(boolean, Out) + public static final int foo(boolean, @org.jetbrains.annotations.NotNull() Out);// foo(boolean, Out) @kotlin.jvm.JvmSuppressWildcards(suppress = true) @org.jetbrains.annotations.NotNull() @@ -27,10 +27,10 @@ public final class JvmWildcardAnnotationsKt /* JvmWildcardAnnotationsKt*/ { public static final Out foo2();// foo2() @kotlin.jvm.JvmSuppressWildcards(suppress = true) - public static final int bar(boolean, @org.jetbrains.annotations.NotNull() In, long);// bar(boolean, In, long) + public static final int bar(boolean, @org.jetbrains.annotations.NotNull() In, long);// bar(boolean, In, long) @kotlin.jvm.JvmSuppressWildcards(suppress = true) - public static final void deepOpen(@org.jetbrains.annotations.NotNull() Out>>);// deepOpen(Out>>) + public static final void deepOpen(@org.jetbrains.annotations.NotNull() Out>>);// deepOpen(Out>>) @org.jetbrains.annotations.NotNull() public static final OutPair, Out>> falseTrueFalse();// falseTrueFalse() diff --git a/compiler/testData/asJava/lightClasses/lightClassByPsi/jvmWildcardAnnotations.fir.java b/compiler/testData/asJava/lightClasses/lightClassByPsi/jvmWildcardAnnotations.fir.java index 147441a80df..bf59de0f9d3 100644 --- a/compiler/testData/asJava/lightClasses/lightClassByPsi/jvmWildcardAnnotations.fir.java +++ b/compiler/testData/asJava/lightClasses/lightClassByPsi/jvmWildcardAnnotations.fir.java @@ -13,19 +13,19 @@ public abstract interface B /* B*/ { public final class Container /* Container*/ { @kotlin.jvm.JvmSuppressWildcards(suppress = false) @org.jetbrains.annotations.NotNull() - public final Out bar();// bar() + public final Out bar();// bar() @kotlin.jvm.JvmSuppressWildcards(suppress = false) - public final int foo(boolean, @org.jetbrains.annotations.NotNull() Out);// foo(boolean, Out) + public final int foo(boolean, @org.jetbrains.annotations.NotNull() Out);// foo(boolean, Out) @kotlin.jvm.JvmSuppressWildcards(suppress = true) - public final int bar(boolean, @org.jetbrains.annotations.NotNull() In, long);// bar(boolean, In, long) + public final int bar(boolean, @org.jetbrains.annotations.NotNull() In, long);// bar(boolean, In, long) @kotlin.jvm.JvmSuppressWildcards(suppress = true) - public final void deepOpen(@org.jetbrains.annotations.NotNull() Out>>);// deepOpen(Out>>) + public final void deepOpen(@org.jetbrains.annotations.NotNull() Out>>);// deepOpen(Out>>) @kotlin.jvm.JvmSuppressWildcards(suppress = true) - public final void zoo(@org.jetbrains.annotations.NotNull() Out>>, @org.jetbrains.annotations.NotNull() Out);// zoo(Out>>, Out) + public final void zoo(@org.jetbrains.annotations.NotNull() Out>>, @org.jetbrains.annotations.NotNull() Out);// zoo(Out>>, Out) @org.jetbrains.annotations.NotNull() public final OutPair, Out>> falseTrueFalse();// falseTrueFalse() @@ -60,10 +60,10 @@ public final class ContainerForPropertyAndAccessors /* ContainerForPropertyAndAc public final Out getSimpleOut();// getSimpleOut() @org.jetbrains.annotations.NotNull() - public final Out getZoo(@org.jetbrains.annotations.NotNull() Out>>);// getZoo(Out>>) + public final Out getBar();// getBar() @org.jetbrains.annotations.NotNull() - public final Out getBar();// getBar() + public final Out getZoo(@org.jetbrains.annotations.NotNull() Out>>);// getZoo(Out>>) @org.jetbrains.annotations.NotNull() public final Out>> getDeepOpen();// getDeepOpen() @@ -81,7 +81,7 @@ public final class Final /* Final*/ { public final class HasAnnotation /* HasAnnotation*/ { public HasAnnotation();// .ctor() - public final void doesNot(@org.jetbrains.annotations.NotNull() Out>);// doesNot(Out>) + public final void doesNot(@org.jetbrains.annotations.NotNull() Out>);// doesNot(Out>) public final void parameterDisagrees(@org.jetbrains.annotations.NotNull() Out);// parameterDisagrees(Out) }