diff --git a/idea/idea-fir/tests/org/jetbrains/kotlin/idea/fir/resolve/FirReferenceResolveTestGenerated.java b/idea/idea-fir/tests/org/jetbrains/kotlin/idea/fir/resolve/FirReferenceResolveTestGenerated.java index b44b08721ce..7afe75870ea 100644 --- a/idea/idea-fir/tests/org/jetbrains/kotlin/idea/fir/resolve/FirReferenceResolveTestGenerated.java +++ b/idea/idea-fir/tests/org/jetbrains/kotlin/idea/fir/resolve/FirReferenceResolveTestGenerated.java @@ -716,6 +716,64 @@ public class FirReferenceResolveTestGenerated extends AbstractFirReferenceResolv } } + @TestMetadata("idea/testData/resolve/references/inImport") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class InImport extends AbstractFirReferenceResolveTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInInImport() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/resolve/references/inImport"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("javaClass.kt") + public void testJavaClass() throws Exception { + runTest("idea/testData/resolve/references/inImport/javaClass.kt"); + } + + @TestMetadata("javaPackageFirstQualifier.kt") + public void testJavaPackageFirstQualifier() throws Exception { + runTest("idea/testData/resolve/references/inImport/javaPackageFirstQualifier.kt"); + } + + @TestMetadata("javaPackageSecondQualifier.kt") + public void testJavaPackageSecondQualifier() throws Exception { + runTest("idea/testData/resolve/references/inImport/javaPackageSecondQualifier.kt"); + } + + @TestMetadata("kotlinClass.kt") + public void testKotlinClass() throws Exception { + runTest("idea/testData/resolve/references/inImport/kotlinClass.kt"); + } + + @TestMetadata("kotlinPackageFirstQualifier.kt") + public void testKotlinPackageFirstQualifier() throws Exception { + runTest("idea/testData/resolve/references/inImport/kotlinPackageFirstQualifier.kt"); + } + + @TestMetadata("kotlinPackageSecondQualifier.kt") + public void testKotlinPackageSecondQualifier() throws Exception { + runTest("idea/testData/resolve/references/inImport/kotlinPackageSecondQualifier.kt"); + } + + @TestMetadata("kotlinTopLevelFunction.kt") + public void testKotlinTopLevelFunction() throws Exception { + runTest("idea/testData/resolve/references/inImport/kotlinTopLevelFunction.kt"); + } + + @TestMetadata("staticMethodFromJavaClass.kt") + public void testStaticMethodFromJavaClass() throws Exception { + runTest("idea/testData/resolve/references/inImport/staticMethodFromJavaClass.kt"); + } + + @TestMetadata("staticMethodFromJavaClassJavaClass.kt") + public void testStaticMethodFromJavaClassJavaClass() throws Exception { + runTest("idea/testData/resolve/references/inImport/staticMethodFromJavaClassJavaClass.kt"); + } + } + @TestMetadata("idea/testData/resolve/references/invoke") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt index e2cf1b39a4e..71a036cc16d 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt @@ -6,18 +6,25 @@ package org.jetbrains.kotlin.idea.references import com.intellij.psi.tree.TokenSet -import org.jetbrains.kotlin.fir.* +import org.jetbrains.kotlin.fir.FirFakeSourceElementKind +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.ROOT_PREFIX_FOR_IDE_RESOLUTION_MODE import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.declarations.builder.buildImport import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty import org.jetbrains.kotlin.fir.expressions.* +import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.references.* +import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticPropertySymbol import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeOperatorAmbiguityError import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnmatchedTypeArgumentsError -import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.toSymbol +import org.jetbrains.kotlin.fir.resolve.transformers.FirImportResolveTransformer +import org.jetbrains.kotlin.fir.scopes.impl.FirExplicitSimpleImportingScope +import org.jetbrains.kotlin.fir.scopes.processClassifiersByName import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl @@ -39,6 +46,7 @@ import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector import org.jetbrains.kotlin.psi.psiUtil.unwrapNullability +import org.jetbrains.kotlin.utils.addIfNotNull internal object FirReferenceResolveHelper { fun FirResolvedTypeRef.toTargetSymbol(session: FirSession, symbolBuilder: KtSymbolByFirBuilder): KtSymbol? { @@ -116,11 +124,18 @@ internal object FirReferenceResolveHelper { symbolBuilder: KtSymbolByFirBuilder, forQualifiedType: Boolean ): KtFirPackageSymbol? { + return symbolBuilder.createPackageSymbolIfOneExists(getQualifierSelected(expression, forQualifiedType)) + } + + private fun getQualifierSelected( + expression: KtSimpleNameExpression, + forQualifiedType: Boolean + ): FqName { val qualified = when { forQualifiedType -> expression.parent?.takeIf { it is KtUserType && it.referenceExpression === expression } else -> expression.getQualifiedExpressionForSelector() } - val fqName = when (qualified) { + return when (qualified) { null -> FqName(expression.getReferencedName()) else -> { qualified @@ -130,7 +145,6 @@ internal object FirReferenceResolveHelper { .let(::FqName) } } - return symbolBuilder.createPackageSymbolIfOneExists(fqName) } private fun KtSimpleNameExpression.isPartOfQualifiedExpression(): Boolean { @@ -313,32 +327,30 @@ internal object FirReferenceResolveHelper { return listOf(symbolBuilder.buildSymbol(fir)) } + @OptIn(ExperimentalStdlibApi::class) private fun getSymbolsByResolvedImport( expression: KtSimpleNameExpression, - symbolBuilder: KtSymbolByFirBuilder, + builder: KtSymbolByFirBuilder, fir: FirResolvedImport, session: FirSession ): List { - if (expression.isPartOfQualifiedExpression()) { - return listOfNotNull(getPackageSymbolFor(expression, symbolBuilder, forQualifiedType = false)) + val fullFqName = fir.importedFqName + val selectedFqName = getQualifierSelected(expression, forQualifiedType = false) + val rawImportForSelectedFqName = buildImport { + importedFqName = selectedFqName + isAllUnder = false } - - val classId = fir.resolvedClassId - if (classId != null) { - return listOfNotNull(classId.toTargetPsi(session, symbolBuilder)) - } - val name = fir.importedName ?: return emptyList() - val symbolProvider = session.symbolProvider - - @OptIn(ExperimentalStdlibApi::class) + val resolvedImport = FirImportResolveTransformer(session).transformImport(rawImportForSelectedFqName, null) as FirResolvedImport + val scope = FirExplicitSimpleImportingScope(listOf(resolvedImport), session, ScopeSession()) + val selectedName = resolvedImport.importedName ?: return emptyList() return buildList { - symbolProvider.getTopLevelCallableSymbols(fir.packageFqName, name) - .mapTo(this) { it.fir.buildSymbol(symbolBuilder) } - symbolProvider - .getClassLikeSymbolByFqName(ClassId(fir.packageFqName, name)) - ?.fir - ?.buildSymbol(symbolBuilder) - ?.let(::add) + if (selectedFqName == fullFqName) { + // callables cannot be used as receiver expressions in imports + scope.processFunctionsByName(selectedName) { add(it.fir.buildSymbol(builder)) } + scope.processPropertiesByName(selectedName) { add(it.fir.buildSymbol(builder)) } + } + scope.processClassifiersByName(selectedName) { addIfNotNull(it.fir.buildSymbol(builder)) } + builder.createPackageSymbolIfOneExists(selectedFqName)?.let(::add) } } diff --git a/idea/testData/resolve/references/inImport/javaClass.kt b/idea/testData/resolve/references/inImport/javaClass.kt new file mode 100644 index 00000000000..fa4e0827226 --- /dev/null +++ b/idea/testData/resolve/references/inImport/javaClass.kt @@ -0,0 +1,3 @@ +import java.util.HashMap + +// REF: (java.util).HashMap diff --git a/idea/testData/resolve/references/inImport/javaPackageFirstQualifier.kt b/idea/testData/resolve/references/inImport/javaPackageFirstQualifier.kt new file mode 100644 index 00000000000..d9fc1261812 --- /dev/null +++ b/idea/testData/resolve/references/inImport/javaPackageFirstQualifier.kt @@ -0,0 +1,2 @@ +import java.util.ArrayList +// REF: java diff --git a/idea/testData/resolve/references/inImport/javaPackageSecondQualifier.kt b/idea/testData/resolve/references/inImport/javaPackageSecondQualifier.kt new file mode 100644 index 00000000000..f21f5e7466c --- /dev/null +++ b/idea/testData/resolve/references/inImport/javaPackageSecondQualifier.kt @@ -0,0 +1,2 @@ +import java.util.ArrayList +// REF: util diff --git a/idea/testData/resolve/references/inImport/kotlinClass.kt b/idea/testData/resolve/references/inImport/kotlinClass.kt new file mode 100644 index 00000000000..82634c51c3d --- /dev/null +++ b/idea/testData/resolve/references/inImport/kotlinClass.kt @@ -0,0 +1,4 @@ +import kotlin.collections.MutableList +// MULTIRESOLVE +// REF: (kotlin.collections).MutableList +// REF: (kotlin.collections).MutableList(kotlin.Int, (kotlin.Int) -> T) diff --git a/idea/testData/resolve/references/inImport/kotlinPackageFirstQualifier.kt b/idea/testData/resolve/references/inImport/kotlinPackageFirstQualifier.kt new file mode 100644 index 00000000000..51212bc5b35 --- /dev/null +++ b/idea/testData/resolve/references/inImport/kotlinPackageFirstQualifier.kt @@ -0,0 +1,2 @@ +import kotlin.text.toString +// REF: kotlin diff --git a/idea/testData/resolve/references/inImport/kotlinPackageSecondQualifier.kt b/idea/testData/resolve/references/inImport/kotlinPackageSecondQualifier.kt new file mode 100644 index 00000000000..66029e849e8 --- /dev/null +++ b/idea/testData/resolve/references/inImport/kotlinPackageSecondQualifier.kt @@ -0,0 +1,2 @@ +import kotlin.text.toString +// REF: text diff --git a/idea/testData/resolve/references/inImport/kotlinTopLevelFunction.kt b/idea/testData/resolve/references/inImport/kotlinTopLevelFunction.kt new file mode 100644 index 00000000000..77a6f8d61dc --- /dev/null +++ b/idea/testData/resolve/references/inImport/kotlinTopLevelFunction.kt @@ -0,0 +1,4 @@ +import kotlin.collections.mutableListOf +// MULTIRESOLVE +// REF: (kotlin.collections).mutableListOf() +// REF: (kotlin.collections).mutableListOf(vararg T) \ No newline at end of file diff --git a/idea/testData/resolve/references/inImport/staticMethodFromJavaClass.kt b/idea/testData/resolve/references/inImport/staticMethodFromJavaClass.kt new file mode 100644 index 00000000000..f361f278597 --- /dev/null +++ b/idea/testData/resolve/references/inImport/staticMethodFromJavaClass.kt @@ -0,0 +1,2 @@ +import java.lang.Math.sin +// REF: (in java.lang.Math).sin(double) diff --git a/idea/testData/resolve/references/inImport/staticMethodFromJavaClassJavaClass.kt b/idea/testData/resolve/references/inImport/staticMethodFromJavaClassJavaClass.kt new file mode 100644 index 00000000000..568b94418aa --- /dev/null +++ b/idea/testData/resolve/references/inImport/staticMethodFromJavaClassJavaClass.kt @@ -0,0 +1,2 @@ +import java.lang.Math.sin +// REF: (java.lang).Math diff --git a/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java index cf923f1de51..14ab38e4bc9 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java @@ -716,6 +716,64 @@ public class ReferenceResolveTestGenerated extends AbstractReferenceResolveTest } } + @TestMetadata("idea/testData/resolve/references/inImport") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class InImport extends AbstractReferenceResolveTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInInImport() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/resolve/references/inImport"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("javaClass.kt") + public void testJavaClass() throws Exception { + runTest("idea/testData/resolve/references/inImport/javaClass.kt"); + } + + @TestMetadata("javaPackageFirstQualifier.kt") + public void testJavaPackageFirstQualifier() throws Exception { + runTest("idea/testData/resolve/references/inImport/javaPackageFirstQualifier.kt"); + } + + @TestMetadata("javaPackageSecondQualifier.kt") + public void testJavaPackageSecondQualifier() throws Exception { + runTest("idea/testData/resolve/references/inImport/javaPackageSecondQualifier.kt"); + } + + @TestMetadata("kotlinClass.kt") + public void testKotlinClass() throws Exception { + runTest("idea/testData/resolve/references/inImport/kotlinClass.kt"); + } + + @TestMetadata("kotlinPackageFirstQualifier.kt") + public void testKotlinPackageFirstQualifier() throws Exception { + runTest("idea/testData/resolve/references/inImport/kotlinPackageFirstQualifier.kt"); + } + + @TestMetadata("kotlinPackageSecondQualifier.kt") + public void testKotlinPackageSecondQualifier() throws Exception { + runTest("idea/testData/resolve/references/inImport/kotlinPackageSecondQualifier.kt"); + } + + @TestMetadata("kotlinTopLevelFunction.kt") + public void testKotlinTopLevelFunction() throws Exception { + runTest("idea/testData/resolve/references/inImport/kotlinTopLevelFunction.kt"); + } + + @TestMetadata("staticMethodFromJavaClass.kt") + public void testStaticMethodFromJavaClass() throws Exception { + runTest("idea/testData/resolve/references/inImport/staticMethodFromJavaClass.kt"); + } + + @TestMetadata("staticMethodFromJavaClassJavaClass.kt") + public void testStaticMethodFromJavaClassJavaClass() throws Exception { + runTest("idea/testData/resolve/references/inImport/staticMethodFromJavaClassJavaClass.kt"); + } + } + @TestMetadata("idea/testData/resolve/references/invoke") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)