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");
|
||||
}
|
||||
|
||||
@TestMetadata("ParameterTypeImplicitImportBeatsStarImport.kt")
|
||||
public void testParameterTypeImplicitImportBeatsStarImport() throws Exception {
|
||||
runTest("idea/testData/shortenRefsFir/types/ParameterTypeImplicitImportBeatsStarImport.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("ParameterTypeImportedNestedClass.kt")
|
||||
public void testParameterTypeImportedNestedClass() throws Exception {
|
||||
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.resolve.ScopeSession
|
||||
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.FirPackageMemberScope
|
||||
import org.jetbrains.kotlin.fir.scopes.processClassifiersByName
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
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.idea.fir.low.level.api.api.FirModuleResolveState
|
||||
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) {
|
||||
val classifierSymbol = scope.findFirstClassifierByName(targetClassName) ?: continue
|
||||
val classifierLookupTag = classifierSymbol.toLookupTag() as? ConeClassLikeLookupTag ?: continue
|
||||
|
||||
return classifierLookupTag.classId
|
||||
return AvailableClassifier(
|
||||
classifierLookupTag.classId,
|
||||
isFromStarOrPackageImport = scope is FirAbstractStarImportingScope || scope is FirPackageMemberScope
|
||||
)
|
||||
}
|
||||
|
||||
return null
|
||||
@@ -137,7 +145,7 @@ internal class KtFirReferenceShortener(
|
||||
private fun processTypeRef(resolvedTypeRef: FirResolvedTypeRef) {
|
||||
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
|
||||
|
||||
if (wholeTypeElement.qualifier == null) return
|
||||
@@ -152,7 +160,7 @@ internal class KtFirReferenceShortener(
|
||||
val positionScopes = findScopesAtPosition(wholeTypeElement, typesToImport) ?: return
|
||||
|
||||
for ((classId, typeElement) in allClassIds.zip(allTypeElements)) {
|
||||
val firstFoundClass = findFirstClassifierInScopesByName(positionScopes, classId.shortClassName)
|
||||
val firstFoundClass = findFirstClassifierInScopesByName(positionScopes, classId.shortClassName)?.classId
|
||||
|
||||
if (firstFoundClass == classId) {
|
||||
addTypeToShorten(typeElement)
|
||||
@@ -162,11 +170,11 @@ internal class KtFirReferenceShortener(
|
||||
|
||||
// none class matched
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
import dependency.*
|
||||
import dependency.T
|
||||
|
||||
class T
|
||||
|
||||
fun foo(t: dependency.T) {}
|
||||
fun foo(t: T) {}
|
||||
Reference in New Issue
Block a user