[AA LC] Approximate anonymous type to single supertype if possible
^KT-55780 Fixed ^KT-55778 Fixed
This commit is contained in:
committed by
Space Team
parent
935b4f2feb
commit
3a536bb32f
+8
-11
@@ -96,7 +96,9 @@ private fun ConeKotlinType.simplifyType(
|
|||||||
return currentType
|
return currentType
|
||||||
}
|
}
|
||||||
currentType = currentType.upperBoundIfFlexible()
|
currentType = currentType.upperBoundIfFlexible()
|
||||||
currentType = substitutor.substituteOrSelf(currentType)
|
if (visibilityForApproximation != Visibilities.Local) {
|
||||||
|
currentType = substitutor.substituteOrSelf(currentType)
|
||||||
|
}
|
||||||
val needLocalTypeApproximation = needLocalTypeApproximation(visibilityForApproximation, isInlineFunction, session, useSitePosition)
|
val needLocalTypeApproximation = needLocalTypeApproximation(visibilityForApproximation, isInlineFunction, session, useSitePosition)
|
||||||
// TODO: can we approximate local types in type arguments *selectively* ?
|
// TODO: can we approximate local types in type arguments *selectively* ?
|
||||||
currentType = PublicTypeApproximator.approximateTypeToPublicDenotable(currentType, session, needLocalTypeApproximation)
|
currentType = PublicTypeApproximator.approximateTypeToPublicDenotable(currentType, session, needLocalTypeApproximation)
|
||||||
@@ -132,6 +134,7 @@ private val PsiElement.visibilityForApproximation: Visibility
|
|||||||
val containerVisibility =
|
val containerVisibility =
|
||||||
if (parent is KtLightClassForFacade) Visibilities.Public
|
if (parent is KtLightClassForFacade) Visibilities.Public
|
||||||
else (parent as? PsiClass)?.visibility ?: Visibilities.Local
|
else (parent as? PsiClass)?.visibility ?: Visibilities.Local
|
||||||
|
val visibility = visibility
|
||||||
if (containerVisibility == Visibilities.Local || visibility == Visibilities.Local) return Visibilities.Local
|
if (containerVisibility == Visibilities.Local || visibility == Visibilities.Local) return Visibilities.Local
|
||||||
if (containerVisibility == Visibilities.Private) return Visibilities.Private
|
if (containerVisibility == Visibilities.Private) return Visibilities.Private
|
||||||
return visibility
|
return visibility
|
||||||
@@ -140,6 +143,7 @@ private val PsiElement.visibilityForApproximation: Visibility
|
|||||||
// Mimic JavaElementUtil#getVisibility
|
// Mimic JavaElementUtil#getVisibility
|
||||||
private val PsiModifierListOwner.visibility: Visibility
|
private val PsiModifierListOwner.visibility: Visibility
|
||||||
get() {
|
get() {
|
||||||
|
if (parents.any { it is PsiMethod }) return Visibilities.Local
|
||||||
if (hasModifierProperty(PsiModifier.PUBLIC)) {
|
if (hasModifierProperty(PsiModifier.PUBLIC)) {
|
||||||
return Visibilities.Public
|
return Visibilities.Public
|
||||||
}
|
}
|
||||||
@@ -211,19 +215,12 @@ private class AnonymousTypesSubstitutor(
|
|||||||
override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
|
override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
|
||||||
if (type !is ConeClassLikeType) return null
|
if (type !is ConeClassLikeType) return null
|
||||||
|
|
||||||
val isAnonymous = type.classId.let { it?.shortClassName?.asString() == SpecialNames.ANONYMOUS_STRING }
|
val hasStableName = type.classId?.isLocal == true
|
||||||
if (!isAnonymous) return null
|
if (!hasStableName) return null
|
||||||
|
|
||||||
fun ConeClassLikeType.isNotInterface(): Boolean {
|
|
||||||
val firClassNode = lookupTag.toSymbol(session) as? FirClassSymbol<*> ?: return false
|
|
||||||
return firClassNode.classKind != ClassKind.INTERFACE
|
|
||||||
}
|
|
||||||
|
|
||||||
val firClassNode = type.lookupTag.toSymbol(session) as? FirClassSymbol
|
val firClassNode = type.lookupTag.toSymbol(session) as? FirClassSymbol
|
||||||
if (firClassNode != null) {
|
if (firClassNode != null) {
|
||||||
val superTypesCones = firClassNode.resolvedSuperTypes
|
firClassNode.resolvedSuperTypes.singleOrNull()?.let { return it }
|
||||||
val superClass = superTypesCones.firstOrNull { (it as? ConeClassLikeType)?.isNotInterface() == true }
|
|
||||||
if (superClass != null) return superClass
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (type.nullability.isNullable) session.builtinTypes.nullableAnyType.type
|
return if (type.nullability.isNullable) session.builtinTypes.nullableAnyType.type
|
||||||
|
|||||||
+10
-4
@@ -14,11 +14,11 @@ import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerPro
|
|||||||
import org.jetbrains.kotlin.analysis.test.framework.utils.executeOnPooledThreadInReadAction
|
import org.jetbrains.kotlin.analysis.test.framework.utils.executeOnPooledThreadInReadAction
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||||
import org.jetbrains.kotlin.test.services.TestModuleStructure
|
import org.jetbrains.kotlin.test.services.TestModuleStructure
|
||||||
import org.jetbrains.kotlin.test.services.TestServices
|
import org.jetbrains.kotlin.test.services.TestServices
|
||||||
import org.jetbrains.kotlin.test.services.assertions
|
import org.jetbrains.kotlin.test.services.assertions
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
|
||||||
|
|
||||||
abstract class AbstractAnalysisApiPsiTypeProviderTest : AbstractAnalysisApiBasedTest() {
|
abstract class AbstractAnalysisApiPsiTypeProviderTest : AbstractAnalysisApiBasedTest() {
|
||||||
override fun doTestByModuleStructure(moduleStructure: TestModuleStructure, testServices: TestServices) {
|
override fun doTestByModuleStructure(moduleStructure: TestModuleStructure, testServices: TestServices) {
|
||||||
@@ -26,9 +26,14 @@ abstract class AbstractAnalysisApiPsiTypeProviderTest : AbstractAnalysisApiBased
|
|||||||
val ktFiles = testServices.ktModuleProvider.getModuleFiles(module).filterIsInstance<KtFile>()
|
val ktFiles = testServices.ktModuleProvider.getModuleFiles(module).filterIsInstance<KtFile>()
|
||||||
testServices.expressionMarkerProvider.getElementsOfTypeAtCarets<KtDeclaration>(ktFiles)
|
testServices.expressionMarkerProvider.getElementsOfTypeAtCarets<KtDeclaration>(ktFiles)
|
||||||
}.single()
|
}.single()
|
||||||
val containingClass = getContainingKtLightClass(declaration, ktFile)
|
|
||||||
val psiContext = containingClass.findLightDeclarationContext(declaration)
|
val psiContext = if (KtPsiUtil.isLocal(declaration)) {
|
||||||
?: error("Can't find psi context for $declaration")
|
declaration
|
||||||
|
} else {
|
||||||
|
val containingClass = getContainingKtLightClass(declaration, ktFile)
|
||||||
|
containingClass.findLightDeclarationContext(declaration) ?: error("Can't find psi context for $declaration")
|
||||||
|
}
|
||||||
|
|
||||||
val actual = buildString {
|
val actual = buildString {
|
||||||
executeOnPooledThreadInReadAction {
|
executeOnPooledThreadInReadAction {
|
||||||
analyze(declaration) {
|
analyze(declaration) {
|
||||||
@@ -38,6 +43,7 @@ abstract class AbstractAnalysisApiPsiTypeProviderTest : AbstractAnalysisApiBased
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
testServices.assertions.assertEqualsToTestDataFileSibling(actual)
|
testServices.assertions.assertEqualsToTestDataFileSibling(actual)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+6
@@ -96,6 +96,12 @@ public class SymbolLightClassesByPsiForLibraryTestGenerated extends AbstractSymb
|
|||||||
runTest("compiler/testData/asJava/lightClasses/lightClassByPsi/enums.kt");
|
runTest("compiler/testData/asJava/lightClasses/lightClassByPsi/enums.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("exposedAnonymousType.kt")
|
||||||
|
public void testExposedAnonymousType() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/lightClassByPsi/exposedAnonymousType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("generics.kt")
|
@TestMetadata("generics.kt")
|
||||||
public void testGenerics() throws Exception {
|
public void testGenerics() throws Exception {
|
||||||
|
|||||||
+6
@@ -96,6 +96,12 @@ public class SymbolLightClassesByPsiForSourceTestGenerated extends AbstractSymbo
|
|||||||
runTest("compiler/testData/asJava/lightClasses/lightClassByPsi/enums.kt");
|
runTest("compiler/testData/asJava/lightClasses/lightClassByPsi/enums.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("exposedAnonymousType.kt")
|
||||||
|
public void testExposedAnonymousType() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/lightClassByPsi/exposedAnonymousType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("generics.kt")
|
@TestMetadata("generics.kt")
|
||||||
public void testGenerics() throws Exception {
|
public void testGenerics() throws Exception {
|
||||||
|
|||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
final class null /* null*/ {
|
||||||
|
private ();// .ctor()
|
||||||
|
}
|
||||||
|
|
||||||
|
final class null /* null*/ extends A {
|
||||||
|
private ();// .ctor()
|
||||||
|
}
|
||||||
|
|
||||||
|
final class null /* null*/ implements B {
|
||||||
|
private ();// .ctor()
|
||||||
|
}
|
||||||
|
|
||||||
|
final class null /* null*/ extends A implements B {
|
||||||
|
private ();// .ctor()
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class A /* A*/ {
|
||||||
|
public A();// .ctor()
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract interface B /* B*/ {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class C /* C*/ {
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
private final A x2;
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
private final B x3;
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
private final java.lang.Object x1;
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
private final java.lang.Object x4;
|
||||||
|
|
||||||
|
public C();// .ctor()
|
||||||
|
}
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
final class null /* null*/ {
|
||||||
|
private ();// .ctor()
|
||||||
|
}
|
||||||
|
|
||||||
|
final class null /* null*/ extends A {
|
||||||
|
private ();// .ctor()
|
||||||
|
}
|
||||||
|
|
||||||
|
final class null /* null*/ implements B {
|
||||||
|
private ();// .ctor()
|
||||||
|
}
|
||||||
|
|
||||||
|
final class null /* null*/ extends A implements B {
|
||||||
|
private ();// .ctor()
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class A /* A*/ {
|
||||||
|
public A();// .ctor()
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract interface B /* B*/ {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class C /* C*/ {
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
private final A x2;
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
private final A x4;
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
private final B x3;
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
private final java.lang.Object x1;
|
||||||
|
|
||||||
|
public C();// .ctor()
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
abstract class A
|
||||||
|
interface B
|
||||||
|
|
||||||
|
class C {
|
||||||
|
private val x1 = object {}
|
||||||
|
private val x2 = object : A() {}
|
||||||
|
private val x3 = object : B {}
|
||||||
|
private val x4 = object : A(), B {}
|
||||||
|
}
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
public abstract class A /* A*/ {
|
||||||
|
public A();// .ctor()
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract interface B /* B*/ {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class C /* C*/ {
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
private final C.x1.1 x1;
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
private final C.x2.1 x2;
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
private final C.x3.1 x3;
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
private final C.x4.1 x4;
|
||||||
|
|
||||||
|
public C();// .ctor()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user