diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10SymbolInfoProvider.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10SymbolInfoProvider.kt index f875146df03..90ff8ceb6d2 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10SymbolInfoProvider.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10SymbolInfoProvider.kt @@ -13,14 +13,15 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtPropertyAccessorSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor -import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget +import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.psi.KtProperty +import org.jetbrains.kotlin.resolve.AnnotationChecker import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.deprecation.DeprecationInfo import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue @@ -132,4 +133,11 @@ internal class KtFe10SymbolInfoProvider( val ktPropertyName = (symbol.psi as? KtProperty)?.takeIf { it.isVar }?.name ?: return SpecialNames.NO_NAME_PROVIDED return Name.identifier(JvmAbi.setterName(ktPropertyName)) } + + override fun getAnnotationApplicableTargets(symbol: KtClassOrObjectSymbol): Set? { + val descriptor = getSymbolDescriptor(symbol) as? ClassDescriptor ?: return null + if (descriptor.kind != ClassKind.ANNOTATION_CLASS) return null + + return AnnotationChecker.applicableTargetSet(descriptor) + } } \ No newline at end of file diff --git a/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/symbolInfoProvider/Fe10IdeNormalAnalysisSourceModuleAnnotationApplicableTargetsTestGenerated.java b/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/symbolInfoProvider/Fe10IdeNormalAnalysisSourceModuleAnnotationApplicableTargetsTestGenerated.java new file mode 100644 index 00000000000..5fbf37b0fbc --- /dev/null +++ b/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/symbolInfoProvider/Fe10IdeNormalAnalysisSourceModuleAnnotationApplicableTargetsTestGenerated.java @@ -0,0 +1,78 @@ +/* + * 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.analysis.api.fe10.test.cases.generated.cases.components.symbolInfoProvider; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.util.KtTestUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.analysis.api.fe10.test.configurator.AnalysisApiFe10TestConfiguratorFactory; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfiguratorFactoryData; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfigurator; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.TestModuleKind; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.FrontendKind; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisSessionMode; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiMode; +import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.symbolInfoProvider.AbstractAnnotationApplicableTargetsTest; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.analysis.api.GenerateAnalysisApiTestsKt}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets") +@TestDataPath("$PROJECT_ROOT") +public class Fe10IdeNormalAnalysisSourceModuleAnnotationApplicableTargetsTestGenerated extends AbstractAnnotationApplicableTargetsTest { + @NotNull + @Override + public AnalysisApiTestConfigurator getConfigurator() { + return AnalysisApiFe10TestConfiguratorFactory.INSTANCE.createConfigurator( + new AnalysisApiTestConfiguratorFactoryData( + FrontendKind.Fe10, + TestModuleKind.Source, + AnalysisSessionMode.Normal, + AnalysisApiMode.Ide + ) + ); + } + + @Test + public void testAllFilesPresentInAnnotationApplicableTargets() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("defaultTargets.kt") + public void testDefaultTargets() throws Exception { + runTest("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/defaultTargets.kt"); + } + + @Test + @TestMetadata("emptyTargets.kt") + public void testEmptyTargets() throws Exception { + runTest("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/emptyTargets.kt"); + } + + @Test + @TestMetadata("javaAnnotation.kt") + public void testJavaAnnotation() throws Exception { + runTest("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/javaAnnotation.kt"); + } + + @Test + @TestMetadata("listedTargets.kt") + public void testListedTargets() throws Exception { + runTest("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/listedTargets.kt"); + } + + @Test + @TestMetadata("nonAnnotationClass.kt") + public void testNonAnnotationClass() throws Exception { + runTest("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/nonAnnotationClass.kt"); + } +} diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirSymbolInfoProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirSymbolInfoProvider.kt index f2d4f80c4ed..a231b4c5f55 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirSymbolInfoProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirSymbolInfoProvider.kt @@ -7,16 +7,20 @@ package org.jetbrains.kotlin.analysis.api.fir.components import org.jetbrains.kotlin.analysis.api.components.KtSymbolInfoProvider import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession +import org.jetbrains.kotlin.analysis.api.fir.symbols.* import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirBackingFieldSymbol -import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirPackageSymbol import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirSymbol import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirSyntheticJavaPropertySymbol import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken +import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtReceiverParameterSymbol import org.jetbrains.kotlin.analysis.utils.errors.requireIsInstance +import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget +import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget +import org.jetbrains.kotlin.fir.analysis.checkers.getAllowedAnnotationTargets import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.getDeprecationForCallSite import org.jetbrains.kotlin.fir.declarations.getJvmNameFromAnnotation @@ -94,6 +98,13 @@ internal class KtFirSymbolInfoProvider( return getJvmName(firProperty, isSetter = true) } + override fun getAnnotationApplicableTargets(symbol: KtClassOrObjectSymbol): Set? { + requireIsInstance>(symbol) + if (symbol !is KtFirNamedClassOrObjectSymbol) return null + if (symbol.firSymbol.classKind != ClassKind.ANNOTATION_CLASS) return null + return symbol.firSymbol.getAllowedAnnotationTargets(analysisSession.useSiteSession) + } + private fun getJvmName(property: FirProperty, isSetter: Boolean): Name { if (property.hasAnnotation(StandardClassIds.Annotations.JvmField, analysisSession.useSiteSession)) return property.name return Name.identifier(getJvmNameAsString(property, isSetter)) diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/symbolInfoProvider/FirIdeDependentAnalysisSourceModuleAnnotationApplicableTargetsTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/symbolInfoProvider/FirIdeDependentAnalysisSourceModuleAnnotationApplicableTargetsTestGenerated.java new file mode 100644 index 00000000000..f022502518f --- /dev/null +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/symbolInfoProvider/FirIdeDependentAnalysisSourceModuleAnnotationApplicableTargetsTestGenerated.java @@ -0,0 +1,78 @@ +/* + * 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.analysis.api.fir.test.cases.generated.cases.components.symbolInfoProvider; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.util.KtTestUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.analysis.api.fir.test.configurators.AnalysisApiFirTestConfiguratorFactory; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfiguratorFactoryData; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfigurator; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.TestModuleKind; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.FrontendKind; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisSessionMode; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiMode; +import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.symbolInfoProvider.AbstractAnnotationApplicableTargetsTest; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.analysis.api.GenerateAnalysisApiTestsKt}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets") +@TestDataPath("$PROJECT_ROOT") +public class FirIdeDependentAnalysisSourceModuleAnnotationApplicableTargetsTestGenerated extends AbstractAnnotationApplicableTargetsTest { + @NotNull + @Override + public AnalysisApiTestConfigurator getConfigurator() { + return AnalysisApiFirTestConfiguratorFactory.INSTANCE.createConfigurator( + new AnalysisApiTestConfiguratorFactoryData( + FrontendKind.Fir, + TestModuleKind.Source, + AnalysisSessionMode.Dependent, + AnalysisApiMode.Ide + ) + ); + } + + @Test + public void testAllFilesPresentInAnnotationApplicableTargets() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("defaultTargets.kt") + public void testDefaultTargets() throws Exception { + runTest("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/defaultTargets.kt"); + } + + @Test + @TestMetadata("emptyTargets.kt") + public void testEmptyTargets() throws Exception { + runTest("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/emptyTargets.kt"); + } + + @Test + @TestMetadata("javaAnnotation.kt") + public void testJavaAnnotation() throws Exception { + runTest("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/javaAnnotation.kt"); + } + + @Test + @TestMetadata("listedTargets.kt") + public void testListedTargets() throws Exception { + runTest("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/listedTargets.kt"); + } + + @Test + @TestMetadata("nonAnnotationClass.kt") + public void testNonAnnotationClass() throws Exception { + runTest("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/nonAnnotationClass.kt"); + } +} diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/symbolInfoProvider/FirIdeNormalAnalysisSourceModuleAnnotationApplicableTargetsTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/symbolInfoProvider/FirIdeNormalAnalysisSourceModuleAnnotationApplicableTargetsTestGenerated.java new file mode 100644 index 00000000000..7913d688841 --- /dev/null +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/symbolInfoProvider/FirIdeNormalAnalysisSourceModuleAnnotationApplicableTargetsTestGenerated.java @@ -0,0 +1,78 @@ +/* + * 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.analysis.api.fir.test.cases.generated.cases.components.symbolInfoProvider; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.util.KtTestUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.analysis.api.fir.test.configurators.AnalysisApiFirTestConfiguratorFactory; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfiguratorFactoryData; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfigurator; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.TestModuleKind; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.FrontendKind; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisSessionMode; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiMode; +import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.symbolInfoProvider.AbstractAnnotationApplicableTargetsTest; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.analysis.api.GenerateAnalysisApiTestsKt}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets") +@TestDataPath("$PROJECT_ROOT") +public class FirIdeNormalAnalysisSourceModuleAnnotationApplicableTargetsTestGenerated extends AbstractAnnotationApplicableTargetsTest { + @NotNull + @Override + public AnalysisApiTestConfigurator getConfigurator() { + return AnalysisApiFirTestConfiguratorFactory.INSTANCE.createConfigurator( + new AnalysisApiTestConfiguratorFactoryData( + FrontendKind.Fir, + TestModuleKind.Source, + AnalysisSessionMode.Normal, + AnalysisApiMode.Ide + ) + ); + } + + @Test + public void testAllFilesPresentInAnnotationApplicableTargets() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("defaultTargets.kt") + public void testDefaultTargets() throws Exception { + runTest("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/defaultTargets.kt"); + } + + @Test + @TestMetadata("emptyTargets.kt") + public void testEmptyTargets() throws Exception { + runTest("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/emptyTargets.kt"); + } + + @Test + @TestMetadata("javaAnnotation.kt") + public void testJavaAnnotation() throws Exception { + runTest("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/javaAnnotation.kt"); + } + + @Test + @TestMetadata("listedTargets.kt") + public void testListedTargets() throws Exception { + runTest("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/listedTargets.kt"); + } + + @Test + @TestMetadata("nonAnnotationClass.kt") + public void testNonAnnotationClass() throws Exception { + runTest("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/nonAnnotationClass.kt"); + } +} diff --git a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/symbolInfoProvider/AbstractAnnotationApplicableTargetsTest.kt b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/symbolInfoProvider/AbstractAnnotationApplicableTargetsTest.kt new file mode 100644 index 00000000000..fca9e4b502e --- /dev/null +++ b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/symbolInfoProvider/AbstractAnnotationApplicableTargetsTest.kt @@ -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.analysis.api.impl.base.test.cases.components.symbolInfoProvider + +import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiSingleFileTest +import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerProvider +import org.jetbrains.kotlin.psi.KtAnnotationEntry +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.test.model.TestModule +import org.jetbrains.kotlin.test.services.TestServices +import org.jetbrains.kotlin.test.services.assertions + +abstract class AbstractAnnotationApplicableTargetsTest : AbstractAnalysisApiSingleFileTest() { + override fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices) { + val annotationEntry = testServices.expressionMarkerProvider.getElementOfTypeAtCaret(ktFile) + val actual = analyseForTest(annotationEntry) { + val annotationClassSymbol = annotationEntry.typeReference?.getKtType()?.expandedClassSymbol!! + val applicableTargetsInOrder = + annotationClassSymbol.annotationApplicableTargets + ?.map { it.name } + ?.sorted() + ?.joinToString(prefix = "[", separator = ", ", postfix = "]") + ?: "" + + buildString { + appendLine("KtAnnotationEntry: ${annotationEntry.text}") + appendLine() + appendLine("Resolved annotation symbol:") + appendLine(annotationClassSymbol.render()) + appendLine() + appendLine("Applicable targets: $applicableTargetsInOrder") + } + } + + testServices.assertions.assertEqualsToTestDataFileSibling(actual) + } +} diff --git a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/symbolInfoProvider/FirStandaloneNormalAnalysisSourceModuleAnnotationApplicableTargetsTestGenerated.java b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/symbolInfoProvider/FirStandaloneNormalAnalysisSourceModuleAnnotationApplicableTargetsTestGenerated.java new file mode 100644 index 00000000000..dc46f198589 --- /dev/null +++ b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/symbolInfoProvider/FirStandaloneNormalAnalysisSourceModuleAnnotationApplicableTargetsTestGenerated.java @@ -0,0 +1,78 @@ +/* + * 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.analysis.api.standalone.fir.test.cases.generated.cases.components.symbolInfoProvider; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.util.KtTestUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.analysis.api.standalone.fir.test.AnalysisApiFirStandaloneModeTestConfiguratorFactory; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfiguratorFactoryData; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfigurator; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.TestModuleKind; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.FrontendKind; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisSessionMode; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiMode; +import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.symbolInfoProvider.AbstractAnnotationApplicableTargetsTest; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.analysis.api.GenerateAnalysisApiTestsKt}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets") +@TestDataPath("$PROJECT_ROOT") +public class FirStandaloneNormalAnalysisSourceModuleAnnotationApplicableTargetsTestGenerated extends AbstractAnnotationApplicableTargetsTest { + @NotNull + @Override + public AnalysisApiTestConfigurator getConfigurator() { + return AnalysisApiFirStandaloneModeTestConfiguratorFactory.INSTANCE.createConfigurator( + new AnalysisApiTestConfiguratorFactoryData( + FrontendKind.Fir, + TestModuleKind.Source, + AnalysisSessionMode.Normal, + AnalysisApiMode.Standalone + ) + ); + } + + @Test + public void testAllFilesPresentInAnnotationApplicableTargets() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("defaultTargets.kt") + public void testDefaultTargets() throws Exception { + runTest("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/defaultTargets.kt"); + } + + @Test + @TestMetadata("emptyTargets.kt") + public void testEmptyTargets() throws Exception { + runTest("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/emptyTargets.kt"); + } + + @Test + @TestMetadata("javaAnnotation.kt") + public void testJavaAnnotation() throws Exception { + runTest("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/javaAnnotation.kt"); + } + + @Test + @TestMetadata("listedTargets.kt") + public void testListedTargets() throws Exception { + runTest("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/listedTargets.kt"); + } + + @Test + @TestMetadata("nonAnnotationClass.kt") + public void testNonAnnotationClass() throws Exception { + runTest("analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/nonAnnotationClass.kt"); + } +} diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtSymbolInfoProvider.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtSymbolInfoProvider.kt index c89fca6c51c..d463456f5b4 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtSymbolInfoProvider.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtSymbolInfoProvider.kt @@ -22,6 +22,8 @@ public abstract class KtSymbolInfoProvider : KtAnalysisSessionComponent() { public abstract fun getJavaGetterName(symbol: KtPropertySymbol): Name public abstract fun getJavaSetterName(symbol: KtPropertySymbol): Name? + + public abstract fun getAnnotationApplicableTargets(symbol: KtClassOrObjectSymbol): Set? } public interface KtSymbolInfoProviderMixIn : KtAnalysisSessionMixIn { @@ -66,5 +68,5 @@ public interface KtSymbolInfoProviderMixIn : KtAnalysisSessionMixIn { /** Gets the set of applicable targets for an annotation class symbol. Returns `null` if the symbol is not an annotation class. */ public val KtClassOrObjectSymbol.annotationApplicableTargets: Set? - get() = withValidityAssertion { null /* TODO */ } + get() = withValidityAssertion { analysisSession.symbolInfoProvider.getAnnotationApplicableTargets(this) } } diff --git a/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/defaultTargets.kt b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/defaultTargets.kt new file mode 100644 index 00000000000..98256fcc09c --- /dev/null +++ b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/defaultTargets.kt @@ -0,0 +1,3 @@ +annotation class A() + +@A object Foo \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/defaultTargets.txt b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/defaultTargets.txt new file mode 100644 index 00000000000..3677e5d6722 --- /dev/null +++ b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/defaultTargets.txt @@ -0,0 +1,6 @@ +KtAnnotationEntry: @A + +Resolved annotation symbol: +annotation class A + +Applicable targets: [ANNOTATION_CLASS, BACKING_FIELD, CLASS, CONSTRUCTOR, FIELD, FUNCTION, LOCAL_VARIABLE, PROPERTY, PROPERTY_GETTER, PROPERTY_SETTER, VALUE_PARAMETER] diff --git a/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/emptyTargets.descriptors.txt b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/emptyTargets.descriptors.txt new file mode 100644 index 00000000000..6437f1bd8bc --- /dev/null +++ b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/emptyTargets.descriptors.txt @@ -0,0 +1,7 @@ +KtAnnotationEntry: @A + +Resolved annotation symbol: +@kotlin.annotation.Target(allowedTargets = []) +annotation class A + +Applicable targets: [] diff --git a/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/emptyTargets.kt b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/emptyTargets.kt new file mode 100644 index 00000000000..9bf327adf8b --- /dev/null +++ b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/emptyTargets.kt @@ -0,0 +1,4 @@ +@Target() +annotation class A + +@A object Foo \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/emptyTargets.txt b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/emptyTargets.txt new file mode 100644 index 00000000000..75c6e83e9e3 --- /dev/null +++ b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/emptyTargets.txt @@ -0,0 +1,7 @@ +KtAnnotationEntry: @A + +Resolved annotation symbol: +@kotlin.annotation.Target +annotation class A + +Applicable targets: [] diff --git a/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/javaAnnotation.descriptors.txt b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/javaAnnotation.descriptors.txt new file mode 100644 index 00000000000..f6576cac3ac --- /dev/null +++ b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/javaAnnotation.descriptors.txt @@ -0,0 +1,7 @@ +KtAnnotationEntry: @A + +Resolved annotation symbol: +@kotlin.annotation.Target(allowedTargets = [kotlin.annotation.AnnotationTarget.CLASS, kotlin.annotation.AnnotationTarget.FILE, kotlin.annotation.AnnotationTarget.FUNCTION, kotlin.annotation.AnnotationTarget.PROPERTY_GETTER, kotlin.annotation.AnnotationTarget.PROPERTY_SETTER]) +annotation class A + +Applicable targets: [CLASS, FILE, FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER] diff --git a/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/javaAnnotation.kt b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/javaAnnotation.kt new file mode 100644 index 00000000000..53e7366a23f --- /dev/null +++ b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/javaAnnotation.kt @@ -0,0 +1,10 @@ +// FILE: A.java + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +@Target({ElementType.TYPE, ElementType.METHOD}) +public @interface A {} + +// FILE: Foo.kt +@A object Foo \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/javaAnnotation.txt b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/javaAnnotation.txt new file mode 100644 index 00000000000..b3604700adf --- /dev/null +++ b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/javaAnnotation.txt @@ -0,0 +1,7 @@ +KtAnnotationEntry: @A + +Resolved annotation symbol: +@kotlin.annotation.Target(allowedTargets = [kotlin.annotation.AnnotationTarget.CLASS, kotlin.annotation.AnnotationTarget.FUNCTION, kotlin.annotation.AnnotationTarget.PROPERTY_GETTER, kotlin.annotation.AnnotationTarget.PROPERTY_SETTER, kotlin.annotation.AnnotationTarget.FILE]) +annotation class A + +Applicable targets: [CLASS, FILE, FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER] diff --git a/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/listedTargets.kt b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/listedTargets.kt new file mode 100644 index 00000000000..feb3c227d13 --- /dev/null +++ b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/listedTargets.kt @@ -0,0 +1,7 @@ +import kotlin.annotation.AnnotationTarget +import kotlin.annotation.Target + +@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY) +annotation class A + +@A object Foo \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/listedTargets.txt b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/listedTargets.txt new file mode 100644 index 00000000000..c46b12f4e60 --- /dev/null +++ b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/listedTargets.txt @@ -0,0 +1,7 @@ +KtAnnotationEntry: @A + +Resolved annotation symbol: +@kotlin.annotation.Target(allowedTargets = [kotlin.annotation.AnnotationTarget.CLASS, kotlin.annotation.AnnotationTarget.PROPERTY]) +annotation class A + +Applicable targets: [CLASS, PROPERTY] diff --git a/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/nonAnnotationClass.kt b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/nonAnnotationClass.kt new file mode 100644 index 00000000000..726c1b66a09 --- /dev/null +++ b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/nonAnnotationClass.kt @@ -0,0 +1,3 @@ +class A() + +@A object Foo \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/nonAnnotationClass.txt b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/nonAnnotationClass.txt new file mode 100644 index 00000000000..6db463d5733 --- /dev/null +++ b/analysis/analysis-api/testData/components/symbolInfoProvider/annotationApplicableTargets/nonAnnotationClass.txt @@ -0,0 +1,6 @@ +KtAnnotationEntry: @A + +Resolved annotation symbol: +class A + +Applicable targets: diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/annotations.descriptors.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/annotations.descriptors.txt index 7f9fab4c1d1..5b48eb26de2 100644 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/annotations.descriptors.txt +++ b/analysis/analysis-api/testData/symbols/symbolByPsi/annotations.descriptors.txt @@ -180,7 +180,7 @@ KtNamedClassOrObjectSymbol: typeParameters: [] visibility: Public getContainingModule: KtSourceModule "Sources of main" - annotationApplicableTargets: null + annotationApplicableTargets: [CLASS, ANNOTATION_CLASS, PROPERTY, FIELD, LOCAL_VARIABLE, VALUE_PARAMETER, CONSTRUCTOR, FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER, BACKING_FIELD] deprecationStatus: null KtFunctionSymbol: diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/annotations.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/annotations.txt index 38feb3c80d7..f60378e8e83 100644 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/annotations.txt +++ b/analysis/analysis-api/testData/symbols/symbolByPsi/annotations.txt @@ -180,7 +180,7 @@ KtNamedClassOrObjectSymbol: typeParameters: [] visibility: Public getContainingModule: KtSourceModule "Sources of main" - annotationApplicableTargets: null + annotationApplicableTargets: [CLASS, ANNOTATION_CLASS, PROPERTY, FIELD, LOCAL_VARIABLE, VALUE_PARAMETER, CONSTRUCTOR, FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER, BACKING_FIELD] deprecationStatus: null KtFunctionSymbol: diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/typeAnnotations.descriptors.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/typeAnnotations.descriptors.txt index 03bbaabf25a..30303b9991a 100644 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/typeAnnotations.descriptors.txt +++ b/analysis/analysis-api/testData/symbols/symbolByPsi/typeAnnotations.descriptors.txt @@ -22,7 +22,7 @@ KtNamedClassOrObjectSymbol: typeParameters: [] visibility: Public getContainingModule: KtSourceModule "Sources of main" - annotationApplicableTargets: null + annotationApplicableTargets: [TYPE] deprecationStatus: null KtNamedClassOrObjectSymbol: @@ -49,7 +49,7 @@ KtNamedClassOrObjectSymbol: typeParameters: [] visibility: Public getContainingModule: KtSourceModule "Sources of main" - annotationApplicableTargets: null + annotationApplicableTargets: [TYPE] deprecationStatus: null KtNamedClassOrObjectSymbol: @@ -76,7 +76,7 @@ KtNamedClassOrObjectSymbol: typeParameters: [] visibility: Public getContainingModule: KtSourceModule "Sources of main" - annotationApplicableTargets: null + annotationApplicableTargets: [TYPE] deprecationStatus: null KtNamedClassOrObjectSymbol: @@ -103,7 +103,7 @@ KtNamedClassOrObjectSymbol: typeParameters: [] visibility: Public getContainingModule: KtSourceModule "Sources of main" - annotationApplicableTargets: null + annotationApplicableTargets: [TYPE] deprecationStatus: null KtNamedClassOrObjectSymbol: diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/typeAnnotations.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/typeAnnotations.txt index 178707bd5eb..08af1c5b641 100644 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/typeAnnotations.txt +++ b/analysis/analysis-api/testData/symbols/symbolByPsi/typeAnnotations.txt @@ -22,7 +22,7 @@ KtNamedClassOrObjectSymbol: typeParameters: [] visibility: Public getContainingModule: KtSourceModule "Sources of main" - annotationApplicableTargets: null + annotationApplicableTargets: [TYPE] deprecationStatus: null KtNamedClassOrObjectSymbol: @@ -49,7 +49,7 @@ KtNamedClassOrObjectSymbol: typeParameters: [] visibility: Public getContainingModule: KtSourceModule "Sources of main" - annotationApplicableTargets: null + annotationApplicableTargets: [TYPE] deprecationStatus: null KtNamedClassOrObjectSymbol: @@ -76,7 +76,7 @@ KtNamedClassOrObjectSymbol: typeParameters: [] visibility: Public getContainingModule: KtSourceModule "Sources of main" - annotationApplicableTargets: null + annotationApplicableTargets: [TYPE] deprecationStatus: null KtNamedClassOrObjectSymbol: @@ -103,7 +103,7 @@ KtNamedClassOrObjectSymbol: typeParameters: [] visibility: Public getContainingModule: KtSourceModule "Sources of main" - annotationApplicableTargets: null + annotationApplicableTargets: [TYPE] deprecationStatus: null KtNamedClassOrObjectSymbol: diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirAnnotationHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirAnnotationHelpers.kt index 34a9d146e24..eeecab4c14a 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirAnnotationHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirAnnotationHelpers.kt @@ -70,6 +70,7 @@ fun FirRegularClass.getAllowedAnnotationTargets(session: FirSession): Set.getAllowedAnnotationTargets(session: FirSession): Set { + lazyResolveToPhase(FirResolvePhase.ANNOTATIONS_ARGUMENTS_MAPPING) val targetAnnotation = getTargetAnnotation(session) ?: return defaultAnnotationTargets val arguments = targetAnnotation.findArgumentByName(ParameterNames.targetAllowedTargets)?.unfoldArrayOrVararg().orEmpty() diff --git a/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/analysisApi.kt b/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/analysisApi.kt index 190ae7c6bcf..d19a547be25 100644 --- a/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/analysisApi.kt +++ b/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/analysisApi.kt @@ -35,6 +35,7 @@ import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.substut import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.symbolDeclarationOverridesProvider.AbstractIsSubclassOfTest import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.symbolDeclarationOverridesProvider.AbstractOverriddenDeclarationProviderTest import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.symbolDeclarationRenderer.AbstractRendererTest +import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.symbolInfoProvider.AbstractAnnotationApplicableTargetsTest import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.typeCreator.AbstractBuildClassTypeTest import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.typeCreator.AbstractTypeParameterTypeTest import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.typeInfoProvider.AbstractFunctionClassKindTest @@ -310,6 +311,12 @@ private fun AnalysisApiTestGroup.generateAnalysisApiComponentsTests() { } } + component("symbolInfoProvider") { + test(AbstractAnnotationApplicableTargetsTest::class) { + model("annotationApplicableTargets") + } + } + component("typeCreator") { test(AbstractTypeParameterTypeTest::class) { model("typeParameter")