diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirSimpleNameReference.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirSimpleNameReference.kt index 1204eb800e9..68fc2a1537b 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirSimpleNameReference.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirSimpleNameReference.kt @@ -40,6 +40,10 @@ internal class KtFirSimpleNameReference( } } + override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean { + return getImportAlias(alias.importDirective) != null + } + override fun KtAnalysisSession.resolveToSymbols(): Collection { check(this is KtFirAnalysisSession) val results = FirReferenceResolveHelper.resolveSimpleNameReference(this@KtFirSimpleNameReference, this) @@ -80,8 +84,25 @@ internal class KtFirSimpleNameReference( return false } - override fun getImportAlias(): KtImportAlias? { - // TODO: Implement. + private fun getImportAlias(importDirective: KtImportDirective?): KtImportAlias? { + val fqName = importDirective?.importedFqName ?: return null + val codeFragment = KtPsiFactory(element.project).createExpressionCodeFragment(fqName.asString(), element) + val contentElement = codeFragment.getContentElement() + val importResults = + when (contentElement) { + is KtDotQualifiedExpression -> contentElement.selectorExpression?.mainReference?.multiResolve(false) + is KtSimpleNameExpression -> contentElement.mainReference.multiResolve(false) + else -> null + } ?: return null + if (multiResolve(false).any { it in importResults }) { + return importDirective.alias + } return null } + + override fun getImportAlias(): KtImportAlias? { + val name = element.getReferencedName() + val file = element.containingKtFile + return getImportAlias(file.findImportByAlias(name)) + } } \ No newline at end of file diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisScriptSourceModuleReferenceImportAliasTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisScriptSourceModuleReferenceImportAliasTestGenerated.java new file mode 100644 index 00000000000..e8e24789ec7 --- /dev/null +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisScriptSourceModuleReferenceImportAliasTestGenerated.java @@ -0,0 +1,48 @@ +/* + * 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.references; + +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.references.AbstractReferenceImportAliasTest; +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/imports/importAliases") +@TestDataPath("$PROJECT_ROOT") +public class FirIdeNormalAnalysisScriptSourceModuleReferenceImportAliasTestGenerated extends AbstractReferenceImportAliasTest { + @NotNull + @Override + public AnalysisApiTestConfigurator getConfigurator() { + return AnalysisApiFirTestConfiguratorFactory.INSTANCE.createConfigurator( + new AnalysisApiTestConfiguratorFactoryData( + FrontendKind.Fir, + TestModuleKind.ScriptSource, + AnalysisSessionMode.Normal, + AnalysisApiMode.Ide + ) + ); + } + + @Test + public void testAllFilesPresentInImportAliases() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/imports/importAliases"), Pattern.compile("^(.+)\\.kts$"), null, true); + } +} diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleReferenceImportAliasTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleReferenceImportAliasTestGenerated.java new file mode 100644 index 00000000000..94a174ef703 --- /dev/null +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleReferenceImportAliasTestGenerated.java @@ -0,0 +1,66 @@ +/* + * 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.references; + +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.references.AbstractReferenceImportAliasTest; +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/imports/importAliases") +@TestDataPath("$PROJECT_ROOT") +public class FirIdeNormalAnalysisSourceModuleReferenceImportAliasTestGenerated extends AbstractReferenceImportAliasTest { + @NotNull + @Override + public AnalysisApiTestConfigurator getConfigurator() { + return AnalysisApiFirTestConfiguratorFactory.INSTANCE.createConfigurator( + new AnalysisApiTestConfiguratorFactoryData( + FrontendKind.Fir, + TestModuleKind.Source, + AnalysisSessionMode.Normal, + AnalysisApiMode.Ide + ) + ); + } + + @Test + public void testAllFilesPresentInImportAliases() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/imports/importAliases"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("classAlias.kt") + public void testClassAlias() throws Exception { + runTest("analysis/analysis-api/testData/imports/importAliases/classAlias.kt"); + } + + @Test + @TestMetadata("functionAlias.kt") + public void testFunctionAlias() throws Exception { + runTest("analysis/analysis-api/testData/imports/importAliases/functionAlias.kt"); + } + + @Test + @TestMetadata("propertyAlias.kt") + public void testPropertyAlias() throws Exception { + runTest("analysis/analysis-api/testData/imports/importAliases/propertyAlias.kt"); + } +} diff --git a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/references/AbstractReferenceImportAliasTest.kt b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/references/AbstractReferenceImportAliasTest.kt new file mode 100644 index 00000000000..74bfd10576c --- /dev/null +++ b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/references/AbstractReferenceImportAliasTest.kt @@ -0,0 +1,39 @@ +/* + * 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.references + +import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiBasedSingleModuleTest +import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerProvider +import org.jetbrains.kotlin.idea.references.mainReference +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtSimpleNameExpression +import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder +import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer +import org.jetbrains.kotlin.test.model.TestModule +import org.jetbrains.kotlin.test.services.TestServices +import org.jetbrains.kotlin.test.services.assertions + +abstract class AbstractReferenceImportAliasTest : AbstractAnalysisApiBasedSingleModuleTest() { + override fun configureTest(builder: TestConfigurationBuilder) { + super.configureTest(builder) + with(builder) { + useDirectives(Directives) + } + } + + override fun doTestByFileStructure(ktFiles: List, module: TestModule, testServices: TestServices) { + val element = testServices.expressionMarkerProvider.getElementOfTypeAtCaret(ktFiles.first()) + val alias = element.mainReference.getImportAlias() + val expectedAlias = module.directives[Directives.TYPE_ALIAS].joinToString(" ") + testServices.assertions.assertEquals(expectedAlias, alias?.text) + } + + private object Directives : SimpleDirectivesContainer() { + val TYPE_ALIAS by stringDirective( + description = "Type alias for selected reference" + ) + } +} \ No newline at end of file diff --git a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleReferenceImportAliasTestGenerated.java b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleReferenceImportAliasTestGenerated.java new file mode 100644 index 00000000000..e3d07ab238e --- /dev/null +++ b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleReferenceImportAliasTestGenerated.java @@ -0,0 +1,66 @@ +/* + * 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.references; + +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.references.AbstractReferenceImportAliasTest; +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/imports/importAliases") +@TestDataPath("$PROJECT_ROOT") +public class FirStandaloneNormalAnalysisSourceModuleReferenceImportAliasTestGenerated extends AbstractReferenceImportAliasTest { + @NotNull + @Override + public AnalysisApiTestConfigurator getConfigurator() { + return AnalysisApiFirStandaloneModeTestConfiguratorFactory.INSTANCE.createConfigurator( + new AnalysisApiTestConfiguratorFactoryData( + FrontendKind.Fir, + TestModuleKind.Source, + AnalysisSessionMode.Normal, + AnalysisApiMode.Standalone + ) + ); + } + + @Test + public void testAllFilesPresentInImportAliases() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/imports/importAliases"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("classAlias.kt") + public void testClassAlias() throws Exception { + runTest("analysis/analysis-api/testData/imports/importAliases/classAlias.kt"); + } + + @Test + @TestMetadata("functionAlias.kt") + public void testFunctionAlias() throws Exception { + runTest("analysis/analysis-api/testData/imports/importAliases/functionAlias.kt"); + } + + @Test + @TestMetadata("propertyAlias.kt") + public void testPropertyAlias() throws Exception { + runTest("analysis/analysis-api/testData/imports/importAliases/propertyAlias.kt"); + } +} diff --git a/analysis/analysis-api/testData/imports/importAliases/classAlias.kt b/analysis/analysis-api/testData/imports/importAliases/classAlias.kt new file mode 100644 index 00000000000..dd948974c78 --- /dev/null +++ b/analysis/analysis-api/testData/imports/importAliases/classAlias.kt @@ -0,0 +1,9 @@ +// TYPE_ALIAS: as bar +import Foo as bar + +object Foo { +} + +fun test() { + val x: bar? = null +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/imports/importAliases/functionAlias.kt b/analysis/analysis-api/testData/imports/importAliases/functionAlias.kt new file mode 100644 index 00000000000..70c8a07e9ef --- /dev/null +++ b/analysis/analysis-api/testData/imports/importAliases/functionAlias.kt @@ -0,0 +1,10 @@ +// TYPE_ALIAS: as bar +import Foo.foo as bar + +object Foo { + fun foo() {} +} + +fun test() { + bar() +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/imports/importAliases/propertyAlias.kt b/analysis/analysis-api/testData/imports/importAliases/propertyAlias.kt new file mode 100644 index 00000000000..801e17fc53f --- /dev/null +++ b/analysis/analysis-api/testData/imports/importAliases/propertyAlias.kt @@ -0,0 +1,10 @@ +// TYPE_ALIAS: as bar +import Foo.foo as bar + +object Foo { + val foo = 1 +} + +fun test() { + val x = bar +} \ No newline at end of file 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 757c61fd9b7..b2bfeba9cf9 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 @@ -50,6 +50,7 @@ import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.typeInf import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.typeProvider.AbstractAnalysisApiGetSuperTypesTest import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.typeProvider.AbstractHasCommonSubtypeTest import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.typeProvider.AbstractTypeReferenceTest +import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.references.AbstractReferenceImportAliasTest import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.references.AbstractReferenceResolveTest import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.references.AbstractReferenceResolveWithResolveExtensionTest import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.references.AbstractReferenceShortenerForWholeFileTest @@ -204,6 +205,14 @@ private fun AnalysisApiTestGroup.generateAnalysisApiNonComponentsTests() { } + group("imports", filter = frontendIs(FrontendKind.Fir)) { + test( + AbstractReferenceImportAliasTest::class, + filter = analysisSessionModeIs(AnalysisSessionMode.Normal)) { + model(it, "importAliases") + } + } + group("substitutors", filter = frontendIs(FrontendKind.Fir)) { test(AbstractAnalysisApiSubstitutorsTest::class) { model(it, "typeSubstitution")