diff --git a/compiler/fir/analysis-tests/testData/resolve/properties/syntheticPropertiesForJavaAnnotations.kt b/compiler/fir/analysis-tests/testData/resolve/properties/syntheticPropertiesForJavaAnnotations.kt new file mode 100644 index 00000000000..30c39006a34 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/properties/syntheticPropertiesForJavaAnnotations.kt @@ -0,0 +1,14 @@ +// ISSUE: KT-41939 + +// FILE: Ann.java + +public @interface Ann { + String value() +} + +// FILE: main.kt + +fun test(ann: Ann) { + ann.value + ann.value() // should be an error +} diff --git a/compiler/fir/analysis-tests/testData/resolve/properties/syntheticPropertiesForJavaAnnotations.txt b/compiler/fir/analysis-tests/testData/resolve/properties/syntheticPropertiesForJavaAnnotations.txt new file mode 100644 index 00000000000..3cf3c1b2889 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/properties/syntheticPropertiesForJavaAnnotations.txt @@ -0,0 +1,5 @@ +FILE: main.kt + public final fun test(ann: R|Ann|): R|kotlin/Unit| { + R|/ann|.R|/Ann.value| + R|/ann|.#() + } diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index 0e44aecf096..7f6931ded25 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -2031,6 +2031,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { public void testNoBackingFieldForExtension() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/properties/noBackingFieldForExtension.kt"); } + + @TestMetadata("syntheticPropertiesForJavaAnnotations.kt") + public void testSyntheticPropertiesForJavaAnnotations() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/properties/syntheticPropertiesForJavaAnnotations.kt"); + } } @TestMetadata("compiler/fir/analysis-tests/testData/resolve/references") diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java index 178784b2633..da64e5fe21c 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java @@ -2031,6 +2031,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos public void testNoBackingFieldForExtension() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/properties/noBackingFieldForExtension.kt"); } + + @TestMetadata("syntheticPropertiesForJavaAnnotations.kt") + public void testSyntheticPropertiesForJavaAnnotations() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/properties/syntheticPropertiesForJavaAnnotations.kt"); + } } @TestMetadata("compiler/fir/analysis-tests/testData/resolve/references") diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaScopeProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaScopeProvider.kt index e36a56468f3..e4ef71fc251 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaScopeProvider.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaScopeProvider.kt @@ -35,8 +35,25 @@ class JavaScopeProvider( klass: FirClass<*>, useSiteSession: FirSession, scopeSession: ScopeSession - ): FirTypeScope = - buildJavaEnhancementScope(useSiteSession, klass.symbol as FirRegularClassSymbol, scopeSession, mutableSetOf()) + ): FirTypeScope { + val symbol = klass.symbol as FirRegularClassSymbol + val enhancementScope = buildJavaEnhancementScope(useSiteSession, symbol, scopeSession, mutableSetOf()) + if (klass.classKind == ClassKind.ANNOTATION_CLASS) { + return buildSyntheticScopeForAnnotations(useSiteSession, symbol, scopeSession, enhancementScope) + } + return enhancementScope + } + + private fun buildSyntheticScopeForAnnotations( + session: FirSession, + symbol: FirRegularClassSymbol, + scopeSession: ScopeSession, + enhancementScope: JavaClassMembersEnhancementScope + ): FirTypeScope { + return scopeSession.getOrBuild(symbol, JAVA_SYNTHETIC_FOR_ANNOTATIONS) { + JavaAnnotationSyntheticPropertiesScope(session, symbol, enhancementScope) + } + } private fun buildJavaEnhancementScope( useSiteSession: FirSession, @@ -196,6 +213,7 @@ class JavaScopeProvider( } } +private val JAVA_SYNTHETIC_FOR_ANNOTATIONS = scopeSessionKey() private val JAVA_ENHANCEMENT_FOR_STATIC = scopeSessionKey() private val JAVA_ENHANCEMENT = scopeSessionKey() private val JAVA_USE_SITE = scopeSessionKey() diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaAnnotationSyntheticPropertiesScope.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaAnnotationSyntheticPropertiesScope.kt new file mode 100644 index 00000000000..35adabf64c1 --- /dev/null +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaAnnotationSyntheticPropertiesScope.kt @@ -0,0 +1,78 @@ +/* + * Copyright 2010-2020 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.fir.java.scopes + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty +import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor +import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor +import org.jetbrains.kotlin.fir.scopes.FirTypeScope +import org.jetbrains.kotlin.fir.scopes.ProcessorAction +import org.jetbrains.kotlin.fir.symbols.CallableId +import org.jetbrains.kotlin.fir.symbols.impl.* +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.Name + +class JavaAnnotationSyntheticPropertiesScope( + private val session: FirSession, + owner: FirRegularClassSymbol, + private val delegateScope: JavaClassMembersEnhancementScope +) : FirTypeScope() { + private val classId: ClassId = owner.classId + private val names: Set = owner.fir.declarations.mapNotNullTo(mutableSetOf()) { (it as? FirSimpleFunction)?.name } + private val syntheticPropertiesCache = mutableMapOf, FirVariableSymbol<*>>() + + override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) { + delegateScope.processDeclaredConstructors(processor) + } + + override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> Unit) { + if (name in names) return + delegateScope.processFunctionsByName(name, processor) + } + + override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) { + if (name !in names) return + delegateScope.processFunctionsByName(name) { functionSymbol -> + val function = functionSymbol.fir as? FirSimpleFunction ?: return@processFunctionsByName + val symbol = syntheticPropertiesCache.getOrPut(functionSymbol) { + val callableId = CallableId(classId, name) + FirAccessorSymbol(callableId, callableId).also { + val accessor = FirSyntheticPropertyAccessor(function, isGetter = true) + FirSyntheticProperty(session, name, isVar = false, it, function.status, function.resolvePhase, accessor) + } + } + processor(symbol) + } + } + + override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) { + delegateScope.processClassifiersByNameWithSubstitution(name, processor) + } + + override fun processDirectOverriddenFunctionsWithBaseScope( + functionSymbol: FirFunctionSymbol<*>, + processor: (FirFunctionSymbol<*>, FirTypeScope) -> ProcessorAction + ): ProcessorAction { + return ProcessorAction.NONE + } + + override fun processDirectOverriddenPropertiesWithBaseScope( + propertySymbol: FirPropertySymbol, + processor: (FirPropertySymbol, FirTypeScope) -> ProcessorAction + ): ProcessorAction { + return ProcessorAction.NONE + } + + override fun getCallableNames(): Set { + return delegateScope.getCallableNames() + } + + override fun getClassifierNames(): Set { + return delegateScope.getClassifierNames() + } +}