FIR IDE: fix reference resolve in import statement
This commit is contained in:
committed by
TeamCityServer
parent
55621b7aad
commit
b81ef157b2
Generated
+58
@@ -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")
|
@TestMetadata("idea/testData/resolve/references/invoke")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+35
-23
@@ -6,18 +6,25 @@
|
|||||||
package org.jetbrains.kotlin.idea.references
|
package org.jetbrains.kotlin.idea.references
|
||||||
|
|
||||||
import com.intellij.psi.tree.TokenSet
|
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.*
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.builder.buildImport
|
||||||
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
|
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.fir.psi
|
||||||
import org.jetbrains.kotlin.fir.references.*
|
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.calls.FirSyntheticPropertySymbol
|
||||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
|
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
|
||||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError
|
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError
|
||||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeOperatorAmbiguityError
|
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeOperatorAmbiguityError
|
||||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnmatchedTypeArgumentsError
|
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.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.AbstractFirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
|
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.getNonStrictParentOfType
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector
|
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.unwrapNullability
|
import org.jetbrains.kotlin.psi.psiUtil.unwrapNullability
|
||||||
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
|
||||||
internal object FirReferenceResolveHelper {
|
internal object FirReferenceResolveHelper {
|
||||||
fun FirResolvedTypeRef.toTargetSymbol(session: FirSession, symbolBuilder: KtSymbolByFirBuilder): KtSymbol? {
|
fun FirResolvedTypeRef.toTargetSymbol(session: FirSession, symbolBuilder: KtSymbolByFirBuilder): KtSymbol? {
|
||||||
@@ -116,11 +124,18 @@ internal object FirReferenceResolveHelper {
|
|||||||
symbolBuilder: KtSymbolByFirBuilder,
|
symbolBuilder: KtSymbolByFirBuilder,
|
||||||
forQualifiedType: Boolean
|
forQualifiedType: Boolean
|
||||||
): KtFirPackageSymbol? {
|
): KtFirPackageSymbol? {
|
||||||
|
return symbolBuilder.createPackageSymbolIfOneExists(getQualifierSelected(expression, forQualifiedType))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getQualifierSelected(
|
||||||
|
expression: KtSimpleNameExpression,
|
||||||
|
forQualifiedType: Boolean
|
||||||
|
): FqName {
|
||||||
val qualified = when {
|
val qualified = when {
|
||||||
forQualifiedType -> expression.parent?.takeIf { it is KtUserType && it.referenceExpression === expression }
|
forQualifiedType -> expression.parent?.takeIf { it is KtUserType && it.referenceExpression === expression }
|
||||||
else -> expression.getQualifiedExpressionForSelector()
|
else -> expression.getQualifiedExpressionForSelector()
|
||||||
}
|
}
|
||||||
val fqName = when (qualified) {
|
return when (qualified) {
|
||||||
null -> FqName(expression.getReferencedName())
|
null -> FqName(expression.getReferencedName())
|
||||||
else -> {
|
else -> {
|
||||||
qualified
|
qualified
|
||||||
@@ -130,7 +145,6 @@ internal object FirReferenceResolveHelper {
|
|||||||
.let(::FqName)
|
.let(::FqName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return symbolBuilder.createPackageSymbolIfOneExists(fqName)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtSimpleNameExpression.isPartOfQualifiedExpression(): Boolean {
|
private fun KtSimpleNameExpression.isPartOfQualifiedExpression(): Boolean {
|
||||||
@@ -313,32 +327,30 @@ internal object FirReferenceResolveHelper {
|
|||||||
return listOf(symbolBuilder.buildSymbol(fir))
|
return listOf(symbolBuilder.buildSymbol(fir))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
private fun getSymbolsByResolvedImport(
|
private fun getSymbolsByResolvedImport(
|
||||||
expression: KtSimpleNameExpression,
|
expression: KtSimpleNameExpression,
|
||||||
symbolBuilder: KtSymbolByFirBuilder,
|
builder: KtSymbolByFirBuilder,
|
||||||
fir: FirResolvedImport,
|
fir: FirResolvedImport,
|
||||||
session: FirSession
|
session: FirSession
|
||||||
): List<KtSymbol> {
|
): List<KtSymbol> {
|
||||||
if (expression.isPartOfQualifiedExpression()) {
|
val fullFqName = fir.importedFqName
|
||||||
return listOfNotNull(getPackageSymbolFor(expression, symbolBuilder, forQualifiedType = false))
|
val selectedFqName = getQualifierSelected(expression, forQualifiedType = false)
|
||||||
|
val rawImportForSelectedFqName = buildImport {
|
||||||
|
importedFqName = selectedFqName
|
||||||
|
isAllUnder = false
|
||||||
}
|
}
|
||||||
|
val resolvedImport = FirImportResolveTransformer(session).transformImport(rawImportForSelectedFqName, null) as FirResolvedImport
|
||||||
val classId = fir.resolvedClassId
|
val scope = FirExplicitSimpleImportingScope(listOf(resolvedImport), session, ScopeSession())
|
||||||
if (classId != null) {
|
val selectedName = resolvedImport.importedName ?: return emptyList()
|
||||||
return listOfNotNull(classId.toTargetPsi(session, symbolBuilder))
|
|
||||||
}
|
|
||||||
val name = fir.importedName ?: return emptyList()
|
|
||||||
val symbolProvider = session.symbolProvider
|
|
||||||
|
|
||||||
@OptIn(ExperimentalStdlibApi::class)
|
|
||||||
return buildList {
|
return buildList {
|
||||||
symbolProvider.getTopLevelCallableSymbols(fir.packageFqName, name)
|
if (selectedFqName == fullFqName) {
|
||||||
.mapTo(this) { it.fir.buildSymbol(symbolBuilder) }
|
// callables cannot be used as receiver expressions in imports
|
||||||
symbolProvider
|
scope.processFunctionsByName(selectedName) { add(it.fir.buildSymbol(builder)) }
|
||||||
.getClassLikeSymbolByFqName(ClassId(fir.packageFqName, name))
|
scope.processPropertiesByName(selectedName) { add(it.fir.buildSymbol(builder)) }
|
||||||
?.fir
|
}
|
||||||
?.buildSymbol(symbolBuilder)
|
scope.processClassifiersByName(selectedName) { addIfNotNull(it.fir.buildSymbol(builder)) }
|
||||||
?.let(::add)
|
builder.createPackageSymbolIfOneExists(selectedFqName)?.let(::add)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import java.util.Ha<caret>shMap
|
||||||
|
|
||||||
|
// REF: (java.util).HashMap
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
import jav<caret>a.util.ArrayList
|
||||||
|
// REF: java
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
import java.uti<caret>l.ArrayList
|
||||||
|
// REF: util
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import kotlin.collections.Mutab<caret>leList
|
||||||
|
// MULTIRESOLVE
|
||||||
|
// REF: (kotlin.collections).MutableList
|
||||||
|
// REF: (kotlin.collections).MutableList(kotlin.Int, (kotlin.Int) -> T)
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
import kotli<caret>n.text.toString
|
||||||
|
// REF: kotlin
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
import kotlin.tex<caret>t.toString
|
||||||
|
// REF: text
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import kotlin.collections.mut<caret>ableListOf
|
||||||
|
// MULTIRESOLVE
|
||||||
|
// REF: (kotlin.collections).mutableListOf()
|
||||||
|
// REF: (kotlin.collections).mutableListOf(vararg T)
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
import java.lang.Math.si<caret>n
|
||||||
|
// REF: (in java.lang.Math).sin(double)
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
import java.lang.M<caret>ath.sin
|
||||||
|
// REF: (java.lang).Math
|
||||||
+58
@@ -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")
|
@TestMetadata("idea/testData/resolve/references/invoke")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user