FIR IDE: Add import in case when conflicting class comes from * import
This commit is contained in:
+5
@@ -66,6 +66,11 @@ public class FirShortenRefsTestGenerated extends AbstractFirShortenRefsTest {
|
|||||||
runTest("idea/testData/shortenRefsFir/types/ParameterTypeGenericTypes.kt");
|
runTest("idea/testData/shortenRefsFir/types/ParameterTypeGenericTypes.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ParameterTypeImplicitImportBeatsStarImport.kt")
|
||||||
|
public void testParameterTypeImplicitImportBeatsStarImport() throws Exception {
|
||||||
|
runTest("idea/testData/shortenRefsFir/types/ParameterTypeImplicitImportBeatsStarImport.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("ParameterTypeImportedNestedClass.kt")
|
@TestMetadata("ParameterTypeImportedNestedClass.kt")
|
||||||
public void testParameterTypeImportedNestedClass() throws Exception {
|
public void testParameterTypeImportedNestedClass() throws Exception {
|
||||||
runTest("idea/testData/shortenRefsFir/types/ParameterTypeImportedNestedClass.kt");
|
runTest("idea/testData/shortenRefsFir/types/ParameterTypeImportedNestedClass.kt");
|
||||||
|
|||||||
+15
-7
@@ -15,12 +15,15 @@ import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
|
|||||||
import org.jetbrains.kotlin.fir.psi
|
import org.jetbrains.kotlin.fir.psi
|
||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractStarImportingScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirExplicitSimpleImportingScope
|
import org.jetbrains.kotlin.fir.scopes.impl.FirExplicitSimpleImportingScope
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.processClassifiersByName
|
import org.jetbrains.kotlin.fir.scopes.processClassifiersByName
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.classId
|
import org.jetbrains.kotlin.fir.types.classId
|
||||||
|
import org.jetbrains.kotlin.fir.types.lowerBoundIfFlexible
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
|
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFir
|
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFir
|
||||||
@@ -60,12 +63,17 @@ internal class KtFirReferenceShortener(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findFirstClassifierInScopesByName(positionScopes: List<FirScope>, targetClassName: Name): ClassId? {
|
private data class AvailableClassifier(val classId: ClassId, val isFromStarOrPackageImport: Boolean)
|
||||||
|
|
||||||
|
private fun findFirstClassifierInScopesByName(positionScopes: List<FirScope>, targetClassName: Name): AvailableClassifier? {
|
||||||
for (scope in positionScopes) {
|
for (scope in positionScopes) {
|
||||||
val classifierSymbol = scope.findFirstClassifierByName(targetClassName) ?: continue
|
val classifierSymbol = scope.findFirstClassifierByName(targetClassName) ?: continue
|
||||||
val classifierLookupTag = classifierSymbol.toLookupTag() as? ConeClassLikeLookupTag ?: continue
|
val classifierLookupTag = classifierSymbol.toLookupTag() as? ConeClassLikeLookupTag ?: continue
|
||||||
|
|
||||||
return classifierLookupTag.classId
|
return AvailableClassifier(
|
||||||
|
classifierLookupTag.classId,
|
||||||
|
isFromStarOrPackageImport = scope is FirAbstractStarImportingScope || scope is FirPackageMemberScope
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
@@ -137,7 +145,7 @@ internal class KtFirReferenceShortener(
|
|||||||
private fun processTypeRef(resolvedTypeRef: FirResolvedTypeRef) {
|
private fun processTypeRef(resolvedTypeRef: FirResolvedTypeRef) {
|
||||||
val wholeTypeReference = resolvedTypeRef.psi as? KtTypeReference ?: return
|
val wholeTypeReference = resolvedTypeRef.psi as? KtTypeReference ?: return
|
||||||
|
|
||||||
val wholeClassifierId = resolvedTypeRef.type.classId ?: return
|
val wholeClassifierId = resolvedTypeRef.type.lowerBoundIfFlexible().classId ?: return
|
||||||
val wholeTypeElement = wholeTypeReference.typeElement.unwrapNullable() as? KtUserType ?: return
|
val wholeTypeElement = wholeTypeReference.typeElement.unwrapNullable() as? KtUserType ?: return
|
||||||
|
|
||||||
if (wholeTypeElement.qualifier == null) return
|
if (wholeTypeElement.qualifier == null) return
|
||||||
@@ -152,7 +160,7 @@ internal class KtFirReferenceShortener(
|
|||||||
val positionScopes = findScopesAtPosition(wholeTypeElement, typesToImport) ?: return
|
val positionScopes = findScopesAtPosition(wholeTypeElement, typesToImport) ?: return
|
||||||
|
|
||||||
for ((classId, typeElement) in allClassIds.zip(allTypeElements)) {
|
for ((classId, typeElement) in allClassIds.zip(allTypeElements)) {
|
||||||
val firstFoundClass = findFirstClassifierInScopesByName(positionScopes, classId.shortClassName)
|
val firstFoundClass = findFirstClassifierInScopesByName(positionScopes, classId.shortClassName)?.classId
|
||||||
|
|
||||||
if (firstFoundClass == classId) {
|
if (firstFoundClass == classId) {
|
||||||
addTypeToShorten(typeElement)
|
addTypeToShorten(typeElement)
|
||||||
@@ -162,11 +170,11 @@ internal class KtFirReferenceShortener(
|
|||||||
|
|
||||||
// none class matched
|
// none class matched
|
||||||
val (mostTopLevelClassId, mostTopLevelTypeElement) = allClassIds.zip(allTypeElements).last()
|
val (mostTopLevelClassId, mostTopLevelTypeElement) = allClassIds.zip(allTypeElements).last()
|
||||||
val firstFoundClass = findFirstClassifierInScopesByName(positionScopes, mostTopLevelClassId.shortClassName)
|
val availableClassifier = findFirstClassifierInScopesByName(positionScopes, mostTopLevelClassId.shortClassName)
|
||||||
|
|
||||||
check(firstFoundClass != mostTopLevelClassId) { "This should not be true" }
|
check(availableClassifier?.classId != mostTopLevelClassId) { "This should not be true" }
|
||||||
|
|
||||||
if (firstFoundClass == null) {
|
if (availableClassifier == null || availableClassifier.isFromStarOrPackageImport) {
|
||||||
addTypeToImportAndShorten(mostTopLevelClassId.asSingleFqName(), mostTopLevelTypeElement)
|
addTypeToImportAndShorten(mostTopLevelClassId.asSingleFqName(), mostTopLevelTypeElement)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package dependency1
|
||||||
|
|
||||||
|
class T
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package dependency2
|
||||||
|
|
||||||
|
class T
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
// FIR_COMPARISON
|
||||||
|
package test
|
||||||
|
|
||||||
|
import dependency1.*
|
||||||
|
|
||||||
|
<selection>fun foo(t: dependency2.T) {}</selection>
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
// FIR_COMPARISON
|
||||||
|
package test
|
||||||
|
|
||||||
|
import dependency1.*
|
||||||
|
import dependency2.T
|
||||||
|
|
||||||
|
fun foo(t: T) {}
|
||||||
+2
-1
@@ -2,7 +2,8 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
import dependency.*
|
import dependency.*
|
||||||
|
import dependency.T
|
||||||
|
|
||||||
class T
|
class T
|
||||||
|
|
||||||
fun foo(t: dependency.T) {}
|
fun foo(t: T) {}
|
||||||
Reference in New Issue
Block a user