[FE] Implement FE logic of expect actual annotations matching
This implementation only checks annotations set on expect/actual declarations and requires further refinement (e.g. checking of other annotation targets, class scopes within typealiases). ^KT-58551
This commit is contained in:
committed by
Space Team
parent
b1bdb619d8
commit
1a4ab9bb4b
+8
@@ -3504,6 +3504,14 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT) { firDiagnostic ->
|
||||||
|
ActualAnnotationsNotMatchExpectImpl(
|
||||||
|
firSymbolBuilder.buildSymbol(firDiagnostic.a),
|
||||||
|
firSymbolBuilder.buildSymbol(firDiagnostic.b),
|
||||||
|
firDiagnostic as KtPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION) { firDiagnostic ->
|
add(FirErrors.INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION) { firDiagnostic ->
|
||||||
InitializerRequiredForDestructuringDeclarationImpl(
|
InitializerRequiredForDestructuringDeclarationImpl(
|
||||||
firDiagnostic as KtPsiDiagnostic,
|
firDiagnostic as KtPsiDiagnostic,
|
||||||
|
|||||||
+6
@@ -2448,6 +2448,12 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
val typealiasedClassId: ClassId
|
val typealiasedClassId: ClassId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ActualAnnotationsNotMatchExpect : KtFirDiagnostic<KtElement> {
|
||||||
|
override val diagnosticClass get() = ActualAnnotationsNotMatchExpect::class
|
||||||
|
val expect: KtSymbol
|
||||||
|
val actual: KtSymbol
|
||||||
|
}
|
||||||
|
|
||||||
interface InitializerRequiredForDestructuringDeclaration : KtFirDiagnostic<KtDestructuringDeclaration> {
|
interface InitializerRequiredForDestructuringDeclaration : KtFirDiagnostic<KtDestructuringDeclaration> {
|
||||||
override val diagnosticClass get() = InitializerRequiredForDestructuringDeclaration::class
|
override val diagnosticClass get() = InitializerRequiredForDestructuringDeclaration::class
|
||||||
}
|
}
|
||||||
|
|||||||
+7
@@ -2952,6 +2952,13 @@ internal class ActualTypealiasToSpecialAnnotationImpl(
|
|||||||
token: KtLifetimeToken,
|
token: KtLifetimeToken,
|
||||||
) : KtAbstractFirDiagnostic<KtTypeAlias>(firDiagnostic, token), KtFirDiagnostic.ActualTypealiasToSpecialAnnotation
|
) : KtAbstractFirDiagnostic<KtTypeAlias>(firDiagnostic, token), KtFirDiagnostic.ActualTypealiasToSpecialAnnotation
|
||||||
|
|
||||||
|
internal class ActualAnnotationsNotMatchExpectImpl(
|
||||||
|
override val expect: KtSymbol,
|
||||||
|
override val actual: KtSymbol,
|
||||||
|
firDiagnostic: KtPsiDiagnostic,
|
||||||
|
token: KtLifetimeToken,
|
||||||
|
) : KtAbstractFirDiagnostic<KtElement>(firDiagnostic, token), KtFirDiagnostic.ActualAnnotationsNotMatchExpect
|
||||||
|
|
||||||
internal class InitializerRequiredForDestructuringDeclarationImpl(
|
internal class InitializerRequiredForDestructuringDeclarationImpl(
|
||||||
firDiagnostic: KtPsiDiagnostic,
|
firDiagnostic: KtPsiDiagnostic,
|
||||||
token: KtLifetimeToken,
|
token: KtLifetimeToken,
|
||||||
|
|||||||
+94
@@ -205,6 +205,100 @@ public class FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated extends Abst
|
|||||||
runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibilityInActualClassifier.kt");
|
runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibilityInActualClassifier.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/annotationMatching")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class AnnotationMatching {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInAnnotationMatching() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform/annotationMatching"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("annotationArgumentsConstExpressions.kt")
|
||||||
|
public void testAnnotationArgumentsConstExpressions() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/annotationArgumentsConstExpressions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("annotationArgumentsDefaults.kt")
|
||||||
|
public void testAnnotationArgumentsDefaults() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/annotationArgumentsDefaults.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("annotationTypeParameters.kt")
|
||||||
|
public void testAnnotationTypeParameters() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/annotationTypeParameters.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("basicOnDeclaration.kt")
|
||||||
|
public void testBasicOnDeclaration() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/basicOnDeclaration.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("checkDiagnosticFullText.kt")
|
||||||
|
public void testCheckDiagnosticFullText() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/checkDiagnosticFullText.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("compatibleOverrides.kt")
|
||||||
|
public void testCompatibleOverrides() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/compatibleOverrides.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("differentOrder.kt")
|
||||||
|
public void testDifferentOrder() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/differentOrder.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("floatNumbersComparison.kt")
|
||||||
|
public void testFloatNumbersComparison() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/floatNumbersComparison.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kclassArgWithExpectClass.kt")
|
||||||
|
public void testKclassArgWithExpectClass() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/kclassArgWithExpectClass.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kotlinAnaloguesForJavaAnnotations.kt")
|
||||||
|
public void testKotlinAnaloguesForJavaAnnotations() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/kotlinAnaloguesForJavaAnnotations.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("typealias.kt")
|
||||||
|
public void testTypealias() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typealias.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("typealiasToJavaLibrary.kt")
|
||||||
|
public void testTypealiasToJavaLibrary() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typealiasToJavaLibrary.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("typealiasToKtLibrary.kt")
|
||||||
|
public void testTypealiasToKtLibrary() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typealiasToKtLibrary.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("withOtherIncomatibilities.kt")
|
||||||
|
public void testWithOtherIncomatibilities() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/withOtherIncomatibilities.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/defaultArguments")
|
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/defaultArguments")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+94
@@ -205,6 +205,100 @@ public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFi
|
|||||||
runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibilityInActualClassifier.kt");
|
runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibilityInActualClassifier.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/annotationMatching")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class AnnotationMatching {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInAnnotationMatching() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform/annotationMatching"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("annotationArgumentsConstExpressions.kt")
|
||||||
|
public void testAnnotationArgumentsConstExpressions() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/annotationArgumentsConstExpressions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("annotationArgumentsDefaults.kt")
|
||||||
|
public void testAnnotationArgumentsDefaults() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/annotationArgumentsDefaults.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("annotationTypeParameters.kt")
|
||||||
|
public void testAnnotationTypeParameters() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/annotationTypeParameters.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("basicOnDeclaration.kt")
|
||||||
|
public void testBasicOnDeclaration() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/basicOnDeclaration.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("checkDiagnosticFullText.kt")
|
||||||
|
public void testCheckDiagnosticFullText() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/checkDiagnosticFullText.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("compatibleOverrides.kt")
|
||||||
|
public void testCompatibleOverrides() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/compatibleOverrides.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("differentOrder.kt")
|
||||||
|
public void testDifferentOrder() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/differentOrder.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("floatNumbersComparison.kt")
|
||||||
|
public void testFloatNumbersComparison() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/floatNumbersComparison.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kclassArgWithExpectClass.kt")
|
||||||
|
public void testKclassArgWithExpectClass() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/kclassArgWithExpectClass.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kotlinAnaloguesForJavaAnnotations.kt")
|
||||||
|
public void testKotlinAnaloguesForJavaAnnotations() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/kotlinAnaloguesForJavaAnnotations.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("typealias.kt")
|
||||||
|
public void testTypealias() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typealias.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("typealiasToJavaLibrary.kt")
|
||||||
|
public void testTypealiasToJavaLibrary() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typealiasToJavaLibrary.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("typealiasToKtLibrary.kt")
|
||||||
|
public void testTypealiasToKtLibrary() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typealiasToKtLibrary.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("withOtherIncomatibilities.kt")
|
||||||
|
public void testWithOtherIncomatibilities() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/withOtherIncomatibilities.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/defaultArguments")
|
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/defaultArguments")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+5
@@ -1180,6 +1180,11 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
|||||||
val ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION by error<KtTypeAlias>(PositioningStrategy.TYPEALIAS_TYPE_REFERENCE) {
|
val ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION by error<KtTypeAlias>(PositioningStrategy.TYPEALIAS_TYPE_REFERENCE) {
|
||||||
parameter<ClassId>("typealiasedClassId")
|
parameter<ClassId>("typealiasedClassId")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT by warning<KtElement>(PositioningStrategy.DECLARATION_NAME_ONLY) {
|
||||||
|
parameter<Symbol>("expect")
|
||||||
|
parameter<Symbol>("actual")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val DESTRUCTING_DECLARATION by object : DiagnosticGroup("Destructuring declaration") {
|
val DESTRUCTING_DECLARATION by object : DiagnosticGroup("Destructuring declaration") {
|
||||||
|
|||||||
@@ -628,6 +628,7 @@ object FirErrors {
|
|||||||
val NOT_A_MULTIPLATFORM_COMPILATION by error0<PsiElement>()
|
val NOT_A_MULTIPLATFORM_COMPILATION by error0<PsiElement>()
|
||||||
val EXPECT_ACTUAL_OPT_IN_ANNOTATION by error0<KtNamedDeclaration>(SourceElementPositioningStrategies.EXPECT_ACTUAL_MODIFIER)
|
val EXPECT_ACTUAL_OPT_IN_ANNOTATION by error0<KtNamedDeclaration>(SourceElementPositioningStrategies.EXPECT_ACTUAL_MODIFIER)
|
||||||
val ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION by error1<KtTypeAlias, ClassId>(SourceElementPositioningStrategies.TYPEALIAS_TYPE_REFERENCE)
|
val ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION by error1<KtTypeAlias, ClassId>(SourceElementPositioningStrategies.TYPEALIAS_TYPE_REFERENCE)
|
||||||
|
val ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT by warning2<KtElement, FirBasedSymbol<*>, FirBasedSymbol<*>>(SourceElementPositioningStrategies.DECLARATION_NAME_ONLY)
|
||||||
|
|
||||||
// Destructuring declaration
|
// Destructuring declaration
|
||||||
val INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION by error0<KtDestructuringDeclaration>()
|
val INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION by error0<KtDestructuringDeclaration>()
|
||||||
|
|||||||
+27
-4
@@ -20,17 +20,20 @@ import org.jetbrains.kotlin.fir.declarations.utils.isActual
|
|||||||
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isExternal
|
import org.jetbrains.kotlin.fir.declarations.utils.isExternal
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isTailRec
|
import org.jetbrains.kotlin.fir.declarations.utils.isTailRec
|
||||||
|
import org.jetbrains.kotlin.fir.expectActualMatchingContextFactory
|
||||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.fir.scopes.collectAllFunctions
|
import org.jetbrains.kotlin.fir.scopes.collectAllFunctions
|
||||||
import org.jetbrains.kotlin.fir.scopes.getDeclaredConstructors
|
import org.jetbrains.kotlin.fir.scopes.getDeclaredConstructors
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
|
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.coneType
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.toSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.name.StandardClassIds
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualAnnotationMatchChecker
|
||||||
import org.jetbrains.kotlin.resolve.checkers.OptInNames
|
import org.jetbrains.kotlin.resolve.checkers.OptInNames
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.*
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.*
|
||||||
@@ -176,7 +179,9 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() {
|
|||||||
|
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
val expectedSingleCandidate = symbol.getSingleExpectForActualOrNull()
|
// We want to report errors even if a candidate is incompatible, but it's single
|
||||||
|
val expectedSingleCandidate = compatibilityToMembersMap[Compatible]?.singleOrNull()
|
||||||
|
?: symbol.getSingleExpectForActualOrNull()
|
||||||
if (expectedSingleCandidate != null) {
|
if (expectedSingleCandidate != null) {
|
||||||
checkIfExpectHasDefaultArgumentsAndActualizedWithTypealias(
|
checkIfExpectHasDefaultArgumentsAndActualizedWithTypealias(
|
||||||
expectedSingleCandidate,
|
expectedSingleCandidate,
|
||||||
@@ -185,6 +190,7 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() {
|
|||||||
reporter,
|
reporter,
|
||||||
)
|
)
|
||||||
checkOptInAnnotation(declaration, expectedSingleCandidate, context, reporter)
|
checkOptInAnnotation(declaration, expectedSingleCandidate, context, reporter)
|
||||||
|
checkAnnotationsMatch(expectedSingleCandidate, symbol, context, reporter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,6 +249,23 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun checkAnnotationsMatch(
|
||||||
|
expectSymbol: FirBasedSymbol<*>,
|
||||||
|
actualSymbol: FirBasedSymbol<*>,
|
||||||
|
context: CheckerContext,
|
||||||
|
reporter: DiagnosticReporter
|
||||||
|
) {
|
||||||
|
val matchingContext = context.session.expectActualMatchingContextFactory.create(context.session, context.scopeSession)
|
||||||
|
val incompatibility =
|
||||||
|
AbstractExpectActualAnnotationMatchChecker.areAnnotationsCompatible(expectSymbol, actualSymbol, matchingContext) ?: return
|
||||||
|
reporter.reportOn(
|
||||||
|
actualSymbol.source, FirErrors.ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT,
|
||||||
|
incompatibility.expectSymbol as FirBasedSymbol<*>,
|
||||||
|
incompatibility.actualSymbol as FirBasedSymbol<*>,
|
||||||
|
context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun Map<out ExpectActualCompatibility<*>, *>.allStrongIncompatibilities(): Boolean {
|
fun Map<out ExpectActualCompatibility<*>, *>.allStrongIncompatibilities(): Boolean {
|
||||||
return keys.all { it is Incompatible && it.kind == IncompatibilityKind.STRONG }
|
return keys.all { it is Incompatible && it.kind == IncompatibilityKind.STRONG }
|
||||||
}
|
}
|
||||||
|
|||||||
+10
@@ -178,4 +178,14 @@ object FirDiagnosticRenderers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val FUNCTIONAL_TYPE_KINDS = KtDiagnosticRenderers.COLLECTION(FUNCTIONAL_TYPE_KIND)
|
val FUNCTIONAL_TYPE_KINDS = KtDiagnosticRenderers.COLLECTION(FUNCTIONAL_TYPE_KIND)
|
||||||
|
|
||||||
|
@OptIn(SymbolInternals::class)
|
||||||
|
val SYMBOL_WITH_ANNOTATIONS = Renderer { s: FirBasedSymbol<*> ->
|
||||||
|
FirRenderer(
|
||||||
|
typeRenderer = ConeTypeRenderer(),
|
||||||
|
idRenderer = ConeIdShortRenderer(),
|
||||||
|
classMemberRenderer = null,
|
||||||
|
bodyRenderer = null,
|
||||||
|
).renderElementAsString(s.fir, trim = true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
@@ -51,6 +51,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_PROPERTY
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_SUPER_CALL
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_SUPER_CALL
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_SUPER_CALL_WARNING
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_SUPER_CALL_WARNING
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACCESSOR_FOR_DELEGATED_PROPERTY
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACCESSOR_FOR_DELEGATED_PROPERTY
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_MISSING
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_MISSING
|
||||||
@@ -1854,6 +1855,13 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
|||||||
"`actual typealias` to annotation which affects code compilation can lead to incorrect behavior. Instead, use ''{0}'' annotation directly.",
|
"`actual typealias` to annotation which affects code compilation can lead to incorrect behavior. Instead, use ''{0}'' annotation directly.",
|
||||||
TO_STRING
|
TO_STRING
|
||||||
)
|
)
|
||||||
|
map.put(
|
||||||
|
ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT,
|
||||||
|
"All annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.\n" +
|
||||||
|
"Expected: {0}\n" +
|
||||||
|
"Actual: {1}",
|
||||||
|
FirDiagnosticRenderers.SYMBOL_WITH_ANNOTATIONS, FirDiagnosticRenderers.SYMBOL_WITH_ANNOTATIONS
|
||||||
|
)
|
||||||
|
|
||||||
// Destructuring declaration
|
// Destructuring declaration
|
||||||
map.put(INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION, "Initializer required for destructuring declaration")
|
map.put(INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION, "Initializer required for destructuring declaration")
|
||||||
|
|||||||
+48
-4
@@ -11,12 +11,13 @@ import org.jetbrains.kotlin.descriptors.Visibility
|
|||||||
import org.jetbrains.kotlin.fir.FirExpectActualMatchingContext
|
import org.jetbrains.kotlin.fir.FirExpectActualMatchingContext
|
||||||
import org.jetbrains.kotlin.fir.FirExpectActualMatchingContextFactory
|
import org.jetbrains.kotlin.fir.FirExpectActualMatchingContextFactory
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||||
import org.jetbrains.kotlin.fir.declarations.collectEnumEntries
|
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||||
import org.jetbrains.kotlin.fir.declarations.isAnnotationConstructor
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride
|
import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride
|
||||||
import org.jetbrains.kotlin.fir.resolve.*
|
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.resolve.substitution.ConeSubstitutor
|
||||||
import org.jetbrains.kotlin.fir.scopes.*
|
import org.jetbrains.kotlin.fir.scopes.*
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
@@ -26,6 +27,7 @@ import org.jetbrains.kotlin.mpp.*
|
|||||||
import org.jetbrains.kotlin.name.CallableId
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext.AnnotationCallInfo
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
import org.jetbrains.kotlin.types.TypeCheckerState
|
import org.jetbrains.kotlin.types.TypeCheckerState
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
@@ -311,6 +313,48 @@ class FirExpectActualMatchingContextImpl private constructor(
|
|||||||
override val CallableSymbolMarker.hasStableParameterNames: Boolean
|
override val CallableSymbolMarker.hasStableParameterNames: Boolean
|
||||||
get() = asSymbol().rawStatus.hasStableParameterNames
|
get() = asSymbol().rawStatus.hasStableParameterNames
|
||||||
|
|
||||||
|
override val DeclarationSymbolMarker.annotations: List<AnnotationCallInfo>
|
||||||
|
get() = asSymbol().resolvedAnnotationsWithArguments.map(::AnnotationCallInfoImpl)
|
||||||
|
|
||||||
|
override fun areAnnotationArgumentsEqual(annotation1: AnnotationCallInfo, annotation2: AnnotationCallInfo): Boolean {
|
||||||
|
fun AnnotationCallInfo.getFirAnnotation(): FirAnnotation {
|
||||||
|
return (this as AnnotationCallInfoImpl).annotation
|
||||||
|
}
|
||||||
|
return areFirAnnotationsEqual(annotation1.getFirAnnotation(), annotation2.getFirAnnotation())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun areFirAnnotationsEqual(annotation1: FirAnnotation, annotation2: FirAnnotation): Boolean {
|
||||||
|
if (!areCompatibleExpectActualTypes(annotation1.typeRef.coneType, annotation2.typeRef.coneType)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
val args1 = annotation1.argumentMapping.mapping
|
||||||
|
val args2 = annotation2.argumentMapping.mapping
|
||||||
|
if (args1.size != args2.size) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return args1.all { (key, value1) ->
|
||||||
|
val value2 = args2[key]
|
||||||
|
value2 != null && areAnnotationArgumentsEqual(value1, value2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun areAnnotationArgumentsEqual(expression1: FirExpression, expression2: FirExpression): Boolean {
|
||||||
|
// In K2 const expression calculated in backend.
|
||||||
|
// Because of that, we have "honest" checker at backend IR stage
|
||||||
|
// and "only simplest case" checker in frontend, so that we have at least some reporting in the IDE.
|
||||||
|
return when {
|
||||||
|
expression1 is FirConstExpression<*> && expression2 is FirConstExpression<*> -> {
|
||||||
|
expression1.value == expression2.value
|
||||||
|
}
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class AnnotationCallInfoImpl(val annotation: FirAnnotation) : AnnotationCallInfo {
|
||||||
|
override val classId: ClassId?
|
||||||
|
get() = annotation.toAnnotationClassId(actualSession)
|
||||||
|
}
|
||||||
|
|
||||||
object Factory : FirExpectActualMatchingContextFactory {
|
object Factory : FirExpectActualMatchingContextFactory {
|
||||||
override fun create(session: FirSession, scopeSession: ScopeSession): FirExpectActualMatchingContextImpl =
|
override fun create(session: FirSession, scopeSession: ScopeSession): FirExpectActualMatchingContextImpl =
|
||||||
FirExpectActualMatchingContextImpl(session, scopeSession)
|
FirExpectActualMatchingContextImpl(session, scopeSession)
|
||||||
|
|||||||
@@ -840,6 +840,8 @@ public interface Errors {
|
|||||||
DiagnosticFactory0<KtNamedDeclaration> EXPECT_ACTUAL_OPT_IN_ANNOTATION = DiagnosticFactory0.create(ERROR, EXPECT_ACTUAL_MODIFIER);
|
DiagnosticFactory0<KtNamedDeclaration> EXPECT_ACTUAL_OPT_IN_ANNOTATION = DiagnosticFactory0.create(ERROR, EXPECT_ACTUAL_MODIFIER);
|
||||||
DiagnosticFactory1<KtTypeAlias, ClassId> ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION =
|
DiagnosticFactory1<KtTypeAlias, ClassId> ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION =
|
||||||
DiagnosticFactory1.create(ERROR, TYPEALIAS_TYPE_REFERENCE);
|
DiagnosticFactory1.create(ERROR, TYPEALIAS_TYPE_REFERENCE);
|
||||||
|
DiagnosticFactory2<KtNamedDeclaration, DeclarationDescriptor, DeclarationDescriptor> ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT
|
||||||
|
= DiagnosticFactory2.create(WARNING, DECLARATION_NAME_ONLY);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|||||||
+5
@@ -396,6 +396,11 @@ public class DefaultErrorMessages {
|
|||||||
MAP.put(ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION,
|
MAP.put(ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION,
|
||||||
"`actual typealias` to annotation which affects code compilation can lead to incorrect behavior. Instead, use ''{0}'' annotation directly.",
|
"`actual typealias` to annotation which affects code compilation can lead to incorrect behavior. Instead, use ''{0}'' annotation directly.",
|
||||||
TO_STRING);
|
TO_STRING);
|
||||||
|
MAP.put(ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT,
|
||||||
|
"All annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.\n" +
|
||||||
|
" Expected: {0}\n" +
|
||||||
|
" Actual: {1}",
|
||||||
|
DESCRIPTOR_WITH_ANNOTATIONS, DESCRIPTOR_WITH_ANNOTATIONS);
|
||||||
|
|
||||||
MAP.put(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT, "Projections are not allowed on type arguments of functions and properties");
|
MAP.put(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT, "Projections are not allowed on type arguments of functions and properties");
|
||||||
MAP.put(SUPERTYPE_NOT_INITIALIZED, "This type has a constructor, and thus must be initialized here");
|
MAP.put(SUPERTYPE_NOT_INITIALIZED, "This type has a constructor, and thus must be initialized here");
|
||||||
|
|||||||
@@ -32,8 +32,10 @@ import org.jetbrains.kotlin.name.FqNameUnsafe
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.platform.isCommon
|
import org.jetbrains.kotlin.platform.isCommon
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.renderer.AnnotationArgumentsRenderingPolicy
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer.Companion.DEBUG_TEXT
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer.Companion.DEBUG_TEXT
|
||||||
|
import org.jetbrains.kotlin.renderer.DescriptorRendererModifier
|
||||||
import org.jetbrains.kotlin.renderer.PropertyAccessorRenderingPolicy
|
import org.jetbrains.kotlin.renderer.PropertyAccessorRenderingPolicy
|
||||||
import org.jetbrains.kotlin.resolve.*
|
import org.jetbrains.kotlin.resolve.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.*
|
import org.jetbrains.kotlin.resolve.calls.inference.*
|
||||||
@@ -708,6 +710,14 @@ object Renderers {
|
|||||||
val SHORT_NAMES_IN_TYPES = DescriptorRenderer.SHORT_NAMES_IN_TYPES.asRenderer()
|
val SHORT_NAMES_IN_TYPES = DescriptorRenderer.SHORT_NAMES_IN_TYPES.asRenderer()
|
||||||
@JvmField
|
@JvmField
|
||||||
val COMPACT_WITH_MODIFIERS = DescriptorRenderer.COMPACT_WITH_MODIFIERS.asRenderer()
|
val COMPACT_WITH_MODIFIERS = DescriptorRenderer.COMPACT_WITH_MODIFIERS.asRenderer()
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val DESCRIPTOR_WITH_ANNOTATIONS = DescriptorRenderer.withOptions {
|
||||||
|
annotationArgumentsRenderingPolicy = AnnotationArgumentsRenderingPolicy.UNLESS_EMPTY
|
||||||
|
modifiers = modifiers.plus(DescriptorRendererModifier.ANNOTATIONS)
|
||||||
|
withDefinedIn = true
|
||||||
|
}.asRenderer()
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
val DEPRECATION_RENDERER = DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES.withOptions {
|
val DEPRECATION_RENDERER = DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES.withOptions {
|
||||||
withoutTypeParameters = false
|
withoutTypeParameters = false
|
||||||
|
|||||||
+22
-1
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
|
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
|
||||||
import org.jetbrains.kotlin.resolve.*
|
import org.jetbrains.kotlin.resolve.*
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualAnnotationMatchChecker
|
||||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isAnnotationConstructor
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isAnnotationConstructor
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isPrimaryConstructorOfInlineClass
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isPrimaryConstructorOfInlineClass
|
||||||
@@ -338,9 +339,11 @@ class ExpectedActualDeclarationChecker(
|
|||||||
checkOptInAnnotation(reportOn, descriptor, expected, trace)
|
checkOptInAnnotation(reportOn, descriptor, expected, trace)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val expectSingleCandidate = compatibility.values.singleOrNull()?.singleOrNull()
|
// We want to report errors even if a candidate is incompatible, but it's single
|
||||||
|
val expectSingleCandidate = (compatibility[Compatible] ?: compatibility.values.singleOrNull())?.singleOrNull()
|
||||||
if (expectSingleCandidate != null) {
|
if (expectSingleCandidate != null) {
|
||||||
checkIfExpectHasDefaultArgumentsAndActualizedWithTypealias(expectSingleCandidate, reportOn, trace)
|
checkIfExpectHasDefaultArgumentsAndActualizedWithTypealias(expectSingleCandidate, reportOn, trace)
|
||||||
|
checkAnnotationsMatch(expectSingleCandidate, descriptor, reportOn, trace)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,6 +446,24 @@ class ExpectedActualDeclarationChecker(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun checkAnnotationsMatch(
|
||||||
|
expectDescriptor: MemberDescriptor,
|
||||||
|
actualDescriptor: MemberDescriptor,
|
||||||
|
reportOn: KtNamedDeclaration,
|
||||||
|
trace: BindingTrace
|
||||||
|
) {
|
||||||
|
val context = ClassicExpectActualMatchingContext(actualDescriptor.module)
|
||||||
|
val incompatibility =
|
||||||
|
AbstractExpectActualAnnotationMatchChecker.areAnnotationsCompatible(expectDescriptor, actualDescriptor, context) ?: return
|
||||||
|
trace.report(
|
||||||
|
Errors.ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT.on(
|
||||||
|
reportOn,
|
||||||
|
incompatibility.expectSymbol as DeclarationDescriptor,
|
||||||
|
incompatibility.actualSymbol as DeclarationDescriptor
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun Map<out ExpectActualCompatibility<MemberDescriptor>, Collection<MemberDescriptor>>.allStrongIncompatibilities(): Boolean =
|
fun Map<out ExpectActualCompatibility<MemberDescriptor>, Collection<MemberDescriptor>>.allStrongIncompatibilities(): Boolean =
|
||||||
this.keys.all { it is Incompatible && it.kind == IncompatibilityKind.STRONG }
|
this.keys.all { it is Incompatible && it.kind == IncompatibilityKind.STRONG }
|
||||||
|
|||||||
+15
-1
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.Modality
|
|||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||||
@@ -25,7 +26,10 @@ import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext
|
|||||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
import org.jetbrains.kotlin.types.TypeCheckerState
|
import org.jetbrains.kotlin.types.TypeCheckerState
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.types.model.*
|
import org.jetbrains.kotlin.types.model.AnnotationMarker
|
||||||
|
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||||
|
import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker
|
||||||
|
import org.jetbrains.kotlin.types.model.TypeSystemContext
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.UnsafeCastFunction
|
import org.jetbrains.kotlin.utils.addToStdlib.UnsafeCastFunction
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.castAll
|
import org.jetbrains.kotlin.utils.addToStdlib.castAll
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
|
import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
|
||||||
@@ -75,6 +79,7 @@ internal abstract class IrExpectActualMatchingContext(
|
|||||||
private fun TypeParameterSymbolMarker.asIr(): IrTypeParameter = (this as IrTypeParameterSymbol).owner
|
private fun TypeParameterSymbolMarker.asIr(): IrTypeParameter = (this as IrTypeParameterSymbol).owner
|
||||||
private fun RegularClassSymbolMarker.asIr(): IrClass = (this as IrClassSymbol).owner
|
private fun RegularClassSymbolMarker.asIr(): IrClass = (this as IrClassSymbol).owner
|
||||||
private fun TypeAliasSymbolMarker.asIr(): IrTypeAlias = (this as IrTypeAliasSymbol).owner
|
private fun TypeAliasSymbolMarker.asIr(): IrTypeAlias = (this as IrTypeAliasSymbol).owner
|
||||||
|
private fun AnnotationMarker.asIr(): IrConstructorCall = this as IrConstructorCall
|
||||||
|
|
||||||
private inline fun <reified T : IrDeclaration> DeclarationSymbolMarker.safeAsIr(): T? = (this as IrSymbol).owner as? T
|
private inline fun <reified T : IrDeclaration> DeclarationSymbolMarker.safeAsIr(): T? = (this as IrSymbol).owner as? T
|
||||||
|
|
||||||
@@ -440,4 +445,13 @@ internal abstract class IrExpectActualMatchingContext(
|
|||||||
|
|
||||||
abstract fun onMatchedClasses(expectClassSymbol: IrClassSymbol, actualClassSymbol: IrClassSymbol)
|
abstract fun onMatchedClasses(expectClassSymbol: IrClassSymbol, actualClassSymbol: IrClassSymbol)
|
||||||
abstract fun onMatchedCallables(expectSymbol: IrSymbol, actualSymbol: IrSymbol)
|
abstract fun onMatchedCallables(expectSymbol: IrSymbol, actualSymbol: IrSymbol)
|
||||||
|
|
||||||
|
override val DeclarationSymbolMarker.annotations: List<ExpectActualMatchingContext.AnnotationCallInfo>
|
||||||
|
// TODO(Roman.Efremov): implement in subsequent commits
|
||||||
|
get() = emptyList()
|
||||||
|
|
||||||
|
override fun areAnnotationArgumentsEqual(annotation1: ExpectActualMatchingContext.AnnotationCallInfo, annotation2: ExpectActualMatchingContext.AnnotationCallInfo): Boolean {
|
||||||
|
// TODO(Roman.Efremov): implement in subsequent commits
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* 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.resolve.calls.mpp
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.mpp.DeclarationSymbolMarker
|
||||||
|
import org.jetbrains.kotlin.mpp.TypeAliasSymbolMarker
|
||||||
|
|
||||||
|
object AbstractExpectActualAnnotationMatchChecker {
|
||||||
|
class Incompatibility(val expectSymbol: DeclarationSymbolMarker, val actualSymbol: DeclarationSymbolMarker)
|
||||||
|
|
||||||
|
fun areAnnotationsCompatible(
|
||||||
|
expectSymbol: DeclarationSymbolMarker,
|
||||||
|
actualSymbol: DeclarationSymbolMarker,
|
||||||
|
context: ExpectActualMatchingContext<*>,
|
||||||
|
): Incompatibility? = with(context) { areAnnotationsCompatible(expectSymbol, actualSymbol) }
|
||||||
|
|
||||||
|
context (ExpectActualMatchingContext<*>)
|
||||||
|
private fun areAnnotationsCompatible(
|
||||||
|
expectSymbol: DeclarationSymbolMarker,
|
||||||
|
actualSymbol: DeclarationSymbolMarker,
|
||||||
|
): Incompatibility? {
|
||||||
|
if (actualSymbol is TypeAliasSymbolMarker) {
|
||||||
|
val expanded = actualSymbol.expandToRegularClass() ?: return null
|
||||||
|
return areAnnotationsCompatible(expectSymbol, expanded)
|
||||||
|
}
|
||||||
|
|
||||||
|
val actualAnnotationsByName = actualSymbol.annotations.groupBy { it.classId }
|
||||||
|
|
||||||
|
for (expectAnnotation in expectSymbol.annotations) {
|
||||||
|
val actualAnnotationsWithSameClassId = actualAnnotationsByName[expectAnnotation.classId] ?: emptyList()
|
||||||
|
if (actualAnnotationsWithSameClassId.none { areAnnotationArgumentsEqual(expectAnnotation, it) }) {
|
||||||
|
return Incompatibility(expectSymbol, actualSymbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.Visibility
|
|||||||
import org.jetbrains.kotlin.mpp.*
|
import org.jetbrains.kotlin.mpp.*
|
||||||
import org.jetbrains.kotlin.name.CallableId
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
@@ -157,4 +158,12 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
|
|||||||
expectSymbol: DeclarationSymbolMarker,
|
expectSymbol: DeclarationSymbolMarker,
|
||||||
actualSymbolsByIncompatibility: Map<ExpectActualCompatibility.Incompatible<*>, List<DeclarationSymbolMarker>>
|
actualSymbolsByIncompatibility: Map<ExpectActualCompatibility.Incompatible<*>, List<DeclarationSymbolMarker>>
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
val DeclarationSymbolMarker.annotations: List<AnnotationCallInfo>
|
||||||
|
|
||||||
|
fun areAnnotationArgumentsEqual(annotation1: AnnotationCallInfo, annotation2: AnnotationCallInfo): Boolean
|
||||||
|
|
||||||
|
interface AnnotationCallInfo {
|
||||||
|
val classId: ClassId?
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-3
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.resolve.multiplatform
|
package org.jetbrains.kotlin.resolve.multiplatform
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.mpp.*
|
import org.jetbrains.kotlin.mpp.*
|
||||||
import org.jetbrains.kotlin.name.CallableId
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
@@ -14,9 +15,8 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.ClassicTypeSystemContextForCS
|
import org.jetbrains.kotlin.resolve.calls.components.ClassicTypeSystemContextForCS
|
||||||
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext
|
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext.AnnotationCallInfo
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getKotlinTypeRefiner
|
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isTypeRefinementEnabled
|
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
||||||
@@ -35,6 +35,7 @@ class ClassicExpectActualMatchingContext(val platformModule: ModuleDescriptor) :
|
|||||||
override val shouldCheckReturnTypesOfCallables: Boolean
|
override val shouldCheckReturnTypesOfCallables: Boolean
|
||||||
get() = true
|
get() = true
|
||||||
|
|
||||||
|
private fun DeclarationSymbolMarker.asDescriptor(): DeclarationDescriptor = this as DeclarationDescriptor
|
||||||
private fun CallableSymbolMarker.asDescriptor(): CallableDescriptor = this as CallableDescriptor
|
private fun CallableSymbolMarker.asDescriptor(): CallableDescriptor = this as CallableDescriptor
|
||||||
private fun FunctionSymbolMarker.asDescriptor(): FunctionDescriptor = this as FunctionDescriptor
|
private fun FunctionSymbolMarker.asDescriptor(): FunctionDescriptor = this as FunctionDescriptor
|
||||||
private fun PropertySymbolMarker.asDescriptor(): PropertyDescriptor = this as PropertyDescriptor
|
private fun PropertySymbolMarker.asDescriptor(): PropertyDescriptor = this as PropertyDescriptor
|
||||||
@@ -328,4 +329,21 @@ class ClassicExpectActualMatchingContext(val platformModule: ModuleDescriptor) :
|
|||||||
|
|
||||||
override val CallableSymbolMarker.hasStableParameterNames: Boolean
|
override val CallableSymbolMarker.hasStableParameterNames: Boolean
|
||||||
get() = asDescriptor().hasStableParameterNames()
|
get() = asDescriptor().hasStableParameterNames()
|
||||||
|
|
||||||
|
override val DeclarationSymbolMarker.annotations: List<AnnotationCallInfo>
|
||||||
|
get() = asDescriptor().annotations.map(::AnnotationCallInfoImpl)
|
||||||
|
|
||||||
|
|
||||||
|
override fun areAnnotationArgumentsEqual(annotation1: AnnotationCallInfo, annotation2: AnnotationCallInfo): Boolean {
|
||||||
|
fun AnnotationCallInfo.getDescriptor(): AnnotationDescriptor = (this as AnnotationCallInfoImpl).annotationDescriptor
|
||||||
|
|
||||||
|
return areExpressionConstValuesEqual(annotation1.getDescriptor(), annotation2.getDescriptor())
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AnnotationCallInfoImpl(
|
||||||
|
val annotationDescriptor: AnnotationDescriptor,
|
||||||
|
) : AnnotationCallInfo {
|
||||||
|
override val classId: ClassId?
|
||||||
|
get() = annotationDescriptor.annotationClass?.classId
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* 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.resolve.multiplatform
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||||
|
|
||||||
|
internal fun ExpectActualMatchingContext<*>.areExpressionConstValuesEqual(a: Any?, b: Any?): Boolean {
|
||||||
|
return when {
|
||||||
|
a is AnnotationDescriptor && b is AnnotationDescriptor -> {
|
||||||
|
val aArgs = a.allValueArguments
|
||||||
|
val bArgs = b.allValueArguments
|
||||||
|
a.fqName == b.fqName &&
|
||||||
|
aArgs.size == bArgs.size &&
|
||||||
|
areCompatibleExpectActualTypes(a.type, b.type) &&
|
||||||
|
aArgs.keys.all { k -> areExpressionConstValuesEqual(aArgs[k], bArgs[k]) }
|
||||||
|
}
|
||||||
|
a is ConstantValue<*> && b is ConstantValue<*> -> {
|
||||||
|
areExpressionConstValuesEqual(a.value, b.value)
|
||||||
|
}
|
||||||
|
a is Collection<*> && b is Collection<*> -> {
|
||||||
|
a.size == b.size && a.zip(b).all { (f, s) -> areExpressionConstValuesEqual(f, s) }
|
||||||
|
}
|
||||||
|
a is Array<*> && b is Array<*> -> {
|
||||||
|
a.size == b.size && a.zip(b).all { (f, s) -> areExpressionConstValuesEqual(f, s) }
|
||||||
|
}
|
||||||
|
else -> a == b
|
||||||
|
}
|
||||||
|
}
|
||||||
+138
@@ -0,0 +1,138 @@
|
|||||||
|
// WITH_STDLIB
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
package test
|
||||||
|
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
annotation class ClassArgAnn(val clazz: KClass<*>)
|
||||||
|
|
||||||
|
class ClassForReference {
|
||||||
|
class ClassForReference
|
||||||
|
}
|
||||||
|
|
||||||
|
@ClassArgAnn(ClassForReference::class)
|
||||||
|
expect fun getClassExpression()
|
||||||
|
|
||||||
|
@ClassArgAnn(ClassForReference.ClassForReference::class)
|
||||||
|
expect fun differentClassesWithSameName()
|
||||||
|
|
||||||
|
annotation class StringArgAnn(val s: String)
|
||||||
|
|
||||||
|
@StringArgAnn("1.9")
|
||||||
|
expect fun stringConstant()
|
||||||
|
|
||||||
|
@StringArgAnn("1" + ".9")
|
||||||
|
expect fun stringConcatentation()
|
||||||
|
|
||||||
|
object Constants {
|
||||||
|
const val STR = "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
@StringArgAnn(Constants.STR)
|
||||||
|
expect fun constantFromInsideObject()
|
||||||
|
|
||||||
|
@StringArgAnn(Constants.STR + ".9")
|
||||||
|
expect fun stringConcatentationWithProperty()
|
||||||
|
|
||||||
|
enum class MyEnum { FOO, BAR }
|
||||||
|
|
||||||
|
annotation class EnumArgAnn(val e: MyEnum)
|
||||||
|
|
||||||
|
@EnumArgAnn(MyEnum.FOO)
|
||||||
|
expect fun enumArg()
|
||||||
|
|
||||||
|
annotation class VarargAnn(vararg val strings: String)
|
||||||
|
|
||||||
|
@VarargAnn("foo", "bar")
|
||||||
|
expect fun varargInAnnotation()
|
||||||
|
|
||||||
|
@VarargAnn(*["foo", "bar"])
|
||||||
|
expect fun varargInAnnotationWithArraySpread()
|
||||||
|
|
||||||
|
annotation class ArrayArgAnn(val strings: Array<String>)
|
||||||
|
|
||||||
|
@ArrayArgAnn(["foo", "bar"])
|
||||||
|
expect fun arrayInAnnotation()
|
||||||
|
|
||||||
|
@ArrayArgAnn(["foo", "bar"])
|
||||||
|
expect fun arrayInAnnotationNotMatch()
|
||||||
|
|
||||||
|
annotation class NestedAnnArg(val text: String, vararg val children: NestedAnnArg)
|
||||||
|
|
||||||
|
@NestedAnnArg(
|
||||||
|
text = "root",
|
||||||
|
NestedAnnArg("1"),
|
||||||
|
NestedAnnArg("2",
|
||||||
|
NestedAnnArg("2.1"),
|
||||||
|
NestedAnnArg("2.2")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
expect fun complexNestedAnnotations()
|
||||||
|
|
||||||
|
@NestedAnnArg(
|
||||||
|
text = "root",
|
||||||
|
NestedAnnArg("1"),
|
||||||
|
NestedAnnArg("2",
|
||||||
|
NestedAnnArg("2.1"),
|
||||||
|
NestedAnnArg("2.2")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
expect fun complexNestedAnnotationsNotMatch()
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
package test
|
||||||
|
|
||||||
|
@ClassArgAnn(ClassForReference::class)
|
||||||
|
actual fun getClassExpression() {}
|
||||||
|
|
||||||
|
@ClassArgAnn(ClassForReference::class)
|
||||||
|
actual fun differentClassesWithSameName() {}
|
||||||
|
|
||||||
|
@StringArgAnn("1.9")
|
||||||
|
actual fun stringConstant() {}
|
||||||
|
|
||||||
|
@StringArgAnn("1.9")
|
||||||
|
actual fun stringConcatentation() {}
|
||||||
|
|
||||||
|
@StringArgAnn("1")
|
||||||
|
actual fun constantFromInsideObject() {}
|
||||||
|
|
||||||
|
@StringArgAnn("1.9")
|
||||||
|
actual fun stringConcatentationWithProperty() {}
|
||||||
|
|
||||||
|
@EnumArgAnn(MyEnum.FOO)
|
||||||
|
actual fun enumArg() {}
|
||||||
|
|
||||||
|
@VarargAnn("foo", "bar")
|
||||||
|
actual fun varargInAnnotation() {}
|
||||||
|
|
||||||
|
@VarargAnn("foo", "bar")
|
||||||
|
actual fun varargInAnnotationWithArraySpread() {}
|
||||||
|
|
||||||
|
@ArrayArgAnn(arrayOf("foo", "bar"))
|
||||||
|
actual fun arrayInAnnotation() {}
|
||||||
|
|
||||||
|
@ArrayArgAnn(["foo"])
|
||||||
|
actual fun arrayInAnnotationNotMatch() {}
|
||||||
|
|
||||||
|
@NestedAnnArg(
|
||||||
|
text = "root",
|
||||||
|
NestedAnnArg("1"),
|
||||||
|
NestedAnnArg("2",
|
||||||
|
NestedAnnArg("2.1"),
|
||||||
|
NestedAnnArg("2.2")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
actual fun complexNestedAnnotations() {}
|
||||||
|
|
||||||
|
@NestedAnnArg(
|
||||||
|
text = "root",
|
||||||
|
NestedAnnArg("1"),
|
||||||
|
NestedAnnArg("2",
|
||||||
|
NestedAnnArg("2.1"),
|
||||||
|
NestedAnnArg("DIFFERENT")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
actual fun complexNestedAnnotationsNotMatch() {}
|
||||||
+138
@@ -0,0 +1,138 @@
|
|||||||
|
// WITH_STDLIB
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
package test
|
||||||
|
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
annotation class ClassArgAnn(val clazz: KClass<*>)
|
||||||
|
|
||||||
|
class ClassForReference {
|
||||||
|
class ClassForReference
|
||||||
|
}
|
||||||
|
|
||||||
|
@ClassArgAnn(ClassForReference::class)
|
||||||
|
expect fun getClassExpression()
|
||||||
|
|
||||||
|
@ClassArgAnn(ClassForReference.ClassForReference::class)
|
||||||
|
expect fun differentClassesWithSameName()
|
||||||
|
|
||||||
|
annotation class StringArgAnn(val s: String)
|
||||||
|
|
||||||
|
@StringArgAnn("1.9")
|
||||||
|
expect fun stringConstant()
|
||||||
|
|
||||||
|
@StringArgAnn("1" + ".9")
|
||||||
|
expect fun stringConcatentation()
|
||||||
|
|
||||||
|
object Constants {
|
||||||
|
const val STR = "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
@StringArgAnn(Constants.STR)
|
||||||
|
expect fun constantFromInsideObject()
|
||||||
|
|
||||||
|
@StringArgAnn(Constants.STR + ".9")
|
||||||
|
expect fun stringConcatentationWithProperty()
|
||||||
|
|
||||||
|
enum class MyEnum { FOO, BAR }
|
||||||
|
|
||||||
|
annotation class EnumArgAnn(val e: MyEnum)
|
||||||
|
|
||||||
|
@EnumArgAnn(MyEnum.FOO)
|
||||||
|
expect fun enumArg()
|
||||||
|
|
||||||
|
annotation class VarargAnn(vararg val strings: String)
|
||||||
|
|
||||||
|
@VarargAnn("foo", "bar")
|
||||||
|
expect fun varargInAnnotation()
|
||||||
|
|
||||||
|
@VarargAnn(*["foo", "bar"])
|
||||||
|
expect fun varargInAnnotationWithArraySpread()
|
||||||
|
|
||||||
|
annotation class ArrayArgAnn(val strings: Array<String>)
|
||||||
|
|
||||||
|
@ArrayArgAnn(["foo", "bar"])
|
||||||
|
expect fun arrayInAnnotation()
|
||||||
|
|
||||||
|
@ArrayArgAnn(["foo", "bar"])
|
||||||
|
expect fun arrayInAnnotationNotMatch()
|
||||||
|
|
||||||
|
annotation class NestedAnnArg(val text: String, vararg val children: NestedAnnArg)
|
||||||
|
|
||||||
|
@NestedAnnArg(
|
||||||
|
text = "root",
|
||||||
|
NestedAnnArg("1"),
|
||||||
|
NestedAnnArg("2",
|
||||||
|
NestedAnnArg("2.1"),
|
||||||
|
NestedAnnArg("2.2")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
expect fun complexNestedAnnotations()
|
||||||
|
|
||||||
|
@NestedAnnArg(
|
||||||
|
text = "root",
|
||||||
|
NestedAnnArg("1"),
|
||||||
|
NestedAnnArg("2",
|
||||||
|
NestedAnnArg("2.1"),
|
||||||
|
NestedAnnArg("2.2")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
expect fun complexNestedAnnotationsNotMatch()
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
package test
|
||||||
|
|
||||||
|
@ClassArgAnn(ClassForReference::class)
|
||||||
|
actual fun getClassExpression() {}
|
||||||
|
|
||||||
|
@ClassArgAnn(ClassForReference::class)
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>differentClassesWithSameName<!>() {}
|
||||||
|
|
||||||
|
@StringArgAnn("1.9")
|
||||||
|
actual fun stringConstant() {}
|
||||||
|
|
||||||
|
@StringArgAnn("1.9")
|
||||||
|
actual fun stringConcatentation() {}
|
||||||
|
|
||||||
|
@StringArgAnn("1")
|
||||||
|
actual fun constantFromInsideObject() {}
|
||||||
|
|
||||||
|
@StringArgAnn("1.9")
|
||||||
|
actual fun stringConcatentationWithProperty() {}
|
||||||
|
|
||||||
|
@EnumArgAnn(MyEnum.FOO)
|
||||||
|
actual fun enumArg() {}
|
||||||
|
|
||||||
|
@VarargAnn("foo", "bar")
|
||||||
|
actual fun varargInAnnotation() {}
|
||||||
|
|
||||||
|
@VarargAnn("foo", "bar")
|
||||||
|
actual fun varargInAnnotationWithArraySpread() {}
|
||||||
|
|
||||||
|
@ArrayArgAnn(arrayOf("foo", "bar"))
|
||||||
|
actual fun arrayInAnnotation() {}
|
||||||
|
|
||||||
|
@ArrayArgAnn(["foo"])
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>arrayInAnnotationNotMatch<!>() {}
|
||||||
|
|
||||||
|
@NestedAnnArg(
|
||||||
|
text = "root",
|
||||||
|
NestedAnnArg("1"),
|
||||||
|
NestedAnnArg("2",
|
||||||
|
NestedAnnArg("2.1"),
|
||||||
|
NestedAnnArg("2.2")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
actual fun complexNestedAnnotations() {}
|
||||||
|
|
||||||
|
@NestedAnnArg(
|
||||||
|
text = "root",
|
||||||
|
NestedAnnArg("1"),
|
||||||
|
NestedAnnArg("2",
|
||||||
|
NestedAnnArg("2.1"),
|
||||||
|
NestedAnnArg("DIFFERENT")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>complexNestedAnnotationsNotMatch<!>() {}
|
||||||
Vendored
+12
@@ -0,0 +1,12 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
annotation class Ann(val p: String = "")
|
||||||
|
@Ann("")
|
||||||
|
expect fun explicitDefaultArgument()
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
// No special handling for this case
|
||||||
|
@Ann
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>explicitDefaultArgument<!>() {}
|
||||||
compiler/testData/diagnostics/tests/multiplatform/annotationMatching/annotationTypeParameters.fir.kt
Vendored
+101
@@ -0,0 +1,101 @@
|
|||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
annotation class Ann<T>
|
||||||
|
|
||||||
|
class A
|
||||||
|
class B
|
||||||
|
private object FakeA {
|
||||||
|
class A
|
||||||
|
}
|
||||||
|
|
||||||
|
@Ann<A>
|
||||||
|
expect fun sameTypeParam()
|
||||||
|
|
||||||
|
@Ann<B>
|
||||||
|
expect fun differentTypeParam()
|
||||||
|
|
||||||
|
@Ann<FakeA.A>
|
||||||
|
expect fun differentWithSameName()
|
||||||
|
|
||||||
|
@Ann<A?>
|
||||||
|
expect fun nonNullvsNull()
|
||||||
|
|
||||||
|
@Ann<Ann<in A>>
|
||||||
|
expect fun differentVariance()
|
||||||
|
|
||||||
|
@Ann<Ann<in A>>
|
||||||
|
expect fun varianceVsNoVariance()
|
||||||
|
|
||||||
|
@Ann<Ann<in A>>
|
||||||
|
expect fun sameVariance()
|
||||||
|
|
||||||
|
@Ann<Ann<*>>
|
||||||
|
expect fun startProjection()
|
||||||
|
|
||||||
|
annotation class ComplexNested<T>(
|
||||||
|
vararg val anns: ComplexNested<*>,
|
||||||
|
)
|
||||||
|
|
||||||
|
@ComplexNested<A>(
|
||||||
|
ComplexNested<A>(),
|
||||||
|
ComplexNested<A>(),
|
||||||
|
)
|
||||||
|
expect fun complexSame()
|
||||||
|
|
||||||
|
@ComplexNested<A>(
|
||||||
|
ComplexNested<A>(),
|
||||||
|
ComplexNested<B>(),
|
||||||
|
)
|
||||||
|
expect fun complexDiffer()
|
||||||
|
|
||||||
|
annotation class NestedWithSameTypeArgument<T>(
|
||||||
|
vararg val anns: NestedWithSameTypeArgument<T>
|
||||||
|
)
|
||||||
|
|
||||||
|
@NestedWithSameTypeArgument<A>(
|
||||||
|
NestedWithSameTypeArgument()
|
||||||
|
)
|
||||||
|
expect fun explicitVsInfered()
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
@Ann<A>
|
||||||
|
actual fun sameTypeParam() {}
|
||||||
|
|
||||||
|
@Ann<A>
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>differentTypeParam<!>() {}
|
||||||
|
|
||||||
|
@Ann<A>
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>differentWithSameName<!>() {}
|
||||||
|
|
||||||
|
@Ann<A>
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>nonNullvsNull<!>() {}
|
||||||
|
|
||||||
|
@Ann<Ann<out A>>
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>differentVariance<!>() {}
|
||||||
|
|
||||||
|
@Ann<Ann<A>>
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>varianceVsNoVariance<!>() {}
|
||||||
|
|
||||||
|
@Ann<Ann<in A>>
|
||||||
|
actual fun sameVariance() {}
|
||||||
|
|
||||||
|
@Ann<Ann<Any>>
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>startProjection<!>() {}
|
||||||
|
|
||||||
|
@ComplexNested<A>(
|
||||||
|
ComplexNested<A>(),
|
||||||
|
ComplexNested<A>(),
|
||||||
|
)
|
||||||
|
actual fun complexSame() {}
|
||||||
|
|
||||||
|
@ComplexNested<A>(
|
||||||
|
ComplexNested<A>(),
|
||||||
|
ComplexNested<A>(),
|
||||||
|
)
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>complexDiffer<!>() {}
|
||||||
|
|
||||||
|
@NestedWithSameTypeArgument<A>(
|
||||||
|
NestedWithSameTypeArgument<A>()
|
||||||
|
)
|
||||||
|
actual fun explicitVsInfered() {}
|
||||||
Vendored
+101
@@ -0,0 +1,101 @@
|
|||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
annotation class Ann<T>
|
||||||
|
|
||||||
|
class A
|
||||||
|
class B
|
||||||
|
private object FakeA {
|
||||||
|
class A
|
||||||
|
}
|
||||||
|
|
||||||
|
@Ann<A>
|
||||||
|
expect fun sameTypeParam()
|
||||||
|
|
||||||
|
@Ann<B>
|
||||||
|
expect fun differentTypeParam()
|
||||||
|
|
||||||
|
@Ann<FakeA.A>
|
||||||
|
expect fun differentWithSameName()
|
||||||
|
|
||||||
|
@Ann<A?>
|
||||||
|
expect fun nonNullvsNull()
|
||||||
|
|
||||||
|
@Ann<Ann<in A>>
|
||||||
|
expect fun differentVariance()
|
||||||
|
|
||||||
|
@Ann<Ann<in A>>
|
||||||
|
expect fun varianceVsNoVariance()
|
||||||
|
|
||||||
|
@Ann<Ann<in A>>
|
||||||
|
expect fun sameVariance()
|
||||||
|
|
||||||
|
@Ann<Ann<*>>
|
||||||
|
expect fun startProjection()
|
||||||
|
|
||||||
|
annotation class ComplexNested<T>(
|
||||||
|
vararg val anns: ComplexNested<*>,
|
||||||
|
)
|
||||||
|
|
||||||
|
@ComplexNested<A>(
|
||||||
|
ComplexNested<A>(),
|
||||||
|
ComplexNested<A>(),
|
||||||
|
)
|
||||||
|
expect fun complexSame()
|
||||||
|
|
||||||
|
@ComplexNested<A>(
|
||||||
|
ComplexNested<A>(),
|
||||||
|
ComplexNested<B>(),
|
||||||
|
)
|
||||||
|
expect fun complexDiffer()
|
||||||
|
|
||||||
|
annotation class NestedWithSameTypeArgument<T>(
|
||||||
|
vararg val anns: NestedWithSameTypeArgument<T>
|
||||||
|
)
|
||||||
|
|
||||||
|
@NestedWithSameTypeArgument<A>(
|
||||||
|
NestedWithSameTypeArgument()
|
||||||
|
)
|
||||||
|
expect fun explicitVsInfered()
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
@Ann<A>
|
||||||
|
actual fun sameTypeParam() {}
|
||||||
|
|
||||||
|
@Ann<A>
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>differentTypeParam<!>() {}
|
||||||
|
|
||||||
|
@Ann<A>
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>differentWithSameName<!>() {}
|
||||||
|
|
||||||
|
@Ann<A>
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>nonNullvsNull<!>() {}
|
||||||
|
|
||||||
|
@Ann<Ann<out A>>
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>differentVariance<!>() {}
|
||||||
|
|
||||||
|
@Ann<Ann<A>>
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>varianceVsNoVariance<!>() {}
|
||||||
|
|
||||||
|
@Ann<Ann<in A>>
|
||||||
|
actual fun sameVariance() {}
|
||||||
|
|
||||||
|
@Ann<Ann<Any>>
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>startProjection<!>() {}
|
||||||
|
|
||||||
|
@ComplexNested<A>(
|
||||||
|
ComplexNested<A>(),
|
||||||
|
ComplexNested<A>(),
|
||||||
|
)
|
||||||
|
actual fun complexSame() {}
|
||||||
|
|
||||||
|
@ComplexNested<A>(
|
||||||
|
ComplexNested<A>(),
|
||||||
|
ComplexNested<A>(),
|
||||||
|
)
|
||||||
|
actual fun complexDiffer() {}
|
||||||
|
|
||||||
|
@NestedWithSameTypeArgument<A>(
|
||||||
|
NestedWithSameTypeArgument<A>()
|
||||||
|
)
|
||||||
|
actual fun explicitVsInfered() {}
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
annotation class Ann
|
||||||
|
|
||||||
|
@Ann
|
||||||
|
expect class AnnotationMatching
|
||||||
|
|
||||||
|
@Ann
|
||||||
|
expect class AnnotationOnExpectOnly
|
||||||
|
|
||||||
|
expect class AnnotationOnActualOnly
|
||||||
|
|
||||||
|
expect class AnnotationInside {
|
||||||
|
@Ann
|
||||||
|
fun matches()
|
||||||
|
|
||||||
|
@Ann
|
||||||
|
fun onlyOnExpect()
|
||||||
|
|
||||||
|
fun onlyOnActual()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
@Ann
|
||||||
|
actual class AnnotationMatching
|
||||||
|
|
||||||
|
actual class <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>AnnotationOnExpectOnly<!>
|
||||||
|
|
||||||
|
@Ann
|
||||||
|
actual class AnnotationOnActualOnly
|
||||||
|
|
||||||
|
actual class AnnotationInside {
|
||||||
|
@Ann
|
||||||
|
actual fun matches() {}
|
||||||
|
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>onlyOnExpect<!>() {}
|
||||||
|
|
||||||
|
@Ann
|
||||||
|
actual fun onlyOnActual() {}
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
// -- Module: <m1-common> --
|
||||||
|
|
||||||
|
// -- Module: <m1-jvm> --
|
||||||
|
/jvm.kt:24:14: warning: all annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
|
||||||
|
Expected: @Ann public final expect class OnClass defined in root package in file common.kt
|
||||||
|
Actual: public final actual class OnClass defined in root package in file jvm.kt
|
||||||
|
actual class OnClass
|
||||||
|
^
|
||||||
|
/jvm.kt:27:16: warning: all annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
|
||||||
|
Expected: @Ann public final expect fun onMember(): Unit defined in OnMember
|
||||||
|
Actual: public final actual fun onMember(): Unit defined in OnMember
|
||||||
|
actual fun onMember() {}
|
||||||
|
^
|
||||||
|
/jvm.kt:34:18: warning: all annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
|
||||||
|
Expected: @Ann public final expect class ViaTypealias defined in root package in file common.kt
|
||||||
|
Actual: public final class ViaTypealiasImpl defined in root package in file jvm.kt
|
||||||
|
actual typealias ViaTypealias = ViaTypealiasImpl
|
||||||
|
^
|
||||||
|
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
/jvm.kt:(83,90): warning: All annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
|
||||||
|
Expected: @Ann() public final expect class OnClass : Any
|
||||||
|
Actual: public final actual class OnClass : Any
|
||||||
|
|
||||||
|
/jvm.kt:(131,139): warning: All annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
|
||||||
|
Expected: @Ann() public final expect fun onMember(): Unit
|
||||||
|
Actual: public final actual fun onMember(): Unit
|
||||||
|
|
||||||
|
/jvm.kt:(210,222): warning: All annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
|
||||||
|
Expected: @Ann() public final expect class ViaTypealias : Any
|
||||||
|
Actual: public final class ViaTypealiasImpl : Any
|
||||||
Vendored
+34
@@ -0,0 +1,34 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
annotation class Ann
|
||||||
|
|
||||||
|
@Ann
|
||||||
|
expect class OnClass
|
||||||
|
|
||||||
|
expect class OnMember {
|
||||||
|
@Ann
|
||||||
|
fun onMember()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Ann
|
||||||
|
expect class ViaTypealias {
|
||||||
|
@Ann
|
||||||
|
fun foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
actual class <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>OnClass<!>
|
||||||
|
|
||||||
|
actual class OnMember {
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>onMember<!>() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViaTypealiasImpl {
|
||||||
|
fun foo() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual typealias <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>ViaTypealias<!> = ViaTypealiasImpl
|
||||||
Vendored
+19
@@ -0,0 +1,19 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
annotation class Ann
|
||||||
|
|
||||||
|
expect class CompatibleOverrides {
|
||||||
|
fun foo()
|
||||||
|
|
||||||
|
@Ann
|
||||||
|
fun foo(withArg: Any)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
actual class CompatibleOverrides {
|
||||||
|
actual fun foo() {}
|
||||||
|
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>foo<!>(withArg: Any) {}
|
||||||
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
annotation class Ann1
|
||||||
|
annotation class Ann2
|
||||||
|
|
||||||
|
@Ann1
|
||||||
|
@Ann2
|
||||||
|
expect class AnnotationOrder
|
||||||
|
|
||||||
|
annotation class Ann3(vararg val numbers: Int)
|
||||||
|
|
||||||
|
@Ann3(1, 2)
|
||||||
|
expect class ValuesOrderInsideAnnotationArgument
|
||||||
|
|
||||||
|
annotation class Ann4(val arg1: String, val arg2: String)
|
||||||
|
|
||||||
|
@Ann4(arg1 = "1", arg2 = "2")
|
||||||
|
expect fun differentArgumentsOrder()
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
|
||||||
|
@Ann2
|
||||||
|
@Ann1
|
||||||
|
actual class AnnotationOrder
|
||||||
|
|
||||||
|
@Ann3(2, 1)
|
||||||
|
actual class ValuesOrderInsideAnnotationArgument
|
||||||
|
|
||||||
|
@Ann4(arg2 = "2", arg1 = "1")
|
||||||
|
actual fun differentArgumentsOrder() {}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
annotation class Ann1
|
||||||
|
annotation class Ann2
|
||||||
|
|
||||||
|
@Ann1
|
||||||
|
@Ann2
|
||||||
|
expect class AnnotationOrder
|
||||||
|
|
||||||
|
annotation class Ann3(vararg val numbers: Int)
|
||||||
|
|
||||||
|
@Ann3(1, 2)
|
||||||
|
expect class ValuesOrderInsideAnnotationArgument
|
||||||
|
|
||||||
|
annotation class Ann4(val arg1: String, val arg2: String)
|
||||||
|
|
||||||
|
@Ann4(arg1 = "1", arg2 = "2")
|
||||||
|
expect fun differentArgumentsOrder()
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
|
||||||
|
@Ann2
|
||||||
|
@Ann1
|
||||||
|
actual class AnnotationOrder
|
||||||
|
|
||||||
|
@Ann3(2, 1)
|
||||||
|
actual class <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>ValuesOrderInsideAnnotationArgument<!>
|
||||||
|
|
||||||
|
@Ann4(arg2 = "2", arg1 = "1")
|
||||||
|
actual fun differentArgumentsOrder() {}
|
||||||
Vendored
+11
@@ -0,0 +1,11 @@
|
|||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
annotation class Ann(val p: Double)
|
||||||
|
|
||||||
|
@Ann(0.3)
|
||||||
|
expect fun floatNumbersComparison()
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
@Ann(0.1 + 0.1 + 0.1)
|
||||||
|
actual fun floatNumbersComparison() {}
|
||||||
Vendored
+11
@@ -0,0 +1,11 @@
|
|||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
annotation class Ann(val p: Double)
|
||||||
|
|
||||||
|
@Ann(0.3)
|
||||||
|
expect fun floatNumbersComparison()
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
@Ann(0.1 + 0.1 + 0.1)
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>floatNumbersComparison<!>() {}
|
||||||
Vendored
+35
@@ -0,0 +1,35 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// WITH_STDLIB
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
annotation class Ann(val clazz: KClass<*>)
|
||||||
|
|
||||||
|
@Ann(LinkToExpectInnerClass.Inner::class)
|
||||||
|
expect class LinkToExpectInnerClass {
|
||||||
|
object Inner
|
||||||
|
}
|
||||||
|
|
||||||
|
expect class WillBeTypealiased
|
||||||
|
|
||||||
|
@Ann(WillBeTypealiased::class)
|
||||||
|
expect fun linkToExpectClassWhichWillBeTypealiased()
|
||||||
|
|
||||||
|
@Ann(WillBeTypealiased::class)
|
||||||
|
expect fun linkToExpectClassWhichWillBeTypealiased2()
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
@Ann(LinkToExpectInnerClass.Inner::class)
|
||||||
|
actual class LinkToExpectInnerClass {
|
||||||
|
actual object Inner
|
||||||
|
}
|
||||||
|
|
||||||
|
actual typealias WillBeTypealiased = Any
|
||||||
|
|
||||||
|
@Ann(WillBeTypealiased::class)
|
||||||
|
actual fun linkToExpectClassWhichWillBeTypealiased() {}
|
||||||
|
|
||||||
|
@Ann(Any::class)
|
||||||
|
actual fun linkToExpectClassWhichWillBeTypealiased2() {}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// WITH_STDLIB
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
expect annotation class JavaTypealiasAnnotationAnalogue
|
||||||
|
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
expect annotation class JavaTypealiasKotlinAnnotation
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
actual typealias JavaTypealiasAnnotationAnalogue = JavaTypealiasAnnotationAnalogueImpl
|
||||||
|
|
||||||
|
actual typealias JavaTypealiasKotlinAnnotation = JavaTypealiasKotlinAnnotationImpl
|
||||||
|
|
||||||
|
// FILE: jvmJavaImpls.java
|
||||||
|
import kotlin.annotation.AnnotationRetention;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface JavaTypealiasAnnotationAnalogueImpl {
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
|
||||||
|
public @interface JavaTypealiasKotlinAnnotationImpl {
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// WITH_STDLIB
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
@Target(AnnotationTarget.TYPEALIAS, AnnotationTarget.CLASS)
|
||||||
|
annotation class Ann
|
||||||
|
|
||||||
|
@Ann
|
||||||
|
expect class KtTypealiasNotMatch
|
||||||
|
|
||||||
|
@Ann
|
||||||
|
expect class AnnotationsNotConsideredOnTypealias
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
class KtTypealiasNotMatchImpl
|
||||||
|
|
||||||
|
actual typealias <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>KtTypealiasNotMatch<!> = KtTypealiasNotMatchImpl
|
||||||
|
|
||||||
|
class AnnotationsNotConsideredOnTypealiasImpl
|
||||||
|
|
||||||
|
@Ann
|
||||||
|
actual typealias <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>AnnotationsNotConsideredOnTypealias<!> = AnnotationsNotConsideredOnTypealiasImpl
|
||||||
Vendored
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// WITH_STDLIB
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
|
expect annotation class MyDeprecatedNotMatch
|
||||||
|
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
expect annotation class MyDeprecatedMatch
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
actual typealias MyDeprecatedNotMatch = java.lang.Deprecated
|
||||||
|
|
||||||
|
actual typealias MyDeprecatedMatch = java.lang.Deprecated
|
||||||
Vendored
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// WITH_STDLIB
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
|
expect annotation class MyDeprecatedNotMatch
|
||||||
|
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
expect annotation class MyDeprecatedMatch
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
actual typealias <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>MyDeprecatedNotMatch<!> = java.lang.Deprecated
|
||||||
|
|
||||||
|
actual typealias MyDeprecatedMatch = java.lang.Deprecated
|
||||||
Vendored
+32
@@ -0,0 +1,32 @@
|
|||||||
|
// WITH_STDLIB
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
@Target(
|
||||||
|
AnnotationTarget.CLASS,
|
||||||
|
AnnotationTarget.FUNCTION,
|
||||||
|
AnnotationTarget.PROPERTY,
|
||||||
|
AnnotationTarget.ANNOTATION_CLASS,
|
||||||
|
AnnotationTarget.CONSTRUCTOR,
|
||||||
|
AnnotationTarget.PROPERTY_SETTER,
|
||||||
|
AnnotationTarget.PROPERTY_GETTER,
|
||||||
|
// removed target TYPEALIAS
|
||||||
|
)
|
||||||
|
expect annotation class MyDeprecatedNotMatch
|
||||||
|
|
||||||
|
@Target(
|
||||||
|
AnnotationTarget.CLASS,
|
||||||
|
AnnotationTarget.FUNCTION,
|
||||||
|
AnnotationTarget.PROPERTY,
|
||||||
|
AnnotationTarget.ANNOTATION_CLASS,
|
||||||
|
AnnotationTarget.CONSTRUCTOR,
|
||||||
|
AnnotationTarget.PROPERTY_SETTER,
|
||||||
|
AnnotationTarget.PROPERTY_GETTER,
|
||||||
|
AnnotationTarget.TYPEALIAS
|
||||||
|
)
|
||||||
|
expect annotation class MyDeprecatedMatch
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
actual typealias MyDeprecatedNotMatch = kotlin.Deprecated
|
||||||
|
|
||||||
|
actual typealias MyDeprecatedMatch = kotlin.Deprecated
|
||||||
Vendored
+32
@@ -0,0 +1,32 @@
|
|||||||
|
// WITH_STDLIB
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
@Target(
|
||||||
|
AnnotationTarget.CLASS,
|
||||||
|
AnnotationTarget.FUNCTION,
|
||||||
|
AnnotationTarget.PROPERTY,
|
||||||
|
AnnotationTarget.ANNOTATION_CLASS,
|
||||||
|
AnnotationTarget.CONSTRUCTOR,
|
||||||
|
AnnotationTarget.PROPERTY_SETTER,
|
||||||
|
AnnotationTarget.PROPERTY_GETTER,
|
||||||
|
// removed target TYPEALIAS
|
||||||
|
)
|
||||||
|
expect annotation class MyDeprecatedNotMatch
|
||||||
|
|
||||||
|
@Target(
|
||||||
|
AnnotationTarget.CLASS,
|
||||||
|
AnnotationTarget.FUNCTION,
|
||||||
|
AnnotationTarget.PROPERTY,
|
||||||
|
AnnotationTarget.ANNOTATION_CLASS,
|
||||||
|
AnnotationTarget.CONSTRUCTOR,
|
||||||
|
AnnotationTarget.PROPERTY_SETTER,
|
||||||
|
AnnotationTarget.PROPERTY_GETTER,
|
||||||
|
AnnotationTarget.TYPEALIAS
|
||||||
|
)
|
||||||
|
expect annotation class MyDeprecatedMatch
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
actual typealias <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>MyDeprecatedNotMatch<!> = kotlin.Deprecated
|
||||||
|
|
||||||
|
actual typealias MyDeprecatedMatch = kotlin.Deprecated
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
annotation class Ann
|
||||||
|
|
||||||
|
<!INCOMPATIBLE_MATCHING{JVM}!>@Ann
|
||||||
|
expect inline fun hasWeakIncompatibility()<!>
|
||||||
|
|
||||||
|
<!INCOMPATIBLE_MATCHING{JVM}, INCOMPATIBLE_MATCHING{JVM}!>@Ann
|
||||||
|
expect fun hasStrongIncompatibility(arg: Int)<!>
|
||||||
|
|
||||||
|
expect fun hasStrongIncompatibility(arg: Double)
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_WITHOUT_EXPECT!>hasWeakIncompatibility<!>() {}
|
||||||
|
|
||||||
|
actual fun <!ACTUAL_WITHOUT_EXPECT!>hasStrongIncompatibility<!>(arg: Any?) {}
|
||||||
|
|
||||||
|
actual fun hasStrongIncompatibility(arg: Double) {}
|
||||||
Vendored
+19
@@ -0,0 +1,19 @@
|
|||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
annotation class Ann
|
||||||
|
|
||||||
|
@Ann
|
||||||
|
expect inline fun hasWeakIncompatibility()
|
||||||
|
|
||||||
|
@Ann
|
||||||
|
expect fun hasStrongIncompatibility<!NO_ACTUAL_FOR_EXPECT{JVM}!>(arg: Int)<!>
|
||||||
|
|
||||||
|
expect fun hasStrongIncompatibility(arg: Double)
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
<!ACTUAL_WITHOUT_EXPECT!>actual<!> fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>hasWeakIncompatibility<!>() {}
|
||||||
|
|
||||||
|
actual fun hasStrongIncompatibility<!ACTUAL_WITHOUT_EXPECT!>(arg: Any?)<!> {}
|
||||||
|
|
||||||
|
actual fun hasStrongIncompatibility(arg: Double) {}
|
||||||
+2
-1
@@ -1,12 +1,13 @@
|
|||||||
// WITH_STDLIB
|
// WITH_STDLIB
|
||||||
// MODULE: m1-common
|
// MODULE: m1-common
|
||||||
// FILE: common.kt
|
// FILE: common.kt
|
||||||
|
@file:OptIn(ExperimentalMultiplatform::class)
|
||||||
|
|
||||||
expect annotation class ActualOnly
|
expect annotation class ActualOnly
|
||||||
|
|
||||||
@RequiresOptIn
|
@RequiresOptIn
|
||||||
<!EXPECT_ACTUAL_OPT_IN_ANNOTATION!>expect<!> annotation class Both
|
<!EXPECT_ACTUAL_OPT_IN_ANNOTATION!>expect<!> annotation class Both
|
||||||
|
|
||||||
@OptIn(ExperimentalMultiplatform::class)
|
|
||||||
@RequiresOptIn
|
@RequiresOptIn
|
||||||
@OptionalExpectation
|
@OptionalExpectation
|
||||||
expect annotation class MyOptIn
|
expect annotation class MyOptIn
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
// WITH_STDLIB
|
// WITH_STDLIB
|
||||||
// MODULE: m1-common
|
// MODULE: m1-common
|
||||||
// FILE: common.kt
|
// FILE: common.kt
|
||||||
|
@file:OptIn(ExperimentalMultiplatform::class)
|
||||||
|
|
||||||
expect annotation class ActualOnly
|
expect annotation class ActualOnly
|
||||||
|
|
||||||
@RequiresOptIn
|
@RequiresOptIn
|
||||||
<!EXPECT_ACTUAL_OPT_IN_ANNOTATION{JVM}!>expect<!> annotation class Both
|
<!EXPECT_ACTUAL_OPT_IN_ANNOTATION{JVM}!>expect<!> annotation class Both
|
||||||
|
|
||||||
@OptIn(ExperimentalMultiplatform::class)
|
|
||||||
@RequiresOptIn
|
@RequiresOptIn
|
||||||
@OptionalExpectation
|
@OptionalExpectation
|
||||||
expect annotation class MyOptIn
|
expect annotation class MyOptIn
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
@OptionalExpectation
|
@OptionalExpectation
|
||||||
expect annotation class A()
|
expect annotation class A()
|
||||||
|
|
||||||
expect class C {
|
class C {
|
||||||
@A
|
@A
|
||||||
fun f()
|
fun f() {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
actual class C {
|
|
||||||
actual fun f() {}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1 @@
|
|||||||
actual annotation class A
|
actual annotation class A
|
||||||
|
|
||||||
actual class C {
|
|
||||||
@A
|
|
||||||
actual fun f() {}
|
|
||||||
}
|
|
||||||
|
|||||||
Generated
+94
@@ -22750,6 +22750,100 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibilityInActualClassifier.kt");
|
runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibilityInActualClassifier.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/annotationMatching")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class AnnotationMatching {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInAnnotationMatching() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform/annotationMatching"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("annotationArgumentsConstExpressions.kt")
|
||||||
|
public void testAnnotationArgumentsConstExpressions() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/annotationArgumentsConstExpressions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("annotationArgumentsDefaults.kt")
|
||||||
|
public void testAnnotationArgumentsDefaults() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/annotationArgumentsDefaults.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("annotationTypeParameters.kt")
|
||||||
|
public void testAnnotationTypeParameters() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/annotationTypeParameters.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("basicOnDeclaration.kt")
|
||||||
|
public void testBasicOnDeclaration() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/basicOnDeclaration.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("checkDiagnosticFullText.kt")
|
||||||
|
public void testCheckDiagnosticFullText() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/checkDiagnosticFullText.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("compatibleOverrides.kt")
|
||||||
|
public void testCompatibleOverrides() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/compatibleOverrides.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("differentOrder.kt")
|
||||||
|
public void testDifferentOrder() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/differentOrder.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("floatNumbersComparison.kt")
|
||||||
|
public void testFloatNumbersComparison() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/floatNumbersComparison.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kclassArgWithExpectClass.kt")
|
||||||
|
public void testKclassArgWithExpectClass() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/kclassArgWithExpectClass.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kotlinAnaloguesForJavaAnnotations.kt")
|
||||||
|
public void testKotlinAnaloguesForJavaAnnotations() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/kotlinAnaloguesForJavaAnnotations.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("typealias.kt")
|
||||||
|
public void testTypealias() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typealias.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("typealiasToJavaLibrary.kt")
|
||||||
|
public void testTypealiasToJavaLibrary() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typealiasToJavaLibrary.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("typealiasToKtLibrary.kt")
|
||||||
|
public void testTypealiasToKtLibrary() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typealiasToKtLibrary.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("withOtherIncomatibilities.kt")
|
||||||
|
public void testWithOtherIncomatibilities() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/withOtherIncomatibilities.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/defaultArguments")
|
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/defaultArguments")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
Reference in New Issue
Block a user