[FE, IR] Don't check SOURCE annotations if actual declaration has no source
^KT-58551
This commit is contained in:
committed by
Space Team
parent
59f1a0dd8e
commit
234f453173
+6
@@ -286,6 +286,12 @@ public class FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated extends Abst
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/optionalExpectation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("sourceRetentionAnnotationsWhenTypealias.kt")
|
||||
public void testSourceRetentionAnnotationsWhenTypealias() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/sourceRetentionAnnotationsWhenTypealias.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typealias.kt")
|
||||
public void testTypealias() throws Exception {
|
||||
|
||||
+6
@@ -286,6 +286,12 @@ public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFi
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/optionalExpectation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("sourceRetentionAnnotationsWhenTypealias.kt")
|
||||
public void testSourceRetentionAnnotationsWhenTypealias() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/sourceRetentionAnnotationsWhenTypealias.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typealias.kt")
|
||||
public void testTypealias() throws Exception {
|
||||
|
||||
+13
-1
@@ -11,13 +11,13 @@ import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.fir.FirExpectActualMatchingContext
|
||||
import org.jetbrains.kotlin.fir.FirExpectActualMatchingContextFactory
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.getRetention
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.coneType
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.scopes.*
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
@@ -353,8 +353,20 @@ class FirExpectActualMatchingContextImpl private constructor(
|
||||
private inner class AnnotationCallInfoImpl(val annotation: FirAnnotation) : AnnotationCallInfo {
|
||||
override val classId: ClassId?
|
||||
get() = annotation.toAnnotationClassId(actualSession)
|
||||
|
||||
override val isRetentionSource: Boolean
|
||||
get() = getAnnotationClass()?.getRetention(actualSession) == AnnotationRetention.SOURCE
|
||||
|
||||
private fun getAnnotationClass(): FirRegularClassSymbol? =
|
||||
annotation.annotationTypeRef.coneType.toRegularClassSymbol(actualSession)
|
||||
}
|
||||
|
||||
override val DeclarationSymbolMarker.hasSourceAnnotationsErased: Boolean
|
||||
get() {
|
||||
val symbol = asSymbol()
|
||||
return symbol.source != null || symbol.origin is FirDeclarationOrigin.Plugin
|
||||
}
|
||||
|
||||
object Factory : FirExpectActualMatchingContextFactory {
|
||||
override fun create(session: FirSession, scopeSession: ScopeSession): FirExpectActualMatchingContextImpl =
|
||||
FirExpectActualMatchingContextImpl(session, scopeSession)
|
||||
|
||||
+15
-4
@@ -6,19 +6,22 @@
|
||||
package org.jetbrains.kotlin.fir.analysis
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.findArgumentByName
|
||||
import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.references.toResolvedEnumEntrySymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
|
||||
fun FirRegularClass.getRetention(session: FirSession): AnnotationRetention {
|
||||
return getRetentionAnnotation(session)?.getRetention() ?: AnnotationRetention.RUNTIME
|
||||
}
|
||||
|
||||
fun FirRegularClassSymbol.getRetention(session: FirSession): AnnotationRetention {
|
||||
return getRetentionAnnotation(session)?.getRetention() ?: AnnotationRetention.RUNTIME
|
||||
}
|
||||
|
||||
fun FirAnnotation.getRetention(): AnnotationRetention? {
|
||||
val propertyAccess = findArgumentByName(StandardClassIds.Annotations.ParameterNames.retentionValue) as? FirQualifiedAccessExpression
|
||||
val callableId = propertyAccess?.calleeReference?.toResolvedEnumEntrySymbol()?.callableId ?: return null
|
||||
@@ -33,3 +36,11 @@ fun FirAnnotation.getRetention(): AnnotationRetention? {
|
||||
fun FirDeclaration.getRetentionAnnotation(session: FirSession): FirAnnotation? {
|
||||
return getAnnotationByClassId(StandardClassIds.Annotations.Retention, session)
|
||||
}
|
||||
|
||||
private fun FirRegularClassSymbol.getRetentionAnnotation(session: FirSession): FirAnnotation? {
|
||||
return getAnnotationByClassId(StandardClassIds.Annotations.Retention, session)
|
||||
}
|
||||
|
||||
private fun FirRegularClassSymbol.getAnnotationByClassId(classId: ClassId, session: FirSession): FirAnnotation? {
|
||||
return resolvedAnnotationsWithArguments.firstOrNull { it.toAnnotationClassId(session) == classId }
|
||||
}
|
||||
+3
-1
@@ -9,6 +9,7 @@ import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorBase
|
||||
import org.jetbrains.kotlin.mpp.K1SyntheticClassifierSymbolMarker
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
@@ -50,7 +51,8 @@ class SyntheticClassOrObjectDescriptor(
|
||||
constructorVisibility: DescriptorVisibility,
|
||||
private val kind: ClassKind,
|
||||
private val isCompanionObject: Boolean
|
||||
) : ClassDescriptorBase(c.storageManager, containingDeclaration, name, source, false), ClassDescriptorWithResolutionScopes {
|
||||
) : ClassDescriptorBase(c.storageManager, containingDeclaration, name, source, false), ClassDescriptorWithResolutionScopes,
|
||||
K1SyntheticClassifierSymbolMarker {
|
||||
val syntheticDeclaration: KtPureClassOrObject = SyntheticDeclaration(parentClassOrObject, name.asString())
|
||||
|
||||
private val thisDescriptor: SyntheticClassOrObjectDescriptor get() = this // code readability
|
||||
|
||||
+14
-1
@@ -5,13 +5,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.actualizer
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.sourceElement
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
@@ -464,5 +465,17 @@ internal abstract class IrExpectActualMatchingContext(
|
||||
private class AnnotationCallInfoImpl(val irElement: IrConstructorCall) : AnnotationCallInfo {
|
||||
override val classId: ClassId?
|
||||
get() = irElement.type.getClass()?.classId
|
||||
|
||||
override val isRetentionSource: Boolean
|
||||
get() {
|
||||
val annotationClass = irElement.symbol.owner.parent as? IrClass ?: return false
|
||||
return annotationClass.getAnnotationRetention() == KotlinRetention.SOURCE
|
||||
}
|
||||
}
|
||||
|
||||
override val DeclarationSymbolMarker.hasSourceAnnotationsErased: Boolean
|
||||
get() {
|
||||
val ir = asIr()
|
||||
return ir.sourceElement() != null || ir.origin is IrDeclarationOrigin.GeneratedByPlugin
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -28,12 +28,16 @@ object AbstractExpectActualAnnotationMatchChecker {
|
||||
return areAnnotationsCompatible(expectSymbol, expanded)
|
||||
}
|
||||
|
||||
val skipSourceAnnotations = !actualSymbol.hasSourceAnnotationsErased
|
||||
val actualAnnotationsByName = actualSymbol.annotations.groupBy { it.classId }
|
||||
|
||||
for (expectAnnotation in expectSymbol.annotations) {
|
||||
if (expectAnnotation.classId == StandardClassIds.Annotations.OptionalExpectation) {
|
||||
continue
|
||||
}
|
||||
if (expectAnnotation.isRetentionSource && skipSourceAnnotations) {
|
||||
continue
|
||||
}
|
||||
val actualAnnotationsWithSameClassId = actualAnnotationsByName[expectAnnotation.classId] ?: emptyList()
|
||||
if (actualAnnotationsWithSameClassId.none { areAnnotationArgumentsEqual(expectAnnotation, it) }) {
|
||||
return Incompatibility(expectSymbol, actualSymbol)
|
||||
|
||||
+3
-1
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.mpp.*
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
@@ -163,7 +162,10 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
|
||||
|
||||
fun areAnnotationArgumentsEqual(annotation1: AnnotationCallInfo, annotation2: AnnotationCallInfo): Boolean
|
||||
|
||||
val DeclarationSymbolMarker.hasSourceAnnotationsErased: Boolean
|
||||
|
||||
interface AnnotationCallInfo {
|
||||
val classId: ClassId?
|
||||
val isRetentionSource: Boolean
|
||||
}
|
||||
}
|
||||
|
||||
+14
-1
@@ -22,7 +22,10 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.*
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeSystemContext
|
||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.UnsafeCastFunction
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.castAll
|
||||
@@ -345,5 +348,15 @@ class ClassicExpectActualMatchingContext(val platformModule: ModuleDescriptor) :
|
||||
) : AnnotationCallInfo {
|
||||
override val classId: ClassId?
|
||||
get() = annotationDescriptor.annotationClass?.classId
|
||||
|
||||
override val isRetentionSource: Boolean
|
||||
get() = annotationDescriptor.isSourceAnnotation
|
||||
}
|
||||
|
||||
override val DeclarationSymbolMarker.hasSourceAnnotationsErased: Boolean
|
||||
get() {
|
||||
return DescriptorUtils.getContainingSourceFile(asDescriptor()) != SourceFile.NO_SOURCE_FILE ||
|
||||
this is K1SyntheticClassifierSymbolMarker ||
|
||||
this is CallableMemberDescriptor && kind == CallableMemberDescriptor.Kind.SYNTHESIZED
|
||||
}
|
||||
}
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// WITH_STDLIB
|
||||
// DIAGNOSTICS: -ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION
|
||||
// MODULE: m1-common
|
||||
// FILE: common.kt
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
annotation class Ann
|
||||
|
||||
@Ann
|
||||
expect class SourceAvailable {
|
||||
@Ann
|
||||
fun foo()
|
||||
}
|
||||
|
||||
@Ann
|
||||
expect annotation class FromLib
|
||||
|
||||
// MODULE: m1-jvm()()(m1-common)
|
||||
// FILE: jvm.kt
|
||||
class SourceAvailableImpl {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual typealias <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>SourceAvailable<!> = SourceAvailableImpl<!>
|
||||
|
||||
actual typealias FromLib = kotlin.SinceKotlin
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// WITH_STDLIB
|
||||
// DIAGNOSTICS: -ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION
|
||||
// MODULE: m1-common
|
||||
// FILE: common.kt
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
annotation class Ann
|
||||
|
||||
@Ann
|
||||
expect class SourceAvailable {
|
||||
@Ann
|
||||
fun foo()
|
||||
}
|
||||
|
||||
@Ann
|
||||
expect annotation class FromLib
|
||||
|
||||
// MODULE: m1-jvm()()(m1-common)
|
||||
// FILE: jvm.kt
|
||||
class SourceAvailableImpl {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
actual typealias <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>SourceAvailable<!> = SourceAvailableImpl
|
||||
|
||||
actual typealias FromLib = kotlin.SinceKotlin
|
||||
Generated
+6
@@ -22831,6 +22831,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/optionalExpectation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("sourceRetentionAnnotationsWhenTypealias.kt")
|
||||
public void testSourceRetentionAnnotationsWhenTypealias() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/sourceRetentionAnnotationsWhenTypealias.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typealias.kt")
|
||||
public void testTypealias() throws Exception {
|
||||
|
||||
@@ -25,4 +25,4 @@ interface TypeParameterSymbolMarker : ClassifierSymbolMarker
|
||||
interface ClassLikeSymbolMarker : ClassifierSymbolMarker
|
||||
interface RegularClassSymbolMarker : ClassLikeSymbolMarker
|
||||
interface TypeAliasSymbolMarker : ClassLikeSymbolMarker
|
||||
|
||||
interface K1SyntheticClassifierSymbolMarker : ClassifierSymbolMarker
|
||||
|
||||
Reference in New Issue
Block a user